littlejsengine 1.0.14 → 1.1.8
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/build.bat +5 -1
- package/docs/Audio.html +2268 -0
- package/docs/Color.html +2989 -0
- package/docs/Debug.html +2933 -0
- package/docs/Draw.html +4092 -0
- package/docs/EngineObject.html +4458 -0
- package/docs/Input.html +2482 -0
- package/docs/Medal.html +1007 -0
- package/docs/Medals.html +628 -0
- package/docs/Music.html +584 -0
- package/docs/Newgrounds.html +1399 -0
- package/docs/Particle.html +4535 -0
- package/docs/ParticleEmitter.html +7770 -0
- package/docs/Random.html +1774 -0
- package/docs/Settings.html +2679 -0
- package/docs/Sound.html +1249 -0
- package/docs/TileCollision.html +1409 -0
- package/docs/TileLayer.html +6948 -0
- package/docs/TileLayerData.html +1052 -0
- package/docs/Timer.html +1183 -0
- package/docs/Utilities.html +3281 -0
- package/docs/Vector2.html +4207 -0
- package/docs/WebGL.html +2327 -0
- package/docs/engine.js.html +429 -0
- package/docs/engineAudio.js.html +609 -0
- package/docs/engineDebug.js.html +725 -0
- package/docs/engineDraw.js.html +419 -0
- package/docs/engineInput.js.html +401 -0
- package/docs/engineMedals.js.html +461 -0
- package/docs/engineObject.js.html +518 -0
- package/docs/engineParticles.js.html +441 -0
- package/docs/engineSettings.js.html +349 -0
- package/docs/engineTileLayer.js.html +513 -0
- package/docs/engineUtilities.js.html +647 -0
- package/docs/engineWebGL.js.html +522 -0
- 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 +93 -0
- package/docs/fonts/OFL-montserrat.txt +93 -0
- package/docs/global.html +1691 -0
- package/docs/index.css +6 -0
- package/docs/index.html +247 -0
- package/docs/scripts/fix-code-block.js +53 -0
- package/docs/scripts/fix-navbar.js +25 -0
- package/docs/scripts/linenumber.js +25 -0
- package/docs/scripts/misc.js +217 -0
- package/docs/scripts/resize.js +85 -0
- package/docs/scripts/search.js +83 -0
- package/docs/scripts/third-party/Apache-License-2.0.txt +202 -0
- package/docs/scripts/third-party/fuse.js +9 -0
- package/docs/scripts/third-party/lang-css.js +2 -0
- package/docs/scripts/third-party/prettify.js +28 -0
- package/docs/static/favicon.png +0 -0
- package/docs/static/index.css +4 -0
- package/docs/styles/clean-jsdoc-theme-base.css +393 -0
- package/docs/styles/clean-jsdoc-theme-dark.css +324 -0
- package/docs/styles/clean-jsdoc-theme-light.css +319 -0
- package/docs/styles/reset.css +346 -0
- package/docs/styles/third-party/ionicons.min.css +11 -0
- package/docs/styles/third-party/prettify-jsdoc.css +111 -0
- package/docs/styles/third-party/prettify-tomorrow.css +5 -0
- package/engine/engine.all.js +1997 -744
- package/engine/engine.all.min.js +1 -1
- package/engine/engine.all.release.js +1743 -569
- package/engine/engine.js +107 -39
- package/engine/engineAudio.js +152 -34
- package/engine/{build.bat → engineBuild.bat} +10 -10
- package/engine/{buildSetup.bat → engineBuildSetup.bat} +0 -0
- package/engine/engineDebug.js +105 -32
- package/engine/engineDraw.js +137 -32
- package/engine/engineInput.js +111 -37
- package/engine/{engineMedal.js → engineMedals.js} +129 -56
- package/engine/engineObject.js +117 -67
- package/engine/engineParticles.js +282 -0
- package/engine/engineRelease.js +3 -9
- package/engine/engineSettings.js +190 -0
- package/engine/engineTileLayer.js +147 -44
- package/engine/engineUtilities.js +488 -0
- package/engine/engineWebGL.js +113 -74
- package/examples/breakout/game.js +1 -1
- package/examples/breakout/gameObjects.js +3 -3
- package/examples/breakout/index.html +3 -3
- package/examples/platformer/game.js +5 -7
- package/examples/platformer/gameEffects.js +7 -7
- package/examples/platformer/gameLevel.js +2 -2
- package/examples/platformer/gameObjects.js +4 -5
- package/examples/platformer/gamePlayer.js +3 -3
- package/examples/platformer/index.html +6 -6
- package/examples/puzzle/game.js +1 -2
- package/examples/puzzle/index.html +2 -2
- package/examples/stress/index.html +2 -8
- package/game.js +5 -11
- package/index.html +13 -13
- package/package.json +4 -4
- package/tiles.png +0 -0
- package/engine/engineConfig.js +0 -64
- package/engine/engineParticle.js +0 -199
- package/engine/engineUtil.js +0 -147
|
@@ -1,24 +1,61 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
7
|
+
*/
|
|
7
8
|
|
|
8
9
|
'use strict';
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
/** List of all medals
|
|
12
|
+
* @memberof Medals */
|
|
13
|
+
const medals = [];
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
/** Set to stop medals from being unlockable (like if cheats are enabled)
|
|
16
|
+
* @memberof Medals */
|
|
17
|
+
let medalsPreventUnlock;
|
|
18
|
+
|
|
19
|
+
/** This can used to enable Newgrounds functionality
|
|
20
|
+
* @type {Newgrounds}
|
|
21
|
+
* @memberof Medals */
|
|
22
|
+
let newgrounds;
|
|
23
|
+
|
|
24
|
+
// Engine internal variables not exposed to documentation
|
|
25
|
+
let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimer;
|
|
26
|
+
|
|
27
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
28
|
+
|
|
29
|
+
/** Initialize medals with a save name used for storage
|
|
30
|
+
* <br> - Checks if medals are unlocked
|
|
31
|
+
* <br> - Call this after creating all medals
|
|
32
|
+
* @param {String} saveName
|
|
33
|
+
* @memberof Medals */
|
|
34
|
+
function medalsInit(saveName)
|
|
14
35
|
{
|
|
15
36
|
// check if medals are unlocked
|
|
16
|
-
|
|
37
|
+
medalsSaveName = saveName;
|
|
17
38
|
debugMedals || medals.forEach(medal=> medal.unlocked = localStorage[medal.storageKey()]);
|
|
18
39
|
}
|
|
19
40
|
|
|
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
|
+
* // unlock the medal
|
|
48
|
+
* medal_example.unlock();
|
|
49
|
+
*/
|
|
20
50
|
class Medal
|
|
21
51
|
{
|
|
52
|
+
/** Create an medal object and adds it to the list of medals
|
|
53
|
+
* @param {Number} id - The unique identifier of the medal
|
|
54
|
+
* @param {String} name - Name of the medal
|
|
55
|
+
* @param {String} [description] - Description of the medal
|
|
56
|
+
* @param {String} [icon='🏆'] - Icon for the medal
|
|
57
|
+
* @param {String} [src] - Image location for the medal
|
|
58
|
+
*/
|
|
22
59
|
constructor(id, name, description='', icon='🏆', src)
|
|
23
60
|
{
|
|
24
61
|
ASSERT(id >= 0 && !medals[id]);
|
|
@@ -37,26 +74,25 @@ class Medal
|
|
|
37
74
|
}
|
|
38
75
|
}
|
|
39
76
|
|
|
77
|
+
/** Unlocks a medal if not already unlocked */
|
|
40
78
|
unlock()
|
|
41
79
|
{
|
|
42
80
|
if (medalsPreventUnlock || this.unlocked)
|
|
43
81
|
return;
|
|
44
82
|
|
|
45
83
|
// save the medal
|
|
46
|
-
ASSERT(
|
|
84
|
+
ASSERT(medalsSaveName); // game name must be set
|
|
47
85
|
localStorage[this.storageKey()] = this.unlocked = 1;
|
|
48
86
|
medalsDisplayQueue.push(this);
|
|
49
87
|
|
|
50
88
|
// save for newgrounds and OS13K
|
|
51
89
|
newgrounds && newgrounds.unlockMedal(this.id);
|
|
52
|
-
localStorage['OS13kTrophy,' + this.icon + ',' +
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
storageKey()
|
|
56
|
-
{
|
|
57
|
-
return medalsGameName + '_medal_' + this.id;
|
|
90
|
+
localStorage['OS13kTrophy,' + this.icon + ',' + medalsSaveName + ',' + this.name] = this.description;
|
|
58
91
|
}
|
|
59
92
|
|
|
93
|
+
/** Render a medal
|
|
94
|
+
* @param {Number} [hidePercent=0] - How much to slide the medal off screen
|
|
95
|
+
*/
|
|
60
96
|
render(hidePercent=0)
|
|
61
97
|
{
|
|
62
98
|
const context = overlayContext;
|
|
@@ -77,25 +113,36 @@ class Medal
|
|
|
77
113
|
|
|
78
114
|
// draw the text
|
|
79
115
|
context.textAlign = 'left';
|
|
80
|
-
context.font = '3em '+
|
|
116
|
+
context.font = '3em '+ fontDefault;
|
|
81
117
|
context.fillText(this.name, x+medalDisplayIconSize+25, y+35);
|
|
82
|
-
context.font = '1.5em '+
|
|
118
|
+
context.font = '1.5em '+ fontDefault;
|
|
83
119
|
context.restore(context.fillText(this.description, x+medalDisplayIconSize+25, y+70));
|
|
84
120
|
}
|
|
85
121
|
|
|
122
|
+
/** Render the icon for a medal
|
|
123
|
+
* @param {Number} x - Screen space X position
|
|
124
|
+
* @param {Number} y - Screen space Y position
|
|
125
|
+
* @param {Number} [size=medalDisplayIconSize] - Screen space size
|
|
126
|
+
*/
|
|
86
127
|
renderIcon(x, y, size=medalDisplayIconSize)
|
|
87
128
|
{
|
|
88
129
|
// draw the image or icon
|
|
89
130
|
const context = overlayContext;
|
|
90
131
|
context.textAlign = 'center';
|
|
91
132
|
context.textBaseline = 'middle';
|
|
92
|
-
context.font = size*.6 + 'px '+
|
|
133
|
+
context.font = size*.6 + 'px '+ fontDefault;
|
|
93
134
|
context.fillStyle = '#000';
|
|
94
135
|
if (this.image)
|
|
95
136
|
context.drawImage(this.image, x-size/2, y-size/2, size, size);
|
|
96
137
|
else
|
|
97
138
|
context.fillText(this.icon, x, y); // show icon if there is no image
|
|
98
139
|
}
|
|
140
|
+
|
|
141
|
+
// Get local storage key used by the medal
|
|
142
|
+
storageKey()
|
|
143
|
+
{
|
|
144
|
+
return medalsSaveName + '_medal_' + this.id;
|
|
145
|
+
}
|
|
99
146
|
}
|
|
100
147
|
|
|
101
148
|
// engine automatically renders medals
|
|
@@ -106,9 +153,9 @@ function medalsRender()
|
|
|
106
153
|
|
|
107
154
|
// update first medal in queue
|
|
108
155
|
const medal = medalsDisplayQueue[0];
|
|
109
|
-
const time =
|
|
156
|
+
const time = timeReal - medalsDisplayTimer;
|
|
110
157
|
if (!medalsDisplayTimer)
|
|
111
|
-
medalsDisplayTimer =
|
|
158
|
+
medalsDisplayTimer = timeReal;
|
|
112
159
|
else if (time > medalDisplayTime)
|
|
113
160
|
medalsDisplayQueue.shift(medalsDisplayTimer = 0);
|
|
114
161
|
else
|
|
@@ -123,15 +170,26 @@ function medalsRender()
|
|
|
123
170
|
}
|
|
124
171
|
|
|
125
172
|
///////////////////////////////////////////////////////////////////////////////
|
|
126
|
-
// Newgrounds API wrapper
|
|
127
173
|
|
|
174
|
+
/**
|
|
175
|
+
* Newgrounds API wrapper object
|
|
176
|
+
* @example
|
|
177
|
+
* // create a newgrounds object, replace the app id and cipher with your own
|
|
178
|
+
* const app_id = '53123:1ZuSTQ9l';
|
|
179
|
+
* const cipher = 'enF0vGH@Mj/FRASKL23Q==';
|
|
180
|
+
* newgrounds = new Newgrounds(app_id, cipher);
|
|
181
|
+
*/
|
|
128
182
|
class Newgrounds
|
|
129
183
|
{
|
|
184
|
+
/** Create a newgrounds object
|
|
185
|
+
* @param {Number} app_id - The newgrounds App ID
|
|
186
|
+
* @param {String} [cipher] - The encryption Key (AES-128/Base64) */
|
|
130
187
|
constructor(app_id, cipher)
|
|
131
188
|
{
|
|
132
189
|
ASSERT(!newgrounds && app_id);
|
|
133
190
|
this.app_id = app_id;
|
|
134
191
|
this.cipher = cipher;
|
|
192
|
+
this.host = location ? location.hostname : '';
|
|
135
193
|
|
|
136
194
|
// create an instance of CryptoJS for encrypted calls
|
|
137
195
|
cipher && (this.cryptoJS = CryptoJS());
|
|
@@ -153,11 +211,16 @@ class Newgrounds
|
|
|
153
211
|
if (medal)
|
|
154
212
|
{
|
|
155
213
|
// copy newgrounds medal data
|
|
156
|
-
medal.
|
|
214
|
+
medal.image = new Image();
|
|
215
|
+
medal.image.src = newgroundsMedal['icon'];
|
|
216
|
+
medal.name = newgroundsMedal['name'];
|
|
157
217
|
medal.description = newgroundsMedal['description'];
|
|
158
|
-
medal.unlocked =
|
|
159
|
-
medal.
|
|
160
|
-
medal.
|
|
218
|
+
medal.unlocked = newgroundsMedal['unlocked'];
|
|
219
|
+
medal.difficulty = newgroundsMedal['difficulty'];
|
|
220
|
+
medal.value = newgroundsMedal['value'];
|
|
221
|
+
|
|
222
|
+
if (medal.value)
|
|
223
|
+
medal.description = medal.description + ' (' + medal.value + ')';
|
|
161
224
|
}
|
|
162
225
|
}
|
|
163
226
|
|
|
@@ -167,30 +230,55 @@ class Newgrounds
|
|
|
167
230
|
debugMedals && console.log(this.scoreboards);
|
|
168
231
|
}
|
|
169
232
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
233
|
+
/** Send message to unlock a medal by id
|
|
234
|
+
* @param {Number} id - The medal id */
|
|
235
|
+
unlockMedal(id) { return this.call('Medal.unlock', {'id':id}, 1); }
|
|
174
236
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
237
|
+
/** Send message to post score
|
|
238
|
+
* @param {Number} id - The scoreboard id
|
|
239
|
+
* @param {Number} value - The score value */
|
|
240
|
+
postScore(id, value) { return this.call('ScoreBoard.postScore', {'id':id, 'value':value}, 1); }
|
|
241
|
+
|
|
242
|
+
/** Send message to log a view */
|
|
243
|
+
logView() { return this.call('App.logView', {'host':this.host}, 1); }
|
|
179
244
|
|
|
245
|
+
/** Get scores from a scoreboard
|
|
246
|
+
* @param {Number} id - The scoreboard id
|
|
247
|
+
* @param {String} [user=0] - A user's id or name
|
|
248
|
+
* @param {Number} [social=0] - If true, only social scores will be loaded
|
|
249
|
+
* @param {Number} [skip=0] - Number of scores to skip before start
|
|
250
|
+
* @param {Number} [limit=10] - Number of scores to include in the list
|
|
251
|
+
* @return {Object} - The response JSON object
|
|
252
|
+
*/
|
|
180
253
|
getScores(id, user=0, social=0, skip=0, limit=10)
|
|
181
|
-
{
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
254
|
+
{ return this.call('ScoreBoard.getScores', {'id':id, 'user':user, 'social':social, 'skip':skip, 'limit':limit}); }
|
|
255
|
+
|
|
256
|
+
/** Send a message to call a component of the Newgrounds API
|
|
257
|
+
* @param {String} component - Name of the component
|
|
258
|
+
* @param {Object} [parameters=0] - Parameters to use for call
|
|
259
|
+
* @param {Boolean} [async=0] - If true, wait for response before continuing (will cause stall)
|
|
260
|
+
* @return {Object} - The response JSON object
|
|
261
|
+
*/
|
|
186
262
|
call(component, parameters=0, async=0)
|
|
187
263
|
{
|
|
264
|
+
const call = {'component':component, 'parameters':parameters};
|
|
265
|
+
if (this.cipher)
|
|
266
|
+
{
|
|
267
|
+
// encrypt using AES-128 Base64 with cryptoJS
|
|
268
|
+
const cryptoJS = this.cryptoJS;
|
|
269
|
+
const aesKey = cryptoJS['enc']['Base64']['parse'](this.cipher);
|
|
270
|
+
const iv = cryptoJS['lib']['WordArray']['random'](16);
|
|
271
|
+
const encrypted = cryptoJS['AES']['encrypt'](JSON.stringify(call), aesKey, {'iv':iv});
|
|
272
|
+
call['secure'] = cryptoJS['enc']['Base64']['stringify'](iv.concat(encrypted['ciphertext']));
|
|
273
|
+
call['parameters'] = 0;
|
|
274
|
+
}
|
|
275
|
+
|
|
188
276
|
// build the input object
|
|
189
277
|
const input =
|
|
190
278
|
{
|
|
191
279
|
'app_id': this.app_id,
|
|
192
280
|
'session_id': this.session_id,
|
|
193
|
-
'call':
|
|
281
|
+
'call': call
|
|
194
282
|
};
|
|
195
283
|
|
|
196
284
|
// build post data
|
|
@@ -205,21 +293,6 @@ class Newgrounds
|
|
|
205
293
|
debugMedals && console.log(xmlHttp.responseText);
|
|
206
294
|
return xmlHttp.responseText && JSON.parse(xmlHttp.responseText);
|
|
207
295
|
}
|
|
208
|
-
|
|
209
|
-
encryptCall(call)
|
|
210
|
-
{
|
|
211
|
-
if (!this.cipher)
|
|
212
|
-
return call;
|
|
213
|
-
|
|
214
|
-
// encrypt using AES-128 Base64 with cryptoJS
|
|
215
|
-
const cryptoJS = this.cryptoJS;
|
|
216
|
-
const aesKey = cryptoJS['enc']['Base64']['parse'](this.cipher);
|
|
217
|
-
const iv = cryptoJS['lib']['WordArray']['random'](16);
|
|
218
|
-
const encrypted = cryptoJS['AES']['encrypt'](JSON.stringify(call), aesKey, {'iv':iv});
|
|
219
|
-
call['secure'] = cryptoJS['enc']['Base64']['stringify'](iv.concat(encrypted['ciphertext']));
|
|
220
|
-
call['parameters'] = 0;
|
|
221
|
-
return call;
|
|
222
|
-
}
|
|
223
296
|
}
|
|
224
297
|
|
|
225
298
|
///////////////////////////////////////////////////////////////////////////////
|
package/engine/engineObject.js
CHANGED
|
@@ -1,49 +1,86 @@
|
|
|
1
1
|
/*
|
|
2
|
-
LittleJS Object
|
|
3
|
-
- Base object class used by the engine
|
|
4
|
-
- Automatically adds self to object list
|
|
5
|
-
- Will be updated and rendered each frame
|
|
6
|
-
- Renders as a sprite from a tilesheet by default
|
|
7
|
-
- Can have color and addtive color applied
|
|
8
|
-
- 2d Physics and collision system
|
|
9
|
-
- Sorted by renderOrder
|
|
10
|
-
- Objects can have children attached
|
|
11
|
-
- Parents are updated before children, and set child transform
|
|
12
|
-
- Call destroy() to get rid of objects
|
|
2
|
+
LittleJS Object System
|
|
13
3
|
*/
|
|
14
4
|
|
|
15
5
|
'use strict';
|
|
16
6
|
|
|
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
|
|
19
|
+
* @example
|
|
20
|
+
* // create an engine object, normally you would first extend the class with your own
|
|
21
|
+
* const pos = vec2(2,3);
|
|
22
|
+
* const object = new EngineObject(pos);
|
|
23
|
+
*/
|
|
17
24
|
class EngineObject
|
|
18
25
|
{
|
|
19
|
-
|
|
26
|
+
/** Create an engine object and adds it to the list of objects
|
|
27
|
+
* @param {Vector2} [position=new Vector2(0,0)] - World space position of the object
|
|
28
|
+
* @param {Vector2} [size=objectDefaultSize] - World space size of the object
|
|
29
|
+
* @param {Number} [tileIndex=-1] - Tile to use to render object, untextured if -1
|
|
30
|
+
* @param {Vector2} [tileSize=tileSizeDefault] - Size of tile in source pixels
|
|
31
|
+
* @param {Number} [angle=0] - Angle to rotate the object
|
|
32
|
+
* @param {Color} [color] - Color to apply to tile when rendered
|
|
33
|
+
* @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
|
|
34
|
+
*/
|
|
35
|
+
constructor(pos=vec2(), size=objectDefaultSize, tileIndex=-1, tileSize=tileSizeDefault, angle=0, color, renderOrder=0)
|
|
20
36
|
{
|
|
21
37
|
// set passed in params
|
|
22
38
|
ASSERT(pos && pos.x != undefined && size.x != undefined); // ensure pos and size are vec2s
|
|
39
|
+
|
|
40
|
+
/** @property {Vector2} - World space position of the object */
|
|
23
41
|
this.pos = pos.copy();
|
|
42
|
+
/** @property {Vector2} - World space width and height of the object */
|
|
24
43
|
this.size = size;
|
|
44
|
+
/** @property {Vector2} - Size of object used for drawing, uses size if not set */
|
|
45
|
+
this.drawSize;
|
|
46
|
+
/** @property {Number} - Tile to use to render object, untextured if -1 */
|
|
25
47
|
this.tileIndex = tileIndex;
|
|
48
|
+
/** @property {Vector2} - Size of tile in source pixels */
|
|
26
49
|
this.tileSize = tileSize;
|
|
50
|
+
/** @property {Number} - Angle to rotate the object */
|
|
27
51
|
this.angle = angle;
|
|
52
|
+
/** @property {Color} - Color to apply when rendered */
|
|
28
53
|
this.color = color;
|
|
54
|
+
/** @property {Color} - Additive color to apply when rendered */
|
|
55
|
+
this.additiveColor;
|
|
29
56
|
|
|
30
|
-
// set
|
|
31
|
-
|
|
32
|
-
this.
|
|
33
|
-
|
|
34
|
-
this.
|
|
35
|
-
|
|
57
|
+
// set object defaults
|
|
58
|
+
/** @property {Number} [mass=objectDefaultMass] - How heavy the object is */
|
|
59
|
+
this.mass = objectDefaultMass;
|
|
60
|
+
/** @property {Number} [damping=objectDefaultDamping] - How much to slow down velocity each frame (0-1) */
|
|
61
|
+
this.damping = objectDefaultDamping;
|
|
62
|
+
/** @property {Number} [angleDamping=objectDefaultAngleDamping] - How much to slow down rotation each frame (0-1) */
|
|
63
|
+
this.angleDamping = objectDefaultAngleDamping;
|
|
64
|
+
/** @property {Number} [elasticity=objectDefaultElasticity] - How bouncy the object is when colliding (0-1) */
|
|
65
|
+
this.elasticity = objectDefaultElasticity;
|
|
66
|
+
/** @property {Number} [friction=objectDefaultFriction] - How much friction to apply when sliding (0-1) */
|
|
67
|
+
this.friction = objectDefaultFriction;
|
|
68
|
+
/** @property {Number} [gravityScale=1] - How much to scale gravity by for this object */
|
|
69
|
+
this.gravityScale = 1;
|
|
70
|
+
/** @property {Number} [renderOrder=0] - Objects are sorted by render order */
|
|
71
|
+
this.renderOrder = renderOrder;
|
|
36
72
|
|
|
37
|
-
// init other object stuff
|
|
73
|
+
// init other internal object stuff
|
|
38
74
|
this.spawnTime = time;
|
|
39
|
-
this.velocity = vec2(this.collideSolidObjects = this.
|
|
40
|
-
this.collideTiles =
|
|
75
|
+
this.velocity = vec2(this.collideSolidObjects = this.angleVelocity = 0);
|
|
76
|
+
this.collideTiles = 1;
|
|
41
77
|
this.children = [];
|
|
42
78
|
|
|
43
79
|
// add to list of objects
|
|
44
80
|
engineObjects.push(this);
|
|
45
81
|
}
|
|
46
82
|
|
|
83
|
+
/** Update the object transform and physics, called automatically by engine once each frame */
|
|
47
84
|
update()
|
|
48
85
|
{
|
|
49
86
|
const parent = this.parent;
|
|
@@ -56,8 +93,8 @@ class EngineObject
|
|
|
56
93
|
}
|
|
57
94
|
|
|
58
95
|
// limit max speed to prevent missing collisions
|
|
59
|
-
this.velocity.x = clamp(this.velocity.x,
|
|
60
|
-
this.velocity.y = clamp(this.velocity.y,
|
|
96
|
+
this.velocity.x = clamp(this.velocity.x, objectMaxSpeed, -objectMaxSpeed);
|
|
97
|
+
this.velocity.y = clamp(this.velocity.y, objectMaxSpeed, -objectMaxSpeed);
|
|
61
98
|
|
|
62
99
|
// apply physics
|
|
63
100
|
const oldPos = this.pos.copy();
|
|
@@ -111,7 +148,7 @@ class EngineObject
|
|
|
111
148
|
if (o.mass) // push away if not fixed
|
|
112
149
|
o.velocity = o.velocity.subtract(velocity);
|
|
113
150
|
|
|
114
|
-
debugPhysics && debugAABB(this.pos,
|
|
151
|
+
debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f00');
|
|
115
152
|
continue;
|
|
116
153
|
}
|
|
117
154
|
|
|
@@ -177,7 +214,7 @@ class EngineObject
|
|
|
177
214
|
this.velocity.x *= -this.elasticity;
|
|
178
215
|
}
|
|
179
216
|
|
|
180
|
-
debugPhysics && debugAABB(this.pos,
|
|
217
|
+
debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f0f');
|
|
181
218
|
}
|
|
182
219
|
}
|
|
183
220
|
if (this.collideTiles)
|
|
@@ -185,8 +222,6 @@ class EngineObject
|
|
|
185
222
|
// check collision against tiles
|
|
186
223
|
if (tileCollisionTest(this.pos, this.size, this))
|
|
187
224
|
{
|
|
188
|
-
//debugPhysics && debugRect(this.pos, this.size, '#ff0');
|
|
189
|
-
|
|
190
225
|
// if already was stuck in collision, don't do anything
|
|
191
226
|
// this should not happen unless something starts in collision
|
|
192
227
|
if (!tileCollisionTest(oldPos, this.size, this))
|
|
@@ -199,13 +234,20 @@ class EngineObject
|
|
|
199
234
|
// set if landed on ground
|
|
200
235
|
this.groundObject = wasMovingDown;
|
|
201
236
|
|
|
202
|
-
//
|
|
203
|
-
this.pos.y = oldPos.y;
|
|
237
|
+
// bounce velocity
|
|
204
238
|
this.velocity.y *= -this.elasticity;
|
|
239
|
+
|
|
240
|
+
// adjust next velocity to settle on ground
|
|
241
|
+
const o = (oldPos.y - this.size.y/2|0) - (oldPos.y - this.size.y/2);
|
|
242
|
+
if (o < 0 && o > -1 && o > this.damping * this.velocity.y + gravity * this.gravityScale)
|
|
243
|
+
this.velocity.y = this.damping ? (o - gravity * this.gravityScale) / this.damping : 0;
|
|
244
|
+
|
|
245
|
+
// move to previous position
|
|
246
|
+
this.pos.y = oldPos.y;
|
|
205
247
|
}
|
|
206
248
|
if (isBlockedX)
|
|
207
249
|
{
|
|
208
|
-
//
|
|
250
|
+
// move to previous position and bounce
|
|
209
251
|
this.pos.x = oldPos.x;
|
|
210
252
|
this.velocity.x *= -this.elasticity;
|
|
211
253
|
}
|
|
@@ -214,12 +256,14 @@ class EngineObject
|
|
|
214
256
|
}
|
|
215
257
|
}
|
|
216
258
|
|
|
259
|
+
/** Render the object, draws a tile by default, automatically called each frame, sorted by renderOrder */
|
|
217
260
|
render()
|
|
218
261
|
{
|
|
219
262
|
// default object render
|
|
220
263
|
drawTile(this.pos, this.drawSize || this.size, this.tileIndex, this.tileSize, this.color, this.angle, this.mirror, this.additiveColor);
|
|
221
264
|
}
|
|
222
265
|
|
|
266
|
+
/** Destroy this object, destroy it's children, detach it's parent, and mark it for removal */
|
|
223
267
|
destroy()
|
|
224
268
|
{
|
|
225
269
|
if (this.destroyed)
|
|
@@ -231,15 +275,45 @@ class EngineObject
|
|
|
231
275
|
for (const child of this.children)
|
|
232
276
|
child.destroy(child.parent = 0);
|
|
233
277
|
}
|
|
234
|
-
|
|
235
|
-
|
|
278
|
+
|
|
279
|
+
/** Called to check if a tile collision should be resolved
|
|
280
|
+
* @param {Number} tileData - the value of the tile at the position
|
|
281
|
+
* @param {Vector2} pos - tile where the collision occured
|
|
282
|
+
* @return {Boolean} true if the collision should be resolved */
|
|
283
|
+
collideWithTile(tileData, pos) { return tileData > 0; }
|
|
284
|
+
|
|
285
|
+
/** Called to check if a tile raycast hit
|
|
286
|
+
* @param {Number} tileData - the value of the tile at the position
|
|
287
|
+
* @param {Vector2} pos - tile where the raycast is
|
|
288
|
+
* @return {Boolean} true if the raycast should hit */
|
|
289
|
+
collideWithTileRaycast(tileData, pos) { return tileData > 0; }
|
|
290
|
+
|
|
291
|
+
/** Called to check if a tile raycast hit
|
|
292
|
+
* @param {EngineObject} object - the object to test against
|
|
293
|
+
* @return {Boolean} true if the collision should be resolved
|
|
294
|
+
*/
|
|
236
295
|
collideWithObject(o) { return 1; }
|
|
296
|
+
|
|
297
|
+
/** How long since the object was created
|
|
298
|
+
* @return {Number} */
|
|
237
299
|
getAliveTime() { return time - this.spawnTime; }
|
|
238
|
-
|
|
300
|
+
|
|
301
|
+
/** Apply acceleration to this object (adjust velocity, not affected by mass)
|
|
302
|
+
* @param {Vector2} acceleration */
|
|
303
|
+
applyAcceleration(a) { if (this.mass) this.velocity = this.velocity.add(a); }
|
|
304
|
+
|
|
305
|
+
/** Apply force to this object (adjust velocity, affected by mass)
|
|
306
|
+
* @param {Vector2} force */
|
|
239
307
|
applyForce(force) { this.applyAcceleration(force.scale(1/this.mass)); }
|
|
240
|
-
|
|
241
|
-
|
|
308
|
+
|
|
309
|
+
/** Get the direction of the mirror
|
|
310
|
+
* @return {Number} -1 if this.mirror is true, or 1 if not mirrored */
|
|
311
|
+
getMirrorSign() { return this.mirror ? -1 : 1; }
|
|
242
312
|
|
|
313
|
+
/** Attaches a child to this with a given local transform
|
|
314
|
+
* @param {EngineObject} child
|
|
315
|
+
* @param {Vector2} [localPos=new Vector2]
|
|
316
|
+
* @param {Number} [localAngle=0] */
|
|
243
317
|
addChild(child, localPos=vec2(), localAngle=0)
|
|
244
318
|
{
|
|
245
319
|
ASSERT(!child.parent && !this.children.includes(child));
|
|
@@ -248,6 +322,9 @@ class EngineObject
|
|
|
248
322
|
child.localPos = localPos.copy();
|
|
249
323
|
child.localAngle = localAngle;
|
|
250
324
|
}
|
|
325
|
+
|
|
326
|
+
/** Removes a child from this one
|
|
327
|
+
* @param {EngineObject} child */
|
|
251
328
|
removeChild(child)
|
|
252
329
|
{
|
|
253
330
|
ASSERT(child.parent == this && this.children.includes(child));
|
|
@@ -255,7 +332,11 @@ class EngineObject
|
|
|
255
332
|
child.parent = 0;
|
|
256
333
|
}
|
|
257
334
|
|
|
258
|
-
|
|
335
|
+
/** Set how this object collides
|
|
336
|
+
* @param {boolean} [collideSolidObjects=0] - Does it collide with solid objects
|
|
337
|
+
* @param {boolean} [isSolid=0] - Does it collide with and block other objects (expensive in large numbers)
|
|
338
|
+
* @param {boolean} [collideTiles=1] - Does it collide with the tile collision */
|
|
339
|
+
setCollision(collideSolidObjects=0, isSolid=0, collideTiles=1)
|
|
259
340
|
{
|
|
260
341
|
ASSERT(collideSolidObjects || !isSolid); // solid objects must be set to collide
|
|
261
342
|
|
|
@@ -275,35 +356,4 @@ class EngineObject
|
|
|
275
356
|
this.isSolid = isSolid;
|
|
276
357
|
this.collideTiles = collideTiles;
|
|
277
358
|
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function destroyAllObjects()
|
|
281
|
-
{
|
|
282
|
-
// remove all objects that are not persistent or are descendants of something persistent
|
|
283
|
-
for (const o of engineObjects)
|
|
284
|
-
o.persistent || o.parent || o.destroy();
|
|
285
|
-
engineObjects = engineObjects.filter(o=>!o.destroyed);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function forEachObject(pos, size, callbackFunction, objects=engineObjects)
|
|
289
|
-
{
|
|
290
|
-
if (!pos)
|
|
291
|
-
{
|
|
292
|
-
// all objects
|
|
293
|
-
for (const o of objects)
|
|
294
|
-
callbackFunction(o);
|
|
295
|
-
}
|
|
296
|
-
else if (size.x != undefined)
|
|
297
|
-
{
|
|
298
|
-
// aabb test
|
|
299
|
-
for (const o of objects)
|
|
300
|
-
isOverlapping(pos, size, o.pos, o.size) && callbackFunction(o);
|
|
301
|
-
}
|
|
302
|
-
else
|
|
303
|
-
{
|
|
304
|
-
// circle test
|
|
305
|
-
const sizeSquared = size*size;
|
|
306
|
-
for (const o of objects)
|
|
307
|
-
pos.distanceSquared(o.pos) < sizeSquared && callbackFunction(o);
|
|
308
|
-
}
|
|
309
359
|
}
|