littlejsengine 1.14.19 → 1.14.28
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/dist/littlejs.d.ts +217 -38
- package/dist/littlejs.esm.js +879 -324
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +861 -324
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +799 -325
- package/examples/box2d/gameObjects.js +6 -10
- package/examples/box2d/scenes.js +2 -2
- package/examples/breakout/gameObjects.js +1 -1
- package/examples/electron/game.js +1 -41
- package/examples/electron/index.html +2 -2
- package/examples/htmlMenu/game.js +1 -1
- package/examples/index.html +19 -10
- package/examples/module/game.js +5 -7
- package/examples/particles/index.html +6 -9
- package/examples/platformer/gameCharacter.js +4 -3
- package/examples/platformer/gameEffects.js +7 -2
- package/examples/platformer/gameObjects.js +6 -11
- package/examples/shorts/animation.js +2 -2
- package/examples/shorts/base.html +4 -1
- package/examples/shorts/box2d.js +2 -2
- package/examples/shorts/box2dCar.js +18 -7
- package/examples/shorts/box2dPool.js +108 -0
- package/examples/shorts/cameraDrag.js +22 -0
- package/examples/shorts/debugDraw.js +37 -0
- package/examples/shorts/flappyGame.js +1 -0
- package/examples/shorts/fps.js +90 -0
- package/examples/shorts/helloWorld.js +1 -1
- package/examples/shorts/hillGlideGame.js +1 -3
- package/examples/shorts/input.js +59 -0
- package/examples/shorts/landerGame.js +1 -3
- package/examples/shorts/medals.js +15 -9
- package/examples/shorts/music.js +15 -17
- package/examples/shorts/musicPlayer.js +24 -24
- package/examples/shorts/platformer.js +0 -2
- package/examples/shorts/postProcess.js +1 -1
- package/examples/shorts/sequencer.js +3 -3
- package/examples/shorts/slidingPuzzle.js +1 -1
- package/examples/shorts/spaceGame.js +1 -3
- package/examples/shorts/spriteAtlas.js +6 -8
- package/examples/shorts/starfield.js +1 -1
- package/examples/shorts/tileRaycast.js +39 -0
- package/examples/shorts/tiles.png +0 -0
- package/examples/shorts/tiltedView.js +1 -4
- package/examples/shorts/timers.js +1 -2
- package/examples/shorts/topDown.js +0 -2
- package/examples/starter/game.js +5 -7
- package/examples/starter/index.html +2 -2
- package/examples/typescript/game.js +3 -2
- package/examples/typescript/game.ts +5 -7
- package/examples/uiSystem/game.js +2 -2
- package/package.json +1 -1
- package/plugins/box2d.js +170 -50
- package/plugins/pluginExport.js +2 -0
- package/plugins/uiSystem.js +55 -27
- package/src/engine.js +19 -16
- package/src/engineAudio.js +27 -15
- package/src/engineDebug.js +64 -0
- package/src/engineDraw.js +88 -32
- package/src/engineExport.js +16 -0
- package/src/engineInput.js +35 -25
- package/src/engineMedals.js +2 -2
- package/src/engineObject.js +55 -10
- package/src/engineParticles.js +36 -20
- package/src/engineRelease.js +2 -1
- package/src/engineSettings.js +20 -1
- package/src/engineTileLayer.js +64 -59
- package/src/engineUtilities.js +213 -59
- package/src/engineWebGL.js +13 -8
- package/examples/shorts/raycasting.js +0 -79
package/plugins/box2d.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LittleJS Box2D Physics Plugin
|
|
3
3
|
* - Box2dObject extends EngineObject with Box2D physics
|
|
4
|
-
* - Call box2dInit()
|
|
4
|
+
* - Call box2dInit() to enable
|
|
5
5
|
* - You will also need to include box2d.wasm.js
|
|
6
|
-
* - Uses a super fast web assembly port of Box2D
|
|
6
|
+
* - Uses a super fast web assembly port of Box2D v2.3.1
|
|
7
7
|
* - More info: https://github.com/kripken/box2d.js
|
|
8
8
|
* - Functions to create polygon, circle, and edge shapes
|
|
9
9
|
* - Contact begin and end callbacks
|
|
@@ -35,9 +35,9 @@ function box2dSetDebug(enable) { box2dDebug = enable; }
|
|
|
35
35
|
///////////////////////////////////////////////////////////////////////////////
|
|
36
36
|
/**
|
|
37
37
|
* Box2D Object - extend with your own custom physics objects
|
|
38
|
-
* - A LittleJS object with Box2D physics
|
|
39
|
-
* - Each object has a Box2D body which can have multiple fixtures and joints
|
|
38
|
+
* - A LittleJS object with Box2D physics, dynamic by default
|
|
40
39
|
* - Provides interface for Box2D body and fixture functions
|
|
40
|
+
* - Each object can have multiple fixtures and joints
|
|
41
41
|
* @extends EngineObject
|
|
42
42
|
* @memberof Box2D
|
|
43
43
|
*/
|
|
@@ -51,7 +51,7 @@ class Box2dObject extends EngineObject
|
|
|
51
51
|
* @param {Color} [color]
|
|
52
52
|
* @param {number} [bodyType]
|
|
53
53
|
* @param {number} [renderOrder] */
|
|
54
|
-
constructor(pos, size, tileInfo, angle=0, color, bodyType=box2d.bodyTypeDynamic, renderOrder=0)
|
|
54
|
+
constructor(pos=vec2(), size=vec2(), tileInfo, angle=0, color, bodyType=box2d.bodyTypeDynamic, renderOrder=0)
|
|
55
55
|
{
|
|
56
56
|
super(pos, size, tileInfo, angle, color, renderOrder);
|
|
57
57
|
|
|
@@ -63,24 +63,27 @@ class Box2dObject extends EngineObject
|
|
|
63
63
|
this.body = box2d.world.CreateBody(bodyDef);
|
|
64
64
|
this.body.object = this;
|
|
65
65
|
this.lineColor = BLACK;
|
|
66
|
+
box2d.objects.push(this);
|
|
67
|
+
|
|
68
|
+
// edge lists and loops for drawing
|
|
69
|
+
this.edgeLists = [];
|
|
70
|
+
this.edgeLoops = [];
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
/** Destroy this object and its physics body */
|
|
69
74
|
destroy()
|
|
70
75
|
{
|
|
76
|
+
if (this.destroyed)
|
|
77
|
+
return;
|
|
78
|
+
|
|
71
79
|
// destroy physics body, fixtures, and joints
|
|
72
|
-
this.body
|
|
73
|
-
this.body
|
|
80
|
+
ASSERT(this.body, 'Box2dObject has no body to destroy');
|
|
81
|
+
box2d.world.DestroyBody(this.body);
|
|
74
82
|
super.destroy();
|
|
75
83
|
}
|
|
76
84
|
|
|
77
|
-
/**
|
|
78
|
-
|
|
79
|
-
{
|
|
80
|
-
// use box2d physics update instead of normal engine update
|
|
81
|
-
this.pos = box2d.vec2From(this.body.GetPosition());
|
|
82
|
-
this.angle = -this.body.GetAngle();
|
|
83
|
-
}
|
|
85
|
+
/** Box2d objects updated with Box2d world step */
|
|
86
|
+
updatePhysics() {}
|
|
84
87
|
|
|
85
88
|
/** Render the object, uses box2d drawing if no tile info exists */
|
|
86
89
|
render()
|
|
@@ -106,10 +109,23 @@ class Box2dObject extends EngineObject
|
|
|
106
109
|
* @param {Color} [lineColor]
|
|
107
110
|
* @param {number} [lineWidth]
|
|
108
111
|
* @param {CanvasRenderingContext2D} [context] */
|
|
109
|
-
drawFixtures(color=WHITE, lineColor, lineWidth=.1, context)
|
|
112
|
+
drawFixtures(color=WHITE, lineColor=BLACK, lineWidth=.1, context)
|
|
110
113
|
{
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
// draw non-edge fixtures
|
|
115
|
+
this.getFixtureList().forEach((fixture)=>
|
|
116
|
+
{
|
|
117
|
+
const shape = box2d.castObjectType(fixture.GetShape());
|
|
118
|
+
if (shape.GetType() !== box2d.instance.b2Shape.e_edge)
|
|
119
|
+
{
|
|
120
|
+
box2d.drawFixture(fixture, this.pos, this.angle, color, lineColor, lineWidth, context);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// draw edges using a single draw line for better connections
|
|
125
|
+
this.edgeLists.forEach(points=>
|
|
126
|
+
drawLineList(points, lineWidth, lineColor, false, this.pos, this.angle));
|
|
127
|
+
this.edgeLoops.forEach(points=>
|
|
128
|
+
drawLineList(points, lineWidth, lineColor, true, this.pos, this.angle));
|
|
113
129
|
}
|
|
114
130
|
|
|
115
131
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -134,6 +150,10 @@ class Box2dObject extends EngineObject
|
|
|
134
150
|
* @param {boolean} [isSensor] */
|
|
135
151
|
addShape(shape, density=1, friction=.2, restitution=0, isSensor=false)
|
|
136
152
|
{
|
|
153
|
+
ASSERT(isNumber(density), 'density must be a number');
|
|
154
|
+
ASSERT(isNumber(friction), 'friction must be a number');
|
|
155
|
+
ASSERT(isNumber(restitution), 'restitution must be a number');
|
|
156
|
+
|
|
137
157
|
const fd = new box2d.instance.b2FixtureDef();
|
|
138
158
|
fd.set_shape(shape);
|
|
139
159
|
fd.set_density(density);
|
|
@@ -153,6 +173,11 @@ class Box2dObject extends EngineObject
|
|
|
153
173
|
* @param {boolean} [isSensor] */
|
|
154
174
|
addBox(size=vec2(1), offset=vec2(), angle=0, density, friction, restitution, isSensor)
|
|
155
175
|
{
|
|
176
|
+
ASSERT(isVector2(size), 'size must be a Vector2');
|
|
177
|
+
ASSERT(size.x > 0 && size.y > 0, 'size must be positive');
|
|
178
|
+
ASSERT(isVector2(offset), 'offset must be a Vector2');
|
|
179
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
180
|
+
|
|
156
181
|
const shape = new box2d.instance.b2PolygonShape();
|
|
157
182
|
shape.SetAsBox(size.x/2, size.y/2, box2d.vec2dTo(offset), angle);
|
|
158
183
|
return this.addShape(shape, density, friction, restitution, isSensor);
|
|
@@ -166,6 +191,8 @@ class Box2dObject extends EngineObject
|
|
|
166
191
|
* @param {boolean} [isSensor] */
|
|
167
192
|
addPoly(points, density, friction, restitution, isSensor)
|
|
168
193
|
{
|
|
194
|
+
ASSERT(isArray(points), 'points must be an array');
|
|
195
|
+
|
|
169
196
|
function box2dCreatePolygonShape(points)
|
|
170
197
|
{
|
|
171
198
|
function box2dCreatePointList(points)
|
|
@@ -201,6 +228,9 @@ class Box2dObject extends EngineObject
|
|
|
201
228
|
* @param {boolean} [isSensor] */
|
|
202
229
|
addRegularPoly(diameter=1, sides=8, density, friction, restitution, isSensor)
|
|
203
230
|
{
|
|
231
|
+
ASSERT(isNumber(diameter) && diameter>0, 'diameter must be a positive number');
|
|
232
|
+
ASSERT(isNumber(sides) && sides>2, 'sides must be a positive number greater than 2');
|
|
233
|
+
|
|
204
234
|
const points = [];
|
|
205
235
|
const radius = diameter/2;
|
|
206
236
|
for (let i=sides; i--;)
|
|
@@ -216,6 +246,8 @@ class Box2dObject extends EngineObject
|
|
|
216
246
|
* @param {boolean} [isSensor] */
|
|
217
247
|
addRandomPoly(diameter=1, density, friction, restitution, isSensor)
|
|
218
248
|
{
|
|
249
|
+
ASSERT(isNumber(diameter) && diameter>0, 'diameter must be a positive number');
|
|
250
|
+
|
|
219
251
|
const sides = randInt(3, 9);
|
|
220
252
|
const points = [];
|
|
221
253
|
const radius = diameter/2;
|
|
@@ -233,6 +265,9 @@ class Box2dObject extends EngineObject
|
|
|
233
265
|
* @param {boolean} [isSensor] */
|
|
234
266
|
addCircle(diameter=1, offset=vec2(), density, friction, restitution, isSensor)
|
|
235
267
|
{
|
|
268
|
+
ASSERT(isNumber(diameter) && diameter>0, 'diameter must be a positive number');
|
|
269
|
+
ASSERT(isVector2(offset), 'offset must be a Vector2');
|
|
270
|
+
|
|
236
271
|
const shape = new box2d.instance.b2CircleShape();
|
|
237
272
|
shape.set_m_p(box2d.vec2dTo(offset));
|
|
238
273
|
shape.set_m_radius(diameter/2);
|
|
@@ -248,53 +283,63 @@ class Box2dObject extends EngineObject
|
|
|
248
283
|
* @param {boolean} [isSensor] */
|
|
249
284
|
addEdge(point1, point2, density, friction, restitution, isSensor)
|
|
250
285
|
{
|
|
286
|
+
ASSERT(isVector2(point1), 'point1 must be a Vector2');
|
|
287
|
+
ASSERT(isVector2(point2), 'point2 must be a Vector2');
|
|
288
|
+
|
|
251
289
|
const shape = new box2d.instance.b2EdgeShape();
|
|
252
290
|
shape.Set(box2d.vec2dTo(point1), box2d.vec2dTo(point2));
|
|
253
291
|
return this.addShape(shape, density, friction, restitution, isSensor);
|
|
254
292
|
}
|
|
255
293
|
|
|
256
|
-
/** Add an edge
|
|
294
|
+
/** Add an edge list to the body
|
|
257
295
|
* @param {Array<Vector2>} points
|
|
258
296
|
* @param {number} [density]
|
|
259
297
|
* @param {number} [friction]
|
|
260
298
|
* @param {number} [restitution]
|
|
261
299
|
* @param {boolean} [isSensor] */
|
|
262
|
-
|
|
300
|
+
addEdgeList(points, density, friction, restitution, isSensor)
|
|
263
301
|
{
|
|
264
|
-
|
|
265
|
-
const
|
|
266
|
-
for (let i=0; i<points.length; ++i)
|
|
302
|
+
ASSERT(isArray(points), 'points must be an array');
|
|
303
|
+
const fixtures = [], edgePoints = [];
|
|
304
|
+
for (let i=0; i<points.length-1; ++i)
|
|
267
305
|
{
|
|
268
306
|
const shape = new box2d.instance.b2EdgeShape();
|
|
269
|
-
shape.set_m_vertex0(box2d.vec2dTo(
|
|
270
|
-
shape.set_m_vertex1(box2d.vec2dTo(
|
|
271
|
-
shape.set_m_vertex2(box2d.vec2dTo(
|
|
272
|
-
shape.set_m_vertex3(box2d.vec2dTo(
|
|
307
|
+
points[i-1] && shape.set_m_vertex0(box2d.vec2dTo(points[i-1]));
|
|
308
|
+
points[i+0] && shape.set_m_vertex1(box2d.vec2dTo(points[i+0]));
|
|
309
|
+
points[i+1] && shape.set_m_vertex2(box2d.vec2dTo(points[i+1]));
|
|
310
|
+
points[i+2] && shape.set_m_vertex3(box2d.vec2dTo(points[i+2]));
|
|
273
311
|
const f = this.addShape(shape, density, friction, restitution, isSensor);
|
|
274
312
|
fixtures.push(f);
|
|
313
|
+
edgePoints.push(points[i].copy());
|
|
275
314
|
}
|
|
315
|
+
edgePoints.push(points[points.length-1].copy());
|
|
316
|
+
this.edgeLists.push(edgePoints);
|
|
276
317
|
return fixtures;
|
|
277
318
|
}
|
|
278
319
|
|
|
279
|
-
/** Add an edge
|
|
320
|
+
/** Add an edge loop to the body, an edge loop connects the end points
|
|
280
321
|
* @param {Array<Vector2>} points
|
|
281
322
|
* @param {number} [density]
|
|
282
323
|
* @param {number} [friction]
|
|
283
324
|
* @param {number} [restitution]
|
|
284
325
|
* @param {boolean} [isSensor] */
|
|
285
|
-
|
|
326
|
+
addEdgeLoop(points, density, friction, restitution, isSensor)
|
|
286
327
|
{
|
|
287
|
-
|
|
288
|
-
|
|
328
|
+
ASSERT(isArray(points), 'points must be an array');
|
|
329
|
+
const fixtures = [], edgePoints = [];
|
|
330
|
+
const getPoint = i=> points[mod(i,points.length)];
|
|
331
|
+
for (let i=0; i<points.length; ++i)
|
|
289
332
|
{
|
|
290
333
|
const shape = new box2d.instance.b2EdgeShape();
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
334
|
+
shape.set_m_vertex0(box2d.vec2dTo(getPoint(i-1)));
|
|
335
|
+
shape.set_m_vertex1(box2d.vec2dTo(getPoint(i+0)));
|
|
336
|
+
shape.set_m_vertex2(box2d.vec2dTo(getPoint(i+1)));
|
|
337
|
+
shape.set_m_vertex3(box2d.vec2dTo(getPoint(i+2)));
|
|
295
338
|
const f = this.addShape(shape, density, friction, restitution, isSensor);
|
|
296
339
|
fixtures.push(f);
|
|
340
|
+
i < points.length && edgePoints.push(points[i].copy());
|
|
297
341
|
}
|
|
342
|
+
this.edgeLoops.push(edgePoints);
|
|
298
343
|
return fixtures;
|
|
299
344
|
}
|
|
300
345
|
|
|
@@ -329,6 +374,10 @@ class Box2dObject extends EngineObject
|
|
|
329
374
|
* @return {number} */
|
|
330
375
|
getBodyType() { return this.body.GetType(); }
|
|
331
376
|
|
|
377
|
+
/** Get the speed of this object
|
|
378
|
+
* @return {number} */
|
|
379
|
+
getSpeed() { return this.getLinearVelocity().length(); }
|
|
380
|
+
|
|
332
381
|
///////////////////////////////////////////////////////////////////////////////
|
|
333
382
|
// physics set functions
|
|
334
383
|
|
|
@@ -344,33 +393,40 @@ class Box2dObject extends EngineObject
|
|
|
344
393
|
|
|
345
394
|
/** Sets the position
|
|
346
395
|
* @param {Vector2} pos */
|
|
347
|
-
setPosition(pos)
|
|
396
|
+
setPosition(pos)
|
|
397
|
+
{ this.setTransform(pos, this.body.GetAngle()); }
|
|
348
398
|
|
|
349
399
|
/** Sets the angle
|
|
350
400
|
* @param {number} angle */
|
|
351
|
-
setAngle(angle)
|
|
401
|
+
setAngle(angle)
|
|
402
|
+
{ this.setTransform(box2d.vec2From(this.body.GetPosition()), -angle); }
|
|
352
403
|
|
|
353
404
|
/** Sets the linear velocity
|
|
354
405
|
* @param {Vector2} velocity */
|
|
355
|
-
setLinearVelocity(velocity)
|
|
406
|
+
setLinearVelocity(velocity)
|
|
407
|
+
{ this.body.SetLinearVelocity(box2d.vec2dTo(velocity)); }
|
|
356
408
|
|
|
357
409
|
/** Sets the angular velocity
|
|
358
410
|
* @param {number} angularVelocity */
|
|
359
|
-
setAngularVelocity(angularVelocity)
|
|
411
|
+
setAngularVelocity(angularVelocity)
|
|
412
|
+
{ this.body.SetAngularVelocity(angularVelocity); }
|
|
360
413
|
|
|
361
414
|
/** Sets the linear damping
|
|
362
415
|
* @param {number} damping */
|
|
363
|
-
setLinearDamping(damping)
|
|
416
|
+
setLinearDamping(damping)
|
|
417
|
+
{ this.body.SetLinearDamping(damping); }
|
|
364
418
|
|
|
365
419
|
/** Sets the angular damping
|
|
366
420
|
* @param {number} damping */
|
|
367
|
-
setAngularDamping(damping)
|
|
421
|
+
setAngularDamping(damping)
|
|
422
|
+
{ this.body.SetAngularDamping(damping); }
|
|
368
423
|
|
|
369
424
|
/** Sets the gravity scale
|
|
370
425
|
* @param {number} [scale] */
|
|
371
|
-
setGravityScale(scale=1)
|
|
426
|
+
setGravityScale(scale=1)
|
|
427
|
+
{ this.body.SetGravityScale(this.gravityScale = scale); }
|
|
372
428
|
|
|
373
|
-
/** Should
|
|
429
|
+
/** Should be like a bullet for continuous collision detection?
|
|
374
430
|
* @param {boolean} [isBullet] */
|
|
375
431
|
setBullet(isBullet=true) { this.body.SetBullet(isBullet); }
|
|
376
432
|
|
|
@@ -384,11 +440,13 @@ class Box2dObject extends EngineObject
|
|
|
384
440
|
|
|
385
441
|
/** Set whether the body is allowed to sleep
|
|
386
442
|
* @param {boolean} [isAllowed] */
|
|
387
|
-
setSleepingAllowed(isAllowed=true)
|
|
443
|
+
setSleepingAllowed(isAllowed=true)
|
|
444
|
+
{ this.body.SetSleepingAllowed(isAllowed); }
|
|
388
445
|
|
|
389
446
|
/** Set whether the body can rotate
|
|
390
447
|
* @param {boolean} [isFixed] */
|
|
391
|
-
setFixedRotation(isFixed=true)
|
|
448
|
+
setFixedRotation(isFixed=true)
|
|
449
|
+
{ this.body.SetFixedRotation(isFixed); }
|
|
392
450
|
|
|
393
451
|
/** Set the center of mass of the body
|
|
394
452
|
* @param {Vector2} center */
|
|
@@ -400,10 +458,11 @@ class Box2dObject extends EngineObject
|
|
|
400
458
|
|
|
401
459
|
/** Set the moment of inertia of the body
|
|
402
460
|
* @param {number} momentOfInertia */
|
|
403
|
-
setMomentOfInertia(momentOfInertia)
|
|
461
|
+
setMomentOfInertia(momentOfInertia)
|
|
462
|
+
{ this.setMassData(undefined, undefined, momentOfInertia) }
|
|
404
463
|
|
|
405
464
|
/** Reset the mass, center of mass, and moment */
|
|
406
|
-
resetMassData()
|
|
465
|
+
resetMassData() { this.body.ResetMassData(); }
|
|
407
466
|
|
|
408
467
|
/** Set the mass data of the body
|
|
409
468
|
* @param {Vector2} [localCenter]
|
|
@@ -1045,6 +1104,50 @@ class Box2dPrismaticJoint extends Box2dJoint
|
|
|
1045
1104
|
getMotorForce(time) { return this.box2dJoint.GetMotorForce(1/time); }
|
|
1046
1105
|
}
|
|
1047
1106
|
|
|
1107
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
1108
|
+
/**
|
|
1109
|
+
* Box2D Static Object - Box2d with a static physics body
|
|
1110
|
+
* @extends Box2dObject
|
|
1111
|
+
* @memberof Box2D
|
|
1112
|
+
*/
|
|
1113
|
+
class Box2dStaticObject extends Box2dObject
|
|
1114
|
+
{
|
|
1115
|
+
/** Create a LittleJS object with Box2d physics
|
|
1116
|
+
* @param {Vector2} [pos]
|
|
1117
|
+
* @param {Vector2} [size]
|
|
1118
|
+
* @param {TileInfo} [tileInfo]
|
|
1119
|
+
* @param {number} [angle]
|
|
1120
|
+
* @param {Color} [color]
|
|
1121
|
+
* @param {number} [renderOrder] */
|
|
1122
|
+
constructor(pos, size, tileInfo, angle=0, color, renderOrder=0)
|
|
1123
|
+
{
|
|
1124
|
+
const bodyType = box2d.bodyTypeStatic;
|
|
1125
|
+
super(pos, size, tileInfo, angle, color, bodyType, renderOrder);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
1130
|
+
/**
|
|
1131
|
+
* Box2D Kiematic Object - Box2d with a kinematic physics body
|
|
1132
|
+
* @extends Box2dObject
|
|
1133
|
+
* @memberof Box2D
|
|
1134
|
+
*/
|
|
1135
|
+
class Box2dKiematicObject extends Box2dObject
|
|
1136
|
+
{
|
|
1137
|
+
/** Create a LittleJS object with Box2d physics
|
|
1138
|
+
* @param {Vector2} [pos]
|
|
1139
|
+
* @param {Vector2} [size]
|
|
1140
|
+
* @param {TileInfo} [tileInfo]
|
|
1141
|
+
* @param {number} [angle]
|
|
1142
|
+
* @param {Color} [color]
|
|
1143
|
+
* @param {number} [renderOrder] */
|
|
1144
|
+
constructor(pos, size, tileInfo, angle=0, color, renderOrder=0)
|
|
1145
|
+
{
|
|
1146
|
+
const bodyType = box2d.bodyTypeKinematic;
|
|
1147
|
+
super(pos, size, tileInfo, angle, color, bodyType, renderOrder);
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1048
1151
|
///////////////////////////////////////////////////////////////////////////////
|
|
1049
1152
|
/**
|
|
1050
1153
|
* Box2D Wheel Joint
|
|
@@ -1407,6 +1510,7 @@ class Box2dPlugin
|
|
|
1407
1510
|
box2d = this;
|
|
1408
1511
|
this.instance = instance;
|
|
1409
1512
|
this.world = new box2d.instance.b2World();
|
|
1513
|
+
this.objects = [];
|
|
1410
1514
|
|
|
1411
1515
|
/** @property {number} - Velocity iterations per update*/
|
|
1412
1516
|
this.velocityIterations = 8;
|
|
@@ -1649,9 +1753,10 @@ class Box2dPlugin
|
|
|
1649
1753
|
|
|
1650
1754
|
/** converts a box2d vec2 pointer to a Vector2
|
|
1651
1755
|
* @param {Object} v */
|
|
1652
|
-
vec2FromPointer(
|
|
1756
|
+
vec2FromPointer(vp)
|
|
1653
1757
|
{
|
|
1654
|
-
|
|
1758
|
+
const v = box2d.instance.wrapPointer(vp, box2d.instance.b2Vec2);
|
|
1759
|
+
return box2d.vec2From(v);
|
|
1655
1760
|
}
|
|
1656
1761
|
|
|
1657
1762
|
/** converts a Vector2 to a box2 vec2
|
|
@@ -1725,8 +1830,23 @@ async function box2dInit()
|
|
|
1725
1830
|
// add the box2d plugin to the engine
|
|
1726
1831
|
function box2dUpdate()
|
|
1727
1832
|
{
|
|
1728
|
-
if (
|
|
1729
|
-
|
|
1833
|
+
if (paused)
|
|
1834
|
+
return;
|
|
1835
|
+
|
|
1836
|
+
box2d.step();
|
|
1837
|
+
|
|
1838
|
+
// remove destroyed objects
|
|
1839
|
+
box2d.objects = box2d.objects.filter(o=>!o.destroyed);
|
|
1840
|
+
|
|
1841
|
+
// copy box2d physics results to engine objects
|
|
1842
|
+
for (const o of box2d.objects)
|
|
1843
|
+
{
|
|
1844
|
+
if (o.body)
|
|
1845
|
+
{
|
|
1846
|
+
o.pos = box2d.vec2From(o.body.GetPosition());
|
|
1847
|
+
o.angle = -o.body.GetAngle();
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1730
1850
|
}
|
|
1731
1851
|
function box2dRender()
|
|
1732
1852
|
{
|
package/plugins/pluginExport.js
CHANGED
package/plugins/uiSystem.js
CHANGED
|
@@ -145,12 +145,12 @@ class UISystemPlugin
|
|
|
145
145
|
/** Draw a rectangle to the UI context
|
|
146
146
|
* @param {Vector2} pos
|
|
147
147
|
* @param {Vector2} size
|
|
148
|
-
* @param {Color} [color
|
|
149
|
-
* @param {number} [lineWidth
|
|
150
|
-
* @param {Color} [lineColor
|
|
151
|
-
* @param {number} [cornerRadius
|
|
152
|
-
* @param {Color} [gradientColor
|
|
153
|
-
drawRect(pos, size, color=
|
|
148
|
+
* @param {Color} [color]
|
|
149
|
+
* @param {number} [lineWidth]
|
|
150
|
+
* @param {Color} [lineColor]
|
|
151
|
+
* @param {number} [cornerRadius]
|
|
152
|
+
* @param {Color} [gradientColor] */
|
|
153
|
+
drawRect(pos, size, color=WHITE, lineWidth=0, lineColor=BLACK, cornerRadius=0, gradientColor)
|
|
154
154
|
{
|
|
155
155
|
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
156
156
|
ASSERT(isVector2(size), 'size must be a vec2');
|
|
@@ -229,10 +229,14 @@ class UISystemPlugin
|
|
|
229
229
|
* @param {string} [align]
|
|
230
230
|
* @param {string} [font=uiSystem.defaultFont]
|
|
231
231
|
* @param {string} [fontStyle]
|
|
232
|
-
* @param {boolean} [applyMaxWidth=true]
|
|
233
|
-
|
|
232
|
+
* @param {boolean} [applyMaxWidth=true]
|
|
233
|
+
* @param {Vector2} [textShadow]
|
|
234
|
+
*/
|
|
235
|
+
drawText(text, pos, size, color=uiSystem.defaultColor, lineWidth=uiSystem.defaultLineWidth, lineColor=uiSystem.defaultLineColor, align='center', font=uiSystem.defaultFont, fontStyle='', applyMaxWidth=true, textShadow=undefined)
|
|
234
236
|
{
|
|
235
|
-
|
|
237
|
+
if (textShadow)
|
|
238
|
+
drawTextScreen(text, pos.add(textShadow), size.y, BLACK, lineWidth, lineColor, align, font, fontStyle, applyMaxWidth ? size.x : undefined, 0, uiSystem.uiContext);
|
|
239
|
+
drawTextScreen(text, pos, size.y, color, lineWidth, lineColor, align, font, fontStyle, applyMaxWidth ? size.x : undefined, 0, uiSystem.uiContext);
|
|
236
240
|
}
|
|
237
241
|
|
|
238
242
|
/**
|
|
@@ -259,6 +263,25 @@ class UISystemPlugin
|
|
|
259
263
|
setCallback(onDragLeave, 'dragleave');
|
|
260
264
|
setCallback(onDragOver, 'dragover');
|
|
261
265
|
}
|
|
266
|
+
|
|
267
|
+
/** Convert a screen space position to native UI position
|
|
268
|
+
* @param {Vector2} pos
|
|
269
|
+
* @return {Vector2}
|
|
270
|
+
*/
|
|
271
|
+
screenToNative(pos)
|
|
272
|
+
{
|
|
273
|
+
if (!uiSystem.nativeHeight)
|
|
274
|
+
return pos;
|
|
275
|
+
|
|
276
|
+
const s = mainCanvasSize.y / uiSystem.nativeHeight;
|
|
277
|
+
const sInv = 1/s;
|
|
278
|
+
const p = pos.copy();
|
|
279
|
+
p.x += s*mainCanvasSize.x/2;
|
|
280
|
+
p.x *= sInv;
|
|
281
|
+
p.y *= sInv;
|
|
282
|
+
p.x -= sInv*mainCanvasSize.x/2;
|
|
283
|
+
return p;
|
|
284
|
+
}
|
|
262
285
|
}
|
|
263
286
|
|
|
264
287
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -335,6 +358,9 @@ class UIObject
|
|
|
335
358
|
/** @property {boolean} - True if this can be a hover object */
|
|
336
359
|
this.canBeHover = true;
|
|
337
360
|
uiSystem.uiObjects.push(this);
|
|
361
|
+
|
|
362
|
+
/** @property {Vector2} - How much to offset the text shadow or undefined */
|
|
363
|
+
this.textShadow = undefined;
|
|
338
364
|
}
|
|
339
365
|
|
|
340
366
|
/** Add a child UIObject to this object
|
|
@@ -362,24 +388,20 @@ class UIObject
|
|
|
362
388
|
*/
|
|
363
389
|
isMouseOverlapping()
|
|
364
390
|
{
|
|
391
|
+
if (!mouseInWindow) return false;
|
|
392
|
+
|
|
365
393
|
const size = !isTouchDevice ? this.size :
|
|
366
394
|
this.size.add(vec2(this.extraTouchSize || 0));
|
|
367
|
-
|
|
368
|
-
return isOverlapping(this.pos, size, mousePosScreen);
|
|
369
|
-
|
|
370
|
-
const s = mainCanvasSize.y / uiSystem.nativeHeight;
|
|
371
|
-
const sInv = 1/s;
|
|
372
|
-
let pos = mousePosScreen.copy();
|
|
373
|
-
pos.x += s*mainCanvasSize.x/2;
|
|
374
|
-
pos.x *= sInv;
|
|
375
|
-
pos.y *= sInv;
|
|
376
|
-
pos.x -= sInv*mainCanvasSize.x/2;
|
|
395
|
+
const pos = uiSystem.screenToNative(mousePosScreen);
|
|
377
396
|
return isOverlapping(this.pos, size, pos);
|
|
378
397
|
}
|
|
379
398
|
|
|
380
399
|
/** Update the object, called automatically by plugin once each frame */
|
|
381
400
|
update()
|
|
382
401
|
{
|
|
402
|
+
// call the custom update callback
|
|
403
|
+
this.onUpdate();
|
|
404
|
+
|
|
383
405
|
const wasHover = uiSystem.lastHoverObject === this;
|
|
384
406
|
const isActive = this.isActiveObject();
|
|
385
407
|
const mouseDown = mouseIsDown(0);
|
|
@@ -436,7 +458,7 @@ class UIObject
|
|
|
436
458
|
|
|
437
459
|
const lineColor = this.interactive && this.isActiveObject() && !this.disabled ? this.color : this.lineColor;
|
|
438
460
|
const color = this.disabled ? this.disabledColor : this.interactive ? this.isActiveObject() ? this.activeColor || this.color : this.isHoverObject() ? this.hoverColor : this.color : this.color;
|
|
439
|
-
uiSystem.drawRect(this.pos, this.size, color, this.lineWidth, lineColor, this.cornerRadius);
|
|
461
|
+
uiSystem.drawRect(this.pos, this.size, color, this.lineWidth, lineColor, this.cornerRadius, this.gradientColor);
|
|
440
462
|
}
|
|
441
463
|
|
|
442
464
|
/** Special update when object is not visible */
|
|
@@ -463,6 +485,9 @@ class UIObject
|
|
|
463
485
|
/** @return {boolean} - Is the mouse held onto this element */
|
|
464
486
|
isActiveObject() { return uiSystem.activeObject === this; }
|
|
465
487
|
|
|
488
|
+
/** Called each frame when object updates */
|
|
489
|
+
onUpdate() {}
|
|
490
|
+
|
|
466
491
|
/** Called when the mouse enters the object */
|
|
467
492
|
onEnter() {}
|
|
468
493
|
|
|
@@ -517,8 +542,9 @@ class UIText extends UIObject
|
|
|
517
542
|
}
|
|
518
543
|
render()
|
|
519
544
|
{
|
|
545
|
+
// only render the text
|
|
520
546
|
const textSize = this.getTextSize();
|
|
521
|
-
uiSystem.drawText(this.text, this.pos, textSize, this.textColor, this.lineWidth, this.lineColor, this.align, this.font, this.fontStyle);
|
|
547
|
+
uiSystem.drawText(this.text, this.pos, textSize, this.textColor, this.lineWidth, this.lineColor, this.align, this.font, this.fontStyle, true, this.textShadow);
|
|
522
548
|
}
|
|
523
549
|
}
|
|
524
550
|
|
|
@@ -594,7 +620,7 @@ class UIButton extends UIObject
|
|
|
594
620
|
// draw the text scaled to fit
|
|
595
621
|
const textSize = this.getTextSize();
|
|
596
622
|
uiSystem.drawText(this.text, this.pos, textSize,
|
|
597
|
-
this.textColor, 0, undefined, this.align, this.font, this.fontStyle);
|
|
623
|
+
this.textColor, 0, undefined, this.align, this.font, this.fontStyle, true, this.textShadow);
|
|
598
624
|
}
|
|
599
625
|
}
|
|
600
626
|
|
|
@@ -648,7 +674,7 @@ class UICheckbox extends UIObject
|
|
|
648
674
|
const textSize = this.getTextSize();
|
|
649
675
|
const pos = this.pos.add(vec2(this.size.x,0));
|
|
650
676
|
uiSystem.drawText(this.text, pos, textSize,
|
|
651
|
-
this.textColor, 0, undefined, 'left', this.font, this.fontStyle, false);
|
|
677
|
+
this.textColor, 0, undefined, 'left', this.font, this.fontStyle, false, this.textShadow);
|
|
652
678
|
}
|
|
653
679
|
}
|
|
654
680
|
|
|
@@ -703,9 +729,11 @@ class UIScrollbar extends UIObject
|
|
|
703
729
|
const p1 = centerPos - handleWidth/2;
|
|
704
730
|
const p2 = centerPos + handleWidth/2;
|
|
705
731
|
const oldValue = this.value;
|
|
732
|
+
|
|
733
|
+
const p = uiSystem.screenToNative(mousePosScreen);
|
|
706
734
|
this.value = isHorizontal ?
|
|
707
|
-
percent(
|
|
708
|
-
percent(
|
|
735
|
+
percent(p.x, p1, p2) :
|
|
736
|
+
percent(p.y, p2, p1);
|
|
709
737
|
this.value === oldValue || this.onChange();
|
|
710
738
|
}
|
|
711
739
|
}
|
|
@@ -727,11 +755,11 @@ class UIScrollbar extends UIObject
|
|
|
727
755
|
vec2(lerp(p1, p2, this.value), this.pos.y) :
|
|
728
756
|
vec2(this.pos.x, lerp(p2, p1, this.value))
|
|
729
757
|
const handleColor = this.disabled ? this.disabledColor : this.handleColor;
|
|
730
|
-
uiSystem.drawRect(handlePos, vec2(handleSize), handleColor, this.lineWidth, this.lineColor, this.cornerRadius);
|
|
758
|
+
uiSystem.drawRect(handlePos, vec2(handleSize), handleColor, this.lineWidth, this.lineColor, this.cornerRadius, this.gradientColor);
|
|
731
759
|
|
|
732
760
|
// draw the text scaled to fit on the scrollbar
|
|
733
761
|
const textSize = this.getTextSize();
|
|
734
762
|
uiSystem.drawText(this.text, this.pos, textSize,
|
|
735
|
-
this.textColor, 0, undefined, this.align, this.font, this.fontStyle);
|
|
763
|
+
this.textColor, 0, undefined, this.align, this.font, this.fontStyle, true, this.textShadow);
|
|
736
764
|
}
|
|
737
765
|
}
|