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.
- package/README.md +55 -0
- package/build.bat +2 -1
- package/engine/engine.all.js +1320 -930
- package/engine/engine.all.min.js +1 -1
- package/engine/engine.all.release.js +965 -601
- package/engine/engine.js +71 -60
- package/engine/engineAudio.js +80 -22
- package/engine/engineBuild.bat +2 -2
- package/engine/engineDebug.js +65 -36
- package/engine/engineDraw.js +71 -56
- package/engine/engineInput.js +178 -28
- package/engine/engineMedals.js +66 -58
- package/engine/engineObject.js +86 -71
- package/engine/engineParticles.js +101 -63
- package/engine/engineRelease.js +4 -1
- package/engine/engineSettings.js +62 -53
- package/engine/engineTileLayer.js +99 -83
- package/engine/engineUtilities.js +95 -59
- package/engine/engineWebGL.js +53 -48
- package/examples/breakout/game.js +1 -1
- package/examples/breakout/gameObjects.js +2 -2
- package/examples/breakout/index.html +7 -5
- package/examples/platformer/game.js +7 -4
- package/examples/platformer/gameEffects.js +8 -11
- package/examples/platformer/gameLevel.js +15 -8
- package/examples/platformer/gameObjects.js +2 -2
- package/examples/platformer/gamePlayer.js +6 -6
- package/examples/platformer/index.html +10 -8
- package/examples/puzzle/game.js +3 -3
- package/examples/puzzle/index.html +6 -4
- package/examples/stress/index.html +7 -5
- package/game.js +10 -10
- package/index.html +17 -15
- package/package.json +4 -7
- package/tiles.png +0 -0
- package/LittleJS.zip +0 -0
- package/docs/Audio.html +0 -2264
- package/docs/Color.html +0 -2506
- package/docs/Debug.html +0 -2929
- package/docs/Draw.html +0 -3854
- package/docs/EngineObject.html +0 -2506
- package/docs/Input.html +0 -2478
- package/docs/Medal.html +0 -992
- package/docs/Medals.html +0 -624
- package/docs/Music.html +0 -569
- package/docs/Newgrounds.html +0 -1384
- package/docs/Particle.html +0 -567
- package/docs/ParticleEmitter.html +0 -1537
- package/docs/Random.html +0 -1770
- package/docs/Settings.html +0 -2885
- package/docs/Sound.html +0 -998
- package/docs/TileLayer.html +0 -3211
- package/docs/TileLayerData.html +0 -569
- package/docs/Timer.html +0 -1168
- package/docs/Utilities.html +0 -3266
- package/docs/Vector2.html +0 -3956
- package/docs/WebGL.html +0 -1842
- package/docs/engine.js.html +0 -428
- package/docs/engineAudio.js.html +0 -567
- package/docs/engineDebug.js.html +0 -721
- package/docs/engineDraw.js.html +0 -409
- package/docs/engineInput.js.html +0 -397
- package/docs/engineMedals.js.html +0 -445
- package/docs/engineObject.js.html +0 -492
- package/docs/engineParticles.js.html +0 -399
- package/docs/engineSettings.js.html +0 -358
- package/docs/engineTileLayer.js.html +0 -482
- package/docs/engineUtilities.js.html +0 -600
- package/docs/engineWebGL.js.html +0 -507
- package/docs/fonts/MavenPro-Regular.ttf +0 -0
- package/docs/fonts/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Muli-Black.ttf +0 -0
- package/docs/fonts/OFL-hind.txt +0 -93
- package/docs/fonts/OFL-montserrat.txt +0 -93
- package/docs/global.html +0 -1635
- package/docs/index.html +0 -243
- package/docs/scripts/fix-code-block.js +0 -53
- package/docs/scripts/fix-navbar.js +0 -25
- package/docs/scripts/linenumber.js +0 -25
- package/docs/scripts/misc.js +0 -217
- package/docs/scripts/resize.js +0 -85
- package/docs/scripts/search.js +0 -83
- package/docs/scripts/third-party/Apache-License-2.0.txt +0 -202
- package/docs/scripts/third-party/fuse.js +0 -9
- package/docs/scripts/third-party/lang-css.js +0 -2
- package/docs/scripts/third-party/prettify.js +0 -28
- package/docs/static/favicon.png +0 -0
- package/docs/styles/clean-jsdoc-theme-base.css +0 -393
- package/docs/styles/clean-jsdoc-theme-dark.css +0 -324
- package/docs/styles/clean-jsdoc-theme-light.css +0 -319
- package/docs/styles/reset.css +0 -346
- package/docs/styles/third-party/ionicons.min.css +0 -11
- package/docs/styles/third-party/prettify-jsdoc.css +0 -111
- package/docs/styles/third-party/prettify-tomorrow.css +0 -5
package/engine/engineMedals.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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,
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
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); //
|
|
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
|
|
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,
|
|
100
|
-
context.strokeStyle =
|
|
101
|
-
context.lineWidth =
|
|
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 = '
|
|
110
|
-
context.fillText(this.name, x+medalDisplayIconSize+
|
|
111
|
-
context.font = '
|
|
112
|
-
context.
|
|
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*.
|
|
127
|
-
|
|
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 -
|
|
150
|
-
if (!
|
|
151
|
-
|
|
153
|
+
const time = timeReal - medalsDisplayTimeLast;
|
|
154
|
+
if (!medalsDisplayTimeLast)
|
|
155
|
+
medalsDisplayTimeLast = timeReal;
|
|
152
156
|
else if (time > medalDisplayTime)
|
|
153
|
-
medalsDisplayQueue.shift(
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
172
|
-
*
|
|
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
|
|
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
|
|
235
|
-
* @param {String} [user=0]
|
|
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]
|
|
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}
|
|
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
|
|
253
|
+
* @param {String} component - Name of the component
|
|
246
254
|
* @param {Object} [parameters=0] - Parameters to use for call
|
|
247
|
-
* @param {Boolean} [async=0]
|
|
248
|
-
* @return {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
|
{
|
package/engine/engineObject.js
CHANGED
|
@@ -5,51 +5,83 @@
|
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
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
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
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=
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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.
|
|
52
|
-
this.collideTiles =
|
|
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,
|
|
73
|
-
this.velocity.y = clamp(this.velocity.y,
|
|
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
|
|
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)
|
|
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
|
|
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
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
const
|
|
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 + (
|
|
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,
|
|
165
|
-
o.velocity.y = lerp(elasticity,
|
|
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 + (
|
|
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,
|
|
187
|
-
o.velocity.x = lerp(elasticity,
|
|
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
|
|
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
|
|
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]
|
|
316
|
-
* @param {boolean} [collideTiles=1]
|
|
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;
|