littlejsengine 1.7.21 → 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 (51) hide show
  1. package/README.md +27 -55
  2. package/build/littlejs.d.ts +101 -58
  3. package/build/littlejs.esm.js +497 -419
  4. package/build/littlejs.esm.min.js +1 -1
  5. package/build/littlejs.js +493 -228
  6. package/build/littlejs.min.js +1 -1
  7. package/build/littlejs.release.js +493 -228
  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/game.js +3 -2
  15. package/examples/electron/index.html +2 -2
  16. package/examples/empty/game.js +1 -1
  17. package/examples/favicon.png +0 -0
  18. package/examples/js13k/game.js +20 -15
  19. package/examples/js13k/index.html +14 -14
  20. package/examples/module/game.js +4 -3
  21. package/examples/module/index.html +1 -1
  22. package/examples/particles/index.html +19 -22
  23. package/examples/platformer/game.js +3 -3
  24. package/examples/platformer/gameEffects.js +21 -19
  25. package/examples/platformer/gameLevel.js +6 -6
  26. package/examples/platformer/gameObjects.js +18 -18
  27. package/examples/platformer/gamePlayer.js +4 -3
  28. package/examples/platformer/index.html +6 -6
  29. package/examples/platformer/tiles.png +0 -0
  30. package/examples/platformer/tilesLevel.png +0 -0
  31. package/examples/puzzle/game.js +10 -8
  32. package/examples/puzzle/index.html +2 -2
  33. package/examples/screenshot.jpg +0 -0
  34. package/examples/starter/game.js +32 -21
  35. package/examples/starter/index.html +13 -13
  36. package/examples/starter/tiles.png +0 -0
  37. package/examples/stress/index.html +2 -2
  38. package/examples/typescript/game.js +4 -3
  39. package/examples/typescript/game.ts +4 -3
  40. package/examples/typescript/index.html +1 -1
  41. package/package.json +1 -1
  42. package/src/engine.js +59 -52
  43. package/src/engineDraw.js +137 -38
  44. package/src/engineExport.js +4 -191
  45. package/src/engineMedals.js +13 -45
  46. package/src/engineObject.js +12 -13
  47. package/src/engineParticles.js +17 -17
  48. package/src/engineSettings.js +195 -2
  49. package/src/engineTileLayer.js +23 -22
  50. package/src/engineUtilities.js +6 -6
  51. package/src/engineWebGL.js +31 -32
package/src/engineDraw.js CHANGED
@@ -47,13 +47,109 @@ let overlayContext;
47
47
  * @memberof Draw */
48
48
  let mainCanvasSize = vec2();
49
49
 
50
- /** Tile sheet for batch rendering system
51
- * @type {CanvasImageSource}
50
+ /** Array containing texture info for batch rendering system
51
+ * @type {Array}
52
52
  * @memberof Draw */
53
- const tileImage = new Image;
53
+ let textureInfos = [];
54
54
 
55
55
  // Engine internal variables not exposed to documentation
56
- let tileImageSize, tileImageFixBleed, drawCount;
56
+ let drawCount;
57
+
58
+ ///////////////////////////////////////////////////////////////////////////////
59
+
60
+ /**
61
+ * Create a tile info object
62
+ * - This can take vecs or floats for easier use and conversion
63
+ * - If an index is passed in, the tile size and index will determine the position
64
+ * @param {(Number|Vector2)} [pos=Vector2()] - Top left corner of tile in pixels or index
65
+ * @param {(Number|Vector2)} [size=tileSizeDefault] - Size of tile in pixels
66
+ * @param {Number} [textureIndex=0] - Texture index to use
67
+ * @return {TileInfo}
68
+ * @example
69
+ * tile(2) // a tile at index 2 using the default tile size of 16
70
+ * tile(5, 8) // a tile at index 5 using a tile size of 8
71
+ * tile(1, 16, 3) // a tile at index 1 of size 16 on texture 3
72
+ * tile(vec2(4,8), vec2(30,10)) // a tile at pixel location (4,8) with a size of (30,10)
73
+ * @memberof Draw
74
+ */
75
+ function tile(pos=vec2(), size=tileSizeDefault, textureIndex=0)
76
+ {
77
+ // if size is a number, make it a vector
78
+ if (size.x == undefined)
79
+ {
80
+ ASSERT(size > 0);
81
+ size = vec2(size);
82
+ }
83
+
84
+ // if pos is a number, use it as a tile index
85
+ if (pos.x == undefined)
86
+ {
87
+ const textureInfo = textureInfos[textureIndex];
88
+ if (textureInfo)
89
+ {
90
+ const cols = textureInfo.size.x / size.x |0;
91
+ pos = vec2((pos%cols)*size.x, (pos/cols|0)*size.y);
92
+ }
93
+ else
94
+ pos = vec2();
95
+ }
96
+
97
+ // return a tile info object
98
+ return new TileInfo(pos, size, textureIndex);
99
+ }
100
+
101
+ /**
102
+ * Tile Info - Stores info about how to draw a tile
103
+ */
104
+ class TileInfo
105
+ {
106
+ /** Create a tile info object
107
+ * @param {Vector2} [pos=Vector2()] - Top left corner of tile in pixels
108
+ * @param {Vector2} [size=tileSizeDefault] - Size of tile in pixels
109
+ * @param {Number} [textureIndex=0] - Texture index to use
110
+ */
111
+ constructor(pos=vec2(), size=tileSizeDefault, textureIndex=0)
112
+ {
113
+ /** @property {Vector2} - Top left corner of tile in pixels */
114
+ this.pos = pos;
115
+ /** @property {Vector2} - Size of tile in pixels */
116
+ this.size = size;
117
+ /** @property {Number} - Texture index to use */
118
+ this.textureIndex = textureIndex;
119
+ }
120
+
121
+ /** Returns an offset copy of this tile, useful for animation
122
+ * @param {Vector2} offset - Offset to apply in pixels
123
+ * @return {TileInfo}
124
+ */
125
+ offset(offset)
126
+ { return new TileInfo(this.pos.add(offset), this.size, this.textureIndex); }
127
+
128
+ /** Returns the texture info for this tile
129
+ * @return {TextureInfo}
130
+ */
131
+ getTextureInfo()
132
+ { return textureInfos[this.textureIndex]; }
133
+ }
134
+
135
+ /** Texture Info - Stores info about each texture */
136
+ class TextureInfo
137
+ {
138
+ // create a TextureInfo, called automatically by the engine
139
+ constructor(image)
140
+ {
141
+ /** @property {CanvasImageSource} - image source */
142
+ this.image = image;
143
+ /** @property {Vector2} - size of the image */
144
+ this.size = vec2(image.width, image.height);
145
+ /** @property {WebGLTexture} - webgl texture */
146
+ this.glTexture = glEnable && glCreateTexture(image);
147
+ /** @property {Vector2} - size to adjust tile to fix bleeding */
148
+ this.fixBleedSize = vec2(tileFixBleedScale).divide(this.size);
149
+ }
150
+ }
151
+
152
+ ///////////////////////////////////////////////////////////////////////////////
57
153
 
58
154
  /** Convert from screen to world space coordinates
59
155
  * @param {Vector2} screenPos
@@ -84,7 +180,7 @@ function worldToScreen(worldPos)
84
180
  /** Draw textured tile centered in world space, with color applied if using WebGL
85
181
  * @param {Vector2} pos - Center of the tile in world space
86
182
  * @param {Vector2} [size=Vector2(1,1)] - Size of the tile in world space
87
- * @param {Number} [tileIndex=-1] - Tile index to use, negative is untextured
183
+ * @param {TileInfo}[tileInfo] - Tile info to use, untextured if undefined
88
184
  * @param {Vector2} [tileSize=tileSizeDefault] - Tile size in source pixels
89
185
  * @param {Color} [color=Color()] - Color to modulate with
90
186
  * @param {Number} [angle=0] - Angle to rotate by
@@ -93,11 +189,14 @@ function worldToScreen(worldPos)
93
189
  * @param {Boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering
94
190
  * @param {Boolean} [screenSpace=0] - If true the pos and size are in screen space
95
191
  * @memberof Draw */
96
- function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, color=new Color,
192
+ function drawTile(pos, size=vec2(1), tileInfo, color=new Color,
97
193
  angle=0, mirror, additiveColor=new Color(0,0,0,0), useWebGL=glEnable, screenSpace)
98
194
  {
195
+ ASSERT(typeof tileInfo !== 'number' || !tileInfo); // prevent old style calls
196
+ // to fix old calls, replace with tile(tileIndex, tileSize)
197
+
99
198
  showWatermark && ++drawCount;
100
-
199
+ const textureInfo = tileInfo && tileInfo.getTextureInfo();
101
200
  if (glEnable && useWebGL)
102
201
  {
103
202
  if (screenSpace)
@@ -106,46 +205,48 @@ function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, col
106
205
  pos = screenToWorld(pos);
107
206
  size = size.scale(1/cameraScale);
108
207
  }
109
- if (tileIndex < 0 || !tileImage.width)
110
- {
111
- // if negative tile index or image not found, force untextured
112
- glDraw(pos.x, pos.y, size.x, size.y, angle, 0, 0, 0, 0, 0, color.rgbaInt());
113
- }
114
- else
208
+
209
+ if (textureInfo)
115
210
  {
116
211
  // calculate uvs and render
117
- const cols = tileImageSize.x / tileSize.x |0;
118
- const uvSizeX = tileSize.x / tileImageSize.x;
119
- const uvSizeY = tileSize.y / tileImageSize.y;
120
- const uvX = (tileIndex%cols)*uvSizeX, uvY = (tileIndex/cols|0)*uvSizeY;
121
-
212
+ const x = tileInfo.pos.x / textureInfo.size.x;
213
+ const y = tileInfo.pos.y / textureInfo.size.y;
214
+ const w = tileInfo.size.x / textureInfo.size.x;
215
+ const h = tileInfo.size.y / textureInfo.size.y;
216
+ const tileImageFixBleed = textureInfo.fixBleedSize;
217
+ glSetTexture(textureInfo.glTexture);
122
218
  glDraw(pos.x, pos.y, mirror ? -size.x : size.x, size.y, angle,
123
- uvX + tileImageFixBleed.x, uvY + tileImageFixBleed.y,
124
- uvX - tileImageFixBleed.x + uvSizeX, uvY - tileImageFixBleed.y + uvSizeY,
219
+ x + tileImageFixBleed.x, y + tileImageFixBleed.y,
220
+ x - tileImageFixBleed.x + w, y - tileImageFixBleed.y + h,
125
221
  color.rgbaInt(), additiveColor.rgbaInt());
126
222
  }
223
+ else
224
+ {
225
+ // if no tile info, force untextured
226
+ glDraw(pos.x, pos.y, size.x, size.y, angle, 0, 0, 0, 0, 0, color.rgbaInt());
227
+ }
127
228
  }
128
229
  else
129
230
  {
130
231
  // normal canvas 2D rendering method (slower)
131
232
  drawCanvas2D(pos, size, angle, mirror, (context)=>
132
233
  {
133
- if (tileIndex < 0)
234
+ if (textureInfo)
134
235
  {
135
- // if negative tile index, force untextured
136
- context.fillStyle = color;
137
- context.fillRect(-.5, -.5, 1, 1);
236
+ // calculate uvs and render
237
+ const x = tileInfo.pos.x + tileFixBleedScale;
238
+ const y = tileInfo.pos.y + tileFixBleedScale;
239
+ const w = tileInfo.size.x - 2*tileFixBleedScale;
240
+ const h = tileInfo.size.y - 2*tileFixBleedScale;
241
+ context.globalAlpha = color.a; // only alpha is supported
242
+ context.drawImage(textureInfo.image, x, y, w, h, -.5, -.5, 1, 1);
243
+ context.globalAlpha = 1; // set back to full alpha
138
244
  }
139
245
  else
140
246
  {
141
- // calculate uvs and render
142
- const cols = tileImageSize.x / tileSize.x |0;
143
- const sX = (tileIndex%cols)*tileSize.x + tileFixBleedScale;
144
- const sY = (tileIndex/cols|0)*tileSize.y + tileFixBleedScale;
145
- const sWidth = tileSize.x - 2*tileFixBleedScale;
146
- const sHeight = tileSize.y - 2*tileFixBleedScale;
147
- context.globalAlpha = color.a; // only alpha is supported
148
- context.drawImage(tileImage, sX, sY, sWidth, sHeight, -.5, -.5, 1, 1);
247
+ // if no tile info, force untextured
248
+ context.fillStyle = color;
249
+ context.fillRect(-.5, -.5, 1, 1);
149
250
  }
150
251
  }, undefined, screenSpace);
151
252
  }
@@ -160,7 +261,7 @@ function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, col
160
261
  * @param {Boolean} [screenSpace=0]
161
262
  * @memberof Draw */
162
263
  function drawRect(pos, size, color, angle, useWebGL, screenSpace)
163
- { drawTile(pos, size, -1, tileSizeDefault, color, angle, 0, undefined, useWebGL, screenSpace); }
264
+ { drawTile(pos, size, undefined, color, angle, 0, undefined, useWebGL, screenSpace); }
164
265
 
165
266
  /** Draw colored polygon using passed in points
166
267
  * @param {Array} points - Array of Vector2 points
@@ -305,10 +406,9 @@ class FontImage
305
406
  * @param {HTMLImageElement} [image] - Image for the font, if undefined default font is used
306
407
  * @param {Vector2} [tileSize=vec2(8)] - Size of the font source tiles
307
408
  * @param {Vector2} [paddingSize=vec2(0,1)] - How much extra space to add between characters
308
- * @param {Number} [startTileIndex=0] - Tile index in image where font starts
309
409
  * @param {CanvasRenderingContext2D} [context=overlayContext] - context to draw to
310
410
  */
311
- constructor(image, tileSize=vec2(8), paddingSize=vec2(0,1), startTileIndex=0, context=overlayContext)
411
+ constructor(image, tileSize=vec2(8), paddingSize=vec2(0,1), context=overlayContext)
312
412
  {
313
413
  // load default font image
314
414
  if (!engineFontImage)
@@ -317,7 +417,6 @@ class FontImage
317
417
  this.image = image || engineFontImage;
318
418
  this.tileSize = tileSize;
319
419
  this.paddingSize = paddingSize;
320
- this.startTileIndex = startTileIndex;
321
420
  this.context = context;
322
421
  }
323
422
 
@@ -358,7 +457,7 @@ class FontImage
358
457
  charCode = 127; // unknown character
359
458
 
360
459
  // get the character source location and draw it
361
- const tile = this.startTileIndex + charCode - 32;
460
+ const tile = charCode - 32;
362
461
  const x = tile % cols;
363
462
  const y = tile / cols |0;
364
463
  const drawPos = pos.add(vec2(j,i).multiply(drawSize));
@@ -390,4 +489,4 @@ function toggleFullscreen()
390
489
  }
391
490
  else if (document.body.requestFullscreen)
392
491
  document.body.requestFullscreen();
393
- }
492
+ }
@@ -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,
@@ -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 */