littlejsengine 1.18.4 → 1.18.7

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.
Files changed (177) hide show
  1. package/COPYRIGHT.txt +38 -0
  2. package/FAQ.md +633 -0
  3. package/README.md +19 -1
  4. package/dist/littlejs.d.ts +349 -54
  5. package/dist/littlejs.esm.js +1469 -448
  6. package/dist/littlejs.esm.min.js +1 -1
  7. package/dist/littlejs.js +1438 -436
  8. package/dist/littlejs.min.js +1 -1
  9. package/dist/littlejs.release.js +1438 -436
  10. package/package.json +8 -1
  11. package/plugins/box2d.js +32 -7
  12. package/{src/engineMedals.js → plugins/medalSystem.js} +248 -196
  13. package/plugins/pathFinder.js +758 -0
  14. package/plugins/pluginExport.js +19 -0
  15. package/plugins/tween.js +1 -1
  16. package/plugins/tweenSystem.js +509 -0
  17. package/plugins/uiSystem.js +150 -11
  18. package/src/engine.js +2 -141
  19. package/src/engineAudio.js +8 -5
  20. package/src/engineBuild.mjs +4 -2
  21. package/src/engineDebug.js +1 -1
  22. package/src/engineDraw.js +21 -3
  23. package/src/engineExport.js +12 -12
  24. package/src/engineInput.js +1 -1
  25. package/src/engineLogo.js +146 -0
  26. package/src/engineMath.js +10 -3
  27. package/src/engineObject.js +11 -5
  28. package/src/engineParticles.js +6 -3
  29. package/src/engineRelease.js +1 -1
  30. package/src/engineSettings.js +0 -47
  31. package/src/engineUtilities.js +7 -2
  32. package/src/engineWebGL.js +34 -7
  33. package/src/jsconfig.json +3 -1
  34. package/.github/workflows/test.yml +0 -17
  35. package/AI.md +0 -173
  36. package/CLAUDE.md +0 -1
  37. package/examples/box2d/game.js +0 -192
  38. package/examples/box2d/gameObjects.js +0 -564
  39. package/examples/box2d/index.html +0 -9
  40. package/examples/box2d/scenes.js +0 -194
  41. package/examples/box2d/tiles.png +0 -0
  42. package/examples/breakout/game.js +0 -175
  43. package/examples/breakout/gameObjects.js +0 -147
  44. package/examples/breakout/index.html +0 -8
  45. package/examples/breakout/tiles.png +0 -0
  46. package/examples/breakoutTutorial/README.md +0 -521
  47. package/examples/breakoutTutorial/game.js +0 -191
  48. package/examples/breakoutTutorial/images/1.png +0 -0
  49. package/examples/breakoutTutorial/images/10.png +0 -0
  50. package/examples/breakoutTutorial/images/11.png +0 -0
  51. package/examples/breakoutTutorial/images/2.png +0 -0
  52. package/examples/breakoutTutorial/images/3.png +0 -0
  53. package/examples/breakoutTutorial/images/4.png +0 -0
  54. package/examples/breakoutTutorial/images/5.png +0 -0
  55. package/examples/breakoutTutorial/images/6.png +0 -0
  56. package/examples/breakoutTutorial/images/7.png +0 -0
  57. package/examples/breakoutTutorial/images/8.png +0 -0
  58. package/examples/breakoutTutorial/images/9.png +0 -0
  59. package/examples/breakoutTutorial/index.html +0 -8
  60. package/examples/electron/build.mjs +0 -127
  61. package/examples/electron/electron.js +0 -35
  62. package/examples/electron/game.js +0 -54
  63. package/examples/electron/index.html +0 -13
  64. package/examples/electron/package.json +0 -5
  65. package/examples/electron/tiles.png +0 -0
  66. package/examples/empty/game.js +0 -51
  67. package/examples/empty/index.html +0 -5
  68. package/examples/empty/tiles.png +0 -0
  69. package/examples/favicon.png +0 -0
  70. package/examples/games.jpg +0 -0
  71. package/examples/htmlMenu/game.js +0 -82
  72. package/examples/htmlMenu/index.html +0 -45
  73. package/examples/htmlMenu/tiles.png +0 -0
  74. package/examples/index.html +0 -62
  75. package/examples/logo.png +0 -0
  76. package/examples/logo2.png +0 -0
  77. package/examples/module/build.mjs +0 -124
  78. package/examples/module/game.js +0 -132
  79. package/examples/module/index.html +0 -10
  80. package/examples/module/tiles.png +0 -0
  81. package/examples/particles/index.html +0 -426
  82. package/examples/particles/tiles.png +0 -0
  83. package/examples/platformer/data/gameLevelData.tmx +0 -143
  84. package/examples/platformer/data/gameLevelData.tsx +0 -4
  85. package/examples/platformer/game.js +0 -147
  86. package/examples/platformer/gameCharacter.js +0 -309
  87. package/examples/platformer/gameEffects.js +0 -278
  88. package/examples/platformer/gameLevel.js +0 -205
  89. package/examples/platformer/gameLevelData.json +0 -171
  90. package/examples/platformer/gameObjects.js +0 -378
  91. package/examples/platformer/gamePlayer.js +0 -35
  92. package/examples/platformer/index.html +0 -9
  93. package/examples/platformer/tiles.png +0 -0
  94. package/examples/platformer/tilesLevel.png +0 -0
  95. package/examples/puzzle/game.js +0 -331
  96. package/examples/puzzle/index.html +0 -8
  97. package/examples/puzzle/tiles.png +0 -0
  98. package/examples/screenshot.jpg +0 -0
  99. package/examples/shorts/animation.js +0 -18
  100. package/examples/shorts/base.html +0 -54
  101. package/examples/shorts/blending.js +0 -14
  102. package/examples/shorts/box2d.js +0 -51
  103. package/examples/shorts/box2dCar.js +0 -59
  104. package/examples/shorts/box2dPool.js +0 -107
  105. package/examples/shorts/box2dTileLayer.js +0 -48
  106. package/examples/shorts/cameraDrag.js +0 -22
  107. package/examples/shorts/clock.js +0 -21
  108. package/examples/shorts/colors.js +0 -25
  109. package/examples/shorts/debugDraw.js +0 -37
  110. package/examples/shorts/empty.js +0 -30
  111. package/examples/shorts/flappyGame.js +0 -55
  112. package/examples/shorts/fontImage.js +0 -17
  113. package/examples/shorts/fps.js +0 -90
  114. package/examples/shorts/helloWorld.js +0 -11
  115. package/examples/shorts/hillGlideGame.js +0 -63
  116. package/examples/shorts/input.js +0 -64
  117. package/examples/shorts/landerGame.js +0 -57
  118. package/examples/shorts/maze.js +0 -48
  119. package/examples/shorts/medals.js +0 -51
  120. package/examples/shorts/music.js +0 -78
  121. package/examples/shorts/musicPlayer.js +0 -137
  122. package/examples/shorts/nineSlice.js +0 -40
  123. package/examples/shorts/parallax.js +0 -72
  124. package/examples/shorts/particles.js +0 -28
  125. package/examples/shorts/piano.js +0 -44
  126. package/examples/shorts/platformer.js +0 -45
  127. package/examples/shorts/pongGame.js +0 -41
  128. package/examples/shorts/postProcess.js +0 -62
  129. package/examples/shorts/sequencer.js +0 -124
  130. package/examples/shorts/shader.js +0 -29
  131. package/examples/shorts/shapes.js +0 -21
  132. package/examples/shorts/slidingPuzzle.js +0 -52
  133. package/examples/shorts/song.mp3 +0 -0
  134. package/examples/shorts/sound.js +0 -36
  135. package/examples/shorts/spaceGame.js +0 -58
  136. package/examples/shorts/spriteAtlas.js +0 -31
  137. package/examples/shorts/starfield.js +0 -15
  138. package/examples/shorts/texture.js +0 -16
  139. package/examples/shorts/textureWrapped.js +0 -12
  140. package/examples/shorts/tileLayer.js +0 -48
  141. package/examples/shorts/tileRaycast.js +0 -39
  142. package/examples/shorts/tiles.png +0 -0
  143. package/examples/shorts/tiltedView.js +0 -63
  144. package/examples/shorts/timers.js +0 -53
  145. package/examples/shorts/topDown.js +0 -38
  146. package/examples/shorts/tween.js +0 -24
  147. package/examples/shorts/uiSystem.js +0 -61
  148. package/examples/shorts/video.webm +0 -0
  149. package/examples/shorts/videoPlayer.js +0 -34
  150. package/examples/shorts.js +0 -743
  151. package/examples/starter/build.bat +0 -7
  152. package/examples/starter/build.mjs +0 -126
  153. package/examples/starter/game.js +0 -137
  154. package/examples/starter/index.html +0 -35
  155. package/examples/starter/tiles.png +0 -0
  156. package/examples/stress/index.html +0 -173
  157. package/examples/style.css +0 -150
  158. package/examples/tweenSystem/game.js +0 -171
  159. package/examples/tweenSystem/index.html +0 -10
  160. package/examples/tweenSystem/tiles.png +0 -0
  161. package/examples/typescript/build.mjs +0 -60
  162. package/examples/typescript/game.js +0 -100
  163. package/examples/typescript/game.ts +0 -132
  164. package/examples/typescript/index.html +0 -10
  165. package/examples/typescript/tiles.png +0 -0
  166. package/examples/typescript/tsconfig.json +0 -17
  167. package/examples/uiSystem/game.js +0 -139
  168. package/examples/uiSystem/index.html +0 -10
  169. package/examples/uiSystem/tiles.png +0 -0
  170. package/jsconfig.json +0 -12
  171. package/plugins/desktop.ini +0 -2
  172. package/reference.md +0 -448
  173. package/test/math.test.mjs +0 -774
  174. package/test/setup.mjs +0 -22
  175. package/test/smoke.test.mjs +0 -274
  176. package/test/tween.test.mjs +0 -576
  177. package/test/util.test.mjs +0 -80
@@ -1,564 +0,0 @@
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
- // import LittleJS module
10
- import * as LJS from '../../dist/littlejs.esm.js';
11
- import * as Game from './game.js';
12
- const {vec2, hsl} = LJS;
13
-
14
- ///////////////////////////////////////////////////////////////////////////////
15
- // spawn object functions
16
-
17
- const density = 1;
18
- const friction = .5;
19
- const restitution = .2;
20
-
21
- export function spawnBox(pos, size=1, color=LJS.WHITE, type=LJS.box2d.bodyTypeDynamic, applyTexture=false, angle=0)
22
- {
23
- size = typeof size === 'number' ? vec2(size) : size; // square
24
- const o = new LJS.Box2dObject(pos, size, applyTexture && Game.spriteAtlas.squareOutline, angle, color, type);
25
- o.drawSize = size.scale(1.02); // slightly enlarge to cover gaps
26
- o.addBox(size, vec2(), 0, density, friction, restitution);
27
- return o;
28
- }
29
-
30
- export function spawnCircle(pos, diameter=1, color=LJS.WHITE, type=LJS.box2d.bodyTypeDynamic, applyTexture=false, angle=0)
31
- {
32
- const size = vec2(diameter);
33
- const o = new LJS.Box2dObject(pos, size, applyTexture && Game.spriteAtlas.circleOutline, angle, color, type);
34
- o.addCircle(diameter, vec2(), density, friction, restitution);
35
- return o;
36
- }
37
-
38
- export function spawnRandomPoly(pos, diameter=1, color=LJS.WHITE, type=LJS.box2d.bodyTypeDynamic, angle=0)
39
- {
40
- const o = new LJS.Box2dObject(pos, vec2(), 0, angle, color, type);
41
- o.addRandomPoly(diameter, density, friction, restitution);
42
- return o;
43
- }
44
-
45
- export function spawnRandomObject(pos, scale=1, type=LJS.box2d.bodyTypeDynamic, angle=0)
46
- {
47
- if (LJS.randInt(2))
48
- {
49
- const size = vec2(scale*LJS.rand(.5,1), scale*LJS.rand(.5,1));
50
- return spawnBox(pos, size, LJS.randColor(), type, true, angle);
51
- }
52
- else
53
- {
54
- const diameter = scale*LJS.rand(.5,1);
55
- return spawnCircle(pos, diameter, LJS.randColor(), type, true, angle);
56
- }
57
- }
58
-
59
- export function spawnPyramid(pos, count)
60
- {
61
- for (let i=count+1;i--;)
62
- for (let j=i;j--;)
63
- spawnBox(pos.add(vec2(j-i/2+.5,count-i+.5)), 1, LJS.randColor());
64
- }
65
-
66
- export function spawnDominoes(pos, count, size=vec2(.5,3))
67
- {
68
- for (let i=count; i--;)
69
- spawnBox(pos.add(vec2(i*size.y*.9,size.y/2)), size, LJS.randColor());
70
- }
71
-
72
- export function spawnRandomEdges()
73
- {
74
- // edge list along bottom
75
- const edgePoints = [];
76
- edgePoints.push(vec2(40,0));
77
- for (let i=40, y=0; i--;)
78
- edgePoints.push(vec2(i, y=LJS.clamp(y+LJS.rand(-2,2),0,5)));
79
- edgePoints.push(vec2());
80
- const o = new LJS.Box2dStaticObject;
81
- o.addEdgeList(edgePoints);
82
- }
83
-
84
- export function spawnRope(startPos, count, angle=PI, color=LJS.WHITE, size=vec2(.3,1))
85
- {
86
- let lastObject = Game.groundObject;
87
- for (let i=0; i<count; ++i)
88
- {
89
- const pos = startPos.add(size.multiply(vec2(0,i+.5)).rotate(-angle));
90
- const o = spawnBox(pos, size, color, LJS.box2d.bodyTypeDynamic, false, angle);
91
- o.setFilterData(2, 2);
92
- const anchorPos = pos.add(vec2(0,-size.y/2).rotate(-angle));
93
- new LJS.Box2dRevoluteJoint(lastObject, o, anchorPos);
94
- lastObject = o;
95
- }
96
- const endPos = lastObject.localToWorld(vec2(0,-size.y/2));
97
- new LJS.Box2dRopeJoint(Game.groundObject, lastObject, startPos, endPos);
98
- return lastObject;
99
- }
100
-
101
- ///////////////////////////////////////////////////////////////////////////////
102
-
103
- // simple car vehicle using wheel joints
104
- export class CarObject extends LJS.Box2dObject
105
- {
106
- constructor(pos)
107
- {
108
- super(pos, vec2(), 0, 0, LJS.randColor());
109
- const carPoints = [
110
- vec2(-1.5,-.5),
111
- vec2(1.5, -.5),
112
- vec2(1.5, 0),
113
- vec2(0, .9),
114
- vec2(-1.15,.9),
115
- vec2(-1.5, .2),
116
- ];
117
- this.addPoly(carPoints);
118
-
119
- // create wheels
120
- const diameter = 1;
121
- const density = 1;
122
- const friction = 1;
123
- const restitution = 0;
124
- const damping = .7;
125
- const frequency = 4;
126
- const maxTorque = 35;
127
- const sprite = Game.spriteAtlas.wheel;
128
- this.wheels = [];
129
- const makeWheel = (pos, isMotor)=>
130
- {
131
- const wheel = new LJS.Box2dObject(pos, vec2(diameter), sprite);
132
- const joint = new LJS.Box2dWheelJoint(this, wheel);
133
- joint.setSpringDampingRatio(damping);
134
- joint.setSpringFrequencyHz(frequency);
135
- if (isMotor)
136
- {
137
- joint.enableMotor();
138
- joint.setMaxMotorTorque(maxTorque);
139
- this.wheelMotorJoint = joint;
140
- }
141
- wheel.addCircle(diameter, vec2(), density, friction, restitution);
142
- this.wheels.push(wheel);
143
- }
144
-
145
- makeWheel(pos.add(vec2( 1, -.6)));
146
- makeWheel(pos.add(vec2(-1, -.65)), true);
147
- }
148
- update()
149
- {
150
- // car controls
151
- const maxSpeed = 40;
152
- const input = LJS.keyDirection().x;
153
- let s = this.wheelMotorJoint.getMotorSpeed();
154
- s = input ? LJS.clamp(s - input, -maxSpeed, maxSpeed) : 0;
155
- this.wheelMotorJoint.setMotorSpeed(s);
156
- }
157
- destroy()
158
- {
159
- this.wheels.forEach(o=>o.destroy());
160
- super.destroy();
161
- }
162
- }
163
-
164
- ///////////////////////////////////////////////////////////////////////////////
165
-
166
- // changes objects color when touched
167
- export class ContactTester extends LJS.Box2dStaticObject
168
- {
169
- constructor(pos, size, color, contactColor, isCircle=true, isSensor=true)
170
- {
171
- super(pos, size, 0, 0, color);
172
- isCircle ? this.addCircle(size.x) : this.addBox(size);
173
- this.setSensor(isSensor);
174
- this.contactColor = contactColor;
175
- }
176
- beginContact(other) { other.color = this.contactColor; }
177
- endContact(other) { other.color = LJS.WHITE; }
178
- }
179
-
180
- ///////////////////////////////////////////////////////////////////////////////
181
-
182
- // balanced recursive mobile object with revolve joints
183
- export class MobileObject extends LJS.Box2dObject
184
- {
185
- constructor(anchor, w, h, depth)
186
- {
187
- super(anchor, vec2(w, h), 0, 0, LJS.randColor());
188
- this.addBox(vec2(h/4, h), vec2(0, -h/2));
189
- this.childMobiles = [];
190
- if (--depth)
191
- {
192
- // long box on bottom
193
- this.addBox(vec2(w, h/4), vec2(0, -h));
194
- for (let i=2; i--;)
195
- {
196
- // spawn smaller mobiles attached to each side
197
- const a = anchor.add(vec2( w/(i?2:-2), -h));
198
- const o = new MobileObject(a, w/2, h, depth);
199
- new LJS.Box2dRevoluteJoint(this, o, a);
200
- this.childMobiles.push(o);
201
- }
202
- }
203
- }
204
- destroy()
205
- {
206
- this.childMobiles.forEach(o=>o && o.destroy());
207
- super.destroy();
208
- }
209
- }
210
-
211
- ///////////////////////////////////////////////////////////////////////////////
212
-
213
- // pulley object renders a rope to connected point
214
- export class PulleyJointObjects extends LJS.Box2dObject
215
- {
216
- constructor(pos, size, color, connectionPos)
217
- {
218
- super(pos, size, Game.spriteAtlas.squareOutline, 0, color);
219
- this.addBox(size);
220
- this.connectionPos = connectionPos;
221
- }
222
- render()
223
- {
224
- // draw rope
225
- const topPos = this.localToWorld(vec2(0,this.size.y/2));
226
- LJS.drawLine(topPos, this.connectionPos, .2, LJS.BLACK);
227
- super.render();
228
- }
229
- }
230
-
231
- ///////////////////////////////////////////////////////////////////////////////
232
-
233
- // motor object renders a rope to connected point
234
- export class MotorJointObject extends LJS.Box2dObject
235
- {
236
- constructor(pos, size, color, otherObject)
237
- {
238
- super(pos, size, Game.spriteAtlas.wheel, 0, color);
239
- this.addCircle(size.x);
240
- this.connectionPos = pos;
241
- const joint = new LJS.Box2dMotorJoint(otherObject, this);
242
- joint.setMaxForce(500);
243
- joint.setMaxTorque(500);
244
- }
245
- render()
246
- {
247
- // draw rope
248
- const width = 2/(1+this.pos.distance(this.connectionPos));
249
- LJS.drawLine(this.pos, this.connectionPos, width, LJS.BLACK);
250
- super.render();
251
- }
252
- }
253
-
254
- ///////////////////////////////////////////////////////////////////////////////
255
-
256
- // soft body sim using grid of weld joints
257
- export class SoftBodyObject extends LJS.Box2dObject
258
- {
259
- constructor(pos, scale, sizeCount, color)
260
- {
261
- super(pos, vec2());
262
- const nodeSize = sizeCount.subtract(vec2(1));
263
- const spacing = scale.divide(nodeSize);
264
- const objectDiameter = LJS.min(spacing.x, spacing.y);
265
- this.sizeCount = sizeCount.copy();
266
-
267
- // create nodes
268
- this.nodes = [];
269
- for (let y=sizeCount.y; y--;)
270
- for (let x=sizeCount.y; x--;)
271
- {
272
- const mass = .1;
273
- const center = vec2(x-nodeSize.x/2, y-nodeSize.y/2);
274
- const p = pos.add(center.multiply(spacing));
275
- const o = new LJS.Box2dObject(p, vec2(objectDiameter*1.1), Game.spriteAtlas.circle, 0, color);
276
- o.addCircle(objectDiameter);
277
- o.setMass(mass);
278
- o.setAngularDamping(10);
279
- o.joints = [];
280
- this.nodes.push(o);
281
- }
282
- // attach joints
283
- for (let y=sizeCount.y; y--;)
284
- for (let x=sizeCount.x; x--;)
285
- {
286
- const o = this.getNode(x, y);
287
- const tryAddJoint = (xo, yo)=>
288
- {
289
- const o2 = this.getNode(x+xo, y+yo);
290
- const joint = o2 ? new LJS.Box2dWeldJoint(o, o2) : 0;
291
- o.joints.push(joint);
292
- }
293
-
294
- // attach horizontal and vertical joints first
295
- tryAddJoint(1, 0);
296
- tryAddJoint(0, 1);
297
- }
298
- }
299
- render()
300
- {
301
- // fill inside background with a poly around the perimeter
302
- const poly = [];
303
- const sx = this.sizeCount.x;
304
- const sy = this.sizeCount.y;
305
- for (let x = 0; x < sx; ++x) poly.push(this.getNode(x, 0).pos);
306
- for (let y = 0; y < sy.y; ++y) poly.push(this.getNode(sx-1, y).pos);
307
- for (let x = sx; x--;) poly.push(this.getNode(x, sy-1).pos);
308
- for (let y = sy; y--;) poly.push(this.getNode(0, y).pos);
309
- LJS.drawPoly(poly, LJS.BLACK)
310
- }
311
- getNode(x, y)
312
- {
313
- if (vec2(x,y).arrayCheck(this.sizeCount))
314
- return this.nodes[y*this.sizeCount.x+x];
315
- }
316
- destroy()
317
- {
318
- this.nodes.forEach(o=>o && o.destroy());
319
- super.destroy();
320
- }
321
- }
322
-
323
- ///////////////////////////////////////////////////////////////////////////////
324
-
325
- // cloth sim using grid of rope joints
326
- export class ClothObject extends LJS.Box2dStaticObject
327
- {
328
- constructor(pos, scale, sizeCount, color, maxJointStress=10)
329
- {
330
- super(pos, vec2(), 0, 0, color);
331
- const nodeSize = sizeCount.subtract(vec2(1));
332
- const spacing = scale.divide(nodeSize);
333
- const objectDiameter = LJS.min(spacing.x, spacing.y);
334
- this.sizeCount = sizeCount.copy();
335
- this.maxJointStress = maxJointStress;
336
- this.lineWidth = .1;
337
-
338
- // create nodes
339
- this.nodes = [];
340
- for (let y=sizeCount.y; y--;)
341
- for (let x=sizeCount.y; x--;)
342
- {
343
- const mass = .5;
344
- const center = vec2(x-nodeSize.x/2, y-nodeSize.y/2);
345
- const p = pos.add(center.multiply(spacing));
346
- const o = new LJS.Box2dObject(p, vec2(.4), Game.spriteAtlas.circle, 0, color);
347
- o.addCircle(objectDiameter);
348
- o.setFilterData(2, 2);
349
- o.setLinearDamping(1);
350
- o.setMass(mass);
351
- o.joints = [];
352
- this.nodes.push(o);
353
- }
354
- // attach joints
355
- for (let pass=2; pass--;)
356
- for (let y=sizeCount.y; y--;)
357
- for (let x=sizeCount.x; x--;)
358
- {
359
- // alternate direction each row for stability
360
- const d = y%2 ? 1 : -1;
361
- const x2 = d>1 ? x : sizeCount.x-1-x;
362
- const o = this.getNode(x2, y);
363
- const tryAddJoint = (xo, yo)=>
364
- {
365
- const o2 = this.getNode(x2+xo, y+yo);
366
- const joint = o2 ? new LJS.Box2dRopeJoint(o, o2) : 0;
367
- o.joints.push(joint);
368
- }
369
-
370
- if (pass)
371
- {
372
- // attach horizontal and vertical joints first
373
- tryAddJoint(d, 0);
374
- tryAddJoint(0, 1);
375
- }
376
- else
377
- {
378
- // attach cross joints
379
- tryAddJoint(-d, 1);
380
- tryAddJoint( d, 1);
381
-
382
- // attach pin joint to top row
383
- y || new LJS.Box2dPinJoint(this.getNode(x, y), this);
384
- }
385
- }
386
- }
387
- getNode(x, y)
388
- {
389
- if (vec2(x,y).arrayCheck(this.sizeCount))
390
- return this.nodes[y*this.sizeCount.x+x];
391
- }
392
- update()
393
- {
394
- for (let y=this.sizeCount.y; y--;)
395
- for (let x=this.sizeCount.x; x--;)
396
- {
397
- const o = this.getNode(x, y)
398
- if (!o) continue;
399
-
400
- // check node joints
401
- const joints = o.joints;
402
- for (let i=joints.length; i--;)
403
- {
404
- const j = joints[i];
405
- if (!j) continue;
406
-
407
- const oA = j.getObjectA();
408
- const oB = j.getObjectB();
409
- const d2 = oA.pos.distanceSquared(oB.pos);
410
- const maxLength2 = j.getMaxLength()**2;
411
- const stress = j.getReactionForce(1).length();
412
- if (stress > this.maxJointStress || d2 > maxLength2*4)
413
- {
414
- // remove stressed joint
415
- j.destroy();
416
- joints[i] = 0;
417
- }
418
- }
419
- if (!o.hasJoints())
420
- {
421
- // destroy if not connected to anything
422
- o.destroy();
423
- this.nodes[y*this.sizeCount.x+x] = 0;
424
- }
425
- }
426
- }
427
- render()
428
- {
429
- // draw connections
430
- for (const o of this.nodes)
431
- {
432
- if (!o) continue;
433
- for (const joint of o.joints)
434
- {
435
- if (!joint) continue;
436
- const oA = joint.getObjectA();
437
- const oB = joint.getObjectB();
438
- LJS.drawLine(oA.pos, oB.pos, this.lineWidth, LJS.BLACK);
439
- }
440
- }
441
- }
442
- destroy()
443
- {
444
- this.nodes.forEach(o=>o && o.destroy());
445
- super.destroy();
446
- }
447
- }
448
-
449
- ///////////////////////////////////////////////////////////////////////////////
450
-
451
- // ragdoll with head, arms, and legs connected to torso by revolute joints
452
- export class RagdollObject extends LJS.Box2dObject
453
- {
454
- constructor(pos, scale=1, color=LJS.randColor())
455
- {
456
- const headSize = .8 * scale;
457
- const torsoWidth = 1.2 * scale;
458
- const torsoHeight = 2 * scale;
459
- const limbWidth = .4 * scale;
460
- const upperArmLen = 1 * scale;
461
- const lowerArmLen = 1 * scale;
462
- const upperLegLen = 1.1 * scale;
463
- const lowerLegLen = 1.1 * scale;
464
-
465
- // torso is the main body
466
- super(pos, vec2(torsoWidth, torsoHeight), 0, 0, color);
467
- this.addBox(vec2(torsoWidth, torsoHeight), vec2(), 0, density, friction, restitution);
468
- this.limbs = [];
469
-
470
- const addLimb = (offset, size, isCircle=false) =>
471
- {
472
- const o = new LJS.Box2dObject(pos.add(offset), size, 0, 0, color);
473
- if (isCircle)
474
- o.addCircle(size.x, vec2(), density, friction, restitution);
475
- else
476
- o.addBox(size, vec2(), 0, density, friction, restitution);
477
- this.limbs.push(o);
478
- return o;
479
- };
480
- const addJoint = (a, b, anchor, lower, upper) =>
481
- {
482
- const joint = new LJS.Box2dRevoluteJoint(a, b, anchor);
483
- joint.enableLimit();
484
- joint.setLimits(lower, upper);
485
- };
486
-
487
- // head
488
- const head = addLimb(vec2(0, torsoHeight/2 + headSize/2 + .1*scale), vec2(headSize), true);
489
- addJoint(this, head, pos.add(vec2(0, torsoHeight/2)), -.5, .5);
490
-
491
- // arms
492
- const shoulderY = torsoHeight/2 - .2*scale;
493
- for (const side of [-1, 1])
494
- {
495
- const shoulder = pos.add(vec2(side*torsoWidth/2, shoulderY));
496
- const upperArm = addLimb(vec2(side*(torsoWidth/2 + upperArmLen/2), shoulderY), vec2(upperArmLen, limbWidth));
497
- addJoint(this, upperArm, shoulder, -2, 2);
498
-
499
- const elbow = shoulder.add(vec2(side*upperArmLen, 0));
500
- const lowerArm = addLimb(vec2(side*(torsoWidth/2 + upperArmLen + lowerArmLen/2), shoulderY), vec2(lowerArmLen, limbWidth));
501
- addJoint(upperArm, lowerArm, elbow, -2.5, 2.5);
502
- }
503
-
504
- // legs
505
- for (const side of [-1, 1])
506
- {
507
- const hip = pos.add(vec2(side*torsoWidth/4, -torsoHeight/2));
508
- const upperLeg = addLimb(vec2(side*torsoWidth/4, -torsoHeight/2 - upperLegLen/2), vec2(limbWidth, upperLegLen));
509
- addJoint(this, upperLeg, hip, -.5, 2.5);
510
-
511
- const knee = hip.add(vec2(0, -upperLegLen));
512
- const lowerLeg = addLimb(vec2(side*torsoWidth/4, -torsoHeight/2 - upperLegLen - lowerLegLen/2), vec2(limbWidth, lowerLegLen));
513
- addJoint(upperLeg, lowerLeg, knee, -2.5, 2.5);
514
- }
515
- }
516
- destroy()
517
- {
518
- this.limbs.forEach(o => o.destroy());
519
- super.destroy();
520
- }
521
- }
522
-
523
- ///////////////////////////////////////////////////////////////////////////////
524
- // Effects
525
-
526
- const sound_explosion = new LJS.Sound([.5,.2,72,.01,.01,.2,4,,,,,,,1,,.5,.1,.5,.02]);
527
-
528
- export function explosion(pos, radius=3, strength=300)
529
- {
530
- sound_explosion.play(pos);
531
- const objects = LJS.box2d.circleCastAll(pos, (radius*2));
532
- const newColor = LJS.randColor();
533
- for (const o of objects)
534
- {
535
- const p = LJS.percent(o.pos.distance(pos), 2*radius, radius);
536
- const force = o.pos.subtract(pos).normalize(p*radius*strength);
537
- o.applyForce(force);
538
- o.color = newColor;
539
- }
540
-
541
- // smoke
542
- new LJS.ParticleEmitter(
543
- pos, 0, // pos, angle
544
- radius/2, .2, 50*radius, 3.14,// emitSize, emitTime, rate, cone
545
- Game.spriteAtlas.dot, // tileInfo
546
- hsl(0,0,0), hsl(0,0,0), // colorStartA, colorStartB
547
- hsl(0,0,0,0), hsl(0,0,0,0), // colorEndA, colorEndB
548
- 1, 1, 2, .1, .1, // time, sizeStart, sizeEnd, speed, angleSpeed
549
- .9, 1, -.5, 3.14, .1, // damp, angleDamp, gravity, particleCone, fade
550
- 1, 0, 0, 0, 1e8 // randomness, collide, additive, colorLinear, renderOrder
551
- );
552
-
553
- // fire
554
- new LJS.ParticleEmitter(
555
- pos, 0, // pos, angle
556
- radius, .1, 100*radius, 3.14, // emitSize, emitTime, rate, cone
557
- Game.spriteAtlas.dot, // tileInfo
558
- hsl(0,.8,.5), hsl(.15,.8,.5), // colorStartA, colorStartB
559
- hsl(0,1,.5,0), hsl(.1, 1,.5,0),// colorEndA, colorEndB
560
- .7, 1, .5, .1, .1, // time, sizeStart, sizeEnd, speed, angleSpeed
561
- .9, 1, 0, 3.14, .05, // damp, angleDamp, gravity, particleCone, fade
562
- 1, 0, 1, 0, 1e9 // randomness, collide, additive, colorLinear, renderOrder
563
- );
564
- }
@@ -1,9 +0,0 @@
1
- <!DOCTYPE html><head>
2
- <title>LittleJS Box2D Example</title>
3
- <meta charset=utf-8>
4
- <meta name=apple-mobile-web-app-capable content=yes>
5
- <meta name=mobile-web-app-capable content=yes>
6
- <link rel=icon type=image/png href=../favicon.png>
7
- </head><body>
8
- <script src=../../dist/box2d.wasm.js></script>
9
- <script src=game.js type=module></script>