littlejsengine 1.8.9 → 1.9.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 (48) hide show
  1. package/README.md +17 -17
  2. package/build/littlejs.d.ts +352 -288
  3. package/build/littlejs.esm.js +695 -658
  4. package/build/littlejs.esm.min.js +1 -1
  5. package/build/littlejs.js +694 -658
  6. package/build/littlejs.min.js +1 -1
  7. package/build/littlejs.release.js +629 -594
  8. package/examples/breakout/game.js +4 -4
  9. package/examples/breakout/index.html +3 -3
  10. package/examples/breakoutTutorial/index.html +2 -2
  11. package/examples/electron/game.js +1 -1
  12. package/examples/electron/index.html +2 -2
  13. package/examples/favicon.png +0 -0
  14. package/examples/js13k/build.js +1 -1
  15. package/examples/js13k/index.html +13 -13
  16. package/examples/module/game.js +1 -1
  17. package/examples/module/index.html +1 -1
  18. package/examples/particles/index.html +1 -1
  19. package/examples/platformer/game.js +6 -6
  20. package/examples/platformer/gameCharacter.js +293 -0
  21. package/examples/platformer/gameEffects.js +8 -5
  22. package/examples/platformer/gameObjects.js +13 -13
  23. package/examples/platformer/gamePlayer.js +9 -293
  24. package/examples/platformer/index.html +7 -6
  25. package/examples/puzzle/game.js +3 -2
  26. package/examples/puzzle/index.html +2 -2
  27. package/examples/starter/build.js +1 -1
  28. package/examples/starter/game.js +2 -2
  29. package/examples/starter/index.html +13 -13
  30. package/examples/stress/index.html +35 -27
  31. package/examples/typescript/index.html +1 -1
  32. package/index.d.ts +2094 -0
  33. package/package.json +1 -1
  34. package/src/engine.js +28 -28
  35. package/src/engineAudio.js +57 -57
  36. package/src/engineDebug.js +66 -65
  37. package/src/engineDraw.js +64 -73
  38. package/src/engineExport.js +1 -0
  39. package/src/engineInput.js +57 -40
  40. package/src/engineMedals.js +32 -29
  41. package/src/engineObject.js +42 -27
  42. package/src/engineParticles.js +98 -72
  43. package/src/engineRelease.js +1 -1
  44. package/src/engineSettings.js +22 -22
  45. package/src/engineTileLayer.js +66 -60
  46. package/src/engineUtilities.js +49 -49
  47. package/src/engineWebGL.js +112 -135
  48. package/src/jsconfig.json +10 -0
@@ -25,36 +25,36 @@ class ParticleEmitter extends EngineObject
25
25
  {
26
26
  /** Create a particle system with the given settings
27
27
  * @param {Vector2} position - World space position of the emitter
28
- * @param {Number} [angle=0] - Angle to emit the particles
29
- * @param {Number|Vector2} [emitSize=0] - World space size of the emitter (float for circle diameter, vec2 for rect)
30
- * @param {Number} [emitTime=0] - How long to stay alive (0 is forever)
31
- * @param {Number} [emitRate=100] - How many particles per second to spawn, does not emit if 0
32
- * @param {Number} [emitConeAngle=PI] - Local angle to apply velocity to particles from emitter
28
+ * @param {Number} [angle] - Angle to emit the particles
29
+ * @param {Number|Vector2} [emitSize] - World space size of the emitter (float for circle diameter, vec2 for rect)
30
+ * @param {Number} [emitTime] - How long to stay alive (0 is forever)
31
+ * @param {Number} [emitRate] - How many particles per second to spawn, does not emit if 0
32
+ * @param {Number} [emitConeAngle=PI] - Local angle to apply velocity to particles from emitter
33
33
  * @param {TileInfo} [tileInfo] - Tile info to render particles (undefined is untextured)
34
- * @param {Color} [colorStartA=Color()] - Color at start of life 1, randomized between start colors
35
- * @param {Color} [colorStartB=Color()] - Color at start of life 2, randomized between start colors
36
- * @param {Color} [colorEndA=Color(1,1,1,0)] - Color at end of life 1, randomized between end colors
37
- * @param {Color} [colorEndB=Color(1,1,1,0)] - Color at end of life 2, randomized between end colors
38
- * @param {Number} [particleTime=.5] - How long particles live
39
- * @param {Number} [sizeStart=.1] - How big are particles at start
40
- * @param {Number} [sizeEnd=1] - How big are particles at end
41
- * @param {Number} [speed=.1] - How fast are particles when spawned
42
- * @param {Number} [angleSpeed=.05] - How fast are particles rotating
43
- * @param {Number} [damping=1] - How much to dampen particle speed
44
- * @param {Number} [angleDamping=1] - How much to dampen particle angular speed
45
- * @param {Number} [gravityScale=0] - How much does gravity effect particles
46
- * @param {Number} [particleConeAngle=PI] - Cone for start particle angle
47
- * @param {Number} [fadeRate=.1] - How quick to fade in particles at start/end in percent of life
48
- * @param {Number} [randomness=.2] - Apply extra randomness percent
49
- * @param {Boolean} [collideTiles=0] - Do particles collide against tiles
50
- * @param {Boolean} [additive=0] - Should particles use addtive blend
51
- * @param {Boolean} [randomColorLinear=1] - Should color be randomized linearly or across each component
52
- * @param {Number} [renderOrder=0] - Render order for particles (additive is above other stuff by default)
53
- * @param {Boolean} [localSpace=0] - Should it be in local space of emitter (world space is default)
34
+ * @param {Color} [colorStartA=(1,1,1,1)] - Color at start of life 1, randomized between start colors
35
+ * @param {Color} [colorStartB=(1,1,1,1)] - Color at start of life 2, randomized between start colors
36
+ * @param {Color} [colorEndA=(1,1,1,0)] - Color at end of life 1, randomized between end colors
37
+ * @param {Color} [colorEndB=(1,1,1,0)] - Color at end of life 2, randomized between end colors
38
+ * @param {Number} [particleTime] - How long particles live
39
+ * @param {Number} [sizeStart] - How big are particles at start
40
+ * @param {Number} [sizeEnd] - How big are particles at end
41
+ * @param {Number} [speed] - How fast are particles when spawned
42
+ * @param {Number} [angleSpeed] - How fast are particles rotating
43
+ * @param {Number} [damping] - How much to dampen particle speed
44
+ * @param {Number} [angleDamping] - How much to dampen particle angular speed
45
+ * @param {Number} [gravityScale] - How much gravity effect particles
46
+ * @param {Number} [particleConeAngle] - Cone for start particle angle
47
+ * @param {Number} [fadeRate] - How quick to fade particles at start/end in percent of life
48
+ * @param {Number} [randomness] - Apply extra randomness percent
49
+ * @param {Boolean} [collideTiles] - Do particles collide against tiles
50
+ * @param {Boolean} [additive] - Should particles use addtive blend
51
+ * @param {Boolean} [randomColorLinear] - Should color be randomized linearly or across each component
52
+ * @param {Number} [renderOrder] - Render order for particles (additive is above other stuff by default)
53
+ * @param {Boolean} [localSpace] - Should it be in local space of emitter (world space is default)
54
54
  */
55
55
  constructor
56
56
  (
57
- pos,
57
+ position,
58
58
  angle,
59
59
  emitSize = 0,
60
60
  emitTime = 0,
@@ -76,14 +76,14 @@ class ParticleEmitter extends EngineObject
76
76
  particleConeAngle = PI,
77
77
  fadeRate = .1,
78
78
  randomness = .2,
79
- collideTiles,
80
- additive,
81
- randomColorLinear = 1,
79
+ collideTiles = false,
80
+ additive = false,
81
+ randomColorLinear = true,
82
82
  renderOrder = additive ? 1e9 : 0,
83
- localSpace
83
+ localSpace = false
84
84
  )
85
85
  {
86
- super(pos, vec2(), tileInfo, angle, undefined, renderOrder);
86
+ super(position, vec2(), tileInfo, angle, undefined, renderOrder);
87
87
 
88
88
  // emitter settings
89
89
  /** @property {Number|Vector2} - World space size of the emitter (float for circle diameter, vec2 for rect) */
@@ -132,14 +132,17 @@ class ParticleEmitter extends EngineObject
132
132
  this.randomness = randomness;
133
133
  /** @property {Boolean} - Do particles collide against tiles */
134
134
  this.collideTiles = collideTiles;
135
- /** @property {Number} - Should particles use addtive blend */
135
+ /** @property {Boolean} - Should particles use addtive blend */
136
136
  this.additive = additive;
137
137
  /** @property {Boolean} - Should it be in local space of emitter */
138
- this.localSpace = localSpace;
139
- /** @property {Number} - If set the partile is drawn as a trail, stretched in the drection of velocity */
138
+ this.localSpace = localSpace;
139
+ /** @property {Number} - If non zero the partile is drawn as a trail, stretched in the drection of velocity */
140
140
  this.trailScale = 0;
141
-
142
- // internal variables
141
+ /** @property {Function} - Callback when particle is destroyed */
142
+ this.particleDestroyCallback = undefined;
143
+ /** @property {Function} - Callback when particle is created */
144
+ this.particleCreateCallback = undefined;
145
+ /** @property {Number} - Track particle emit time */
143
146
  this.emitTimeBuffer = 0;
144
147
  }
145
148
 
@@ -171,18 +174,16 @@ class ParticleEmitter extends EngineObject
171
174
  emitParticle()
172
175
  {
173
176
  // spawn a particle
174
- let pos = this.emitSize.x != undefined ? // check if vec2 was used for size
175
- vec2(rand(-.5,.5), rand(-.5,.5))
176
- .multiply(this.emitSize).rotate(this.angle) // box emitter
177
- : randInCircle(this.emitSize/2); // circle emitter
177
+ let pos = typeof this.emitSize === 'number' ? // check if number was used
178
+ randInCircle(this.emitSize/2) // circle emitter
179
+ : vec2(rand(-.5,.5), rand(-.5,.5)) // box emitter
180
+ .multiply(this.emitSize).rotate(this.angle)
178
181
  let angle = rand(this.particleConeAngle, -this.particleConeAngle);
179
182
  if (!this.localSpace)
180
183
  {
181
184
  pos = this.pos.add(pos);
182
185
  angle += this.angle;
183
186
  }
184
-
185
- const particle = new Particle(pos, this.tileInfo, this.tileSize, angle);
186
187
 
187
188
  // randomness scales each paremeter by a percentage
188
189
  const randomness = this.randomness;
@@ -198,30 +199,21 @@ class ParticleEmitter extends EngineObject
198
199
  const colorStart = randColor(this.colorStartA, this.colorStartB, this.randomColorLinear);
199
200
  const colorEnd = randColor(this.colorEndA, this.colorEndB, this.randomColorLinear);
200
201
  const velocityAngle = this.localSpace ? coneAngle : this.angle + coneAngle;
202
+
203
+ // build particle
204
+ const particle = new Particle(pos, this.tileInfo, angle, colorStart, colorEnd, particleTime, sizeStart, sizeEnd, this.fadeRate, this.additive, this.trailScale, this.localSpace && this, this.particleDestroyCallback);
205
+ particle.velocity = vec2().setAngle(velocityAngle, speed);
206
+ particle.fadeRate = this.fadeRate;
207
+ particle.damping = this.damping;
208
+ particle.angleDamping = this.angleDamping;
209
+ particle.elasticity = this.elasticity;
210
+ particle.friction = this.friction;
211
+ particle.gravityScale = this.gravityScale;
212
+ particle.collideTiles = this.collideTiles;
213
+ particle.renderOrder = this.renderOrder;
214
+ particle.mirror = !!randInt(2);
201
215
 
202
- // build particle settings
203
- particle.colorStart = colorStart;
204
- particle.colorEndDelta = colorEnd.subtract(colorStart);
205
- particle.velocity = vec2().setAngle(velocityAngle, speed);
206
- particle.angleVelocity = angleSpeed;
207
- particle.lifeTime = particleTime;
208
- particle.sizeStart = sizeStart;
209
- particle.sizeEndDelta = sizeEnd - sizeStart;
210
- particle.fadeRate = this.fadeRate;
211
- particle.damping = this.damping;
212
- particle.angleDamping = this.angleDamping;
213
- particle.elasticity = this.elasticity;
214
- particle.friction = this.friction;
215
- particle.gravityScale = this.gravityScale;
216
- particle.collideTiles = this.collideTiles;
217
- particle.additive = this.additive;
218
- particle.renderOrder = this.renderOrder;
219
- particle.trailScale = this.trailScale;
220
- particle.mirror = randInt(2);
221
- particle.localSpaceEmitter = this.localSpace && this;
222
-
223
- // setup callbacks for particles
224
- particle.destroyCallback = this.particleDestroyCallback;
216
+ // call particle create callaback
225
217
  this.particleCreateCallback && this.particleCreateCallback(particle);
226
218
 
227
219
  // return the newly created particle
@@ -240,13 +232,47 @@ class ParticleEmitter extends EngineObject
240
232
  class Particle extends EngineObject
241
233
  {
242
234
  /**
243
- * Create a particle with the given settings
244
- * @param {Vector2} position - World space position of the particle
245
- * @param {TileInfo} [tileInfo] - Tile info to render particles (undefined is untextured)
246
- * @param {Number} [angle=0] - Angle to rotate the particle
235
+ * Create a particle with the given shis.colorStart = undefined;ettings
236
+ * @param {Vector2} position - World space position of the particle
237
+ * @param {TileInfo} [tileInfo] - Tile info to render particles
238
+ * @param {Number} [angle] - Angle to rotate the particle
239
+ * @param {Color} [colorStart] - Color at start of life
240
+ * @param {Color} [colorEnd] - Color at end of life
241
+ * @param {Number} [lifeTime] - How long to live for
242
+ * @param {Number} [sizeStart] - Angle to rotate the particle
243
+ * @param {Number} [sizeEnd] - Angle to rotate the particle
244
+ * @param {Number} [fadeRate] - Angle to rotate the particle
245
+ * @param {Boolean} [additive] - Angle to rotate the particle
246
+ * @param {Number} [trailScale] - If a trail, how long to make it
247
+ * @param {ParticleEmitter} [localSpaceEmitter] - Parent emitter if local space
248
+ * @param {Function} [destroyCallback] - Called when particle dies
247
249
  */
248
- constructor(pos, tileInfo, angle)
249
- { super(pos, vec2(), tileInfo, angle); }
250
+ constructor(position, tileInfo, angle, colorStart, colorEnd, lifeTime, sizeStart, sizeEnd, fadeRate, additive, trailScale, localSpaceEmitter, destroyCallback
251
+ )
252
+ {
253
+ super(position, vec2(), tileInfo, angle);
254
+
255
+ /** @property {Color} - Color at start of life */
256
+ this.colorStart = colorStart;
257
+ /** @property {Color} - Calculated change in color */
258
+ this.colorEndDelta = colorEnd.subtract(colorStart);
259
+ /** @property {Number} - How long to live for */
260
+ this.lifeTime = lifeTime;
261
+ /** @property {Number} - Size at start of life */
262
+ this.sizeStart = sizeStart;
263
+ /** @property {Number} - Calculated change in size */
264
+ this.sizeEndDelta = sizeEnd - sizeStart;
265
+ /** @property {Number} - How quick to fade in/out */
266
+ this.fadeRate = fadeRate;
267
+ /** @property {Boolean} - Is it additive */
268
+ this.additive = additive;
269
+ /** @property {Number} - If a trail, how long to make it */
270
+ this.trailScale = trailScale;
271
+ /** @property {ParticleEmitter} - Parent emitter if local space */
272
+ this.localSpaceEmitter = localSpaceEmitter;
273
+ /** @property {Function} - Called when particle dies */
274
+ this.destroyCallback = destroyCallback;
275
+ }
250
276
 
251
277
  /** Render the particle, automatically called each frame, sorted by renderOrder */
252
278
  render()
@@ -264,7 +290,7 @@ class Particle extends EngineObject
264
290
  (p < fadeRate ? p/fadeRate : p > 1-fadeRate ? (1-p)/fadeRate : 1)); // fade alpha
265
291
 
266
292
  // draw the particle
267
- this.additive && setBlendMode(1);
293
+ this.additive && setBlendMode(true);
268
294
 
269
295
  let pos = this.pos, angle = this.angle;
270
296
  if (this.localSpaceEmitter)
@@ -7,7 +7,7 @@
7
7
  'use strict';
8
8
 
9
9
  let showWatermark = 0;
10
- let debugKey = 0;
10
+ let debugKey = '';
11
11
  const debug = 0;
12
12
  const debugOverlay = 0;
13
13
  const debugPhysics = 0;
@@ -41,7 +41,7 @@ let canvasFixedSize = vec2();
41
41
  * @type {Boolean}
42
42
  * @default
43
43
  * @memberof Settings */
44
- let canvasPixelated = 1;
44
+ let canvasPixelated = true;
45
45
 
46
46
  /** Default font used for text rendering
47
47
  * @type {String}
@@ -53,7 +53,7 @@ let fontDefault = 'arial';
53
53
  * @type {Boolean}
54
54
  * @default
55
55
  * @memberof Settings */
56
- let showSplashScreen = 0;
56
+ let showSplashScreen = false;
57
57
 
58
58
  ///////////////////////////////////////////////////////////////////////////////
59
59
  // WebGL settings
@@ -62,13 +62,13 @@ let showSplashScreen = 0;
62
62
  * @type {Boolean}
63
63
  * @default
64
64
  * @memberof Settings */
65
- let glEnable = 1;
65
+ let glEnable = true;
66
66
 
67
67
  /** Fixes slow rendering in some browsers by not compositing the WebGL canvas
68
68
  * @type {Boolean}
69
69
  * @default
70
70
  * @memberof Settings */
71
- let glOverlay = 1;
71
+ let glOverlay = true;
72
72
 
73
73
  ///////////////////////////////////////////////////////////////////////////////
74
74
  // Tile sheet settings
@@ -92,7 +92,7 @@ let tileFixBleedScale = .3;
92
92
  * @type {Boolean}
93
93
  * @default
94
94
  * @memberof Settings */
95
- let enablePhysicsSolver = 1;
95
+ let enablePhysicsSolver = true;
96
96
 
97
97
  /** Default object mass for collison calcuations (how heavy objects are)
98
98
  * @type {Number}
@@ -114,7 +114,7 @@ let objectDefaultAngleDamping = 1;
114
114
 
115
115
  /** How much to bounce when a collision occurs (0-1)
116
116
  * @type {Number}
117
- * @default 0
117
+ * @default
118
118
  * @memberof Settings */
119
119
  let objectDefaultElasticity = 0;
120
120
 
@@ -132,7 +132,7 @@ let objectMaxSpeed = 1;
132
132
 
133
133
  /** How much gravity to apply to objects along the Y axis, negative is down
134
134
  * @type {Number}
135
- * @default 0
135
+ * @default
136
136
  * @memberof Settings */
137
137
  let gravity = 0;
138
138
 
@@ -149,33 +149,33 @@ let particleEmitRateScale = 1;
149
149
  * @type {Boolean}
150
150
  * @default
151
151
  * @memberof Settings */
152
- let gamepadsEnable = 1;
152
+ let gamepadsEnable = true;
153
153
 
154
154
  /** If true, the dpad input is also routed to the left analog stick (for better accessability)
155
155
  * @type {Boolean}
156
156
  * @default
157
157
  * @memberof Settings */
158
- let gamepadDirectionEmulateStick = 1;
158
+ let gamepadDirectionEmulateStick = true;
159
159
 
160
160
  /** If true the WASD keys are also routed to the direction keys (for better accessability)
161
161
  * @type {Boolean}
162
162
  * @default
163
163
  * @memberof Settings */
164
- let inputWASDEmulateDirection = 1;
164
+ let inputWASDEmulateDirection = true;
165
165
 
166
166
  /** True if touch gamepad should appear on mobile devices
167
167
  * - Supports left analog stick, 4 face buttons and start button (button 9)
168
168
  * - Must be set by end of gameInit to be activated
169
169
  * @type {Boolean}
170
- * @default 0
170
+ * @default
171
171
  * @memberof Settings */
172
- let touchGamepadEnable = 0;
172
+ let touchGamepadEnable = false;
173
173
 
174
174
  /** True if touch gamepad should be analog stick or false to use if 8 way dpad
175
175
  * @type {Boolean}
176
176
  * @default
177
177
  * @memberof Settings */
178
- let touchGamepadAnalog = 1;
178
+ let touchGamepadAnalog = true;
179
179
 
180
180
  /** Size of virutal gamepad for touch devices in pixels
181
181
  * @type {Number}
@@ -193,7 +193,7 @@ let touchGamepadAlpha = .3;
193
193
  * @type {Boolean}
194
194
  * @default
195
195
  * @memberof Settings */
196
- let vibrateEnable = 1;
196
+ let vibrateEnable = true;
197
197
 
198
198
  ///////////////////////////////////////////////////////////////////////////////
199
199
  // Audio settings
@@ -202,7 +202,7 @@ let vibrateEnable = 1;
202
202
  * @type {Boolean}
203
203
  * @default
204
204
  * @memberof Settings */
205
- let soundEnable = 1;
205
+ let soundEnable = true;
206
206
 
207
207
  /** Volume scale to apply to all sound, music and speech
208
208
  * @type {Number}
@@ -251,9 +251,9 @@ let medalDisplayIconSize = 50;
251
251
 
252
252
  /** Set to stop medals from being unlockable (like if cheats are enabled)
253
253
  * @type {Boolean}
254
- * @default 0
254
+ * @default
255
255
  * @memberof Settings */
256
- let medalsPreventUnlock;
256
+ let medalsPreventUnlock = false;
257
257
 
258
258
  ///////////////////////////////////////////////////////////////////////////////
259
259
  // Setters for global variables
@@ -324,12 +324,12 @@ function setEnablePhysicsSolver(enable) { enablePhysicsSolver = enable; }
324
324
  function setObjectDefaultMass(mass) { objectDefaultMass = mass; }
325
325
 
326
326
  /** Set how much to slow velocity by each frame
327
- * @param {Number} damping
327
+ * @param {Number} damp
328
328
  * @memberof Settings */
329
329
  function setObjectDefaultDamping(damp) { objectDefaultDamping = damp; }
330
330
 
331
331
  /** Set how much to slow angular velocity each frame
332
- * @param {Number} damping
332
+ * @param {Number} damp
333
333
  * @memberof Settings */
334
334
  function setObjectDefaultAngleDamping(damp) { objectDefaultAngleDamping = damp; }
335
335
 
@@ -349,9 +349,9 @@ function setObjectDefaultFriction(friction) { objectDefaultFriction = friction;
349
349
  function setObjectMaxSpeed(speed) { objectMaxSpeed = speed; }
350
350
 
351
351
  /** Set how much gravity to apply to objects along the Y axis
352
- * @param {Number} gravity
352
+ * @param {Number} newGravity
353
353
  * @memberof Settings */
354
- function setGravity(g) { gravity = g; }
354
+ function setGravity(newGravity) { gravity = newGravity; }
355
355
 
356
356
  /** Set to scales emit rate of particles
357
357
  * @param {Number} scale
@@ -449,6 +449,6 @@ function setMedalsPreventUnlock(preventUnlock) { medalsPreventUnlock = preventUn
449
449
  function setShowWatermark(show) { showWatermark = show; }
450
450
 
451
451
  /** Set key code used to toggle debug mode, Esc by default
452
- * @param {Number} key
452
+ * @param {String} key
453
453
  * @memberof Debug */
454
454
  function setDebugKey(key) { debugKey = key; }
@@ -35,7 +35,7 @@ function initTileCollision(size)
35
35
 
36
36
  /** Set tile collision data
37
37
  * @param {Vector2} pos
38
- * @param {Number} [data=0]
38
+ * @param {Number} [data]
39
39
  * @memberof TileCollision */
40
40
  function setTileCollisionData(pos, data=0)
41
41
  {
@@ -53,7 +53,7 @@ function getTileCollisionData(pos)
53
53
 
54
54
  /** Check if collision with another object should occur
55
55
  * @param {Vector2} pos
56
- * @param {Vector2} [size=Vector2(1,1)]
56
+ * @param {Vector2} [size=(1,1)]
57
57
  * @param {EngineObject} [object]
58
58
  * @return {Boolean}
59
59
  * @memberof TileCollision */
@@ -68,7 +68,7 @@ function tileCollisionTest(pos, size=vec2(), object)
68
68
  {
69
69
  const tileData = tileCollision[y*tileCollisionSize.x+x];
70
70
  if (tileData && (!object || object.collideWithTile(tileData, vec2(x, y))))
71
- return 1;
71
+ return true;
72
72
  }
73
73
  }
74
74
 
@@ -134,11 +134,11 @@ function tileCollisionRaycast(posStart, posEnd, object)
134
134
  class TileLayerData
135
135
  {
136
136
  /** Create a tile layer data object, one for each tile in a TileLayer
137
- * @param {Number} [tile] - The tile to use, untextured if undefined
138
- * @param {Number} [direction=0] - Integer direction of tile, in 90 degree increments
139
- * @param {Boolean} [mirror=0] - If the tile should be mirrored along the x axis
140
- * @param {Color} [color=Color()] - Color of the tile */
141
- constructor(tile, direction=0, mirror=0, color=new Color())
137
+ * @param {Number} [tile] - The tile to use, untextured if undefined
138
+ * @param {Number} [direction] - Integer direction of tile, in 90 degree increments
139
+ * @param {Boolean} [mirror] - If the tile should be mirrored along the x axis
140
+ * @param {Color} [color] - Color of the tile */
141
+ constructor(tile, direction=0, mirror=false, color=new Color())
142
142
  {
143
143
  /** @property {Number} - The tile to use, untextured if undefined */
144
144
  this.tile = tile;
@@ -151,7 +151,7 @@ class TileLayerData
151
151
  }
152
152
 
153
153
  /** Set this tile to clear, it will not be rendered */
154
- clear() { this.tile = this.direction = this.mirror = 0; color = new Color; }
154
+ clear() { this.tile = this.direction = 0; this.mirror = false; this.color = new Color; }
155
155
  }
156
156
 
157
157
  /**
@@ -168,25 +168,25 @@ class TileLayerData
168
168
  */
169
169
  class TileLayer extends EngineObject
170
170
  {
171
- /** Create a tile layer object
172
- * @param {Vector2} [position=Vector2()] - World space position
173
- * @param {Vector2} [size=tileCollisionSize] - World space size
174
- * @param {TileInfo} [tileInfo] - Tile info for layer
175
- * @param {Vector2} [scale=Vector2(1,1)] - How much to scale this layer when rendered
176
- * @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
171
+ /** Create a tile layer object
172
+ * @param {Vector2} [position=(0,0)] - World space position
173
+ * @param {Vector2} [size=tileCollisionSize] - World space size
174
+ * @param {TileInfo} [tileInfo] - Tile info for layer
175
+ * @param {Vector2} [scale=(1,1)] - How much to scale this layer when rendered
176
+ * @param {Number} [renderOrder] - Objects are sorted by renderOrder
177
177
  */
178
- constructor(pos, size=tileCollisionSize, tileInfo=tile(), scale=vec2(1), renderOrder=0)
178
+ constructor(position, size=tileCollisionSize, tileInfo=tile(), scale=vec2(1), renderOrder=0)
179
179
  {
180
- super(pos, size, tileInfo, 0, undefined, renderOrder);
180
+ super(position, size, tileInfo, 0, undefined, renderOrder);
181
181
 
182
- /** @property {HTMLCanvasElement} - The canvas used by this tile layer */
182
+ /** @property {HTMLCanvasElement} - The canvas used by this tile layer */
183
183
  this.canvas = document.createElement('canvas');
184
184
  /** @property {CanvasRenderingContext2D} - The 2D canvas context used by this tile layer */
185
185
  this.context = this.canvas.getContext('2d');
186
- /** @property {Vector2} - How much to scale this layer when rendered */
186
+ /** @property {Vector2} - How much to scale this layer when rendered */
187
187
  this.scale = scale;
188
- /** @property {Boolean} [isOverlay=0] - If true this layer will render to overlay canvas and appear above all objects */
189
- this.isOverlay;
188
+ /** @property {Boolean} - If true this layer will render to overlay canvas and appear above all objects */
189
+ this.isOverlay = false;
190
190
 
191
191
  // init tile data
192
192
  this.data = [];
@@ -195,10 +195,10 @@ constructor(pos, size=tileCollisionSize, tileInfo=tile(), scale=vec2(1), renderO
195
195
  }
196
196
 
197
197
  /** Set data at a given position in the array
198
- * @param {Vector2} position - Local position in array
199
- * @param {TileLayerData} data - Data to set
200
- * @param {Boolean} [redraw=0] - Force the tile to redraw if true */
201
- setData(layerPos, data, redraw)
198
+ * @param {Vector2} layerPos - Local position in array
199
+ * @param {TileLayerData} data - Data to set
200
+ * @param {Boolean} [redraw] - Force the tile to redraw if true */
201
+ setData(layerPos, data, redraw=false)
202
202
  {
203
203
  if (layerPos.arrayCheck(this.size))
204
204
  {
@@ -219,7 +219,7 @@ constructor(pos, size=tileCollisionSize, tileInfo=tile(), scale=vec2(1), renderO
219
219
  // Render the tile layer, called automatically by the engine
220
220
  render()
221
221
  {
222
- ASSERT(mainContext != this.context); // must call redrawEnd() after drawing tiles
222
+ ASSERT(mainContext != this.context, 'must call redrawEnd() after drawing tiles');
223
223
 
224
224
  // flush and copy gl canvas because tile canvas does not use webgl
225
225
  glEnable && !glOverlay && !this.isOverlay && glCopyToContext(mainContext);
@@ -234,33 +234,38 @@ constructor(pos, size=tileCollisionSize, tileInfo=tile(), scale=vec2(1), renderO
234
234
  }
235
235
 
236
236
  /** Draw all the tile data to an offscreen canvas
237
- * - This may be slow in some browsers
238
- */
237
+ * - This may be slow in some browsers but only needs to be done once */
239
238
  redraw()
240
239
  {
241
- this.redrawStart(1);
242
- this.drawAllTileData();
240
+ this.redrawStart(true);
241
+ for (let x = this.size.x; x--;)
242
+ for (let y = this.size.y; y--;)
243
+ this.drawTileData(vec2(x,y), false);
243
244
  this.redrawEnd();
244
245
  }
245
246
 
246
247
  /** Call to start the redraw process
247
- * @param {Boolean} [clear=0] - Should it clear the canvas before drawing */
248
- redrawStart(clear = 0)
248
+ * - This can be used to manually update small parts of the level
249
+ * @param {Boolean} [clear] - Should it clear the canvas before drawing */
250
+ redrawStart(clear=false)
249
251
  {
250
252
  // save current render settings
253
+ /** @type {[HTMLCanvasElement, CanvasRenderingContext2D, Vector2, Vector2, number]} */
251
254
  this.savedRenderSettings = [mainCanvas, mainContext, mainCanvasSize, cameraPos, cameraScale];
252
255
 
253
- // hack: use normal rendering system to render the tiles
256
+ // use webgl rendering system to render the tiles if enabled
257
+ // this works by temporally taking control of the rendering system
254
258
  mainCanvas = this.canvas;
255
259
  mainContext = this.context;
260
+ mainCanvasSize = this.size.multiply(this.tileInfo.size);
256
261
  cameraPos = this.size.scale(.5);
257
262
  cameraScale = this.tileInfo.size.x;
258
263
 
259
264
  if (clear)
260
265
  {
261
266
  // clear and set size
262
- mainCanvas.width = this.size.x * this.tileInfo.size.x;
263
- mainCanvas.height = this.size.y * this.tileInfo.size.y;
267
+ mainCanvas.width = mainCanvasSize.x;
268
+ mainCanvas.height = mainCanvasSize.y;
264
269
  }
265
270
 
266
271
  // begin a new render for the tile canvas
@@ -270,40 +275,41 @@ constructor(pos, size=tileCollisionSize, tileInfo=tile(), scale=vec2(1), renderO
270
275
  /** Call to end the redraw process */
271
276
  redrawEnd()
272
277
  {
273
- ASSERT(mainContext == this.context); // must call redrawStart() before drawing tiles
274
- glEnable && glCopyToContext(mainContext, 1);
278
+ ASSERT(mainContext == this.context, 'must call redrawStart() before drawing tiles');
279
+ glEnable && glCopyToContext(mainContext, true);
275
280
  //debugSaveCanvas(this.canvas);
276
281
 
277
282
  // set stuff back to normal
278
283
  [mainCanvas, mainContext, mainCanvasSize, cameraPos, cameraScale] = this.savedRenderSettings;
279
284
  }
280
285
 
281
- /** Draw the tile at a given position
282
- * @param {Vector2} layerPos */
283
- drawTileData(layerPos)
286
+ /** Draw the tile at a given position in the tile grid
287
+ * This can be used to clear out tiles when they are destroyed
288
+ * Tiles can also be redrawn if isinde a redrawStart/End block
289
+ * @param {Vector2} layerPos
290
+ * @param {Boolean} [clear] - should the old tile be cleared out
291
+ */
292
+ drawTileData(layerPos, clear=true)
284
293
  {
285
- // first clear out where the tile was
286
- const pos = layerPos.floor().add(this.pos).add(vec2(.5));
287
- this.drawCanvas2D(pos, vec2(1), 0, 0, (context)=>context.clearRect(-.5, -.5, 1, 1));
294
+ // clear out where the tile was, for full opaque tiles this can be skipped
295
+ const s = this.tileInfo.size;
296
+ if (clear)
297
+ {
298
+ const pos = layerPos.multiply(s);
299
+ this.context.clearRect(pos.x, this.canvas.height-pos.y, s.x, -s.y);
300
+ }
288
301
 
289
302
  // draw the tile if not undefined
290
303
  const d = this.getData(layerPos);
291
304
  if (d.tile != undefined)
292
305
  {
293
- ASSERT(mainContext == this.context); // must call redrawStart() before drawing tiles
294
- const tileInfo = tile(d.tile, this.tileInfo.size, this.tileInfo.textureIndex);
306
+ const pos = this.pos.add(layerPos).add(vec2(.5));
307
+ ASSERT(mainContext == this.context, 'must call redrawStart() before drawing tiles');
308
+ const tileInfo = tile(d.tile, s, this.tileInfo.textureIndex);
295
309
  drawTile(pos, vec2(1), tileInfo, d.color, d.direction*PI/2, d.mirror);
296
310
  }
297
311
  }
298
312
 
299
- /** Draw all the tiles in this layer */
300
- drawAllTileData()
301
- {
302
- for (let x = this.size.x; x--;)
303
- for (let y = this.size.y; y--;)
304
- this.drawTileData(vec2(x,y));
305
- }
306
-
307
313
  /** Draw directly to the 2D canvas in world space (bipass webgl)
308
314
  * @param {Vector2} pos
309
315
  * @param {Vector2} size
@@ -323,11 +329,11 @@ constructor(pos, size=tileCollisionSize, tileInfo=tile(), scale=vec2(1), renderO
323
329
  context.restore();
324
330
  }
325
331
 
326
- /** Draw a tile directly onto the layer canvas
332
+ /** Draw a tile directly onto the layer canvas in world space
327
333
  * @param {Vector2} pos
328
- * @param {Vector2} [size=Vector2(1,1)]
334
+ * @param {Vector2} [size=(1,1)]
329
335
  * @param {TileInfo} [tileInfo]
330
- * @param {Color} [color=Color()]
336
+ * @param {Color} [color=(1,1,1,1)]
331
337
  * @param {Number} [angle=0]
332
338
  * @param {Boolean} [mirror=0] */
333
339
  drawTile(pos, size=vec2(1), tileInfo, color=new Color, angle, mirror)
@@ -352,11 +358,11 @@ constructor(pos, size=tileCollisionSize, tileInfo=tile(), scale=vec2(1), renderO
352
358
  });
353
359
  }
354
360
 
355
- /** Draw a rectangle directly onto the layer canvas
361
+ /** Draw a rectangle directly onto the layer canvas in world space
356
362
  * @param {Vector2} pos
357
- * @param {Vector2} [size=Vector2(1,1)]
358
- * @param {Color} [color=Color()]
363
+ * @param {Vector2} [size=(1,1)]
364
+ * @param {Color} [color=(1,1,1,1)]
359
365
  * @param {Number} [angle=0] */
360
366
  drawRect(pos, size, color, angle)
361
- { this.drawTile(pos, size, -1, 0, color, angle); }
367
+ { this.drawTile(pos, size, undefined, color, angle); }
362
368
  }