littlejsengine 1.18.28 → 1.19.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/FAQ.md +5 -0
- package/README.md +207 -199
- package/dist/littlejs.d.ts +2099 -48
- package/dist/littlejs.esm.js +16251 -10315
- package/dist/littlejs.esm.min.js +13 -1
- package/dist/littlejs.js +15747 -9888
- package/dist/littlejs.min.js +13 -1
- package/dist/littlejs.release.js +15719 -9867
- package/package.json +1 -1
- package/plugins/audioEffects.js +371 -0
- package/plugins/lightSystem.js +5 -3
- package/plugins/math3d.js +870 -0
- package/plugins/medalSystem.js +280 -280
- package/plugins/pluginExport.js +181 -115
- package/plugins/postProcess.js +241 -166
- package/plugins/render3d.js +4006 -0
- package/plugins/textureSheet.js +458 -458
- package/plugins/threejs.js +6 -1
- package/plugins/tweenSystem.js +528 -526
- package/plugins/zzfxm.js +159 -166
- package/src/engine.js +172 -137
- package/src/engineAudio.js +918 -775
- package/src/engineBuild.mjs +3 -0
- package/src/engineDebug.js +15 -8
- package/src/engineDraw.js +1672 -1510
- package/src/engineExport.js +407 -396
- package/src/engineInput.js +1 -1
- package/src/engineLogo.js +4 -3
- package/src/engineMath.js +69 -0
- package/src/engineObject.js +560 -551
- package/src/engineSettings.js +759 -725
- package/src/engineTileLayer.js +3 -3
- package/src/engineUtilities.js +13 -0
- package/src/engineWebGL.js +1005 -941
package/src/engineObject.js
CHANGED
|
@@ -1,552 +1,561 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LittleJS Object System
|
|
3
|
-
* - EngineObject is the base class for all game objects
|
|
4
|
-
* - Handles automatic updating, rendering, physics, and collision
|
|
5
|
-
* - Supports parent-child hierarchies with transform inheritance
|
|
6
|
-
* - 2D physics with velocity, acceleration, damping, and gravity
|
|
7
|
-
* - Collision system with tiles and other objects
|
|
8
|
-
* - Renders sprites from tile sheets with color and rotation
|
|
9
|
-
* - Objects sorted by renderOrder for layered rendering
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
'use strict';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* LittleJS Object Base Object Class
|
|
16
|
-
* - Top level object class used by the engine
|
|
17
|
-
* - Automatically adds self to object list
|
|
18
|
-
* - Will be updated and rendered each frame
|
|
19
|
-
* - Renders as a sprite from a tilesheet by default
|
|
20
|
-
* - Can have color and additive color applied
|
|
21
|
-
* - 2D Physics and collision system
|
|
22
|
-
* - Sorted by renderOrder
|
|
23
|
-
* - Objects can have children attached
|
|
24
|
-
* - Parents are updated before children, and set child transform
|
|
25
|
-
* - Call destroy() to get rid of objects
|
|
26
|
-
*
|
|
27
|
-
* The physics system used by objects is simple and fast with some caveats...
|
|
28
|
-
* - Collision uses the axis aligned size, the object's rotation angle is only for rendering
|
|
29
|
-
* - Objects are guaranteed to not intersect tile collision from physics
|
|
30
|
-
* - If an object starts or is moved inside tile collision, it will not collide with that tile
|
|
31
|
-
* - Collision for objects can be set to be solid to block other objects
|
|
32
|
-
* - Objects may get pushed into overlapping other solid objects, if so they will push away
|
|
33
|
-
* - Solid objects are more performance intensive and should be used sparingly
|
|
34
|
-
* @memberof Engine
|
|
35
|
-
* @example
|
|
36
|
-
* // create an engine object, normally you would first extend the class with your own
|
|
37
|
-
* const pos = vec2(2,3);
|
|
38
|
-
* const object = new EngineObject(pos);
|
|
39
|
-
*/
|
|
40
|
-
class EngineObject
|
|
41
|
-
{
|
|
42
|
-
/** Create an engine object and adds it to the list of objects
|
|
43
|
-
* @param {Vector2} [pos=vec2()] - World space position of the object
|
|
44
|
-
* @param {Vector2} [size=vec2(1)] - World space size of the object
|
|
45
|
-
* @param {TileInfo} [tileInfo] - Tile info to render object (undefined is untextured)
|
|
46
|
-
* @param {number} [angle] - Angle the object is rotated by
|
|
47
|
-
* @param {Color} [color=WHITE] - Color to apply to tile when rendered
|
|
48
|
-
* @param {number} [renderOrder] - Objects sorted by renderOrder before being rendered
|
|
49
|
-
*/
|
|
50
|
-
constructor(pos=vec2(), size=vec2(1), tileInfo, angle=0, color=WHITE, renderOrder=0)
|
|
51
|
-
{
|
|
52
|
-
// check passed in params
|
|
53
|
-
ASSERT(isVector2(pos), 'object pos must be a vec2');
|
|
54
|
-
ASSERT(isVector2(size), 'object size must be a vec2');
|
|
55
|
-
ASSERT(!tileInfo || tileInfo instanceof TileInfo, 'object tileInfo should be a TileInfo or undefined');
|
|
56
|
-
ASSERT(typeof angle === 'number' && isFinite(angle), 'object angle should be a number');
|
|
57
|
-
ASSERT(isColor(color), 'object color should be a valid rgba color');
|
|
58
|
-
ASSERT(typeof renderOrder === 'number', 'object renderOrder should be a number');
|
|
59
|
-
|
|
60
|
-
/** @property {Vector2} - World space position of the object */
|
|
61
|
-
this.pos = pos.copy();
|
|
62
|
-
/** @property {Vector2} - World space width and height of the object */
|
|
63
|
-
this.size = size.copy();
|
|
64
|
-
/** @property {Vector2} - Size of object used for drawing, uses size if not set */
|
|
65
|
-
this.drawSize = undefined;
|
|
66
|
-
/** @property {TileInfo} - Tile info to render object (undefined is untextured) */
|
|
67
|
-
this.tileInfo = tileInfo;
|
|
68
|
-
/** @property {number} - Angle to rotate the object */
|
|
69
|
-
this.angle = angle;
|
|
70
|
-
/** @property {Color} - Color to apply when rendered */
|
|
71
|
-
this.color = color.copy();
|
|
72
|
-
/** @property {Color} - Additive color to apply when rendered */
|
|
73
|
-
this.additiveColor = undefined;
|
|
74
|
-
/** @property {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
this
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
this
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
this.
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (!
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
//
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
this.pos.x
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
//
|
|
348
|
-
this
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
/** Convert from local space to world space
|
|
403
|
-
* @param {Vector2}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
/** Convert from world space to local space
|
|
407
|
-
* @param {Vector2}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
/**
|
|
411
|
-
* @param {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
* @return {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
/** Get
|
|
437
|
-
* @
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
{
|
|
444
|
-
|
|
445
|
-
/**
|
|
446
|
-
* @
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* @param {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
child
|
|
476
|
-
return child;
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
child
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
*
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
*
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
* @param {
|
|
506
|
-
* @param {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
1
|
+
/**
|
|
2
|
+
* LittleJS Object System
|
|
3
|
+
* - EngineObject is the base class for all game objects
|
|
4
|
+
* - Handles automatic updating, rendering, physics, and collision
|
|
5
|
+
* - Supports parent-child hierarchies with transform inheritance
|
|
6
|
+
* - 2D physics with velocity, acceleration, damping, and gravity
|
|
7
|
+
* - Collision system with tiles and other objects
|
|
8
|
+
* - Renders sprites from tile sheets with color and rotation
|
|
9
|
+
* - Objects sorted by renderOrder for layered rendering
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* LittleJS Object Base Object Class
|
|
16
|
+
* - Top level object class used by the engine
|
|
17
|
+
* - Automatically adds self to object list
|
|
18
|
+
* - Will be updated and rendered each frame
|
|
19
|
+
* - Renders as a sprite from a tilesheet by default
|
|
20
|
+
* - Can have color and additive color applied
|
|
21
|
+
* - 2D Physics and collision system
|
|
22
|
+
* - Sorted by renderOrder
|
|
23
|
+
* - Objects can have children attached
|
|
24
|
+
* - Parents are updated before children, and set child transform
|
|
25
|
+
* - Call destroy() to get rid of objects
|
|
26
|
+
*
|
|
27
|
+
* The physics system used by objects is simple and fast with some caveats...
|
|
28
|
+
* - Collision uses the axis aligned size, the object's rotation angle is only for rendering
|
|
29
|
+
* - Objects are guaranteed to not intersect tile collision from physics
|
|
30
|
+
* - If an object starts or is moved inside tile collision, it will not collide with that tile
|
|
31
|
+
* - Collision for objects can be set to be solid to block other objects
|
|
32
|
+
* - Objects may get pushed into overlapping other solid objects, if so they will push away
|
|
33
|
+
* - Solid objects are more performance intensive and should be used sparingly
|
|
34
|
+
* @memberof Engine
|
|
35
|
+
* @example
|
|
36
|
+
* // create an engine object, normally you would first extend the class with your own
|
|
37
|
+
* const pos = vec2(2,3);
|
|
38
|
+
* const object = new EngineObject(pos);
|
|
39
|
+
*/
|
|
40
|
+
class EngineObject
|
|
41
|
+
{
|
|
42
|
+
/** Create an engine object and adds it to the list of objects
|
|
43
|
+
* @param {Vector2} [pos=vec2()] - World space position of the object
|
|
44
|
+
* @param {Vector2} [size=vec2(1)] - World space size of the object
|
|
45
|
+
* @param {TileInfo} [tileInfo] - Tile info to render object (undefined is untextured)
|
|
46
|
+
* @param {number} [angle] - Angle the object is rotated by
|
|
47
|
+
* @param {Color} [color=WHITE] - Color to apply to tile when rendered
|
|
48
|
+
* @param {number} [renderOrder] - Objects sorted by renderOrder before being rendered
|
|
49
|
+
*/
|
|
50
|
+
constructor(pos=vec2(), size=vec2(1), tileInfo, angle=0, color=WHITE, renderOrder=0)
|
|
51
|
+
{
|
|
52
|
+
// check passed in params
|
|
53
|
+
ASSERT(isVector2(pos), 'object pos must be a vec2');
|
|
54
|
+
ASSERT(isVector2(size), 'object size must be a vec2');
|
|
55
|
+
ASSERT(!tileInfo || tileInfo instanceof TileInfo, 'object tileInfo should be a TileInfo or undefined');
|
|
56
|
+
ASSERT(typeof angle === 'number' && isFinite(angle), 'object angle should be a number');
|
|
57
|
+
ASSERT(isColor(color), 'object color should be a valid rgba color');
|
|
58
|
+
ASSERT(typeof renderOrder === 'number', 'object renderOrder should be a number');
|
|
59
|
+
|
|
60
|
+
/** @property {Vector2} - World space position of the object */
|
|
61
|
+
this.pos = pos.copy();
|
|
62
|
+
/** @property {Vector2} - World space width and height of the object */
|
|
63
|
+
this.size = size.copy();
|
|
64
|
+
/** @property {Vector2} - Size of object used for drawing, uses size if not set */
|
|
65
|
+
this.drawSize = undefined;
|
|
66
|
+
/** @property {TileInfo} - Tile info to render object (undefined is untextured) */
|
|
67
|
+
this.tileInfo = tileInfo;
|
|
68
|
+
/** @property {number} - Angle to rotate the object */
|
|
69
|
+
this.angle = angle;
|
|
70
|
+
/** @property {Color} - Color to apply when rendered */
|
|
71
|
+
this.color = color.copy();
|
|
72
|
+
/** @property {Color} - Additive color to apply when rendered */
|
|
73
|
+
this.additiveColor = undefined;
|
|
74
|
+
/** @property {Shader|undefined} - Custom shader to render with, undefined for the engine's own
|
|
75
|
+
* @type {Shader|undefined} */
|
|
76
|
+
this.shader = undefined;
|
|
77
|
+
/** @property {boolean} - Should the rendered tile flip along the y axis. Affects rendering and the local→world transform of attached children (a mirrored parent flips its children's localPos.x and localAngle). Does not affect this object's own physics, collision, or localToWorld/worldToLocal. */
|
|
78
|
+
this.mirror = false;
|
|
79
|
+
/** @property {boolean} - Has object been destroyed? */
|
|
80
|
+
this.destroyed = false;
|
|
81
|
+
|
|
82
|
+
// physical properties
|
|
83
|
+
/** @property {number} - How heavy the object is, static if 0 */
|
|
84
|
+
this.mass = objectDefaultMass;
|
|
85
|
+
/** @property {number} - How much to slow down velocity each frame (0-1) */
|
|
86
|
+
this.damping = objectDefaultDamping;
|
|
87
|
+
/** @property {number} - How much to slow down rotation each frame (0-1) */
|
|
88
|
+
this.angleDamping = objectDefaultAngleDamping;
|
|
89
|
+
/** @property {number} - How bouncy the object is when colliding (0-1) */
|
|
90
|
+
this.restitution = objectDefaultRestitution;
|
|
91
|
+
/** @property {number} - How much friction to apply when sliding (0-1) */
|
|
92
|
+
this.friction = objectDefaultFriction;
|
|
93
|
+
/** @property {number} - How much to scale gravity by for this object */
|
|
94
|
+
this.gravityScale = 1;
|
|
95
|
+
/** @property {number} - Objects are sorted by render order */
|
|
96
|
+
this.renderOrder = renderOrder;
|
|
97
|
+
/** @property {Vector2} - Velocity of the object */
|
|
98
|
+
this.velocity = vec2();
|
|
99
|
+
/** @property {number} - Angular velocity of the object */
|
|
100
|
+
this.angleVelocity = 0;
|
|
101
|
+
/** @property {number} - Track when object was created */
|
|
102
|
+
this.spawnTime = time;
|
|
103
|
+
/** @property {Array<EngineObject>} - List of children of this object */
|
|
104
|
+
this.children = [];
|
|
105
|
+
/** @property {boolean} - Limit object speed along x and y axis */
|
|
106
|
+
this.clampSpeed = true;
|
|
107
|
+
/** @property {EngineObject} - Object we are standing on, if any */
|
|
108
|
+
this.groundObject = undefined;
|
|
109
|
+
|
|
110
|
+
// parent child system
|
|
111
|
+
/** @property {EngineObject} - Parent of object if in local space */
|
|
112
|
+
this.parent = undefined;
|
|
113
|
+
/** @property {Vector2} - Local position if child */
|
|
114
|
+
this.localPos = vec2();
|
|
115
|
+
/** @property {number} - Local angle if child */
|
|
116
|
+
this.localAngle = 0;
|
|
117
|
+
|
|
118
|
+
// collision flags
|
|
119
|
+
/** @property {boolean} - Object collides with the tile collision */
|
|
120
|
+
this.collideTiles = false;
|
|
121
|
+
/** @property {boolean} - Object collides with solid objects */
|
|
122
|
+
this.collideSolidObjects = false;
|
|
123
|
+
/** @property {boolean} - Object collides with and blocks other objects */
|
|
124
|
+
this.isSolid = false;
|
|
125
|
+
/** @property {boolean} - Object collides with raycasts */
|
|
126
|
+
this.collideRaycast = false;
|
|
127
|
+
|
|
128
|
+
/** @property {boolean} - Object is skipped by engineObjectsDestroy, for things that outlive a level like a camera
|
|
129
|
+
* - Calling destroy on it still destroys it, and its children go with it either way */
|
|
130
|
+
this.persistent = false;
|
|
131
|
+
|
|
132
|
+
// add to list of objects
|
|
133
|
+
engineObjects.push(this);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Update the object transform, called automatically by engine even when paused */
|
|
137
|
+
updateTransforms()
|
|
138
|
+
{
|
|
139
|
+
const parent = this.parent;
|
|
140
|
+
if (parent)
|
|
141
|
+
{
|
|
142
|
+
// compose with parent transform inline to avoid intermediate vector allocs
|
|
143
|
+
const mirror = parent.getMirrorSign();
|
|
144
|
+
const lp = this.localPos, pp = parent.pos;
|
|
145
|
+
const lx = lp.x*mirror, ly = lp.y, pa = parent.angle;
|
|
146
|
+
if (pa)
|
|
147
|
+
{
|
|
148
|
+
const c = cos(-pa), s = sin(-pa);
|
|
149
|
+
this.pos.set(lx*c - ly*s + pp.x, lx*s + ly*c + pp.y);
|
|
150
|
+
}
|
|
151
|
+
else
|
|
152
|
+
this.pos.set(lx + pp.x, ly + pp.y);
|
|
153
|
+
this.angle = mirror*this.localAngle + pa;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// update children
|
|
157
|
+
for (const child of this.children)
|
|
158
|
+
child.updateTransforms();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Update the object physics, called automatically by engine once each frame. Can be overridden to stop or change how physics works for an object. */
|
|
162
|
+
updatePhysics()
|
|
163
|
+
{
|
|
164
|
+
// child objects do not have physics
|
|
165
|
+
ASSERT(!this.parent);
|
|
166
|
+
|
|
167
|
+
// bail if a collision callback destroyed us mid-frame
|
|
168
|
+
if (this.destroyed) return;
|
|
169
|
+
|
|
170
|
+
if (this.clampSpeed)
|
|
171
|
+
{
|
|
172
|
+
// limit max speed to prevent missing collisions
|
|
173
|
+
this.velocity.x = clamp(this.velocity.x, -objectMaxSpeed, objectMaxSpeed);
|
|
174
|
+
this.velocity.y = clamp(this.velocity.y, -objectMaxSpeed, objectMaxSpeed);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// apply physics
|
|
178
|
+
const oldPos = this.pos.copy();
|
|
179
|
+
this.velocity.x *= this.damping;
|
|
180
|
+
this.velocity.y *= this.damping;
|
|
181
|
+
if (this.mass)
|
|
182
|
+
{
|
|
183
|
+
// apply gravity only if it has mass
|
|
184
|
+
this.velocity.x += gravity.x * this.gravityScale;
|
|
185
|
+
this.velocity.y += gravity.y * this.gravityScale;
|
|
186
|
+
}
|
|
187
|
+
this.pos.x += this.velocity.x;
|
|
188
|
+
this.pos.y += this.velocity.y;
|
|
189
|
+
this.angle += this.angleVelocity *= this.angleDamping;
|
|
190
|
+
|
|
191
|
+
// physics sanity checks
|
|
192
|
+
ASSERT(this.angleDamping >= 0 && this.angleDamping <= 1);
|
|
193
|
+
ASSERT(this.damping >= 0 && this.damping <= 1);
|
|
194
|
+
|
|
195
|
+
// don't do collision for static objects or if solver disabled
|
|
196
|
+
if (!enablePhysicsSolver || !this.mass) return;
|
|
197
|
+
|
|
198
|
+
const wasFalling = this.velocity.y < 0 && gravity.y < 0 || this.velocity.y > 0 && gravity.y > 0;
|
|
199
|
+
if (this.groundObject)
|
|
200
|
+
{
|
|
201
|
+
// apply friction in local space of ground object
|
|
202
|
+
const friction = max(this.friction, this.groundObject.friction);
|
|
203
|
+
const groundSpeed = this.groundObject.velocity.x;
|
|
204
|
+
this.velocity.x = groundSpeed + (this.velocity.x - groundSpeed) * friction;
|
|
205
|
+
this.groundObject = undefined;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// an object with no width or height has no box to push out of, or to be pushed out of
|
|
209
|
+
if (this.collideSolidObjects && this.size.x && this.size.y)
|
|
210
|
+
{
|
|
211
|
+
// check collisions against solid objects
|
|
212
|
+
const epsilon = .001; // necessary to push slightly outside of the collision
|
|
213
|
+
for (const o of engineObjectsCollide)
|
|
214
|
+
{
|
|
215
|
+
// skip destroyed, child objects, self collision, or objects with no box
|
|
216
|
+
if (o.destroyed || o.parent || o === this || !o.size.x || !o.size.y) continue;
|
|
217
|
+
|
|
218
|
+
// non solid objects don't collide with each other
|
|
219
|
+
if (!this.isSolid && !o.isSolid) continue;
|
|
220
|
+
|
|
221
|
+
// check collision
|
|
222
|
+
if (!this.isOverlappingObject(o)) continue;
|
|
223
|
+
|
|
224
|
+
// notify objects of collision and check if should be resolved
|
|
225
|
+
const collide1 = this.collideWithObject(o);
|
|
226
|
+
const collide2 = o.collideWithObject(this);
|
|
227
|
+
if (!collide1 || !collide2) continue;
|
|
228
|
+
|
|
229
|
+
if (isOverlapping(oldPos, this.size, o.pos, o.size))
|
|
230
|
+
{
|
|
231
|
+
// if already was touching, try to push away
|
|
232
|
+
const deltaPos = oldPos.subtract(o.pos);
|
|
233
|
+
const length = deltaPos.length();
|
|
234
|
+
const pushAwayAccel = .001;
|
|
235
|
+
const velocity = length < .001 ? vec2(0,1) : deltaPos.scale(pushAwayAccel/length);
|
|
236
|
+
this.velocity = this.velocity.add(velocity);
|
|
237
|
+
if (o.mass) // push away other object if not fixed
|
|
238
|
+
o.velocity = o.velocity.subtract(velocity);
|
|
239
|
+
|
|
240
|
+
debugPhysics && debugOverlap(this.pos, this.size, o.pos, o.size, '#f00');
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// check for collision
|
|
245
|
+
const sizeBoth = this.size.add(o.size);
|
|
246
|
+
const smallStepUp = (oldPos.y - o.pos.y)*2 > sizeBoth.y + gravity.y; // prefer to push up if small delta
|
|
247
|
+
const isBlockedX = abs(oldPos.y - o.pos.y)*2 < sizeBoth.y;
|
|
248
|
+
const isBlockedY = abs(oldPos.x - o.pos.x)*2 < sizeBoth.x;
|
|
249
|
+
const restitution = max(this.restitution, o.restitution);
|
|
250
|
+
|
|
251
|
+
if (smallStepUp || isBlockedY || !isBlockedX) // resolve y collision
|
|
252
|
+
{
|
|
253
|
+
// push outside object collision
|
|
254
|
+
this.pos.y = o.pos.y + (sizeBoth.y/2 + epsilon) * sign(oldPos.y - o.pos.y);
|
|
255
|
+
if ((o.groundObject && wasFalling) || !o.mass)
|
|
256
|
+
{
|
|
257
|
+
// set ground object if landed on something
|
|
258
|
+
if (wasFalling)
|
|
259
|
+
this.groundObject = o;
|
|
260
|
+
|
|
261
|
+
// bounce if other object is fixed or grounded
|
|
262
|
+
this.velocity.y *= -restitution;
|
|
263
|
+
}
|
|
264
|
+
else if (o.mass)
|
|
265
|
+
{
|
|
266
|
+
// inelastic collision
|
|
267
|
+
const inelastic = (this.mass * this.velocity.y + o.mass * o.velocity.y) / (this.mass + o.mass);
|
|
268
|
+
|
|
269
|
+
// elastic collision
|
|
270
|
+
const elastic0 = this.velocity.y * (this.mass - o.mass) / (this.mass + o.mass)
|
|
271
|
+
+ o.velocity.y * 2 * o.mass / (this.mass + o.mass);
|
|
272
|
+
const elastic1 = o.velocity.y * (o.mass - this.mass) / (this.mass + o.mass)
|
|
273
|
+
+ this.velocity.y * 2 * this.mass / (this.mass + o.mass);
|
|
274
|
+
|
|
275
|
+
// lerp between elastic or inelastic based on restitution
|
|
276
|
+
this.velocity.y = lerp(inelastic, elastic0, restitution);
|
|
277
|
+
o.velocity.y = lerp(inelastic, elastic1, restitution);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (!smallStepUp && isBlockedX) // resolve x collision
|
|
281
|
+
{
|
|
282
|
+
// push outside collision
|
|
283
|
+
this.pos.x = o.pos.x + (sizeBoth.x/2 + epsilon) * sign(oldPos.x - o.pos.x);
|
|
284
|
+
if (o.mass)
|
|
285
|
+
{
|
|
286
|
+
// inelastic collision
|
|
287
|
+
const inelastic = (this.mass * this.velocity.x + o.mass * o.velocity.x) / (this.mass + o.mass);
|
|
288
|
+
|
|
289
|
+
// elastic collision
|
|
290
|
+
const elastic0 = this.velocity.x * (this.mass - o.mass) / (this.mass + o.mass)
|
|
291
|
+
+ o.velocity.x * 2 * o.mass / (this.mass + o.mass);
|
|
292
|
+
const elastic1 = o.velocity.x * (o.mass - this.mass) / (this.mass + o.mass)
|
|
293
|
+
+ this.velocity.x * 2 * this.mass / (this.mass + o.mass);
|
|
294
|
+
|
|
295
|
+
// lerp between elastic or inelastic based on restitution
|
|
296
|
+
this.velocity.x = lerp(inelastic, elastic0, restitution);
|
|
297
|
+
o.velocity.x = lerp(inelastic, elastic1, restitution);
|
|
298
|
+
}
|
|
299
|
+
else // bounce if other object is fixed
|
|
300
|
+
this.velocity.x *= -restitution;
|
|
301
|
+
}
|
|
302
|
+
debugPhysics && debugOverlap(this.pos, this.size, o.pos, o.size, '#f0f');
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (this.collideTiles)
|
|
306
|
+
{
|
|
307
|
+
// check collision against tiles
|
|
308
|
+
const hitLayer = tileCollisionTest(this.pos, this.size, this);
|
|
309
|
+
if (hitLayer)
|
|
310
|
+
{
|
|
311
|
+
// if already was stuck in collision, don't do anything
|
|
312
|
+
// this should not happen unless something starts in collision
|
|
313
|
+
if (!tileCollisionTest(oldPos, this.size, this))
|
|
314
|
+
{
|
|
315
|
+
// test which side we bounced off (or both if a corner)
|
|
316
|
+
const isBlockedX = tileCollisionTest(vec2(this.pos.x, oldPos.y), this.size, this);
|
|
317
|
+
const isBlockedY = tileCollisionTest(vec2(oldPos.x, this.pos.y), this.size, this);
|
|
318
|
+
const restitution = max(this.restitution, hitLayer.restitution);
|
|
319
|
+
if (isBlockedX)
|
|
320
|
+
{
|
|
321
|
+
// try to step over a 1-tile bump (direction follows gravity sign
|
|
322
|
+
// so inverted gravity steps down off a ceiling bump instead of up;
|
|
323
|
+
// zero gravity defaults to the normal-gravity step-up direction)
|
|
324
|
+
const epsilon = 1e-3;
|
|
325
|
+
const maxMove = .1;
|
|
326
|
+
const gravitySign = gravity.y > 0 ? -1 : 1;
|
|
327
|
+
const y = gravitySign > 0 ?
|
|
328
|
+
floor(oldPos.y-this.size.y/2+1) + this.size.y/2 + epsilon :
|
|
329
|
+
ceil( oldPos.y+this.size.y/2-1) - this.size.y/2 - epsilon;
|
|
330
|
+
const delta = abs(y - this.pos.y);
|
|
331
|
+
if (delta < maxMove)
|
|
332
|
+
if (!tileCollisionTest(vec2(this.pos.x, y), this.size, this))
|
|
333
|
+
{
|
|
334
|
+
this.pos.y = y;
|
|
335
|
+
debugPhysics && debugRect(this.pos, this.size, '#ff0');
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// move to previous X position and bounce
|
|
340
|
+
this.pos.x = oldPos.x;
|
|
341
|
+
this.velocity.x *= -restitution;
|
|
342
|
+
}
|
|
343
|
+
if (isBlockedY || !isBlockedX)
|
|
344
|
+
{
|
|
345
|
+
if (wasFalling)
|
|
346
|
+
{
|
|
347
|
+
// adjust position to slightly away from nearest tile
|
|
348
|
+
// this prevents gap between object and ground
|
|
349
|
+
const epsilon = .0001;
|
|
350
|
+
const offset = this.size.y/2 + epsilon;
|
|
351
|
+
this.pos.y = gravity.y < 0 ?
|
|
352
|
+
floor(oldPos.y-this.size.y/2) + offset :
|
|
353
|
+
ceil( oldPos.y+this.size.y/2) - offset;
|
|
354
|
+
|
|
355
|
+
// set ground object for tile collision
|
|
356
|
+
this.groundObject = hitLayer;
|
|
357
|
+
}
|
|
358
|
+
else
|
|
359
|
+
{
|
|
360
|
+
// move to previous Y position
|
|
361
|
+
this.pos.y = oldPos.y;
|
|
362
|
+
this.groundObject = undefined;
|
|
363
|
+
}
|
|
364
|
+
// bounce velocity
|
|
365
|
+
this.velocity.y *= -restitution;
|
|
366
|
+
}
|
|
367
|
+
debugPhysics && debugRect(this.pos, this.size, '#f00');
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/** Update the object, called automatically by engine once each frame. Does nothing by default. */
|
|
374
|
+
update() {}
|
|
375
|
+
|
|
376
|
+
/** Render the object, draws a tile by default, automatically called each frame, sorted by renderOrder */
|
|
377
|
+
render()
|
|
378
|
+
{
|
|
379
|
+
// default object render
|
|
380
|
+
drawTile(this.pos, this.drawSize || this.size, this.tileInfo, this.color, this.angle, this.mirror, this.additiveColor);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/** Optional hook called during the light system plugin's lightmap pass to draw this object's lightmap contribution. Does nothing by default. */
|
|
384
|
+
renderLight() {}
|
|
385
|
+
|
|
386
|
+
/** Destroy this object, destroy its children, detach its parent, and mark it for removal
|
|
387
|
+
* @param {boolean} [immediate] - should attached effects be allowed to die off? */
|
|
388
|
+
destroy(immediate=false)
|
|
389
|
+
{
|
|
390
|
+
if (this.destroyed) return;
|
|
391
|
+
|
|
392
|
+
// disconnect from parent and destroy children
|
|
393
|
+
this.destroyed = true;
|
|
394
|
+
this.parent?.removeChild(this);
|
|
395
|
+
for (const child of this.children)
|
|
396
|
+
{
|
|
397
|
+
child.parent = undefined;
|
|
398
|
+
child.destroy(immediate);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/** Convert from local space to world space
|
|
403
|
+
* @param {Vector2} pos - local space point */
|
|
404
|
+
localToWorld(pos) { return this.pos.add(pos.rotate(this.angle)); }
|
|
405
|
+
|
|
406
|
+
/** Convert from world space to local space
|
|
407
|
+
* @param {Vector2} pos - world space point */
|
|
408
|
+
worldToLocal(pos) { return pos.subtract(this.pos).rotate(-this.angle); }
|
|
409
|
+
|
|
410
|
+
/** Convert from local space to world space for a vector (rotation only)
|
|
411
|
+
* @param {Vector2} vec - local space vector */
|
|
412
|
+
localToWorldVector(vec) { return vec.rotate(this.angle); }
|
|
413
|
+
|
|
414
|
+
/** Convert from world space to local space for a vector (rotation only)
|
|
415
|
+
* @param {Vector2} vec - world space vector */
|
|
416
|
+
worldToLocalVector(vec) { return vec.rotate(-this.angle); }
|
|
417
|
+
|
|
418
|
+
/** Called to check if a tile collision should be resolved. Return true for physics to resolve the collision or false to ignore and resolve it manually.
|
|
419
|
+
* @param {number} tileData - the value of the tile at the position
|
|
420
|
+
* @param {Vector2} pos - tile where the collision occurred
|
|
421
|
+
* @return {boolean} - true if the collision should be resolved by modifying it's position and velocity */
|
|
422
|
+
collideWithTile(tileData, pos) { return tileData > 0; }
|
|
423
|
+
|
|
424
|
+
/** Called by the engine to check if an object collision should be resolved. Return true for physics to resolve the collision or false to ignore and resolve it manually.
|
|
425
|
+
* @param {EngineObject} object - the object to test against
|
|
426
|
+
* @param {Object} [push] - what it would take to move this object clear, a Vector3 from the 3D plugin, undefined in 2D
|
|
427
|
+
* @return {boolean} - true if the collision should be resolved by modifying it's position and velocity
|
|
428
|
+
*/
|
|
429
|
+
collideWithObject(object, push) { return true; }
|
|
430
|
+
|
|
431
|
+
/** Get this object's up vector
|
|
432
|
+
* @param {number} [scale] - length of the vector
|
|
433
|
+
* @return {Vector2} */
|
|
434
|
+
getUp(scale=1) { return vec2().setAngle(this.angle, scale); }
|
|
435
|
+
|
|
436
|
+
/** Get this object's right vector
|
|
437
|
+
* @param {number} [scale] - length of the vector
|
|
438
|
+
* @return {Vector2} */
|
|
439
|
+
getRight(scale=1) { return vec2().setAngle(this.angle+PI/2, scale); }
|
|
440
|
+
|
|
441
|
+
/** How long since the object was created
|
|
442
|
+
* @return {number} */
|
|
443
|
+
getAliveTime() { return time - this.spawnTime; }
|
|
444
|
+
|
|
445
|
+
/** Get the speed of this object
|
|
446
|
+
* @return {number} */
|
|
447
|
+
getSpeed() { return this.velocity.length(); }
|
|
448
|
+
|
|
449
|
+
/** Apply acceleration to this object (adjust velocity, not affected by mass)
|
|
450
|
+
* @param {Vector2} acceleration */
|
|
451
|
+
applyAcceleration(acceleration)
|
|
452
|
+
{ if (this.mass) this.velocity = this.velocity.add(acceleration); }
|
|
453
|
+
|
|
454
|
+
/** Apply angular acceleration to this object
|
|
455
|
+
* @param {number} acceleration */
|
|
456
|
+
applyAngularAcceleration(acceleration)
|
|
457
|
+
{ if (this.mass) this.angleVelocity += acceleration; }
|
|
458
|
+
|
|
459
|
+
/** Apply force to this object (adjust velocity, affected by mass)
|
|
460
|
+
* @param {Vector2} force */
|
|
461
|
+
applyForce(force)
|
|
462
|
+
{ if (this.mass) this.applyAcceleration(force.scale(1/this.mass)); }
|
|
463
|
+
|
|
464
|
+
/** Get the direction of the mirror
|
|
465
|
+
* @return {number} -1 if this.mirror is true, or 1 if not mirrored */
|
|
466
|
+
getMirrorSign() { return this.mirror ? -1 : 1; }
|
|
467
|
+
|
|
468
|
+
/** Attaches a child to this with a local transform, returns child for chaining
|
|
469
|
+
* @param {EngineObject} child
|
|
470
|
+
* @param {Vector2} [localPos=vec2()]
|
|
471
|
+
* @param {number} [localAngle]
|
|
472
|
+
* @return {EngineObject} The child object added */
|
|
473
|
+
addChild(child, localPos=vec2(), localAngle=0)
|
|
474
|
+
{
|
|
475
|
+
ASSERT(!this.destroyed, 'cannot add child to destroyed object');
|
|
476
|
+
if (this.destroyed) return child;
|
|
477
|
+
ASSERT(!child.parent && !this.children.includes(child));
|
|
478
|
+
ASSERT(child instanceof EngineObject, 'child must be an EngineObject');
|
|
479
|
+
ASSERT(child !== this, 'cannot add self as child');
|
|
480
|
+
this.children.push(child);
|
|
481
|
+
child.parent = this;
|
|
482
|
+
child.localPos = localPos.copy();
|
|
483
|
+
child.localAngle = localAngle;
|
|
484
|
+
child.updateTransforms();
|
|
485
|
+
return child;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/** Removes a child from this one
|
|
489
|
+
* @param {EngineObject} child */
|
|
490
|
+
removeChild(child)
|
|
491
|
+
{
|
|
492
|
+
ASSERT(child.parent === this && this.children.includes(child));
|
|
493
|
+
this.children.splice(this.children.indexOf(child), 1);
|
|
494
|
+
child.parent = undefined;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/** Check if overlapping another engine object
|
|
498
|
+
* Collisions are resolved to prevent overlaps
|
|
499
|
+
* @param {EngineObject} object
|
|
500
|
+
* @return {boolean} */
|
|
501
|
+
isOverlappingObject(object)
|
|
502
|
+
{ return this.isOverlapping(object.pos, object.size); }
|
|
503
|
+
|
|
504
|
+
/** Check if overlapping a point or aligned bounding box
|
|
505
|
+
* @param {Vector2} pos - Center of box
|
|
506
|
+
* @param {Vector2} [size=vec2()] - Size of box, uses a point if undefined
|
|
507
|
+
* @return {boolean} */
|
|
508
|
+
isOverlapping(pos, size=vec2())
|
|
509
|
+
{ return isOverlapping(this.pos, this.size, pos, size); }
|
|
510
|
+
|
|
511
|
+
/** Set how this object collides
|
|
512
|
+
* @param {boolean} [collideSolidObjects] - Does it collide with solid objects?
|
|
513
|
+
* @param {boolean} [isSolid] - Does it collide with and block other objects? (expensive in large numbers)
|
|
514
|
+
* @param {boolean} [collideTiles] - Does it collide with the tile collision?
|
|
515
|
+
* @param {boolean} [collideRaycast] - Does it collide with raycasts? */
|
|
516
|
+
setCollision(collideSolidObjects=true, isSolid=true, collideTiles=true, collideRaycast=true)
|
|
517
|
+
{
|
|
518
|
+
ASSERT(collideSolidObjects || !isSolid, 'solid objects must be set to collide');
|
|
519
|
+
|
|
520
|
+
this.collideSolidObjects = collideSolidObjects;
|
|
521
|
+
this.isSolid = isSolid;
|
|
522
|
+
this.collideTiles = collideTiles;
|
|
523
|
+
this.collideRaycast = collideRaycast;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/** Returns string containing info about this object for debugging
|
|
527
|
+
* @return {string} */
|
|
528
|
+
toString()
|
|
529
|
+
{
|
|
530
|
+
let text = 'type = ' + this.constructor.name;
|
|
531
|
+
if (this.pos.x || this.pos.y)
|
|
532
|
+
text += '\npos = ' + this.pos;
|
|
533
|
+
if (this.velocity.x || this.velocity.y)
|
|
534
|
+
text += '\nvelocity = ' + this.velocity;
|
|
535
|
+
if (this.size.x || this.size.y)
|
|
536
|
+
text += '\nsize = ' + this.size;
|
|
537
|
+
if (this.angle)
|
|
538
|
+
text += '\nangle = ' + this.angle.toFixed(3);
|
|
539
|
+
if (this.color)
|
|
540
|
+
text += '\ncolor = ' + this.color;
|
|
541
|
+
return text;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/** Render debug info for this object */
|
|
545
|
+
renderDebugInfo()
|
|
546
|
+
{
|
|
547
|
+
if (!debug) return;
|
|
548
|
+
|
|
549
|
+
// check if there is anything to show
|
|
550
|
+
const hasPhysics = this.collideTiles || this.collideSolidObjects || this.isSolid;
|
|
551
|
+
if (!hasPhysics && !this.parent) return;
|
|
552
|
+
|
|
553
|
+
// show object info for debugging
|
|
554
|
+
const size = vec2(max(this.size.x, .2), max(this.size.y, .2));
|
|
555
|
+
const color = rgb(this.collideTiles?1:0, this.collideSolidObjects?1:0, this.isSolid?1:0, .5);
|
|
556
|
+
debugRect(this.pos, size, color, 0, this.angle, hasPhysics);
|
|
557
|
+
if (this.parent)
|
|
558
|
+
debugRect(this.pos, size.scale(.8), rgb(1,1,1,.5), 0, this.angle);
|
|
559
|
+
this.parent && debugLine(this.pos, this.parent.pos, rgb(1,1,1,.5), .5);
|
|
560
|
+
}
|
|
552
561
|
}
|