littlejsengine 1.9.9 → 1.9.11
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 +2 -0
- package/dist/littlejs.d.ts +27 -5
- package/dist/littlejs.esm.js +62 -36
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +56 -34
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +39 -32
- package/examples/box2d/game.js +28 -9
- package/examples/box2d/gameObjects.js +485 -0
- package/examples/box2d/index.html +5 -4
- package/examples/box2d/scenes.js +28 -247
- package/examples/box2d/tiles.png +0 -0
- package/examples/breakout/index.html +3 -3
- package/examples/breakoutTutorial/index.html +2 -2
- package/examples/electron/index.html +2 -2
- package/examples/js13k/index.html +13 -13
- package/examples/module/index.html +1 -1
- package/examples/particles/index.html +1 -1
- package/examples/platformer/gameCharacter.js +1 -0
- package/examples/platformer/gameEffects.js +0 -2
- package/examples/platformer/gameObjects.js +1 -1
- package/examples/platformer/index.html +8 -8
- package/examples/puzzle/index.html +2 -2
- package/examples/starter/game.js +1 -1
- package/examples/starter/index.html +13 -13
- package/examples/stress/index.html +1 -1
- package/examples/typescript/index.html +1 -1
- package/package.json +1 -1
- package/plugins/box2d.js +114 -41
- package/src/engine.js +1 -1
- package/src/engineAudio.js +16 -16
- package/src/engineDebug.js +17 -2
- package/src/engineExport.js +5 -2
- package/src/engineInput.js +7 -3
- package/src/engineObject.js +15 -12
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Little JS Box2d Demo Objects
|
|
3
|
+
- Object functions that use Box2D features
|
|
4
|
+
- Feel free to copy and paste these into your own project
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
10
|
+
// spawn object functions
|
|
11
|
+
|
|
12
|
+
function spawnBox(pos, size=1, color=WHITE, type=box2dBodyTypeDynamic, applyTexture=true, angle=0)
|
|
13
|
+
{
|
|
14
|
+
size = typeof size == 'number' ? vec2(size) : size; // square
|
|
15
|
+
const o = new Box2dObject(pos, size, applyTexture && tile(3), angle, color, type);
|
|
16
|
+
o.addBox(size);
|
|
17
|
+
return o;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function spawnCircle(pos, diameter=1, color=WHITE, type=box2dBodyTypeDynamic, applyTexture=true, angle=0)
|
|
21
|
+
{
|
|
22
|
+
const size = vec2(diameter);
|
|
23
|
+
const o = new Box2dObject(pos, size, applyTexture && tile(2), angle, color, type);
|
|
24
|
+
o.addCircle(diameter);
|
|
25
|
+
return o;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function spawnRandomPoly(pos, diameter=1, color=WHITE, type=box2dBodyTypeDynamic, angle=0)
|
|
29
|
+
{
|
|
30
|
+
const o = new Box2dObject(pos, vec2(), 0, angle, color, type);
|
|
31
|
+
o.addRandomPoly(diameter);
|
|
32
|
+
return o;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function spawnRandomObject(pos, scale=1, type=box2dBodyTypeDynamic, angle=0)
|
|
36
|
+
{
|
|
37
|
+
if (randInt(2))
|
|
38
|
+
{
|
|
39
|
+
const size = vec2(scale*rand(.5,1), scale*rand(.5,1));
|
|
40
|
+
return spawnBox(pos, size, randColor(), type, true, angle);
|
|
41
|
+
}
|
|
42
|
+
else
|
|
43
|
+
{
|
|
44
|
+
const diameter = scale*rand(.5,1);
|
|
45
|
+
return spawnCircle(pos, diameter, randColor(), type, true, angle);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function spawnPyramid(pos, count)
|
|
50
|
+
{
|
|
51
|
+
for (let i=count+1;i--;)
|
|
52
|
+
for (let j=i;j--;)
|
|
53
|
+
spawnBox(pos.add(vec2(j-i/2+.5,count-i+.5)), 1, randColor());
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function spawnDominoes(pos, count, size=vec2(.5,2))
|
|
57
|
+
{
|
|
58
|
+
for (let i=count; i--;)
|
|
59
|
+
spawnBox(pos.add(vec2(i*size.y*.9,size.y/2)), size, randColor());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function spawnRandomEdges()
|
|
63
|
+
{
|
|
64
|
+
// edge list along bottom
|
|
65
|
+
const edgePoints = [];
|
|
66
|
+
edgePoints.push(vec2(40,0));
|
|
67
|
+
for (let i=40, y=0; i--;)
|
|
68
|
+
edgePoints.push(vec2(i, y=clamp(y+rand(-2,2),0,5)));
|
|
69
|
+
edgePoints.push(vec2(0,0));
|
|
70
|
+
const o = new Box2dObject(vec2(), vec2(), 0, 0, BLACK, box2dBodyTypeStatic);
|
|
71
|
+
o.addEdgeList(edgePoints);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function spawnRope(startPos, count, angle=PI, color=WHITE, size=vec2(.3,1))
|
|
75
|
+
{
|
|
76
|
+
let lastObject = groundObject;
|
|
77
|
+
for (let i=0; i<count; ++i)
|
|
78
|
+
{
|
|
79
|
+
const pos = startPos.add(size.multiply(vec2(0,i+.5)).rotate(-angle));
|
|
80
|
+
const o = spawnBox(pos, size, color, box2dBodyTypeDynamic, false, angle);
|
|
81
|
+
o.setFilterData(2, 2);
|
|
82
|
+
const anchorPos = pos.add(vec2(0,-size.y/2).rotate(-angle));
|
|
83
|
+
box2dCreateRevoluteJoint(lastObject, o, anchorPos);
|
|
84
|
+
lastObject = o;
|
|
85
|
+
}
|
|
86
|
+
const endPos = lastObject.localToWorld(vec2(0,-size.y/2));
|
|
87
|
+
box2dCreateRopeJoint(groundObject, lastObject, startPos, endPos);
|
|
88
|
+
return lastObject;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
92
|
+
|
|
93
|
+
// simple car vehicle using wheel joints
|
|
94
|
+
class CarObject extends Box2dObject
|
|
95
|
+
{
|
|
96
|
+
constructor(pos)
|
|
97
|
+
{
|
|
98
|
+
super(pos, vec2(), 0, 0, randColor());
|
|
99
|
+
const carPoints = [
|
|
100
|
+
vec2(-1.5,-.5),
|
|
101
|
+
vec2(1.5, -.5),
|
|
102
|
+
vec2(1.5, 0),
|
|
103
|
+
vec2(0, .9),
|
|
104
|
+
vec2(-1.15,.9),
|
|
105
|
+
vec2(-1.5, .2),
|
|
106
|
+
];
|
|
107
|
+
this.addPoly(carPoints);
|
|
108
|
+
|
|
109
|
+
{
|
|
110
|
+
// wheel settings
|
|
111
|
+
const diameter = .8;
|
|
112
|
+
const density = 1;
|
|
113
|
+
const friction = 2;
|
|
114
|
+
const restitution = 0;
|
|
115
|
+
const damping = .7;
|
|
116
|
+
const frequencyHz = 4;
|
|
117
|
+
const maxTorque = 50;
|
|
118
|
+
const sprite = tile(4);
|
|
119
|
+
|
|
120
|
+
// create wheels
|
|
121
|
+
this.wheels = [];
|
|
122
|
+
const makeWheel = (pos, isMotor) =>
|
|
123
|
+
{
|
|
124
|
+
const wheel = new Box2dObject(pos, vec2(diameter), sprite);
|
|
125
|
+
wheel.addCircle(diameter, vec2(), density, friction, restitution);
|
|
126
|
+
this.wheels.push(wheel);
|
|
127
|
+
const joint = box2dCreateWheelJoint(this, wheel);
|
|
128
|
+
joint.SetSpringDampingRatio(damping);
|
|
129
|
+
joint.SetSpringFrequencyHz(frequencyHz);
|
|
130
|
+
if (isMotor)
|
|
131
|
+
{
|
|
132
|
+
joint.SetMaxMotorTorque(maxTorque);
|
|
133
|
+
joint.EnableMotor(true);
|
|
134
|
+
this.wheelMotorJoint = joint;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
makeWheel(pos.add(vec2( 1, -.6)));
|
|
139
|
+
makeWheel(pos.add(vec2(-1, -.65)), true);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
applyMotorInput(input)
|
|
143
|
+
{
|
|
144
|
+
const maxSpeed = 40;
|
|
145
|
+
const brakeAmount = .8;
|
|
146
|
+
let s = this.wheelMotorJoint.GetMotorSpeed();
|
|
147
|
+
s = input ? clamp(s + input, -maxSpeed, maxSpeed) : s * brakeAmount;
|
|
148
|
+
this.wheelMotorJoint.SetMotorSpeed(s);
|
|
149
|
+
}
|
|
150
|
+
destroy()
|
|
151
|
+
{
|
|
152
|
+
this.wheels.forEach(o=>o && o.destroy());
|
|
153
|
+
super.destroy();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
158
|
+
|
|
159
|
+
// changes objects color when touched
|
|
160
|
+
class ContactTester extends Box2dObject
|
|
161
|
+
{
|
|
162
|
+
constructor(pos, size, color, contactColor, isCircle=true, isSensor=true)
|
|
163
|
+
{
|
|
164
|
+
super(pos, size, 0, 0, color, box2dBodyTypeStatic);
|
|
165
|
+
isCircle ? this.addCircle(size.x) : this.addBox(size);
|
|
166
|
+
this.setSensor(isSensor);
|
|
167
|
+
this.contactColor = contactColor;
|
|
168
|
+
}
|
|
169
|
+
beginContact(other) { other.color = this.contactColor; }
|
|
170
|
+
endContact(other) { other.color = WHITE; }
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
174
|
+
|
|
175
|
+
// balanced recursive mobile object with revolve joints
|
|
176
|
+
class MobileObject extends Box2dObject
|
|
177
|
+
{
|
|
178
|
+
constructor(anchor, w, h, depth)
|
|
179
|
+
{
|
|
180
|
+
super(anchor, vec2(w, h), 0, 0, randColor());
|
|
181
|
+
this.addBox(vec2(h/4, h), vec2(0, -h/2));
|
|
182
|
+
this.childMobiles = [];
|
|
183
|
+
if (--depth)
|
|
184
|
+
{
|
|
185
|
+
// long box on bottom
|
|
186
|
+
this.addBox(vec2(w, h/4), vec2(0, -h));
|
|
187
|
+
for (let i=2; i--;)
|
|
188
|
+
{
|
|
189
|
+
// spawn smaller mobiles attached to each side
|
|
190
|
+
const a = anchor.add(vec2( w/(i?2:-2), -h));
|
|
191
|
+
const o = new MobileObject(a, w/2, h, depth);
|
|
192
|
+
box2dCreateRevoluteJoint(this, o, a);
|
|
193
|
+
this.childMobiles.push(o);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
destroy()
|
|
198
|
+
{
|
|
199
|
+
this.childMobiles.forEach(o=>o && o.destroy());
|
|
200
|
+
super.destroy();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
205
|
+
|
|
206
|
+
// pulley object renders a rope to connected point
|
|
207
|
+
class PulleyJointObjects extends Box2dObject
|
|
208
|
+
{
|
|
209
|
+
constructor(pos, size, color, connectionPos)
|
|
210
|
+
{
|
|
211
|
+
super(pos, size, tile(3), 0, color);
|
|
212
|
+
this.addBox(size);
|
|
213
|
+
this.connectionPos = connectionPos;
|
|
214
|
+
}
|
|
215
|
+
render()
|
|
216
|
+
{
|
|
217
|
+
// draw rope
|
|
218
|
+
const topPos = this.localToWorld(vec2(0,this.size.y/2));
|
|
219
|
+
drawLine(topPos, this.connectionPos, .2, BLACK);
|
|
220
|
+
super.render();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
225
|
+
|
|
226
|
+
// motor object renders a rope to connected point
|
|
227
|
+
class MotorJointObject extends Box2dObject
|
|
228
|
+
{
|
|
229
|
+
constructor(pos, size, color, otherObject)
|
|
230
|
+
{
|
|
231
|
+
super(pos, size, tile(4), 0, color);
|
|
232
|
+
this.addCircle(size.x);
|
|
233
|
+
this.connectionPos = pos;
|
|
234
|
+
const joint = box2dCreateMotorJoint(otherObject, this);
|
|
235
|
+
joint.SetMaxForce(500);
|
|
236
|
+
joint.SetMaxTorque(500);
|
|
237
|
+
}
|
|
238
|
+
render()
|
|
239
|
+
{
|
|
240
|
+
// draw rope
|
|
241
|
+
const width = 2/(1+this.pos.distance(this.connectionPos));
|
|
242
|
+
drawLine(this.pos, this.connectionPos, width, BLACK);
|
|
243
|
+
super.render();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
248
|
+
|
|
249
|
+
// soft body sim using grid of weld joints
|
|
250
|
+
class SoftBodyObject extends Box2dObject
|
|
251
|
+
{
|
|
252
|
+
constructor(pos, scale, sizeCount, color)
|
|
253
|
+
{
|
|
254
|
+
super(pos, vec2());
|
|
255
|
+
const nodeSize = sizeCount.subtract(vec2(1));
|
|
256
|
+
const spacing = scale.divide(nodeSize);
|
|
257
|
+
const objectDiameter = min(spacing.x, spacing.y);
|
|
258
|
+
this.sizeCount = sizeCount.copy();
|
|
259
|
+
|
|
260
|
+
// create nodes
|
|
261
|
+
this.nodes = [];
|
|
262
|
+
for (let y=sizeCount.y; y--;)
|
|
263
|
+
for (let x=sizeCount.y; x--;)
|
|
264
|
+
{
|
|
265
|
+
const mass = .1;
|
|
266
|
+
const center = vec2(x-nodeSize.x/2, y-nodeSize.y/2);
|
|
267
|
+
const p = pos.add(center.multiply(spacing));
|
|
268
|
+
const o = new Box2dObject(p, vec2(objectDiameter*1.1), tile(0), 0, color);
|
|
269
|
+
o.addCircle(objectDiameter);
|
|
270
|
+
o.setMass(mass);
|
|
271
|
+
o.setAngularDamping(10);
|
|
272
|
+
o.joints = [];
|
|
273
|
+
this.nodes.push(o);
|
|
274
|
+
}
|
|
275
|
+
// attach joints
|
|
276
|
+
for (let y=sizeCount.y; y--;)
|
|
277
|
+
for (let x=sizeCount.x; x--;)
|
|
278
|
+
{
|
|
279
|
+
const o = this.getNode(x, y);
|
|
280
|
+
const tryAddJoint = (xo, yo) =>
|
|
281
|
+
{
|
|
282
|
+
const o2 = this.getNode(x+xo, y+yo);
|
|
283
|
+
const joint = o2 ? box2dCreateWeldJoint(o, o2) : 0;
|
|
284
|
+
o.joints.push(joint);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// attach horizontal and vertical joints first
|
|
288
|
+
tryAddJoint(1, 0);
|
|
289
|
+
tryAddJoint(0, 1);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
render()
|
|
293
|
+
{
|
|
294
|
+
// fill inside background with a poly around the perimeter
|
|
295
|
+
const poly = [];
|
|
296
|
+
const sx = this.sizeCount.x;
|
|
297
|
+
const sy = this.sizeCount.y;
|
|
298
|
+
for (let x = 0; x < sx; ++x) poly.push(this.getNode(x, 0).pos);
|
|
299
|
+
for (let y = 0; y < sy.y; ++y) poly.push(this.getNode(sx-1, y).pos);
|
|
300
|
+
for (let x = sx; x--;) poly.push(this.getNode(x, sy-1).pos);
|
|
301
|
+
for (let y = sy; y--;) poly.push(this.getNode(0, y).pos);
|
|
302
|
+
box2dDrawPoly(vec2(), 0, poly, BLACK)
|
|
303
|
+
}
|
|
304
|
+
getNode(x, y)
|
|
305
|
+
{
|
|
306
|
+
if (vec2(x,y).arrayCheck(this.sizeCount))
|
|
307
|
+
return this.nodes[y*this.sizeCount.x+x];
|
|
308
|
+
}
|
|
309
|
+
destroy()
|
|
310
|
+
{
|
|
311
|
+
this.nodes.forEach(o=>o && o.destroy());
|
|
312
|
+
super.destroy();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
317
|
+
|
|
318
|
+
// cloth sim using grid of rope joints
|
|
319
|
+
class ClothObject extends Box2dObject
|
|
320
|
+
{
|
|
321
|
+
constructor(pos, scale, sizeCount, color, maxJointStress=10)
|
|
322
|
+
{
|
|
323
|
+
super(pos, vec2(), 0, 0, color, box2dBodyTypeStatic);
|
|
324
|
+
const nodeSize = sizeCount.subtract(vec2(1));
|
|
325
|
+
const spacing = scale.divide(nodeSize);
|
|
326
|
+
const objectDiameter = min(spacing.x, spacing.y);
|
|
327
|
+
this.sizeCount = sizeCount.copy();
|
|
328
|
+
this.maxJointStress = maxJointStress;
|
|
329
|
+
this.lineWidth = .1;
|
|
330
|
+
|
|
331
|
+
// create nodes
|
|
332
|
+
this.nodes = [];
|
|
333
|
+
for (let y=sizeCount.y; y--;)
|
|
334
|
+
for (let x=sizeCount.y; x--;)
|
|
335
|
+
{
|
|
336
|
+
const mass = .5;
|
|
337
|
+
const center = vec2(x-nodeSize.x/2, y-nodeSize.y/2);
|
|
338
|
+
const p = pos.add(center.multiply(spacing));
|
|
339
|
+
const o = new Box2dObject(p, vec2(.4), tile(0), 0, color);
|
|
340
|
+
o.addCircle(objectDiameter);
|
|
341
|
+
o.setFilterData(2, 2);
|
|
342
|
+
o.setLinearDamping(1);
|
|
343
|
+
o.setMass(mass);
|
|
344
|
+
o.joints = [];
|
|
345
|
+
this.nodes.push(o);
|
|
346
|
+
}
|
|
347
|
+
// attach joints
|
|
348
|
+
for (let pass=2; pass--;)
|
|
349
|
+
for (let y=sizeCount.y; y--;)
|
|
350
|
+
for (let x=sizeCount.x; x--;)
|
|
351
|
+
{
|
|
352
|
+
// alternate direction each row for stability
|
|
353
|
+
const d = y%2 ? 1 : -1;
|
|
354
|
+
const x2 = d>1 ? x : sizeCount.x-1-x;
|
|
355
|
+
const o = this.getNode(x2, y);
|
|
356
|
+
const tryAddJoint = (xo, yo) =>
|
|
357
|
+
{
|
|
358
|
+
const o2 = this.getNode(x2+xo, y+yo);
|
|
359
|
+
const joint = o2 ? box2dCreateRopeJoint(o, o2) : 0;
|
|
360
|
+
o.joints.push(joint);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (pass)
|
|
364
|
+
{
|
|
365
|
+
// attach horizontal and vertical joints first
|
|
366
|
+
tryAddJoint(d, 0);
|
|
367
|
+
tryAddJoint(0, 1);
|
|
368
|
+
}
|
|
369
|
+
else
|
|
370
|
+
{
|
|
371
|
+
// attach cross joints
|
|
372
|
+
tryAddJoint(-d, 1);
|
|
373
|
+
tryAddJoint( d, 1);
|
|
374
|
+
|
|
375
|
+
// attach pin joint to top row
|
|
376
|
+
y || box2dCreatePinJoint(this, this.getNode(x, y));
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
getNode(x, y)
|
|
381
|
+
{
|
|
382
|
+
if (vec2(x,y).arrayCheck(this.sizeCount))
|
|
383
|
+
return this.nodes[y*this.sizeCount.x+x];
|
|
384
|
+
}
|
|
385
|
+
update()
|
|
386
|
+
{
|
|
387
|
+
for (let y=this.sizeCount.y; y--;)
|
|
388
|
+
for (let x=this.sizeCount.x; x--;)
|
|
389
|
+
{
|
|
390
|
+
const o = this.getNode(x, y)
|
|
391
|
+
if (!o) continue;
|
|
392
|
+
|
|
393
|
+
// check node joints
|
|
394
|
+
const joints = o.joints;
|
|
395
|
+
for (let i=joints.length; i--;)
|
|
396
|
+
{
|
|
397
|
+
const j = joints[i];
|
|
398
|
+
if (!j) continue;
|
|
399
|
+
|
|
400
|
+
const oA = j.GetBodyA().object;
|
|
401
|
+
const oB = j.GetBodyB().object;
|
|
402
|
+
const d2 = oA.pos.distanceSquared(oB.pos);
|
|
403
|
+
const maxLength2 = j.GetMaxLength()**2;
|
|
404
|
+
const stress = vec2(j.GetReactionForce(1)).length();
|
|
405
|
+
if (stress > this.maxJointStress || d2 > maxLength2*4)
|
|
406
|
+
{
|
|
407
|
+
// remove stessed joint
|
|
408
|
+
box2dDestroyJoint(j);
|
|
409
|
+
joints[i] = 0;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (!o.hasJoints())
|
|
413
|
+
{
|
|
414
|
+
// destroy if not connected to anything
|
|
415
|
+
o.destroy();
|
|
416
|
+
this.nodes[y*this.sizeCount.x+x] = 0;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
super.update();
|
|
420
|
+
}
|
|
421
|
+
render()
|
|
422
|
+
{
|
|
423
|
+
// draw connections
|
|
424
|
+
for (const o of this.nodes)
|
|
425
|
+
{
|
|
426
|
+
if (!o) continue;
|
|
427
|
+
for (const joint of o.joints)
|
|
428
|
+
{
|
|
429
|
+
if (!joint) continue;
|
|
430
|
+
const oA = joint.GetBodyA().object;
|
|
431
|
+
const oB = joint.GetBodyB().object;
|
|
432
|
+
drawLine(oA.pos, oB.pos, this.lineWidth, BLACK);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
destroy()
|
|
437
|
+
{
|
|
438
|
+
this.nodes.forEach(o=>o && o.destroy());
|
|
439
|
+
super.destroy();
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
444
|
+
// Effects
|
|
445
|
+
|
|
446
|
+
const sound_click = new Sound([.2,.1,,,,.01,,,,,,,,,,,,,,,-500]); // Loaded Sound 0
|
|
447
|
+
const sound_explosion = new Sound([.5,.2,72,.01,.01,.2,4,,,,,,,1,,.5,.1,.5,.02]);
|
|
448
|
+
|
|
449
|
+
function explosion(pos, radius=3, strength=300)
|
|
450
|
+
{
|
|
451
|
+
sound_explosion.play(pos);
|
|
452
|
+
const objects = box2dCircleCastAll(pos, (radius*2));
|
|
453
|
+
const newColor = randColor();
|
|
454
|
+
for (const o of objects)
|
|
455
|
+
{
|
|
456
|
+
const p = percent(o.pos.distance(pos), 2*radius, radius);
|
|
457
|
+
const force = o.pos.subtract(pos).normalize(p*radius*strength);
|
|
458
|
+
o.applyForce(force);
|
|
459
|
+
o.color = newColor;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// smoke
|
|
463
|
+
new ParticleEmitter(
|
|
464
|
+
pos, 0, // pos, angle
|
|
465
|
+
radius/2, .2, 50*radius, PI,// emitSize, emitTime, emitRate, emiteCone
|
|
466
|
+
tile(1), // tileInfo
|
|
467
|
+
hsl(0,0,0), hsl(0,0,0), // colorStartA, colorStartB
|
|
468
|
+
hsl(0,0,0,0), hsl(0,0,0,0), // colorEndA, colorEndB
|
|
469
|
+
1, 1, 2, .1, .1, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
470
|
+
.9, 1, -.5, PI, .1, // damp, angleDamp, gravity, particleCone, fade
|
|
471
|
+
1, 0, 0, 0, 1e8 // randomness, collide, additive, colorLinear, renderOrder
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
// fire
|
|
475
|
+
new ParticleEmitter(
|
|
476
|
+
pos, 0, // pos, angle
|
|
477
|
+
radius, .1, 100*radius, PI, // emitSize, emitTime, emitRate, emiteCone
|
|
478
|
+
tile(1), // tileInfo
|
|
479
|
+
hsl(0,1,.5), hsl(.15,1,.5), // colorStartA, colorStartB
|
|
480
|
+
hsl(0,1,.5,0), hsl(.1, 1,.5,0), // colorEndA, colorEndB
|
|
481
|
+
.7, 1, .5, .1, .1, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
482
|
+
.9, 1, 0, PI, .05, // damp, angleDamp, gravity, particleCone, fade
|
|
483
|
+
1, 0, 1, 0, 1e9 // randomness, collide, additive, colorLinear, renderOrder
|
|
484
|
+
);
|
|
485
|
+
}
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
</head><body>
|
|
7
7
|
|
|
8
8
|
<script src=../../dist/littlejs.js></script>
|
|
9
|
-
<script src=../../plugins/Box2D_v2.3.1_min.wasm.js?
|
|
10
|
-
<script src=../../plugins/box2d.js?
|
|
11
|
-
<script src=scenes.js?
|
|
12
|
-
<script src=
|
|
9
|
+
<script src=../../plugins/Box2D_v2.3.1_min.wasm.js?198></script>
|
|
10
|
+
<script src=../../plugins/box2d.js?198></script>
|
|
11
|
+
<script src=scenes.js?198></script>
|
|
12
|
+
<script src=gameObjects.js?198></script>
|
|
13
|
+
<script src=game.js?198></script>
|