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.
- package/README.md +17 -17
- package/build/littlejs.d.ts +352 -288
- package/build/littlejs.esm.js +695 -658
- package/build/littlejs.esm.min.js +1 -1
- package/build/littlejs.js +694 -658
- package/build/littlejs.min.js +1 -1
- package/build/littlejs.release.js +629 -594
- package/examples/breakout/game.js +4 -4
- package/examples/breakout/index.html +3 -3
- package/examples/breakoutTutorial/index.html +2 -2
- package/examples/electron/game.js +1 -1
- package/examples/electron/index.html +2 -2
- package/examples/favicon.png +0 -0
- package/examples/js13k/build.js +1 -1
- package/examples/js13k/index.html +13 -13
- package/examples/module/game.js +1 -1
- package/examples/module/index.html +1 -1
- package/examples/particles/index.html +1 -1
- package/examples/platformer/game.js +6 -6
- package/examples/platformer/gameCharacter.js +293 -0
- package/examples/platformer/gameEffects.js +8 -5
- package/examples/platformer/gameObjects.js +13 -13
- package/examples/platformer/gamePlayer.js +9 -293
- package/examples/platformer/index.html +7 -6
- package/examples/puzzle/game.js +3 -2
- package/examples/puzzle/index.html +2 -2
- package/examples/starter/build.js +1 -1
- package/examples/starter/game.js +2 -2
- package/examples/starter/index.html +13 -13
- package/examples/stress/index.html +35 -27
- package/examples/typescript/index.html +1 -1
- package/index.d.ts +2094 -0
- package/package.json +1 -1
- package/src/engine.js +28 -28
- package/src/engineAudio.js +57 -57
- package/src/engineDebug.js +66 -65
- package/src/engineDraw.js +64 -73
- package/src/engineExport.js +1 -0
- package/src/engineInput.js +57 -40
- package/src/engineMedals.js +32 -29
- package/src/engineObject.js +42 -27
- package/src/engineParticles.js +98 -72
- package/src/engineRelease.js +1 -1
- package/src/engineSettings.js +22 -22
- package/src/engineTileLayer.js +66 -60
- package/src/engineUtilities.js +49 -49
- package/src/engineWebGL.js +112 -135
- package/src/jsconfig.json +10 -0
package/src/engineInput.js
CHANGED
|
@@ -10,28 +10,37 @@
|
|
|
10
10
|
'use strict';
|
|
11
11
|
|
|
12
12
|
/** Returns true if device key is down
|
|
13
|
-
* @param {Number} key
|
|
14
|
-
* @param {Number} [device
|
|
13
|
+
* @param {String|Number} key
|
|
14
|
+
* @param {Number} [device]
|
|
15
15
|
* @return {Boolean}
|
|
16
16
|
* @memberof Input */
|
|
17
17
|
function keyIsDown(key, device=0)
|
|
18
|
-
{
|
|
18
|
+
{
|
|
19
|
+
ASSERT(device > 0 || typeof key !== 'number' || key < 3, 'use code string for keyboard');
|
|
20
|
+
return inputData[device] && !!(inputData[device][key] & 1);
|
|
21
|
+
}
|
|
19
22
|
|
|
20
23
|
/** Returns true if device key was pressed this frame
|
|
21
|
-
* @param {Number} key
|
|
22
|
-
* @param {Number} [device
|
|
24
|
+
* @param {String|Number} key
|
|
25
|
+
* @param {Number} [device]
|
|
23
26
|
* @return {Boolean}
|
|
24
27
|
* @memberof Input */
|
|
25
28
|
function keyWasPressed(key, device=0)
|
|
26
|
-
{
|
|
29
|
+
{
|
|
30
|
+
ASSERT(device > 0 || typeof key !== 'number' || key < 3, 'use code string for keyboard');
|
|
31
|
+
return inputData[device] && !!(inputData[device][key] & 2);
|
|
32
|
+
}
|
|
27
33
|
|
|
28
34
|
/** Returns true if device key was released this frame
|
|
29
|
-
* @param {Number} key
|
|
30
|
-
* @param {Number} [device
|
|
35
|
+
* @param {String|Number} key
|
|
36
|
+
* @param {Number} [device]
|
|
31
37
|
* @return {Boolean}
|
|
32
38
|
* @memberof Input */
|
|
33
39
|
function keyWasReleased(key, device=0)
|
|
34
|
-
{
|
|
40
|
+
{
|
|
41
|
+
ASSERT(device > 0 || typeof key !== 'number' || key < 3, 'use code string for keyboard');
|
|
42
|
+
return inputData[device] && !!(inputData[device][key] & 4);
|
|
43
|
+
}
|
|
35
44
|
|
|
36
45
|
/** Clears all input
|
|
37
46
|
* @memberof Input */
|
|
@@ -76,16 +85,16 @@ let mouseWheel = 0;
|
|
|
76
85
|
/** Returns true if user is using gamepad (has more recently pressed a gamepad button)
|
|
77
86
|
* @type {Boolean}
|
|
78
87
|
* @memberof Input */
|
|
79
|
-
let isUsingGamepad =
|
|
88
|
+
let isUsingGamepad = false;
|
|
80
89
|
|
|
81
90
|
/** Prevents input continuing to the default browser handling (false by default)
|
|
82
91
|
* @type {Boolean}
|
|
83
92
|
* @memberof Input */
|
|
84
|
-
let preventDefaultInput =
|
|
93
|
+
let preventDefaultInput = false;
|
|
85
94
|
|
|
86
95
|
/** Returns true if gamepad button is down
|
|
87
96
|
* @param {Number} button
|
|
88
|
-
* @param {Number} [gamepad
|
|
97
|
+
* @param {Number} [gamepad]
|
|
89
98
|
* @return {Boolean}
|
|
90
99
|
* @memberof Input */
|
|
91
100
|
function gamepadIsDown(button, gamepad=0)
|
|
@@ -93,7 +102,7 @@ function gamepadIsDown(button, gamepad=0)
|
|
|
93
102
|
|
|
94
103
|
/** Returns true if gamepad button was pressed
|
|
95
104
|
* @param {Number} button
|
|
96
|
-
* @param {Number} [gamepad
|
|
105
|
+
* @param {Number} [gamepad]
|
|
97
106
|
* @return {Boolean}
|
|
98
107
|
* @memberof Input */
|
|
99
108
|
function gamepadWasPressed(button, gamepad=0)
|
|
@@ -101,7 +110,7 @@ function gamepadWasPressed(button, gamepad=0)
|
|
|
101
110
|
|
|
102
111
|
/** Returns true if gamepad button was released
|
|
103
112
|
* @param {Number} button
|
|
104
|
-
* @param {Number} [gamepad
|
|
113
|
+
* @param {Number} [gamepad]
|
|
105
114
|
* @return {Boolean}
|
|
106
115
|
* @memberof Input */
|
|
107
116
|
function gamepadWasReleased(button, gamepad=0)
|
|
@@ -109,7 +118,7 @@ function gamepadWasReleased(button, gamepad=0)
|
|
|
109
118
|
|
|
110
119
|
/** Returns gamepad stick value
|
|
111
120
|
* @param {Number} stick
|
|
112
|
-
* @param {Number} [gamepad
|
|
121
|
+
* @param {Number} [gamepad]
|
|
113
122
|
* @return {Vector2}
|
|
114
123
|
* @memberof Input */
|
|
115
124
|
function gamepadStick(stick, gamepad=0)
|
|
@@ -152,9 +161,10 @@ function inputUpdatePost()
|
|
|
152
161
|
if (debug && e.target != document.body) return;
|
|
153
162
|
if (!e.repeat)
|
|
154
163
|
{
|
|
155
|
-
|
|
164
|
+
isUsingGamepad = false;
|
|
165
|
+
inputData[0][e.code] = 3;
|
|
156
166
|
if (inputWASDEmulateDirection)
|
|
157
|
-
inputData[0][remapKey(e.
|
|
167
|
+
inputData[0][remapKey(e.code)] = 3;
|
|
158
168
|
}
|
|
159
169
|
preventDefaultInput && e.preventDefault();
|
|
160
170
|
}
|
|
@@ -162,26 +172,29 @@ function inputUpdatePost()
|
|
|
162
172
|
onkeyup = (e)=>
|
|
163
173
|
{
|
|
164
174
|
if (debug && e.target != document.body) return;
|
|
165
|
-
inputData[0][e.
|
|
175
|
+
inputData[0][e.code] = 4;
|
|
166
176
|
if (inputWASDEmulateDirection)
|
|
167
|
-
inputData[0][remapKey(e.
|
|
177
|
+
inputData[0][remapKey(e.code)] = 4;
|
|
168
178
|
}
|
|
169
179
|
|
|
170
180
|
// handle remapping wasd keys to directions
|
|
171
181
|
function remapKey(c)
|
|
172
|
-
{
|
|
182
|
+
{
|
|
173
183
|
return inputWASDEmulateDirection ?
|
|
174
|
-
c
|
|
184
|
+
c == 'KeyW' ? 'ArrowUp' :
|
|
185
|
+
c == 'KeyS' ? 'ArrowDown' :
|
|
186
|
+
c == 'KeyA' ? 'ArrowLeft' :
|
|
187
|
+
c == 'KeyD' ? 'ArrowRight' : c : c;
|
|
175
188
|
}
|
|
176
189
|
}
|
|
177
190
|
|
|
178
191
|
///////////////////////////////////////////////////////////////////////////////
|
|
179
192
|
// Mouse event handlers
|
|
180
193
|
|
|
181
|
-
onmousedown = (e)=> {
|
|
194
|
+
onmousedown = (e)=> {isUsingGamepad = false; inputData[0][e.button] = 3; mousePosScreen = mouseToScreen(e); e.button && e.preventDefault();}
|
|
182
195
|
onmouseup = (e)=> inputData[0][e.button] = inputData[0][e.button] & 2 | 4;
|
|
183
196
|
onmousemove = (e)=> mousePosScreen = mouseToScreen(e);
|
|
184
|
-
onwheel
|
|
197
|
+
onwheel = (e)=> mouseWheel = e.ctrlKey ? 0 : sign(e.deltaY);
|
|
185
198
|
oncontextmenu = (e)=> false; // prevent right click menu
|
|
186
199
|
|
|
187
200
|
// convert a mouse or touch event position to screen space
|
|
@@ -219,7 +232,7 @@ function gamepadsUpdate()
|
|
|
219
232
|
for (let i=10; i--;)
|
|
220
233
|
{
|
|
221
234
|
const j = i == 3 ? 2 : i == 2 ? 3 : i; // fix button locations
|
|
222
|
-
data[j] = touchGamepadButtons[i] ?
|
|
235
|
+
data[j] = touchGamepadButtons[i] ? gamepadIsDown(j,0) ? 1 : 3 : gamepadIsDown(j,0) ? 4 : 0;
|
|
223
236
|
}
|
|
224
237
|
}
|
|
225
238
|
}
|
|
@@ -251,18 +264,23 @@ function gamepadsUpdate()
|
|
|
251
264
|
for (let j = gamepad.buttons.length; j--;)
|
|
252
265
|
{
|
|
253
266
|
const button = gamepad.buttons[j];
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
267
|
+
const wasDown = gamepadIsDown(j,i);
|
|
268
|
+
data[j] = button.pressed ? wasDown ? 1 : 3 : wasDown ? 4 : 0;
|
|
269
|
+
isUsingGamepad ||= !i && button.pressed;
|
|
257
270
|
}
|
|
258
271
|
|
|
259
272
|
if (gamepadDirectionEmulateStick)
|
|
260
273
|
{
|
|
261
274
|
// copy dpad to left analog stick when pressed
|
|
262
|
-
const dpad = vec2(
|
|
275
|
+
const dpad = vec2(
|
|
276
|
+
(gamepadIsDown(15,i)&&1) - (gamepadIsDown(14,i)&&1),
|
|
277
|
+
(gamepadIsDown(12,i)&&1) - (gamepadIsDown(13,i)&&1));
|
|
263
278
|
if (dpad.lengthSquared())
|
|
264
279
|
sticks[0] = dpad.clampLength();
|
|
265
280
|
}
|
|
281
|
+
|
|
282
|
+
// disable touch gamepad if using real gamepad
|
|
283
|
+
touchGamepadEnable && isUsingGamepad && touchGamepadTimer.unset();
|
|
266
284
|
}
|
|
267
285
|
}
|
|
268
286
|
}
|
|
@@ -270,9 +288,9 @@ function gamepadsUpdate()
|
|
|
270
288
|
///////////////////////////////////////////////////////////////////////////////
|
|
271
289
|
|
|
272
290
|
/** Pulse the vibration hardware if it exists
|
|
273
|
-
* @param {Number} [pattern
|
|
291
|
+
* @param {Number|Array} [pattern] - single value in ms or vibration interval array
|
|
274
292
|
* @memberof Input */
|
|
275
|
-
function vibrate(pattern)
|
|
293
|
+
function vibrate(pattern=100)
|
|
276
294
|
{ vibrateEnable && navigator && navigator.vibrate && navigator.vibrate(pattern); }
|
|
277
295
|
|
|
278
296
|
/** Cancel any ongoing vibration
|
|
@@ -290,29 +308,28 @@ const isTouchDevice = window.ontouchstart !== undefined;
|
|
|
290
308
|
if (isTouchDevice)
|
|
291
309
|
{
|
|
292
310
|
// override mouse events
|
|
293
|
-
let wasTouching
|
|
311
|
+
let wasTouching;
|
|
294
312
|
onmousedown = onmouseup = ()=> 0;
|
|
295
313
|
|
|
296
314
|
// handle all touch events the same way
|
|
297
315
|
ontouchstart = ontouchmove = ontouchend = (e)=>
|
|
298
316
|
{
|
|
299
|
-
e.button = 0; // all touches are left click
|
|
300
|
-
|
|
301
317
|
// fix stalled audio on mobile
|
|
302
318
|
if (soundEnable)
|
|
303
319
|
audioContext ? audioContext.resume() : zzfx(0);
|
|
304
320
|
|
|
305
321
|
// check if touching and pass to mouse events
|
|
306
322
|
const touching = e.touches.length;
|
|
323
|
+
const button = 0; // all touches are left mouse button
|
|
307
324
|
if (touching)
|
|
308
325
|
{
|
|
309
326
|
// set event pos and pass it along
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
wasTouching ?
|
|
327
|
+
const p = vec2(e.touches[0].clientX, e.touches[0].clientY);
|
|
328
|
+
mousePosScreen = mouseToScreen(p);
|
|
329
|
+
wasTouching ? isUsingGamepad = false : inputData[0][button] = 3;
|
|
313
330
|
}
|
|
314
331
|
else if (wasTouching)
|
|
315
|
-
|
|
332
|
+
inputData[0][button] = inputData[0][button] & 2 | 4;
|
|
316
333
|
|
|
317
334
|
// set was touching
|
|
318
335
|
wasTouching = touching;
|
|
@@ -393,8 +410,8 @@ function createTouchGamepad()
|
|
|
393
410
|
}
|
|
394
411
|
|
|
395
412
|
// call default touch handler and set to using gamepad
|
|
396
|
-
touchHandler(e);
|
|
397
|
-
isUsingGamepad =
|
|
413
|
+
touchHandler.bind(window)(e);
|
|
414
|
+
isUsingGamepad = true;
|
|
398
415
|
|
|
399
416
|
// must return true so the document will get focus
|
|
400
417
|
return true;
|
|
@@ -408,7 +425,7 @@ function touchGamepadRender()
|
|
|
408
425
|
return;
|
|
409
426
|
|
|
410
427
|
// fade off when not touching or paused
|
|
411
|
-
const alpha = percent(touchGamepadTimer, 4, 3);
|
|
428
|
+
const alpha = percent(touchGamepadTimer.get(), 4, 3);
|
|
412
429
|
if (!alpha || paused)
|
|
413
430
|
return;
|
|
414
431
|
|
package/src/engineMedals.js
CHANGED
|
@@ -48,7 +48,7 @@ class Medal
|
|
|
48
48
|
* @param {Number} id - The unique identifier of the medal
|
|
49
49
|
* @param {String} name - Name of the medal
|
|
50
50
|
* @param {String} [description] - Description of the medal
|
|
51
|
-
* @param {String} [icon
|
|
51
|
+
* @param {String} [icon] - Icon for the medal
|
|
52
52
|
* @param {String} [src] - Image location for the medal
|
|
53
53
|
*/
|
|
54
54
|
constructor(id, name, description='', icon='🏆', src)
|
|
@@ -71,14 +71,14 @@ class Medal
|
|
|
71
71
|
return;
|
|
72
72
|
|
|
73
73
|
// save the medal
|
|
74
|
-
ASSERT(medalsSaveName
|
|
74
|
+
ASSERT(medalsSaveName, 'save name must be set');
|
|
75
75
|
localStorage[this.storageKey()] = this.unlocked = 1;
|
|
76
76
|
medalsDisplayQueue.push(this);
|
|
77
77
|
newgrounds && newgrounds.unlockMedal(this.id);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/** Render a medal
|
|
81
|
-
* @param {Number} [hidePercent
|
|
81
|
+
* @param {Number} [hidePercent] - How much to slide the medal off screen
|
|
82
82
|
*/
|
|
83
83
|
render(hidePercent=0)
|
|
84
84
|
{
|
|
@@ -90,25 +90,25 @@ class Medal
|
|
|
90
90
|
// draw containing rect and clip to that region
|
|
91
91
|
context.save();
|
|
92
92
|
context.beginPath();
|
|
93
|
-
context.fillStyle =
|
|
94
|
-
context.strokeStyle =
|
|
93
|
+
context.fillStyle = rgb(.9,.9,.9).toString();
|
|
94
|
+
context.strokeStyle = rgb(0,0,0).toString();
|
|
95
95
|
context.lineWidth = 3;
|
|
96
|
-
context.
|
|
96
|
+
context.rect(x, y, width, medalDisplaySize.y);
|
|
97
|
+
context.fill();
|
|
97
98
|
context.stroke();
|
|
98
99
|
context.clip();
|
|
99
100
|
|
|
100
101
|
// draw the icon and text
|
|
101
102
|
this.renderIcon(vec2(x+15+medalDisplayIconSize/2, y+medalDisplaySize.y/2));
|
|
102
103
|
const pos = vec2(x+medalDisplayIconSize+30, y+28);
|
|
103
|
-
drawTextScreen(this.name, pos, 38, new Color(0,0,0), 0,
|
|
104
|
+
drawTextScreen(this.name, pos, 38, new Color(0,0,0), 0, undefined, 'left');
|
|
104
105
|
pos.y += 32;
|
|
105
|
-
drawTextScreen(this.description, pos, 24, new Color(0,0,0), 0,
|
|
106
|
+
drawTextScreen(this.description, pos, 24, new Color(0,0,0), 0, undefined, 'left');
|
|
106
107
|
context.restore();
|
|
107
108
|
}
|
|
108
109
|
|
|
109
110
|
/** Render the icon for a medal
|
|
110
|
-
* @param {
|
|
111
|
-
* @param {Number} y - Screen space Y position
|
|
111
|
+
* @param {Vector2} pos - Screen space position
|
|
112
112
|
* @param {Number} [size=medalDisplayIconSize] - Screen space size
|
|
113
113
|
*/
|
|
114
114
|
renderIcon(pos, size=medalDisplayIconSize)
|
|
@@ -136,7 +136,10 @@ function medalsRender()
|
|
|
136
136
|
if (!medalsDisplayTimeLast)
|
|
137
137
|
medalsDisplayTimeLast = timeReal;
|
|
138
138
|
else if (time > medalDisplayTime)
|
|
139
|
-
|
|
139
|
+
{
|
|
140
|
+
medalsDisplayTimeLast = 0;
|
|
141
|
+
medalsDisplayQueue.shift();
|
|
142
|
+
}
|
|
140
143
|
else
|
|
141
144
|
{
|
|
142
145
|
// slide on/off medals
|
|
@@ -176,8 +179,8 @@ class Newgrounds
|
|
|
176
179
|
* @param {Object} [cryptoJS] - An instance of CryptoJS, if there is a cipher */
|
|
177
180
|
constructor(app_id, cipher, cryptoJS)
|
|
178
181
|
{
|
|
179
|
-
ASSERT(!newgrounds && app_id
|
|
180
|
-
ASSERT(!cipher || cryptoJS
|
|
182
|
+
ASSERT(!newgrounds && app_id>0, 'there can only be one newgrounds object');
|
|
183
|
+
ASSERT(!cipher || cryptoJS, 'must provide cryptojs if there is a cipher');
|
|
181
184
|
|
|
182
185
|
this.app_id = app_id;
|
|
183
186
|
this.cipher = cipher;
|
|
@@ -220,39 +223,39 @@ class Newgrounds
|
|
|
220
223
|
debugMedals && console.log(this.scoreboards);
|
|
221
224
|
|
|
222
225
|
const keepAliveMS = 5 * 60 * 1e3;
|
|
223
|
-
setInterval(()=>this.call('Gateway.ping', 0,
|
|
226
|
+
setInterval(()=>this.call('Gateway.ping', 0, true), keepAliveMS);
|
|
224
227
|
}
|
|
225
228
|
|
|
226
229
|
/** Send message to unlock a medal by id
|
|
227
230
|
* @param {Number} id - The medal id */
|
|
228
|
-
unlockMedal(id) { return this.call('Medal.unlock', {'id':id},
|
|
231
|
+
unlockMedal(id) { return this.call('Medal.unlock', {'id':id}, true); }
|
|
229
232
|
|
|
230
233
|
/** Send message to post score
|
|
231
234
|
* @param {Number} id - The scoreboard id
|
|
232
235
|
* @param {Number} value - The score value */
|
|
233
|
-
postScore(id, value) { return this.call('ScoreBoard.postScore', {'id':id, 'value':value},
|
|
236
|
+
postScore(id, value) { return this.call('ScoreBoard.postScore', {'id':id, 'value':value}, true); }
|
|
234
237
|
|
|
235
238
|
/** Get scores from a scoreboard
|
|
236
|
-
* @param {Number} id
|
|
237
|
-
* @param {String} [user
|
|
238
|
-
* @param {Number} [social
|
|
239
|
-
* @param {Number} [skip
|
|
240
|
-
* @param {Number} [limit
|
|
241
|
-
* @return {Object}
|
|
239
|
+
* @param {Number} id - The scoreboard id
|
|
240
|
+
* @param {String} [user] - A user's id or name
|
|
241
|
+
* @param {Number} [social] - If true, only social scores will be loaded
|
|
242
|
+
* @param {Number} [skip] - Number of scores to skip before start
|
|
243
|
+
* @param {Number} [limit] - Number of scores to include in the list
|
|
244
|
+
* @return {Object} - The response JSON object
|
|
242
245
|
*/
|
|
243
|
-
getScores(id, user
|
|
246
|
+
getScores(id, user, social=0, skip=0, limit=10)
|
|
244
247
|
{ return this.call('ScoreBoard.getScores', {'id':id, 'user':user, 'social':social, 'skip':skip, 'limit':limit}); }
|
|
245
248
|
|
|
246
249
|
/** Send message to log a view */
|
|
247
|
-
logView() { return this.call('App.logView', {'host':this.host},
|
|
250
|
+
logView() { return this.call('App.logView', {'host':this.host}, true); }
|
|
248
251
|
|
|
249
252
|
/** Send a message to call a component of the Newgrounds API
|
|
250
|
-
* @param {String} component
|
|
251
|
-
* @param {Object} [parameters
|
|
252
|
-
* @param {Boolean} [async
|
|
253
|
-
* @return {Object}
|
|
253
|
+
* @param {String} component - Name of the component
|
|
254
|
+
* @param {Object} [parameters] - Parameters to use for call
|
|
255
|
+
* @param {Boolean} [async] - If true, don't wait for response before continuing
|
|
256
|
+
* @return {Object} - The response JSON object
|
|
254
257
|
*/
|
|
255
|
-
call(component, parameters
|
|
258
|
+
call(component, parameters, async=false)
|
|
256
259
|
{
|
|
257
260
|
const call = {'component':component, 'parameters':parameters};
|
|
258
261
|
if (this.cipher)
|
package/src/engineObject.js
CHANGED
|
@@ -32,27 +32,25 @@
|
|
|
32
32
|
class EngineObject
|
|
33
33
|
{
|
|
34
34
|
/** Create an engine object and adds it to the list of objects
|
|
35
|
-
* @param {Vector2}
|
|
36
|
-
* @param {Vector2}
|
|
37
|
-
* @param {TileInfo} [tileInfo]
|
|
38
|
-
* @param {Number}
|
|
39
|
-
* @param {Color}
|
|
40
|
-
* @param {Number}
|
|
35
|
+
* @param {Vector2} [pos=(0,0)] - World space position of the object
|
|
36
|
+
* @param {Vector2} [size=(1,1)] - World space size of the object
|
|
37
|
+
* @param {TileInfo} [tileInfo] - Tile info to render object (undefined is untextured)
|
|
38
|
+
* @param {Number} [angle] - Angle the object is rotated by
|
|
39
|
+
* @param {Color} [color=(1,1,1,1)] - Color to apply to tile when rendered
|
|
40
|
+
* @param {Number} [renderOrder] - Objects sorted by renderOrder before being rendered
|
|
41
41
|
*/
|
|
42
42
|
constructor(pos=vec2(), size=vec2(1), tileInfo, angle=0, color, renderOrder=0)
|
|
43
43
|
{
|
|
44
44
|
// set passed in params
|
|
45
|
-
ASSERT(isVector2(pos) && isVector2(size)
|
|
46
|
-
ASSERT(typeof tileInfo !== 'number' || !tileInfo
|
|
47
|
-
ASSERT(!(renderOrder instanceof Color)); // prevent old style calls
|
|
48
|
-
// to fix old calls, replace with tile(tileIndex, tileSize)
|
|
45
|
+
ASSERT(isVector2(pos) && isVector2(size), 'ensure pos and size are vec2s');
|
|
46
|
+
ASSERT(typeof tileInfo !== 'number' || !tileInfo, 'old style tile setup');
|
|
49
47
|
|
|
50
48
|
/** @property {Vector2} - World space position of the object */
|
|
51
49
|
this.pos = pos.copy();
|
|
52
50
|
/** @property {Vector2} - World space width and height of the object */
|
|
53
51
|
this.size = size;
|
|
54
52
|
/** @property {Vector2} - Size of object used for drawing, uses size if not set */
|
|
55
|
-
this.drawSize;
|
|
53
|
+
this.drawSize = undefined;
|
|
56
54
|
/** @property {TileInfo} - Tile info to render object (undefined is untextured) */
|
|
57
55
|
this.tileInfo = tileInfo;
|
|
58
56
|
/** @property {Number} - Angle to rotate the object */
|
|
@@ -60,9 +58,11 @@ class EngineObject
|
|
|
60
58
|
/** @property {Color} - Color to apply when rendered */
|
|
61
59
|
this.color = color;
|
|
62
60
|
/** @property {Color} - Additive color to apply when rendered */
|
|
63
|
-
this.additiveColor;
|
|
61
|
+
this.additiveColor = undefined;
|
|
62
|
+
/** @property {Boolean} - Should it flip along y axis when rendered */
|
|
63
|
+
this.mirror = false;
|
|
64
64
|
|
|
65
|
-
//
|
|
65
|
+
// physical properties
|
|
66
66
|
/** @property {Number} [mass=objectDefaultMass] - How heavy the object is, static if 0 */
|
|
67
67
|
this.mass = objectDefaultMass;
|
|
68
68
|
/** @property {Number} [damping=objectDefaultDamping] - How much to slow down velocity each frame (0-1) */
|
|
@@ -73,19 +73,34 @@ class EngineObject
|
|
|
73
73
|
this.elasticity = objectDefaultElasticity;
|
|
74
74
|
/** @property {Number} [friction=objectDefaultFriction] - How much friction to apply when sliding (0-1) */
|
|
75
75
|
this.friction = objectDefaultFriction;
|
|
76
|
-
/** @property {Number}
|
|
76
|
+
/** @property {Number} - How much to scale gravity by for this object */
|
|
77
77
|
this.gravityScale = 1;
|
|
78
|
-
/** @property {Number}
|
|
78
|
+
/** @property {Number} - Objects are sorted by render order */
|
|
79
79
|
this.renderOrder = renderOrder;
|
|
80
|
-
/** @property {Vector2}
|
|
80
|
+
/** @property {Vector2} - Velocity of the object */
|
|
81
81
|
this.velocity = vec2();
|
|
82
|
-
/** @property {Number}
|
|
82
|
+
/** @property {Number} - Angular velocity of the object */
|
|
83
83
|
this.angleVelocity = 0;
|
|
84
|
-
|
|
85
|
-
// init other internal object stuff
|
|
84
|
+
/** @property {Number} - Track when object was created */
|
|
86
85
|
this.spawnTime = time;
|
|
86
|
+
/** @property {Array} - List of children of this object */
|
|
87
87
|
this.children = [];
|
|
88
|
+
|
|
89
|
+
// parent child system
|
|
90
|
+
/** @property {EngineObject} - Parent of object if in local space */
|
|
91
|
+
this.parent = undefined;
|
|
92
|
+
/** @property {Vector2} - Local position if child */
|
|
93
|
+
this.localPos = vec2();
|
|
94
|
+
/** @property {Number} - Local angle if child */
|
|
95
|
+
this.localAngle = 0;
|
|
96
|
+
|
|
97
|
+
// collision flags
|
|
98
|
+
/** @property {Boolean} - Object collides with the tile collision */
|
|
88
99
|
this.collideTiles = false;
|
|
100
|
+
/** @property {Boolean} - Object collides with solid objects */
|
|
101
|
+
this.collideSolidObjects = false;
|
|
102
|
+
/** @property {Boolean} - Object collides with and blocks other objects */
|
|
103
|
+
this.isSolid = false;
|
|
89
104
|
|
|
90
105
|
// add to list of objects
|
|
91
106
|
engineObjects.push(this);
|
|
@@ -302,7 +317,7 @@ class EngineObject
|
|
|
302
317
|
* @param {EngineObject} object - the object to test against
|
|
303
318
|
* @return {Boolean} - true if the collision should be resolved
|
|
304
319
|
*/
|
|
305
|
-
collideWithObject(object) { return
|
|
320
|
+
collideWithObject(object) { return true; }
|
|
306
321
|
|
|
307
322
|
/** How long since the object was created
|
|
308
323
|
* @return {Number} */
|
|
@@ -322,8 +337,8 @@ class EngineObject
|
|
|
322
337
|
|
|
323
338
|
/** Attaches a child to this with a given local transform
|
|
324
339
|
* @param {EngineObject} child
|
|
325
|
-
* @param {Vector2} [localPos=
|
|
326
|
-
* @param {Number} [localAngle
|
|
340
|
+
* @param {Vector2} [localPos=(0,0)]
|
|
341
|
+
* @param {Number} [localAngle] */
|
|
327
342
|
addChild(child, localPos=vec2(), localAngle=0)
|
|
328
343
|
{
|
|
329
344
|
ASSERT(!child.parent && !this.children.includes(child));
|
|
@@ -343,12 +358,12 @@ class EngineObject
|
|
|
343
358
|
}
|
|
344
359
|
|
|
345
360
|
/** Set how this object collides
|
|
346
|
-
* @param {Boolean} [collideSolidObjects
|
|
347
|
-
* @param {Boolean} [isSolid
|
|
348
|
-
* @param {Boolean} [collideTiles
|
|
349
|
-
setCollision(collideSolidObjects=
|
|
361
|
+
* @param {Boolean} [collideSolidObjects] - Does it collide with solid objects
|
|
362
|
+
* @param {Boolean} [isSolid] - Does it collide with and block other objects (expensive in large numbers)
|
|
363
|
+
* @param {Boolean} [collideTiles] - Does it collide with the tile collision */
|
|
364
|
+
setCollision(collideSolidObjects=true, isSolid=true, collideTiles=true)
|
|
350
365
|
{
|
|
351
|
-
ASSERT(collideSolidObjects || !isSolid
|
|
366
|
+
ASSERT(collideSolidObjects || !isSolid, 'solid objects must be set to collide');
|
|
352
367
|
|
|
353
368
|
this.collideSolidObjects = collideSolidObjects;
|
|
354
369
|
this.isSolid = isSolid;
|