littlejsengine 1.7.13 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +27 -55
  2. package/build/littlejs.d.ts +253 -76
  3. package/build/littlejs.esm.js +644 -523
  4. package/build/littlejs.esm.min.js +1 -1
  5. package/build/littlejs.js +640 -332
  6. package/build/littlejs.min.js +1 -1
  7. package/build/littlejs.release.js +640 -332
  8. package/examples/breakout/game.js +17 -14
  9. package/examples/breakout/gameObjects.js +29 -8
  10. package/examples/breakout/index.html +3 -3
  11. package/examples/breakoutTutorial/README.md +2 -2
  12. package/examples/breakoutTutorial/game.js +4 -4
  13. package/examples/breakoutTutorial/index.html +2 -2
  14. package/examples/electron/build.js +2 -0
  15. package/examples/electron/game.js +3 -2
  16. package/examples/electron/index.html +2 -2
  17. package/examples/empty/game.js +1 -1
  18. package/examples/favicon.png +0 -0
  19. package/examples/js13k/build.js +2 -0
  20. package/examples/js13k/game.js +20 -15
  21. package/examples/js13k/index.html +14 -14
  22. package/examples/module/game.js +4 -3
  23. package/examples/module/index.html +1 -1
  24. package/examples/particles/index.html +19 -22
  25. package/examples/platformer/game.js +3 -3
  26. package/examples/platformer/gameEffects.js +21 -19
  27. package/examples/platformer/gameLevel.js +6 -6
  28. package/examples/platformer/gameObjects.js +18 -18
  29. package/examples/platformer/gamePlayer.js +4 -3
  30. package/examples/platformer/index.html +6 -6
  31. package/examples/platformer/tiles.png +0 -0
  32. package/examples/platformer/tilesLevel.png +0 -0
  33. package/examples/puzzle/game.js +10 -8
  34. package/examples/puzzle/index.html +2 -2
  35. package/examples/screenshot.jpg +0 -0
  36. package/examples/starter/build.js +2 -0
  37. package/examples/starter/game.js +32 -21
  38. package/examples/starter/index.html +13 -13
  39. package/examples/starter/tiles.png +0 -0
  40. package/examples/stress/index.html +2 -2
  41. package/examples/typescript/build.js +2 -0
  42. package/examples/typescript/game.js +4 -3
  43. package/examples/typescript/game.ts +4 -3
  44. package/examples/typescript/index.html +1 -1
  45. package/package.json +1 -1
  46. package/src/engine.js +59 -49
  47. package/src/engineAudio.js +67 -41
  48. package/src/engineBuild.js +23 -7
  49. package/src/engineDraw.js +139 -40
  50. package/src/engineExport.js +4 -191
  51. package/src/engineInput.js +22 -10
  52. package/src/engineMedals.js +13 -45
  53. package/src/engineObject.js +12 -13
  54. package/src/engineParticles.js +17 -17
  55. package/src/engineSettings.js +195 -2
  56. package/src/engineTileLayer.js +23 -22
  57. package/src/engineUtilities.js +6 -6
  58. package/src/engineWebGL.js +73 -74
@@ -3,196 +3,6 @@
3
3
  * - Export engine as a module with functions where necessary
4
4
  */
5
5
 
6
- /** Set position of camera in world space
7
- * @param {Vector2} pos
8
- * @memberof Settings */
9
- function setCameraPos(pos) { cameraPos = pos; }
10
-
11
- /** Set scale of camera in world space
12
- * @param {Number} scale
13
- * @memberof Settings */
14
- function setCameraScale(scale) { cameraScale = scale; }
15
-
16
- /** Set max size of the canvas
17
- * @param {Vector2} size
18
- * @memberof Settings */
19
- function setCanvasMaxSize(size) { canvasMaxSize = size; }
20
-
21
- /** Set fixed size of the canvas
22
- * @param {Vector2} size
23
- * @memberof Settings */
24
- function setCanvasFixedSize(size) { canvasFixedSize = size; }
25
-
26
- /** Disables anti aliasing for pixel art if true
27
- * @param {Boolean} pixelated
28
- * @memberof Settings */
29
- function setCanvasPixelated(pixelated) { canvasPixelated = pixelated; }
30
-
31
- /** Set default font used for text rendering
32
- * @param {String} font
33
- * @memberof Settings */
34
- function setFontDefault(font) { fontDefault = font; }
35
-
36
- /** Set if webgl rendering is enabled
37
- * @param {Boolean} enable
38
- * @memberof Settings */
39
- function setGlEnable(enable) { glEnable = enable; }
40
-
41
- /** Set to not composite the WebGL canvas
42
- * @param {Boolean} overlay
43
- * @memberof Settings */
44
- function setGlOverlay(overlay) { glOverlay = overlay; }
45
-
46
- /** Set default size of tiles in pixels
47
- * @param {Vector2} size
48
- * @memberof Settings */
49
- function setTileSizeDefault(size) { tileSizeDefault = size; }
50
-
51
- /** Set to prevent tile bleeding from neighbors in pixels
52
- * @param {Number} scale
53
- * @memberof Settings */
54
- function setTileFixBleedScale(scale) { tileFixBleedScale = scale; }
55
-
56
- /** Set if collisions between objects are enabled
57
- * @param {Boolean} enable
58
- * @memberof Settings */
59
- function setEnablePhysicsSolver(enable) { enablePhysicsSolver = enable; }
60
-
61
- /** Set default object mass for collison calcuations
62
- * @param {Number} mass
63
- * @memberof Settings */
64
- function setObjectDefaultMass(mass) { objectDefaultMass = mass; }
65
-
66
- /** Set how much to slow velocity by each frame
67
- * @param {Number} damping
68
- * @memberof Settings */
69
- function setObjectDefaultDamping(damp) { objectDefaultDamping = damp; }
70
-
71
- /** Set how much to slow angular velocity each frame
72
- * @param {Number} damping
73
- * @memberof Settings */
74
- function setObjectDefaultAngleDamping(damp) { objectDefaultAngleDamping = damp; }
75
-
76
- /** Set how much to bounce when a collision occur
77
- * @param {Number} elasticity
78
- * @memberof Settings */
79
- function setObjectDefaultElasticity(elasticity) { objectDefaultElasticity = elasticity; }
80
-
81
- /** Set how much to slow when touching
82
- * @param {Number} friction
83
- * @memberof Settings */
84
- function setObjectDefaultFriction(friction) { objectDefaultFriction = friction; }
85
-
86
- /** Set max speed to avoid fast objects missing collisions
87
- * @param {Number} speed
88
- * @memberof Settings */
89
- function setObjectMaxSpeed(speed) { objectMaxSpeed = speed; }
90
-
91
- /** Set how much gravity to apply to objects along the Y axis
92
- * @param {Number} gravity
93
- * @memberof Settings */
94
- function setGravity(g) { gravity = g; }
95
-
96
- /** Set to scales emit rate of particles
97
- * @param {Number} scale
98
- * @memberof Settings */
99
- function setParticleEmitRateScale(scale) { particleEmitRateScale = scale; }
100
-
101
- /** Set if gamepads are enabled
102
- * @param {Boolean} enable
103
- * @memberof Settings */
104
- function setGamepadsEnable(enable) { gamepadsEnable = enable; }
105
-
106
- /** Set if the dpad input is also routed to the left analog stick
107
- * @param {Boolean} enable
108
- * @memberof Settings */
109
- function setGamepadDirectionEmulateStick(enable) { gamepadDirectionEmulateStick = enable; }
110
-
111
- /** Set if true the WASD keys are also routed to the direction keys
112
- * @param {Boolean} enable
113
- * @memberof Settings */
114
- function setInputWASDEmulateDirection(enable) { inputWASDEmulateDirection = enable; }
115
-
116
- /** Set if touch gamepad should appear on mobile devices
117
- * @param {Boolean} enable
118
- * @memberof Settings */
119
- function setTouchGamepadEnable(enable) { touchGamepadEnable = enable; }
120
-
121
- /** Set if touch gamepad should be analog stick or 8 way dpad
122
- * @param {Boolean} analog
123
- * @memberof Settings */
124
- function setTouchGamepadAnalog(analog) { touchGamepadAnalog = analog; }
125
-
126
- /** Set size of virutal gamepad for touch devices in pixels
127
- * @param {Number} size
128
- * @memberof Settings */
129
- function setTouchGamepadSize(size) { touchGamepadSize = size; }
130
-
131
- /** Set transparency of touch gamepad overlay
132
- * @param {Number} alpha
133
- * @memberof Settings */
134
- function setTouchGamepadAlpha(alpha) { touchGamepadAlpha = alpha; }
135
-
136
- /** Set to allow vibration hardware if it exists
137
- * @param {Boolean} enable
138
- * @memberof Settings */
139
- function setVibrateEnable(enable) { vibrateEnable = enable; }
140
-
141
- /** Set to disable all audio code
142
- * @param {Boolean} enable
143
- * @memberof Settings */
144
- function setSoundEnable(enable) { soundEnable = enable; }
145
-
146
- /** Set volume scale to apply to all sound, music and speech
147
- * @param {Number} volume
148
- * @memberof Settings */
149
- function setSoundVolume(volume) { soundVolume = volume; }
150
-
151
- /** Set default range where sound no longer plays
152
- * @param {Number} range
153
- * @memberof Settings */
154
- function setSoundDefaultRange(range) { soundDefaultRange = range; }
155
-
156
- /** Set default range percent to start tapering off sound
157
- * @param {Number} taper
158
- * @memberof Settings */
159
- function setSoundDefaultTaper(taper) { soundDefaultTaper = taper; }
160
-
161
- /** Set how long to show medals for in seconds
162
- * @param {Number} time
163
- * @memberof Settings */
164
- function setMedalDisplayTime(time) { medalDisplayTime = time; }
165
-
166
- /** Set how quickly to slide on/off medals in seconds
167
- * @param {Number} time
168
- * @memberof Settings */
169
- function setMedalDisplaySlideTime(time) { medalDisplaySlideTime = time; }
170
-
171
- /** Set size of medal display
172
- * @param {Vector2} size
173
- * @memberof Settings */
174
- function setMedalDisplaySize(size) { medalDisplaySize = size; }
175
-
176
- /** Set size of icon in medal display
177
- * @param {Number} size
178
- * @memberof Settings */
179
- function setMedalDisplayIconSize(size) { medalDisplayIconSize = size; }
180
-
181
- /** Set to stop medals from being unlockable
182
- * @param {Boolean} preventUnlock
183
- * @memberof Settings */
184
- function setMedalsPreventUnlock(preventUnlock) { medalsPreventUnlock = preventUnlock; }
185
-
186
- /** Set if watermark with FPS should be shown
187
- * @param {Boolean} show
188
- * @memberof Debug */
189
- function setShowWatermark(show) { showWatermark = show; }
190
-
191
- /** Set key code used to toggle debug mode, Esc by default
192
- * @param {Number} key
193
- * @memberof Debug */
194
- function setDebugKey(key) { debugKey = key; }
195
-
196
6
  export {
197
7
  // Setters for global variables
198
8
  setCameraPos,
@@ -327,7 +137,10 @@ export {
327
137
  EngineObject,
328
138
 
329
139
  // Draw
330
- tileImage,
140
+ textureInfos,
141
+ tile,
142
+ TileInfo,
143
+ TextureInfo,
331
144
  mainCanvas,
332
145
  mainContext,
333
146
  overlayCanvas,
@@ -191,18 +191,26 @@ function mouseToScreen(mousePos)
191
191
  const stickData = [];
192
192
  function gamepadsUpdate()
193
193
  {
194
- if (touchGamepadEnable && touchGamepadTimer.isSet())
194
+ // update touch gamepad if enabled
195
+ if (touchGamepadEnable && isTouchDevice)
195
196
  {
196
- // read virtual analog stick
197
- const sticks = stickData[0] || (stickData[0] = []);
198
- sticks[0] = vec2(touchGamepadStick.x, -touchGamepadStick.y); // flip vertical
197
+ // create the touch gamepad if it doesn't exist
198
+ if (!touchGamepadButtons)
199
+ createTouchGamepad();
199
200
 
200
- // read virtual gamepad buttons
201
- const data = inputData[1] || (inputData[1] = []);
202
- for (let i=10; i--;)
201
+ if (touchGamepadTimer.isSet())
203
202
  {
204
- const j = i == 3 ? 2 : i == 2 ? 3 : i; // fix button locations
205
- data[j] = touchGamepadButtons[i] ? 1 + 2*!gamepadIsDown(j,0) : 4*gamepadIsDown(j,0);
203
+ // read virtual analog stick
204
+ const sticks = stickData[0] || (stickData[0] = []);
205
+ sticks[0] = vec2(touchGamepadStick.x, -touchGamepadStick.y); // flip vertical
206
+
207
+ // read virtual gamepad buttons
208
+ const data = inputData[1] || (inputData[1] = []);
209
+ for (let i=10; i--;)
210
+ {
211
+ const j = i == 3 ? 2 : i == 2 ? 3 : i; // fix button locations
212
+ data[j] = touchGamepadButtons[i] ? 1 + 2*!gamepadIsDown(j,0) : 4*gamepadIsDown(j,0);
213
+ }
206
214
  }
207
215
  }
208
216
 
@@ -299,6 +307,10 @@ if (isTouchDevice)
299
307
  // set was touching
300
308
  wasTouching = touching;
301
309
 
310
+ // prevent default handling like copy and magnifier lens
311
+ if (document.hasFocus()) // allow document to get focus
312
+ e.preventDefault();
313
+
302
314
  // must return true so the document will get focus
303
315
  return true;
304
316
  }
@@ -311,7 +323,7 @@ if (isTouchDevice)
311
323
  let touchGamepadTimer = new Timer, touchGamepadButtons, touchGamepadStick;
312
324
 
313
325
  // create the touch gamepad, called automatically by the engine
314
- if (touchGamepadEnable)
326
+ function createTouchGamepad()
315
327
  {
316
328
  // touch input internal variables
317
329
  touchGamepadButtons = [];
@@ -31,7 +31,7 @@ function medalsInit(saveName)
31
31
  }
32
32
 
33
33
  /**
34
- * Medal Object - Tracks an unlockable medal
34
+ * Medal - Tracks an unlockable medal
35
35
  * @example
36
36
  * // create a medal
37
37
  * const medal_example = new Medal(0, 'Example Medal', 'More info about the medal goes here.', '🎖️');
@@ -44,7 +44,7 @@ function medalsInit(saveName)
44
44
  */
45
45
  class Medal
46
46
  {
47
- /** Create an medal object and adds it to the list of medals
47
+ /** Create a medal object and adds it to the list of medals
48
48
  * @param {Number} id - The unique identifier of the medal
49
49
  * @param {String} name - Name of the medal
50
50
  * @param {String} [description] - Description of the medal
@@ -156,33 +156,33 @@ let newgrounds;
156
156
  /** This can used to enable Newgrounds functionality
157
157
  * @param {Number} app_id - The newgrounds App ID
158
158
  * @param {String} [cipher] - The encryption Key (AES-128/Base64)
159
+ * @param {Object} [cryptoJS] - An instance of CryptoJS, if there is a cipher
159
160
  * @memberof Medals */
160
- function newgroundsInit(app_id, cipher) { newgrounds = new Newgrounds(app_id, cipher); }
161
+ function newgroundsInit(app_id, cipher, cryptoJS)
162
+ { newgrounds = new Newgrounds(app_id, cipher, cryptoJS); }
161
163
 
162
164
  /**
163
165
  * Newgrounds API wrapper object
164
166
  * @example
165
- * // create a newgrounds object, replace the app id and cipher with your own
167
+ * // create a newgrounds object, replace the app id with your own
166
168
  * const app_id = '53123:1ZuSTQ9l';
167
- * const cipher = 'enF0vGH@Mj/FRASKL23Q==';
168
- * newgrounds = new Newgrounds(app_id, cipher);
169
+ * newgrounds = new Newgrounds(app_id);
169
170
  */
170
171
  class Newgrounds
171
172
  {
172
173
  /** Create a newgrounds object
173
174
  * @param {Number} app_id - The newgrounds App ID
174
- * @param {String} [cipher] - The encryption Key (AES-128/Base64) */
175
- constructor(app_id, cipher)
175
+ * @param {String} [cipher] - The encryption Key (AES-128/Base64)
176
+ * @param {Object} [cryptoJS] - An instance of CryptoJS, if there is a cipher */
177
+ constructor(app_id, cipher, cryptoJS)
176
178
  {
177
- ASSERT(!newgrounds && app_id);
179
+ ASSERT(!newgrounds && app_id); // can only be one newgrounds object
180
+ ASSERT(!cipher || cryptoJS); // must provide cryptojs if there is a cipher
178
181
 
179
182
  this.app_id = app_id;
180
183
  this.cipher = cipher;
184
+ this.cryptoJS = cryptoJS;
181
185
  this.host = location ? location.hostname : '';
182
-
183
- // create an instance of CryptoJS for encrypted calls
184
- if (cipher)
185
- this.cryptoJS = this.CryptoJS();
186
186
 
187
187
  // get session id from url search params
188
188
  const url = new URL(location.href);
@@ -286,36 +286,4 @@ class Newgrounds
286
286
  debugMedals && console.log(xmlHttp.responseText);
287
287
  return xmlHttp.responseText && JSON.parse(xmlHttp.responseText);
288
288
  }
289
-
290
- CryptoJS()
291
- {
292
- ///////////////////////////////////////////////////////////////////////////////
293
- // Crypto-JS - https://github.com/brix/crypto-js - MIT License
294
- //
295
- // [The MIT License (MIT)](http://opensource.org/licenses/MIT)
296
- //
297
- // Copyright (c) 2009-2013 Jeff Mott
298
- // Copyright (c) 2013-2016 Evan Vosberg
299
- //
300
- // Permission is hereby granted, free of charge, to any person obtaining a copy
301
- // of this software and associated documentation files (the "Software"), to deal
302
- // in the Software without restriction, including without limitation the rights
303
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
304
- // copies of the Software, and to permit persons to whom the Software is
305
- // furnished to do so, subject to the following conditions:
306
- //
307
- // The above copyright notice and this permission notice shall be included in
308
- // all copies or substantial portions of the Software.
309
- //
310
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
311
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
312
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
313
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
314
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
315
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
316
- // THE SOFTWARE.
317
- return eval(Function("[M='GBMGXz^oVYPPKKbB`agTXU|LxPc_ZBcMrZvCr~wyGfWrwk@ATqlqeTp^N?p{we}jIpEnB_sEr`l?YDkDhWhprc|Er|XETG?pTl`e}dIc[_N~}fzRycIfpW{HTolvoPB_FMe_eH~BTMx]yyOhv?biWPCGc]kABencBhgERHGf{OL`Dj`c^sh@canhy[secghiyotcdOWgO{tJIE^JtdGQRNSCrwKYciZOa]Y@tcRATYKzv|sXpboHcbCBf`}SKeXPFM|RiJsSNaIb]QPc[D]Jy_O^XkOVTZep`ONmntLL`Qz~UupHBX_Ia~WX]yTRJIxG`ioZ{fefLJFhdyYoyLPvqgH?b`[TMnTwwfzDXhfM?rKs^aFr|nyBdPmVHTtAjXoYUloEziWDCw_suyYT~lSMksI~ZNCS[Bex~j]Vz?kx`gdYSEMCsHpjbyxQvw|XxX_^nQYue{sBzVWQKYndtYQMWRef{bOHSfQhiNdtR{o?cUAHQAABThwHPT}F{VvFmgN`E@FiFYS`UJmpQNM`X|tPKHlccT}z}k{sACHL?Rt@MkWplxO`ASgh?hBsuuP|xD~LSH~KBlRs]t|l|_tQAroDRqWS^SEr[sYdPB}TAROtW{mIkE|dWOuLgLmJrucGLpebrAFKWjikTUzS|j}M}szasKOmrjy[?hpwnEfX[jGpLt@^v_eNwSQHNwtOtDgWD{rk|UgASs@mziIXrsHN_|hZuxXlPJOsA^^?QY^yGoCBx{ekLuZzRqQZdsNSx@ezDAn{XNj@fRXIwrDX?{ZQHwTEfu@GhxDOykqts|n{jOeZ@c`dvTY?e^]ATvWpb?SVyg]GC?SlzteilZJAL]mlhLjYZazY__qcVFYvt@|bIQnSno@OXyt]OulzkWqH`rYFWrwGs`v|~XeTsIssLrbmHZCYHiJrX}eEzSssH}]l]IhPQhPoQ}rCXLyhFIT[clhzYOvyHqigxmjz`phKUU^TPf[GRAIhNqSOdayFP@FmKmuIzMOeoqdpxyCOwCthcLq?n`L`tLIBboNn~uXeFcPE{C~mC`h]jUUUQe^`UqvzCutYCgct|SBrAeiYQW?X~KzCz}guXbsUw?pLsg@hDArw?KeJD[BN?GD@wgFWCiHq@Ypp_QKFixEKWqRp]oJFuVIEvjDcTFu~Zz]a{IcXhWuIdMQjJ]lwmGQ|]g~c]Hl]pl`Pd^?loIcsoNir_kikBYyg?NarXZEGYspt_vLBIoj}LI[uBFvm}tbqvC|xyR~a{kob|HlctZslTGtPDhBKsNsoZPuH`U`Fqg{gKnGSHVLJ^O`zmNgMn~{rsQuoymw^JY?iUBvw_~mMr|GrPHTERS[MiNpY[Mm{ggHpzRaJaoFomtdaQ_?xuTRm}@KjU~RtPsAdxa|uHmy}n^i||FVL[eQAPrWfLm^ndczgF~Nk~aplQvTUpHvnTya]kOenZlLAQIm{lPl@CCTchvCF[fI{^zPkeYZTiamoEcKmBMfZhk_j_~Fjp|wPVZlkh_nHu]@tP|hS@^G^PdsQ~f[RqgTDqezxNFcaO}HZhb|MMiNSYSAnQWCDJukT~e|OTgc}sf[cnr?fyzTa|EwEtRG|I~|IO}O]S|rp]CQ}}DWhSjC_|z|oY|FYl@WkCOoPuWuqr{fJu?Brs^_EBI[@_OCKs}?]O`jnDiXBvaIWhhMAQDNb{U`bqVR}oqVAvR@AZHEBY@depD]OLh`kf^UsHhzKT}CS}HQKy}Q~AeMydXPQztWSSzDnghULQgMAmbWIZ|lWWeEXrE^EeNoZApooEmrXe{NAnoDf`m}UNlRdqQ@jOc~HLOMWs]IDqJHYoMziEedGBPOxOb?[X`KxkFRg@`mgFYnP{hSaxwZfBQqTm}_?RSEaQga]w[vxc]hMne}VfSlqUeMo_iqmd`ilnJXnhdj^EEFifvZyxYFRf^VaqBhLyrGlk~qowqzHOBlOwtx?i{m~`n^G?Yxzxux}b{LSlx]dS~thO^lYE}bzKmUEzwW^{rPGhbEov[Plv??xtyKJshbG`KuO?hjBdS@Ru}iGpvFXJRrvOlrKN?`I_n_tplk}kgwSXuKylXbRQ]]?a|{xiT[li?k]CJpwy^o@ebyGQrPfF`aszGKp]baIx~H?ElETtFh]dz[OjGl@C?]VDhr}OE@V]wLTc[WErXacM{We`F|utKKjgllAxvsVYBZ@HcuMgLboFHVZmi}eIXAIFhS@A@FGRbjeoJWZ_NKd^oEH`qgy`q[Tq{x?LRP|GfBFFJV|fgZs`MLbpPYUdIV^]mD@FG]pYAT^A^RNCcXVrPsgk{jTrAIQPs_`mD}rOqAZA[}RETFz]WkXFTz_m{N@{W@_fPKZLT`@aIqf|L^Mb|crNqZ{BVsijzpGPEKQQZGlApDn`ruH}cvF|iXcNqK}cxe_U~HRnKV}sCYb`D~oGvwG[Ca|UaybXea~DdD~LiIbGRxJ_VGheI{ika}KC[OZJLn^IBkPrQj_EuoFwZ}DpoBRcK]Q}?EmTv~i_Tul{bky?Iit~tgS|o}JL_VYcCQdjeJ_MfaA`FgCgc[Ii|CBHwq~nbJeYTK{e`CNstKfTKPzw{jdhp|qsZyP_FcugxCFNpKitlR~vUrx^NrSVsSTaEgnxZTmKc`R|lGJeX}ccKLsQZQhsFkeFd|ckHIVTlGMg`~uPwuHRJS_CPuN_ogXe{Ba}dO_UBhuNXby|h?JlgBIqMKx^_u{molgL[W_iavNQuOq?ap]PGB`clAicnl@k~pA?MWHEZ{HuTLsCpOxxrKlBh]FyMjLdFl|nMIvTHyGAlPogqfZ?PlvlFJvYnDQd}R@uAhtJmDfe|iJqdkYr}r@mEjjIetDl_I`TELfoR|qTBu@Tic[BaXjP?dCS~MUK[HPRI}OUOwAaf|_}HZzrwXvbnNgltjTwkBE~MztTQhtRSWoQHajMoVyBBA`kdgK~h`o[J`dm~pm]tk@i`[F~F]DBlJKklrkR]SNw@{aG~Vhl`KINsQkOy?WhcqUMTGDOM_]bUjVd|Yh_KUCCgIJ|LDIGZCPls{RzbVWVLEhHvWBzKq|^N?DyJB|__aCUjoEgsARki}j@DQXS`RNU|DJ^a~d{sh_Iu{ONcUtSrGWW@cvUjefHHi}eSSGrNtO?cTPBShLqzwMVjWQQCCFB^culBjZHEK_{dO~Q`YhJYFn]jq~XSnG@[lQr]eKrjXpG~L^h~tDgEma^AUFThlaR{xyuP@[^VFwXSeUbVetufa@dX]CLyAnDV@Bs[DnpeghJw^?UIana}r_CKGDySoRudklbgio}kIDpA@McDoPK?iYcG?_zOmnWfJp}a[JLR[stXMo?_^Ng[whQlrDbrawZeSZ~SJstIObdDSfAA{MV}?gNunLOnbMv_~KFQUAjIMj^GkoGxuYtYbGDImEYiwEMyTpMxN_LSnSMdl{bg@dtAnAMvhDTBR_FxoQgANniRqxd`pWv@rFJ|mWNWmh[GMJz_Nq`BIN@KsjMPASXORcdHjf~rJfgZYe_uulzqM_KdPlMsuvU^YJuLtofPhGonVOQxCMuXliNvJIaoC?hSxcxKVVxWlNs^ENDvCtSmO~WxI[itnjs^RDvI@KqG}YekaSbTaB]ki]XM@[ZnDAP~@|BzLRgOzmjmPkRE@_sobkT|SszXK[rZN?F]Z_u}Yue^[BZgLtR}FHzWyxWEX^wXC]MJmiVbQuBzkgRcKGUhOvUc_bga|Tx`KEM`JWEgTpFYVeXLCm|mctZR@uKTDeUONPozBeIkrY`cz]]~WPGMUf`MNUGHDbxZuO{gmsKYkAGRPqjc|_FtblEOwy}dnwCHo]PJhN~JoteaJ?dmYZeB^Xd?X^pOKDbOMF@Ugg^hETLdhwlA}PL@_ur|o{VZosP?ntJ_kG][g{Zq`Tu]dzQlSWiKfnxDnk}KOzp~tdFstMobmy[oPYjyOtUzMWdjcNSUAjRuqhLS@AwB^{BFnqjCmmlk?jpn}TksS{KcKkDboXiwK]qMVjm~V`LgWhjS^nLGwfhAYrjDSBL_{cRus~{?xar_xqPlArrYFd?pHKdMEZzzjJpfC?Hv}mAuIDkyBxFpxhstTx`IO{rp}XGuQ]VtbHerlRc_LFGWK[XluFcNGUtDYMZny[M^nVKVeMllQI[xtvwQnXFlWYqxZZFp_|]^oWX[{pOMpxXxvkbyJA[DrPzwD|LW|QcV{Nw~U^dgguSpG]ClmO@j_TENIGjPWwgdVbHganhM?ema|dBaqla|WBd`poj~klxaasKxGG^xbWquAl~_lKWxUkDFagMnE{zHug{b`A~IYcQYBF_E}wiA}K@yxWHrZ{[d~|ARsYsjeNWzkMs~IOqqp[yzDE|WFrivsidTcnbHFRoW@XpAV`lv_zj?B~tPCppRjgbbDTALeFaOf?VcjnKTQMLyp{NwdylHCqmo?oelhjWuXj~}{fpuX`fra?GNkDiChYgVSh{R[BgF~eQa^WVz}ATI_CpY?g_diae]|ijH`TyNIF}|D_xpmBq_JpKih{Ba|sWzhnAoyraiDvk`h{qbBfsylBGmRH}DRPdryEsSaKS~tIaeF[s]I~xxHVrcNe@Jjxa@jlhZueLQqHh_]twVMqG_EGuwyab{nxOF?`HCle}nBZzlTQjkLmoXbXhOtBglFoMz?eqre`HiE@vNwBulglmQjj]DB@pPkPUgA^sjOAUNdSu_`oAzar?n?eMnw{{hYmslYi[TnlJD'",...']charCodeAtUinyxpf',"for(;e<10359;c[e++]=p-=128,A=A?p-A&&A:p==34&&p)for(p=1;p<128;y=f.map((n,x)=>(U=r[n]*2+1,U=Math.log(U/(h-U)),t-=a[x]*U,U/500)),t=~-h/(1+Math.exp(t))|1,i=o%h<t,o=o%h+(i?t:h-t)*(o>>17)-!i*t,f.map((n,x)=>(U=r[n]+=(i*h/2-r[n]<<13)/((C[n]+=C[n]<5)+1/20)>>13,a[x]+=y[x]*(i-t/h))),p=p*2+i)for(f='010202103203210431053105410642065206541'.split(t=0).map((n,x)=>(U=0,[...n].map((n,x)=>(U=U*997+(c[e-n]|0)|0)),h*32-1&U*997+p+!!A*129)*12+x);o<h*32;o=o*64|M.charCodeAt(d++)&63);for(C=String.fromCharCode(...c);r=/[\0-#?@\\\\~]/.exec(C);)with(C.split(r))C=join(shift());return C")([],[],1<<17,[0,0,0,0,0,0,0,0,0,0,0,0],new Uint16Array(51e6).fill(1<<15),new Uint8Array(51e6),0,0,0,0));
318
- // end of Crypto-JS
319
- ///////////////////////////////////////////////////////////////////////////////
320
- }
321
289
  }
@@ -32,18 +32,19 @@
32
32
  class EngineObject
33
33
  {
34
34
  /** Create an engine object and adds it to the list of objects
35
- * @param {Vector2} [position=Vector2()] - World space position of the object
36
- * @param {Vector2} [size=Vector2(1,1)] - World space size of the object
37
- * @param {Number} [tileIndex=-1] - Tile to use to render object (-1 is untextured)
38
- * @param {Vector2} [tileSize=tileSizeDefault] - Size of tile in source pixels
39
- * @param {Number} [angle=0] - Angle the object is rotated by
40
- * @param {Color} [color=Color()] - Color to apply to tile when rendered
41
- * @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
35
+ * @param {Vector2} [pos=Vector2()] - World space position of the object
36
+ * @param {Vector2} [size=Vector2(1,1)] - World space size of the object
37
+ * @param {TileInfo} [tileInfo] - Tile info to render object (undefined is untextured)
38
+ * @param {Number} [angle=0] - Angle the object is rotated by
39
+ * @param {Color} [color=Color()] - Color to apply to tile when rendered
40
+ * @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
42
41
  */
43
- constructor(pos=vec2(), size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, angle=0, color, renderOrder=0)
42
+ constructor(pos=vec2(), size=vec2(1), tileInfo, angle=0, color, renderOrder=0)
44
43
  {
45
44
  // set passed in params
46
45
  ASSERT(isVector2(pos) && isVector2(size)); // ensure pos and size are vec2s
46
+ ASSERT(typeof tileInfo !== 'number' || !tileInfo); // prevent old style calls
47
+ // to fix old calls, replace with tile(tileIndex, tileSize)
47
48
 
48
49
  /** @property {Vector2} - World space position of the object */
49
50
  this.pos = pos.copy();
@@ -51,10 +52,8 @@ class EngineObject
51
52
  this.size = size;
52
53
  /** @property {Vector2} - Size of object used for drawing, uses size if not set */
53
54
  this.drawSize;
54
- /** @property {Number} - Tile to use to render object (-1 is untextured) */
55
- this.tileIndex = tileIndex;
56
- /** @property {Vector2} - Size of tile in source pixels */
57
- this.tileSize = tileSize;
55
+ /** @property {TileInfo} - Tile info to render object (undefined is untextured) */
56
+ this.tileInfo = tileInfo;
58
57
  /** @property {Number} - Angle to rotate the object */
59
58
  this.angle = angle;
60
59
  /** @property {Color} - Color to apply when rendered */
@@ -270,7 +269,7 @@ class EngineObject
270
269
  render()
271
270
  {
272
271
  // default object render
273
- drawTile(this.pos, this.drawSize || this.size, this.tileIndex, this.tileSize, this.color, this.angle, this.mirror, this.additiveColor);
272
+ drawTile(this.pos, this.drawSize || this.size, this.tileInfo, this.color, this.angle, this.mirror, this.additiveColor);
274
273
  }
275
274
 
276
275
  /** Destroy this object, destroy it's children, detach it's parent, and mark it for removal */
@@ -13,7 +13,7 @@
13
13
  * let particleEmiter = new ParticleEmitter
14
14
  * (
15
15
  * pos, 0, 1, 0, 500, PI, // pos, angle, emitSize, emitTime, emitRate, emiteCone
16
- * 0, vec2(16), // tileIndex, tileSize
16
+ * tile(0, 16), // tileInfo
17
17
  * new Color(1,1,1), new Color(0,0,0), // colorStartA, colorStartB
18
18
  * new Color(1,1,1,0), new Color(0,0,0,0), // colorEndA, colorEndB
19
19
  * 2, .2, .2, .1, .05, // particleTime, sizeStart, sizeEnd, particleSpeed, particleAngleSpeed
@@ -30,8 +30,7 @@ class ParticleEmitter extends EngineObject
30
30
  * @param {Number} [emitTime=0] - How long to stay alive (0 is forever)
31
31
  * @param {Number} [emitRate=100] - How many particles per second to spawn, does not emit if 0
32
32
  * @param {Number} [emitConeAngle=PI] - Local angle to apply velocity to particles from emitter
33
- * @param {Number} [tileIndex=-1] - Index into tile sheet, if <0 no texture is applied
34
- * @param {Vector2} [tileSize=tileSizeDefault] - Tile size for particles
33
+ * @param {TileInfo} [tileInfo] - Tile info to render particles (undefined is untextured)
35
34
  * @param {Color} [colorStartA=Color()] - Color at start of life 1, randomized between start colors
36
35
  * @param {Color} [colorStartB=Color()] - Color at start of life 2, randomized between start colors
37
36
  * @param {Color} [colorEndA=Color(1,1,1,0)] - Color at end of life 1, randomized between end colors
@@ -61,8 +60,7 @@ class ParticleEmitter extends EngineObject
61
60
  emitTime = 0,
62
61
  emitRate = 100,
63
62
  emitConeAngle = PI,
64
- tileIndex = -1,
65
- tileSize = tileSizeDefault,
63
+ tileInfo,
66
64
  colorStartA = new Color,
67
65
  colorStartB = new Color,
68
66
  colorEndA = new Color(1,1,1,0),
@@ -85,7 +83,7 @@ class ParticleEmitter extends EngineObject
85
83
  localSpace
86
84
  )
87
85
  {
88
- super(pos, vec2(), tileIndex, tileSize, angle, undefined, renderOrder);
86
+ super(pos, vec2(), tileInfo, angle, undefined, renderOrder);
89
87
 
90
88
  // emitter settings
91
89
  /** @property {Number} - World space size of the emitter (float for circle diameter, vec2 for rect) */
@@ -184,7 +182,7 @@ class ParticleEmitter extends EngineObject
184
182
  angle += this.angle;
185
183
  }
186
184
 
187
- const particle = new Particle(pos, this.tileIndex, this.tileSize, angle);
185
+ const particle = new Particle(pos, this.tileInfo, this.tileSize, angle);
188
186
 
189
187
  // randomness scales each paremeter by a percentage
190
188
  const randomness = this.randomness;
@@ -244,12 +242,11 @@ class Particle extends EngineObject
244
242
  /**
245
243
  * Create a particle with the given settings
246
244
  * @param {Vector2} position - World space position of the particle
247
- * @param {Number} [tileIndex=-1] - Tile to use to render, untextured if -1
248
- * @param {Vector2} [tileSize=tileSizeDefault] - Size of tile in source pixels
245
+ * @param {TileInfo} [tileInfo] - Tile info to render particles (undefined is untextured)
249
246
  * @param {Number} [angle=0] - Angle to rotate the particle
250
247
  */
251
- constructor(pos, tileIndex, tileSize, angle)
252
- { super(pos, vec2(), tileIndex, tileSize, angle); }
248
+ constructor(pos, tileInfo, angle)
249
+ { super(pos, vec2(), tileInfo, angle); }
253
250
 
254
251
  /** Render the particle, automatically called each frame, sorted by renderOrder */
255
252
  render()
@@ -283,14 +280,17 @@ class Particle extends EngineObject
283
280
  if (this.localSpaceEmitter)
284
281
  velocity = velocity.rotate(-this.localSpaceEmitter.angle);
285
282
  const speed = velocity.length();
286
- const direction = velocity.scale(1/speed);
287
- const trailLength = speed * this.trailScale;
288
- size.y = max(size.x, trailLength);
289
- angle = direction.angle();
290
- drawTile(pos.add(direction.multiply(vec2(0,-trailLength/2))), size, this.tileIndex, this.tileSize, color, angle, this.mirror);
283
+ if (speed)
284
+ {
285
+ const direction = velocity.scale(1/speed);
286
+ const trailLength = speed * this.trailScale;
287
+ size.y = max(size.x, trailLength);
288
+ angle = direction.angle();
289
+ drawTile(pos.add(direction.multiply(vec2(0,-trailLength/2))), size, this.tileInfo, color, angle, this.mirror);
290
+ }
291
291
  }
292
292
  else
293
- drawTile(pos, size, this.tileIndex, this.tileSize, color, angle, this.mirror);
293
+ drawTile(pos, size, this.tileInfo, color, angle, this.mirror);
294
294
  this.additive && setBlendMode();
295
295
  debugParticles && debugRect(pos, size, '#f005', 0, angle);
296
296