littlejsengine 1.1.2 → 1.1.3

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 (94) hide show
  1. package/README.md +55 -0
  2. package/build.bat +2 -1
  3. package/engine/engine.all.js +1320 -930
  4. package/engine/engine.all.min.js +1 -1
  5. package/engine/engine.all.release.js +965 -601
  6. package/engine/engine.js +71 -60
  7. package/engine/engineAudio.js +80 -22
  8. package/engine/engineBuild.bat +2 -2
  9. package/engine/engineDebug.js +65 -36
  10. package/engine/engineDraw.js +71 -56
  11. package/engine/engineInput.js +178 -28
  12. package/engine/engineMedals.js +66 -58
  13. package/engine/engineObject.js +86 -71
  14. package/engine/engineParticles.js +101 -63
  15. package/engine/engineRelease.js +4 -1
  16. package/engine/engineSettings.js +62 -53
  17. package/engine/engineTileLayer.js +99 -83
  18. package/engine/engineUtilities.js +95 -59
  19. package/engine/engineWebGL.js +53 -48
  20. package/examples/breakout/game.js +1 -1
  21. package/examples/breakout/gameObjects.js +2 -2
  22. package/examples/breakout/index.html +7 -5
  23. package/examples/platformer/game.js +7 -4
  24. package/examples/platformer/gameEffects.js +8 -11
  25. package/examples/platformer/gameLevel.js +15 -8
  26. package/examples/platformer/gameObjects.js +2 -2
  27. package/examples/platformer/gamePlayer.js +6 -6
  28. package/examples/platformer/index.html +10 -8
  29. package/examples/puzzle/game.js +3 -3
  30. package/examples/puzzle/index.html +6 -4
  31. package/examples/stress/index.html +7 -5
  32. package/game.js +10 -10
  33. package/index.html +17 -15
  34. package/package.json +4 -7
  35. package/tiles.png +0 -0
  36. package/LittleJS.zip +0 -0
  37. package/docs/Audio.html +0 -2264
  38. package/docs/Color.html +0 -2506
  39. package/docs/Debug.html +0 -2929
  40. package/docs/Draw.html +0 -3854
  41. package/docs/EngineObject.html +0 -2506
  42. package/docs/Input.html +0 -2478
  43. package/docs/Medal.html +0 -992
  44. package/docs/Medals.html +0 -624
  45. package/docs/Music.html +0 -569
  46. package/docs/Newgrounds.html +0 -1384
  47. package/docs/Particle.html +0 -567
  48. package/docs/ParticleEmitter.html +0 -1537
  49. package/docs/Random.html +0 -1770
  50. package/docs/Settings.html +0 -2885
  51. package/docs/Sound.html +0 -998
  52. package/docs/TileLayer.html +0 -3211
  53. package/docs/TileLayerData.html +0 -569
  54. package/docs/Timer.html +0 -1168
  55. package/docs/Utilities.html +0 -3266
  56. package/docs/Vector2.html +0 -3956
  57. package/docs/WebGL.html +0 -1842
  58. package/docs/engine.js.html +0 -428
  59. package/docs/engineAudio.js.html +0 -567
  60. package/docs/engineDebug.js.html +0 -721
  61. package/docs/engineDraw.js.html +0 -409
  62. package/docs/engineInput.js.html +0 -397
  63. package/docs/engineMedals.js.html +0 -445
  64. package/docs/engineObject.js.html +0 -492
  65. package/docs/engineParticles.js.html +0 -399
  66. package/docs/engineSettings.js.html +0 -358
  67. package/docs/engineTileLayer.js.html +0 -482
  68. package/docs/engineUtilities.js.html +0 -600
  69. package/docs/engineWebGL.js.html +0 -507
  70. package/docs/fonts/MavenPro-Regular.ttf +0 -0
  71. package/docs/fonts/Montserrat-Regular.ttf +0 -0
  72. package/docs/fonts/Muli-Black.ttf +0 -0
  73. package/docs/fonts/OFL-hind.txt +0 -93
  74. package/docs/fonts/OFL-montserrat.txt +0 -93
  75. package/docs/global.html +0 -1635
  76. package/docs/index.html +0 -243
  77. package/docs/scripts/fix-code-block.js +0 -53
  78. package/docs/scripts/fix-navbar.js +0 -25
  79. package/docs/scripts/linenumber.js +0 -25
  80. package/docs/scripts/misc.js +0 -217
  81. package/docs/scripts/resize.js +0 -85
  82. package/docs/scripts/search.js +0 -83
  83. package/docs/scripts/third-party/Apache-License-2.0.txt +0 -202
  84. package/docs/scripts/third-party/fuse.js +0 -9
  85. package/docs/scripts/third-party/lang-css.js +0 -2
  86. package/docs/scripts/third-party/prettify.js +0 -28
  87. package/docs/static/favicon.png +0 -0
  88. package/docs/styles/clean-jsdoc-theme-base.css +0 -393
  89. package/docs/styles/clean-jsdoc-theme-dark.css +0 -324
  90. package/docs/styles/clean-jsdoc-theme-light.css +0 -319
  91. package/docs/styles/reset.css +0 -346
  92. package/docs/styles/third-party/ionicons.min.css +0 -11
  93. package/docs/styles/third-party/prettify-jsdoc.css +0 -111
  94. package/docs/styles/third-party/prettify-tomorrow.css +0 -5
@@ -1,9 +1,9 @@
1
1
  /**
2
- * LittleJS Medal System
3
- * <br> - Tracks and displays medals
4
- * <br> - Saves medals to local storage
5
- * <br> - Newgrounds and OS13k integration
6
- * @namespace Medals
2
+ * LittleJS Medal System
3
+ * <br> - Tracks and displays medals
4
+ * <br> - Saves medals to local storage
5
+ * <br> - Newgrounds and OS13k integration
6
+ * @namespace Medals
7
7
  */
8
8
 
9
9
  'use strict';
@@ -22,32 +22,42 @@ let medalsPreventUnlock;
22
22
  let newgrounds;
23
23
 
24
24
  // Engine internal variables not exposed to documentation
25
- let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimer;
25
+ let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimeLast;
26
26
 
27
27
  ///////////////////////////////////////////////////////////////////////////////
28
28
 
29
29
  /** Initialize medals with a save name used for storage
30
- * <br> - Checks if medals are unlocked
31
30
  * <br> - Call this after creating all medals
31
+ * <br> - Checks if medals are unlocked
32
32
  * @param {String} saveName
33
33
  * @memberof Medals */
34
34
  function medalsInit(saveName)
35
35
  {
36
36
  // check if medals are unlocked
37
37
  medalsSaveName = saveName;
38
- debugMedals || medals.forEach(medal=> medal.unlocked = localStorage[medal.storageKey()]);
38
+ debugMedals || medals.forEach(medal=> medal.unlocked = 1 || localStorage[medal.storageKey()]);
39
39
  }
40
40
 
41
- /** Medal Object - Tracks an unlockable medal */
41
+ /**
42
+ * Medal Object - Tracks an unlockable medal
43
+ * @example
44
+ * // create a medal
45
+ * const medal_example = new Medal(0, 'Example Medal', 'More info about the medal goes here.', '🎖️');
46
+ *
47
+ * // initialize medals
48
+ * medalsInit('Example Game');
49
+ *
50
+ * // unlock the medal
51
+ * medal_example.unlock();
52
+ */
42
53
  class Medal
43
54
  {
44
- /**
45
- * Create an medal object and adds it to the list of medals
46
- * @param {Number} id - The unique identifier of the medal
47
- * @param {String} name - Name of the medal
48
- * @param {String} [description] - Description of the medal
49
- * @param {String} [icon='🏆'] - Icon for the medal
50
- * @param {String} [src] - Image location for the medal
55
+ /** Create an medal object and adds it to the list of medals
56
+ * @param {Number} id - The unique identifier of the medal
57
+ * @param {String} name - Name of the medal
58
+ * @param {String} [description] - Description of the medal
59
+ * @param {String} [icon='🏆'] - Icon for the medal
60
+ * @param {String} [src] - Image location for the medal
51
61
  */
52
62
  constructor(id, name, description='', icon='🏆', src)
53
63
  {
@@ -58,13 +68,9 @@ class Medal
58
68
  this.name = name;
59
69
  this.description = description;
60
70
  this.icon = icon;
61
-
71
+ this.image = new Image();
62
72
  if (src)
63
- {
64
- // load image
65
- this.image = new Image();
66
73
  this.image.src = src;
67
- }
68
74
  }
69
75
 
70
76
  /** Unlocks a medal if not already unlocked */
@@ -74,7 +80,7 @@ class Medal
74
80
  return;
75
81
 
76
82
  // save the medal
77
- ASSERT(medalsSaveName); // game name must be set
83
+ ASSERT(medalsSaveName); // save name must be set
78
84
  localStorage[this.storageKey()] = this.unlocked = 1;
79
85
  medalsDisplayQueue.push(this);
80
86
 
@@ -89,27 +95,28 @@ class Medal
89
95
  render(hidePercent=0)
90
96
  {
91
97
  const context = overlayContext;
92
- const x = overlayCanvas.width - medalDisplayWidth;
98
+ const width = min(medalDisplayWidth, mainCanvas.width);
99
+ const x = overlayCanvas.width - width;
93
100
  const y = -medalDisplayHeight*hidePercent;
94
101
 
95
102
  // draw containing rect and clip to that region
96
103
  context.save();
97
104
  context.beginPath();
98
105
  context.fillStyle = '#ddd'
99
- context.fill(context.rect(x, y, medalDisplayWidth, medalDisplayHeight));
100
- context.strokeStyle = context.fillStyle = '#000';
101
- context.lineWidth = 2;
106
+ context.fill(context.rect(x, y, width, medalDisplayHeight));
107
+ context.strokeStyle = '#000';
108
+ context.lineWidth = 3;
102
109
  context.stroke();
103
110
  context.clip();
104
111
 
112
+ // draw the icon and text
105
113
  this.renderIcon(x+15+medalDisplayIconSize/2, y+medalDisplayHeight/2);
106
-
107
- // draw the text
108
114
  context.textAlign = 'left';
109
- context.font = '3em '+ defaultFont;
110
- context.fillText(this.name, x+medalDisplayIconSize+25, y+35);
111
- context.font = '1.5em '+ defaultFont;
112
- context.restore(context.fillText(this.description, x+medalDisplayIconSize+25, y+70));
115
+ context.font = '38px '+ fontDefault;
116
+ context.fillText(this.name, x+medalDisplayIconSize+30, y+28);
117
+ context.font = '24px '+ fontDefault;
118
+ context.fillText(this.description, x+medalDisplayIconSize+30, y+60);
119
+ context.restore();
113
120
  }
114
121
 
115
122
  /** Render the icon for a medal
@@ -121,21 +128,18 @@ class Medal
121
128
  {
122
129
  // draw the image or icon
123
130
  const context = overlayContext;
131
+ context.fillStyle = '#000';
124
132
  context.textAlign = 'center';
125
133
  context.textBaseline = 'middle';
126
- context.font = size*.6 + 'px '+ defaultFont;
127
- context.fillStyle = '#000';
128
- if (this.image)
134
+ context.font = size*.7 + 'px '+ fontDefault;
135
+ if (this.image.src)
129
136
  context.drawImage(this.image, x-size/2, y-size/2, size, size);
130
137
  else
131
138
  context.fillText(this.icon, x, y); // show icon if there is no image
132
139
  }
133
140
 
134
141
  // Get local storage key used by the medal
135
- storageKey()
136
- {
137
- return medalsSaveName + '_medal_' + this.id;
138
- }
142
+ storageKey() { return medalsSaveName + '_' + this.id; }
139
143
  }
140
144
 
141
145
  // engine automatically renders medals
@@ -146,11 +150,11 @@ function medalsRender()
146
150
 
147
151
  // update first medal in queue
148
152
  const medal = medalsDisplayQueue[0];
149
- const time = timeReal - medalsDisplayTimer;
150
- if (!medalsDisplayTimer)
151
- medalsDisplayTimer = timeReal;
153
+ const time = timeReal - medalsDisplayTimeLast;
154
+ if (!medalsDisplayTimeLast)
155
+ medalsDisplayTimeLast = timeReal;
152
156
  else if (time > medalDisplayTime)
153
- medalsDisplayQueue.shift(medalsDisplayTimer = 0);
157
+ medalsDisplayQueue.shift(medalsDisplayTimeLast = 0);
154
158
  else
155
159
  {
156
160
  // slide on/off medals
@@ -164,14 +168,19 @@ function medalsRender()
164
168
 
165
169
  ///////////////////////////////////////////////////////////////////////////////
166
170
 
167
- /** Newgrounds API wrapper object */
171
+ /**
172
+ * Newgrounds API wrapper object
173
+ * @example
174
+ * // create a newgrounds object, replace the app id and cipher with your own
175
+ * const app_id = '53123:1ZuSTQ9l';
176
+ * const cipher = 'enF0vGH@Mj/FRASKL23Q==';
177
+ * newgrounds = new Newgrounds(app_id, cipher);
178
+ */
168
179
  class Newgrounds
169
180
  {
170
- /**
171
- * Create a newgrounds object
172
- * @param {Number} app_id - The newgrounds App ID
173
- * @param {String} [cipher] - The encryption Key (AES-128/Base64)
174
- */
181
+ /** Create a newgrounds object
182
+ * @param {Number} app_id - The newgrounds App ID
183
+ * @param {String} [cipher] - The encryption Key (AES-128/Base64) */
175
184
  constructor(app_id, cipher)
176
185
  {
177
186
  ASSERT(!newgrounds && app_id);
@@ -199,7 +208,6 @@ class Newgrounds
199
208
  if (medal)
200
209
  {
201
210
  // copy newgrounds medal data
202
- medal.image = new Image();
203
211
  medal.image.src = newgroundsMedal['icon'];
204
212
  medal.name = newgroundsMedal['name'];
205
213
  medal.description = newgroundsMedal['description'];
@@ -223,7 +231,7 @@ class Newgrounds
223
231
  unlockMedal(id) { return this.call('Medal.unlock', {'id':id}, 1); }
224
232
 
225
233
  /** Send message to post score
226
- * @param {Number} id - The scoreboard id
234
+ * @param {Number} id - The scoreboard id
227
235
  * @param {Number} value - The score value */
228
236
  postScore(id, value) { return this.call('ScoreBoard.postScore', {'id':id, 'value':value}, 1); }
229
237
 
@@ -231,21 +239,21 @@ class Newgrounds
231
239
  logView() { return this.call('App.logView', {'host':this.host}, 1); }
232
240
 
233
241
  /** Get scores from a scoreboard
234
- * @param {Number} id - The scoreboard id
235
- * @param {String} [user=0] - A user's id or name
242
+ * @param {Number} id - The scoreboard id
243
+ * @param {String} [user=0] - A user's id or name
236
244
  * @param {Number} [social=0] - If true, only social scores will be loaded
237
- * @param {Number} [skip=0] - Number of scores to skip before start
245
+ * @param {Number} [skip=0] - Number of scores to skip before start
238
246
  * @param {Number} [limit=10] - Number of scores to include in the list
239
- * @return {Object} - The response JSON object
247
+ * @return {Object} - The response JSON object
240
248
  */
241
249
  getScores(id, user=0, social=0, skip=0, limit=10)
242
250
  { return this.call('ScoreBoard.getScores', {'id':id, 'user':user, 'social':social, 'skip':skip, 'limit':limit}); }
243
251
 
244
252
  /** Send a message to call a component of the Newgrounds API
245
- * @param {String} component - Name of the component
253
+ * @param {String} component - Name of the component
246
254
  * @param {Object} [parameters=0] - Parameters to use for call
247
- * @param {Boolean} [async=0] - If true, wait for response before continuing (will cause stall)
248
- * @return {Object} - The response JSON object
255
+ * @param {Boolean} [async=0] - If true, don't wait for response before continuing (avoid stall)
256
+ * @return {Object} - The response JSON object
249
257
  */
250
258
  call(component, parameters=0, async=0)
251
259
  {
@@ -5,51 +5,83 @@
5
5
  'use strict';
6
6
 
7
7
  /**
8
- * LittleJS Object Base Object Class
9
- * <br> - Base object class used by the engine
10
- * <br> - Automatically adds self to object list
11
- * <br> - Will be updated and rendered each frame
12
- * <br> - Renders as a sprite from a tilesheet by default
13
- * <br> - Can have color and addtive color applied
14
- * <br> - 2d Physics and collision system
15
- * <br> - Sorted by renderOrder
16
- * <br> - Objects can have children attached
17
- * <br> - Parents are updated before children, and set child transform
18
- * <br> - Call destroy() to get rid of objects
8
+ * LittleJS Object Base Object Class
9
+ * <br> - Base object class used by the engine
10
+ * <br> - Automatically adds self to object list
11
+ * <br> - Will be updated and rendered each frame
12
+ * <br> - Renders as a sprite from a tilesheet by default
13
+ * <br> - Can have color and addtive color applied
14
+ * <br> - 2d Physics and collision system
15
+ * <br> - Sorted by renderOrder
16
+ * <br> - Objects can have children attached
17
+ * <br> - Parents are updated before children, and set child transform
18
+ * <br> - Call destroy() to get rid of objects
19
+ * <br>
20
+ * <br>The physics system used by objects is simple and fast with some caveats...
21
+ * <br> - Collision uses the axis aligned size, the object's rotation angle is only for rendering
22
+ * <br> - Objects are guaranteed to not intersect tile collision from physics
23
+ * <br> - If an object starts or is moved inside tile collision, it will not collide with that tile
24
+ * <br> - Collision for objects can be set to be solid to block other objects
25
+ * <br> - Objects may get pushed into overlapping other solid objects, if so they will push away
26
+ * <br> - Solid objects are more performance intensive and should be used sparingly
27
+ * @example
28
+ * // create an engine object, normally you would first extend the class with your own
29
+ * const pos = vec2(2,3);
30
+ * const object = new EngineObject(pos);
19
31
  */
20
32
  class EngineObject
21
33
  {
22
- /**
23
- * Create an engine object and adds it to the list of objects
24
- * @param {Vector2} [position=new Vector2(0,0)] - World space position of the object
25
- * @param {Vector2} [size=defaultObjectSize] - World space size of the object
26
- * @param {Number} [tileIndex=-1] - Tile to use to render object, untextured if -1
27
- * @param {Vector2} [tileSize=defaultTileSize] - Size of tile in source pixels
28
- * @param {Number} [angle=0] - Angle to rotate the object
29
- * @param {Color} [color] - Color to apply to tile when rendered
34
+ /** Create an engine object and adds it to the list of objects
35
+ * @param {Vector2} [position=new Vector2(0,0)] - World space position of the object
36
+ * @param {Vector2} [size=objectDefaultSize] - World space size of the object
37
+ * @param {Number} [tileIndex=-1] - Tile to use to render object, untextured if -1
38
+ * @param {Vector2} [tileSize=tileSizeDefault] - Size of tile in source pixels
39
+ * @param {Number} [angle=0] - Angle to rotate the object
40
+ * @param {Color} [color] - Color to apply to tile when rendered
41
+ * @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
30
42
  */
31
- constructor(pos=vec2(), size=defaultObjectSize, tileIndex=-1, tileSize=defaultTileSize, angle=0, color)
43
+ constructor(pos=vec2(), size=objectDefaultSize, tileIndex=-1, tileSize=tileSizeDefault, angle=0, color, renderOrder=0)
32
44
  {
33
45
  // set passed in params
34
46
  ASSERT(pos && pos.x != undefined && size.x != undefined); // ensure pos and size are vec2s
47
+
48
+ /** @property {Vector2} - World space position of the object */
35
49
  this.pos = pos.copy();
50
+ /** @property {Vector2} - World space width and height of the object */
36
51
  this.size = size;
52
+ /** @property {Vector2} - Size of object used for drawing, uses size if not set */
53
+ this.drawSize;
54
+ /** @property {Number} - Tile to use to render object, untextured if -1 */
37
55
  this.tileIndex = tileIndex;
56
+ /** @property {Vector2} - Size of tile in source pixels */
38
57
  this.tileSize = tileSize;
58
+ /** @property {Number} - Angle to rotate the object */
39
59
  this.angle = angle;
60
+ /** @property {Color} - Color to apply when rendered */
40
61
  this.color = color;
41
-
42
- // set physics defaults
43
- this.mass = defaultObjectMass;
44
- this.damping = defaultObjectDamping;
45
- this.angleDamping = defaultObjectAngleDamping;
46
- this.elasticity = defaultObjectElasticity;
47
- this.friction = defaultObjectFriction;
48
-
49
- // init other object stuff
62
+ /** @property {Color} - Additive color to apply when rendered */
63
+ this.additiveColor;
64
+
65
+ // set object defaults
66
+ /** @property {Number} [mass=objectDefaultMass] - How heavy the object is */
67
+ this.mass = objectDefaultMass;
68
+ /** @property {Number} [damping=objectDefaultDamping] - How much to slow down velocity each frame (0-1) */
69
+ this.damping = objectDefaultDamping;
70
+ /** @property {Number} [angleDamping=objectDefaultAngleDamping] - How much to slow down rotation each frame (0-1) */
71
+ this.angleDamping = objectDefaultAngleDamping;
72
+ /** @property {Number} [elasticity=objectDefaultElasticity] - How bouncy the object is when colliding (0-1) */
73
+ this.elasticity = objectDefaultElasticity;
74
+ /** @property {Number} [friction=objectDefaultFriction] - How much friction to apply when sliding (0-1) */
75
+ this.friction = objectDefaultFriction;
76
+ /** @property {Number} [gravityScale=1] - How much to scale gravity by for this object */
77
+ this.gravityScale = 1;
78
+ /** @property {Number} [renderOrder=0] - Objects are sorted by render order */
79
+ this.renderOrder = renderOrder;
80
+
81
+ // init other internal object stuff
50
82
  this.spawnTime = time;
51
- this.velocity = vec2(this.collideSolidObjects = this.renderOrder = this.angleVelocity = 0);
52
- this.collideTiles = this.gravityScale = 1;
83
+ this.velocity = vec2(this.collideSolidObjects = this.angleVelocity = 0);
84
+ this.collideTiles = 1;
53
85
  this.children = [];
54
86
 
55
87
  // add to list of objects
@@ -69,8 +101,8 @@ class EngineObject
69
101
  }
70
102
 
71
103
  // limit max speed to prevent missing collisions
72
- this.velocity.x = clamp(this.velocity.x, maxObjectSpeed, -maxObjectSpeed);
73
- this.velocity.y = clamp(this.velocity.y, maxObjectSpeed, -maxObjectSpeed);
104
+ this.velocity.x = clamp(this.velocity.x, -objectMaxSpeed, objectMaxSpeed);
105
+ this.velocity.y = clamp(this.velocity.y, -objectMaxSpeed, objectMaxSpeed);
74
106
 
75
107
  // apply physics
76
108
  const oldPos = this.pos.copy();
@@ -99,14 +131,14 @@ class EngineObject
99
131
  {
100
132
  // check collisions against solid objects
101
133
  const epsilon = 1e-3; // necessary to push slightly outside of the collision
102
- for (const o of engineCollideObjects)
134
+ for (const o of engineObjectsCollide)
103
135
  {
104
136
  // non solid objects don't collide with eachother
105
- if (!this.isSolid & !o.isSolid || o.destroyed || o.parent)
137
+ if (!this.isSolid & !o.isSolid || o.destroyed || o.parent || o == this)
106
138
  continue;
107
139
 
108
140
  // check collision
109
- if (!isOverlapping(this.pos, this.size, o.pos, o.size) || o == this)
141
+ if (!isOverlapping(this.pos, this.size, o.pos, o.size))
110
142
  continue;
111
143
 
112
144
  // pass collision to objects
@@ -118,7 +150,7 @@ class EngineObject
118
150
  // if already was touching, try to push away
119
151
  const deltaPos = oldPos.subtract(o.pos);
120
152
  const length = deltaPos.length();
121
- const pushAwayAccel = .001; // push away if alread overlapping
153
+ const pushAwayAccel = .001; // push away if already overlapping
122
154
  const velocity = length < .01 ? randVector(pushAwayAccel) : deltaPos.scale(pushAwayAccel/length);
123
155
  this.velocity = this.velocity.add(velocity);
124
156
  if (o.mass) // push away if not fixed
@@ -129,16 +161,15 @@ class EngineObject
129
161
  }
130
162
 
131
163
  // check for collision
132
- const sx = this.size.x + o.size.x;
133
- const sy = this.size.y + o.size.y;
134
- const smallStepUp = (oldPos.y - o.pos.y)*2 > sy + gravity; // prefer to push up if small delta
135
- const isBlockedX = abs(oldPos.y - o.pos.y)*2 < sy;
136
- const isBlockedY = abs(oldPos.x - o.pos.x)*2 < sx;
164
+ const sizeBoth = this.size.add(o.size);
165
+ const smallStepUp = (oldPos.y - o.pos.y)*2 > sizeBoth.y + gravity; // prefer to push up if small delta
166
+ const isBlockedX = abs(oldPos.y - o.pos.y)*2 < sizeBoth.y;
167
+ const isBlockedY = abs(oldPos.x - o.pos.x)*2 < sizeBoth.x;
137
168
 
138
169
  if (smallStepUp || isBlockedY || !isBlockedX) // resolve y collision
139
170
  {
140
171
  // push outside object collision
141
- this.pos.y = o.pos.y + (sy/2 + epsilon) * sign(oldPos.y - o.pos.y);
172
+ this.pos.y = o.pos.y + (sizeBoth.y/2 + epsilon) * sign(oldPos.y - o.pos.y);
142
173
  if (o.groundObject && wasMovingDown || !o.mass)
143
174
  {
144
175
  // set ground object if landed on something
@@ -161,15 +192,14 @@ class EngineObject
161
192
 
162
193
  // lerp betwen elastic or inelastic based on elasticity
163
194
  const elasticity = max(this.elasticity, o.elasticity);
164
- this.velocity.y = lerp(elasticity, elastic0, inelastic);
165
- o.velocity.y = lerp(elasticity, elastic1, inelastic);
195
+ this.velocity.y = lerp(elasticity, inelastic, elastic0);
196
+ o.velocity.y = lerp(elasticity, inelastic, elastic1);
166
197
  }
167
- debugPhysics && smallStepUp && (abs(oldPos.x - o.pos.x)*2 > sx) && console.log('stepUp', oldPos.y - o.pos.y);
168
198
  }
169
199
  if (!smallStepUp && (isBlockedX || !isBlockedY)) // resolve x collision
170
200
  {
171
201
  // push outside collision
172
- this.pos.x = o.pos.x + (sx/2 + epsilon) * sign(oldPos.x - o.pos.x);
202
+ this.pos.x = o.pos.x + (sizeBoth.x/2 + epsilon) * sign(oldPos.x - o.pos.x);
173
203
  if (o.mass)
174
204
  {
175
205
  // inelastic collision
@@ -183,13 +213,12 @@ class EngineObject
183
213
 
184
214
  // lerp betwen elastic or inelastic based on elasticity
185
215
  const elasticity = max(this.elasticity, o.elasticity);
186
- this.velocity.x = lerp(elasticity, elastic0, inelastic);
187
- o.velocity.x = lerp(elasticity, elastic1, inelastic);
216
+ this.velocity.x = lerp(elasticity, inelastic, elastic0);
217
+ o.velocity.x = lerp(elasticity, inelastic, elastic1);
188
218
  }
189
219
  else // bounce if other object is fixed
190
220
  this.velocity.x *= -this.elasticity;
191
221
  }
192
-
193
222
  debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f0f');
194
223
  }
195
224
  }
@@ -198,8 +227,6 @@ class EngineObject
198
227
  // check collision against tiles
199
228
  if (tileCollisionTest(this.pos, this.size, this))
200
229
  {
201
- //debugPhysics && debugRect(this.pos, this.size, '#ff0');
202
-
203
230
  // if already was stuck in collision, don't do anything
204
231
  // this should not happen unless something starts in collision
205
232
  if (!tileCollisionTest(oldPos, this.size, this))
@@ -256,19 +283,19 @@ class EngineObject
256
283
 
257
284
  /** Called to check if a tile collision should be resolved
258
285
  * @param {Number} tileData - the value of the tile at the position
259
- * @param {Vector2} pos - tile where the collision occured
260
- * @return {Boolean} true if the collision should be resolved */
286
+ * @param {Vector2} pos - tile where the collision occured
287
+ * @return {Boolean} - true if the collision should be resolved */
261
288
  collideWithTile(tileData, pos) { return tileData > 0; }
262
289
 
263
290
  /** Called to check if a tile raycast hit
264
291
  * @param {Number} tileData - the value of the tile at the position
265
- * @param {Vector2} pos - tile where the raycast is
266
- * @return {Boolean} true if the raycast should hit */
292
+ * @param {Vector2} pos - tile where the raycast is
293
+ * @return {Boolean} - true if the raycast should hit */
267
294
  collideWithTileRaycast(tileData, pos) { return tileData > 0; }
268
295
 
269
296
  /** Called to check if a tile raycast hit
270
297
  * @param {EngineObject} object - the object to test against
271
- * @return {Boolean} true if the collision should be resolved
298
+ * @return {Boolean} - true if the collision should be resolved
272
299
  */
273
300
  collideWithObject(o) { return 1; }
274
301
 
@@ -312,24 +339,12 @@ class EngineObject
312
339
 
313
340
  /** Set how this object collides
314
341
  * @param {boolean} [collideSolidObjects=0] - Does it collide with solid objects
315
- * @param {boolean} [isSolid=0] - Does it collide with and block other objects (expensive in large numbers)
316
- * @param {boolean} [collideTiles=1] - Does it collide with the tile collision */
342
+ * @param {boolean} [isSolid=0] - Does it collide with and block other objects (expensive in large numbers)
343
+ * @param {boolean} [collideTiles=1] - Does it collide with the tile collision */
317
344
  setCollision(collideSolidObjects=0, isSolid=0, collideTiles=1)
318
345
  {
319
346
  ASSERT(collideSolidObjects || !isSolid); // solid objects must be set to collide
320
347
 
321
- // track collidable objects in separate list
322
- if (collideSolidObjects && !this.collideSolidObjects)
323
- {
324
- ASSERT(!engineCollideObjects.includes(this));
325
- engineCollideObjects.push(this);
326
- }
327
- else if (!collideSolidObjects && this.collideSolidObjects)
328
- {
329
- ASSERT(engineCollideObjects.includes(this))
330
- engineCollideObjects.splice(engineCollideObjects.indexOf(this), 1);
331
- }
332
-
333
348
  this.collideSolidObjects = collideSolidObjects;
334
349
  this.isSolid = isSolid;
335
350
  this.collideTiles = collideTiles;