littlejsengine 1.9.7 → 1.9.9

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 (48) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +13 -8
  3. package/dist/littlejs.d.ts +75 -69
  4. package/dist/littlejs.esm.js +313 -354
  5. package/dist/littlejs.esm.min.js +1 -1
  6. package/dist/littlejs.js +307 -350
  7. package/dist/littlejs.min.js +1 -1
  8. package/dist/littlejs.release.js +244 -319
  9. package/examples/box2d/game.js +137 -0
  10. package/examples/box2d/index.html +12 -0
  11. package/examples/box2d/scenes.js +412 -0
  12. package/examples/box2d/tiles.png +0 -0
  13. package/examples/breakout/game.js +3 -3
  14. package/examples/breakout/index.html +4 -3
  15. package/examples/breakoutTutorial/index.html +2 -2
  16. package/examples/electron/build.js +1 -1
  17. package/examples/electron/index.html +2 -2
  18. package/examples/js13k/build.js +19 -1
  19. package/examples/js13k/index.html +13 -13
  20. package/examples/module/index.html +1 -1
  21. package/examples/particles/index.html +1 -1
  22. package/examples/platformer/gameEffects.js +2 -2
  23. package/examples/platformer/gameLevel.js +0 -1
  24. package/examples/platformer/index.html +8 -8
  25. package/examples/puzzle/index.html +2 -2
  26. package/examples/starter/build.js +1 -1
  27. package/examples/starter/index.html +13 -13
  28. package/examples/stress/index.html +1 -1
  29. package/examples/typescript/index.html +1 -1
  30. package/package.json +1 -1
  31. package/plugins/Box2D_v2.3.1_min.wasm.js +630 -0
  32. package/plugins/Box2D_v2.3.1_min.wasm.wasm +0 -0
  33. package/plugins/box2d.js +879 -0
  34. package/plugins/newgrounds.js +169 -0
  35. package/plugins/postProcess.js +102 -0
  36. package/src/engine.js +48 -29
  37. package/src/engineAudio.js +20 -12
  38. package/src/engineBuild.js +1 -1
  39. package/src/engineDebug.js +68 -33
  40. package/src/engineDraw.js +1 -1
  41. package/src/engineExport.js +6 -4
  42. package/src/engineInput.js +7 -4
  43. package/src/engineMedals.js +40 -171
  44. package/src/engineObject.js +33 -2
  45. package/src/engineRelease.js +5 -2
  46. package/src/engineSettings.js +14 -2
  47. package/src/engineUtilities.js +75 -2
  48. package/src/engineWebGL.js +1 -94
@@ -0,0 +1,137 @@
1
+ /*
2
+ Little JS Box2d Demo
3
+ - Demonstrates how to use Box2D with LittleJS
4
+ - Several scenes to demonstrate Box2D features
5
+ - Every type of shape and joint
6
+ - Contact begin and end callbacks
7
+ - Raycasting and querying
8
+ - Collision filtering
9
+ - User Interaction
10
+ */
11
+
12
+ 'use strict';
13
+
14
+ // show the LittleJS splash screen
15
+ setShowSplashScreen(true);
16
+ //box2dDebug = 1; // enable box2d debug draw
17
+
18
+ // game variables
19
+ const maxScenes = 9;
20
+ let scene = 0;
21
+ let sceneName;
22
+ let groundObject;
23
+ let mouseJoint;
24
+ let carWheelJoint;
25
+
26
+ ///////////////////////////////////////////////////////////////////////////////
27
+ function gameInit()
28
+ {
29
+ loadScene(scene);
30
+ }
31
+
32
+ ///////////////////////////////////////////////////////////////////////////////
33
+ function gameUpdate()
34
+ {
35
+ // scale canvas to fit based on 1080p
36
+ cameraScale = mainCanvasSize.y * 48 / 1080;
37
+
38
+ // mouse controls
39
+ if (mouseWasPressed(0))
40
+ {
41
+ // grab object
42
+ sound_click.play(mousePos);
43
+ const object = box2dPointCast(mousePos);
44
+ if (object)
45
+ mouseJoint = box2dCreateMouseJoint(object, groundObject, mousePos);
46
+ }
47
+ if (mouseWasReleased(0))
48
+ {
49
+ // release object
50
+ sound_click.play(mousePos, 1, .5);
51
+ if (mouseJoint)
52
+ {
53
+ box2dDestroyJoint(mouseJoint);
54
+ mouseJoint = 0;
55
+ }
56
+ }
57
+ if (mouseWasPressed(1) || keyWasPressed('KeyZ'))
58
+ spawnRandomObject(mousePos);
59
+ if (mouseWasPressed(2) || keyWasPressed('KeyX'))
60
+ explosion(mousePos);
61
+ if (mouseJoint)
62
+ mouseJoint.SetTarget(mousePos.getBox2d());
63
+
64
+ if (keyWasPressed('ArrowUp') || keyWasPressed('ArrowDown'))
65
+ {
66
+ // change scene
67
+ scene += keyWasPressed('ArrowUp') ? 1 : -1;
68
+ scene = mod(scene, maxScenes);
69
+ loadScene(scene);
70
+ }
71
+
72
+ if (carWheelJoint)
73
+ {
74
+ // update car control
75
+ const control = keyIsDown('ArrowLeft') - keyIsDown('ArrowRight');
76
+ let s = carWheelJoint.GetMotorSpeed();
77
+ s = control ? clamp(s + control, -40, 40) : s * .8;
78
+ carWheelJoint.SetMotorSpeed(s);
79
+ }
80
+ }
81
+
82
+ ///////////////////////////////////////////////////////////////////////////////
83
+ function gameUpdatePost()
84
+ {
85
+
86
+ }
87
+
88
+ ///////////////////////////////////////////////////////////////////////////////
89
+ function gameRender()
90
+ {
91
+ // draw a grey square in the background without using webgl
92
+ drawRect(vec2(20,8), vec2(100), hsl(0,0,.8), 0, 0);
93
+
94
+ if (scene == 5)
95
+ {
96
+ // raycast test
97
+ const count = 100;
98
+ const distance = 10;
99
+ for (let i=count;i--;)
100
+ {
101
+ const start = mousePos;
102
+ const end = mousePos.add(vec2(distance,0).rotate(i/count*PI*2));
103
+ const result = box2dRaycast(start, end);
104
+ const color = result ? hsl(0,1,.5,.5) : hsl(.5,1,.5,.5);
105
+ drawLine(start, result ? result.point : end, .1, color);
106
+ }
107
+ }
108
+ }
109
+
110
+ ///////////////////////////////////////////////////////////////////////////////
111
+ function gameRenderPost()
112
+ {
113
+ // draw to overlay canvas for hud rendering
114
+ const pos = vec2(mainCanvasSize.x/2, 50);
115
+ drawText('LittleJS Box2D Demo', 80, 80);
116
+ drawText(sceneName, 60, 100);
117
+ if (scene == 0)
118
+ {
119
+ drawText('Mouse Left = Grab');
120
+ drawText('Mouse Middle or Z = Spawn');
121
+ drawText('Mouse Right or X = Explode');
122
+ drawText('Arrows Up/Down = Change Scene');
123
+ }
124
+ if (scene == 3)
125
+ {
126
+ drawText('Right = Accelerate');
127
+ drawText('Left = Reverse');
128
+ }
129
+
130
+ function drawText(text, size=40, gap=50)
131
+ { drawTextScreen(text, pos, size, WHITE, size*.1); pos.y += gap; }
132
+ }
133
+
134
+ ///////////////////////////////////////////////////////////////////////////////
135
+ // Startup LittleJS Engine with Box2D
136
+
137
+ box2dEngineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost);
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html><head>
2
+ <title>Little JS Starter Project</title>
3
+ <meta name=apple-mobile-web-app-capable content=yes>
4
+ <meta name=mobile-web-app-capable content=yes>
5
+ <link rel=icon type=image/png href=../favicon.png>
6
+ </head><body>
7
+
8
+ <script src=../../dist/littlejs.js></script>
9
+ <script src=../../plugins/Box2D_v2.3.1_min.wasm.js?197></script>
10
+ <script src=../../plugins/box2d.js?197></script>
11
+ <script src=scenes.js?197></script>
12
+ <script src=game.js?197></script>
@@ -0,0 +1,412 @@
1
+ /*
2
+ LittleJS Box2D Example - Secenes
3
+ - Each scene demonstrates a feature of Box2D
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ function loadScene(_scene)
9
+ {
10
+ scene = _scene;
11
+
12
+ // setup
13
+ cameraPos = vec2(20,10);
14
+ setGravity(-20);
15
+
16
+ // destroy old scene
17
+ engineObjectsDestroy();
18
+ carWheelJoint = 0;
19
+ mouseJoint = 0;
20
+
21
+ // create walls
22
+ groundObject = spawnBox(vec2(0,-4), vec2(1e3,8), hsl(0,0,.2), box2dBodyTypeStatic);
23
+ spawnBox(vec2(-4, 0), vec2(8,1e3), BLACK, box2dBodyTypeStatic);
24
+ spawnBox(vec2(44, 0), vec2(8,1e3), BLACK, box2dBodyTypeStatic);
25
+ spawnBox(vec2(0,100), vec2(1e3,8), BLACK, box2dBodyTypeStatic);
26
+
27
+ if (scene == 0)
28
+ {
29
+ sceneName = 'Shapes';
30
+ spawnRandomEdges();
31
+ spawnBox(vec2(11,8), 4, randColor(), box2dBodyTypeStatic, false);
32
+ spawnCircle(vec2(20,8), 4, randColor(), box2dBodyTypeStatic, false);
33
+ spawnRandomPoly(vec2(29,8), 4, randColor(), box2dBodyTypeStatic, false);
34
+ for (let i=500;i--;)
35
+ spawnRandomObject(vec2(rand(1,39), rand(10,50)));
36
+ }
37
+ if (scene == 1)
38
+ {
39
+ sceneName = 'Pyramid';
40
+ spawnPyramid(vec2(20,0), 15);
41
+ spawnBox(vec2(10,2), 4, randColor());
42
+ spawnCircle(vec2(30,2), 4, randColor());
43
+ }
44
+ if (scene == 2)
45
+ {
46
+ sceneName = 'Dominoes';
47
+ spawnDominoes(vec2(11,11), 11);
48
+ spawnDominoes(vec2(2,0), 13, vec2(1,3));
49
+ spawnCircle(vec2(10,20), 2, randColor());
50
+ spawnCircle(vec2(31.7,12), 2, randColor());
51
+ spawnBox(vec2(16,11), vec2(32,1), randColor(), box2dBodyTypeStatic, false);
52
+ spawnBox(vec2(24,6.5), vec2(32,1), randColor(), box2dBodyTypeStatic, false, -.15);
53
+ }
54
+ if (scene == 3)
55
+ {
56
+ sceneName = 'Car';
57
+ spawnCar(vec2(10,2));
58
+ spawnBox(vec2(20,0), vec2(10,2), randColor(), box2dBodyTypeStatic, false, -.2);
59
+ spawnPyramid(vec2(32,0), 6);
60
+ }
61
+ if (scene == 4)
62
+ {
63
+ sceneName = 'Rope';
64
+ const startPos = vec2(20, 14);
65
+ const angle = PI/2;
66
+ const color = randColor();
67
+ const count = 10;
68
+ const endObject = spawnRope(startPos, count, angle, color);
69
+
70
+ // connect box to end
71
+ const endPos = endObject.localToWorld(vec2(0,-endObject.size.y/2));
72
+ const o = spawnBox(endPos, 3, randColor());
73
+ o.setAngularDamping(.5);
74
+ o.setFilterData(2, 2);
75
+ box2dCreateRevoluteJoint(endObject, o);
76
+ spawnPyramid(vec2(20,0), 7);
77
+ }
78
+ if (scene == 5)
79
+ {
80
+ sceneName = 'Raycasts';
81
+ spawnRandomEdges();
82
+ for (let i=100;i--;)
83
+ spawnRandomObject(vec2(rand(1,39), rand(20)), 2, box2dBodyTypeStatic, rand(PI*2));
84
+ }
85
+ if (scene == 6)
86
+ {
87
+ sceneName = 'Joints';
88
+ {
89
+ // prismatic joint
90
+ const o1 = spawnBox(vec2(20,8), vec2(3,2), randColor());
91
+ box2dCreatePrismaticJoint(groundObject, o1, o1.pos, vec2(1,0), true);
92
+ const o2 = spawnBox(vec2(20,15), vec2(2,3), randColor());
93
+ box2dCreatePrismaticJoint(groundObject, o2, o2.pos, vec2(0,1), true);
94
+
95
+ // lines to make it look line a track
96
+ const l1 = new EngineObject(vec2(20, 8), vec2(39,.5), 0, 0, GRAY);
97
+ const l2 = new EngineObject(vec2(20,50), vec2(.5,99), 0, 0, GRAY);
98
+ l1.gravityScale = l2.gravityScale = 0;
99
+ l1.renderOrder = l2.renderOrder = -2;
100
+ }
101
+ {
102
+ // pulley object renders a rope to connected point
103
+ class PulleyObjects extends Box2dObject
104
+ {
105
+ constructor(pos, size, color, connectionPos)
106
+ {
107
+ super(pos, size, tile(3), 0, color);
108
+ this.addBox(size);
109
+ this.connectionPos = connectionPos;
110
+ }
111
+ render()
112
+ {
113
+ // draw rope
114
+ const topPos = this.localToWorld(vec2(0,this.size.y/2));
115
+ drawLine(topPos, this.connectionPos, .2, BLACK);
116
+ super.render();
117
+ }
118
+ }
119
+
120
+ // pulley joint
121
+ const anchorA = vec2(14,15);
122
+ const anchorB = vec2(26,15);
123
+ const oA = new PulleyObjects(vec2(15,8), vec2(1,2), randColor(), anchorA);
124
+ const oB = new PulleyObjects(vec2(25,8), vec2(1,2), randColor(), anchorB);
125
+ const aA = spawnCircle(anchorA, 2, randColor(), box2dBodyTypeStatic);
126
+ const aB = spawnCircle(anchorB, 2, randColor(), box2dBodyTypeStatic);
127
+ const oaA = oA.localToWorld(vec2(0,oA.size.y/2));
128
+ const oaB = oB.localToWorld(vec2(0,oB.size.y/2));
129
+ box2dCreatePulleyJoint(oA, oB, aA.pos, aB.pos, oaA, oaB);
130
+
131
+ // a line to make it look like conneting rope
132
+ const line = new EngineObject(vec2(20,15), vec2(10,.2), 0, 0, BLACK);
133
+ line.gravityScale = 0;
134
+ line.renderOrder = -1;
135
+ }
136
+ {
137
+ // gear joint
138
+ const o1 = spawnCircle(vec2(23.5,3), 3, randColor());
139
+ const j1 = box2dCreateRevoluteJoint(groundObject, o1, o1.pos);
140
+ const o2 = spawnCircle(vec2(28,3), 6, randColor());
141
+ o1.tileInfo = o2.tileInfo = tile(5);
142
+ const j2 = box2dCreateRevoluteJoint(groundObject, o2, o2.pos);
143
+ box2dCreateGearJoint(o1, o2, j1, j2, 2);
144
+ }
145
+ {
146
+ // weld joint
147
+ const o1 = spawnBox(vec2(15,2), 4, randColor());
148
+ const o2 = spawnBox(vec2(17,2), 2, randColor());
149
+ box2dCreateWeldJoint(o1, o2);
150
+ }
151
+ {
152
+ // distance joint
153
+ const o1 = new Box2dObject(vec2(30,11), vec2(4), tile(2), 0, randColor(), box2dBodyTypeStatic);
154
+ o1.renderOrder = -2;
155
+ const o2 = spawnCircle(vec2(30,8), 2, randColor());
156
+ box2dCreateDistanceJoint(o1, o2);
157
+ }
158
+ {
159
+ // motor object renders a rope to connected point
160
+ class MotorObject extends Box2dObject
161
+ {
162
+ constructor(pos, size, color, otherObject)
163
+ {
164
+ super(pos, size, tile(4), 0, color);
165
+ this.addCircle(size.x);
166
+ this.connectionPos = pos;
167
+ const joint = box2dCreateMotorJoint(otherObject, this);
168
+ joint.SetMaxForce(500);
169
+ joint.SetMaxTorque(500);
170
+ }
171
+ render()
172
+ {
173
+ // draw rope
174
+ const width = 2/(1+this.pos.distance(this.connectionPos));
175
+ drawLine(this.pos, this.connectionPos, width, BLACK);
176
+ super.render();
177
+ }
178
+ }
179
+
180
+ // motor joint
181
+ const o = new Box2dObject(vec2(10,8), vec2(4), tile(2), 0, randColor(), box2dBodyTypeStatic);
182
+ o.renderOrder = -2;
183
+ new MotorObject(vec2(10,8), vec2(2), randColor(), o);
184
+ }
185
+ {
186
+ // friction joint
187
+ const o = spawnBox(vec2(10,15), 3, randColor());
188
+ o.tileInfo = tile(6);
189
+ const joint = box2dCreateFrictionJoint(groundObject, o);
190
+ joint.SetMaxForce(200);
191
+ joint.SetMaxTorque(200);
192
+ }
193
+ }
194
+ if (scene == 7)
195
+ {
196
+ sceneName = 'Contacts';
197
+ // changes objects color when touched
198
+ class ContactTester extends Box2dObject
199
+ {
200
+ constructor(pos, size, color, contactColor, isSensor=false)
201
+ {
202
+ super(pos, size, 0, 0, color, box2dBodyTypeStatic);
203
+ if (isSensor)
204
+ {
205
+ this.addCircle(size.x);
206
+ this.setSensor(isSensor);
207
+ }
208
+ else
209
+ this.addBox(size);
210
+ this.contactColor = contactColor;
211
+ }
212
+ beginContact(other) { other.color = this.contactColor; }
213
+ endContact(other) { other.color = WHITE; }
214
+ }
215
+ new ContactTester(vec2(15,8), vec2(5), hsl(0,0,0,.3), RED, true);
216
+ new ContactTester(vec2(25,8), vec2(5), hsl(0,0,.1), GREEN);
217
+ for (let i=200;i--;)
218
+ spawnRandomObject(vec2(rand(1,39), rand(10,50)));
219
+ }
220
+ if (scene == 8)
221
+ {
222
+ sceneName = 'Mobile';
223
+ const pos = vec2(20, 16);
224
+ const mobile = spawnMobile(pos, 12, 2, 5);
225
+ box2dCreateRevoluteJoint(groundObject, mobile, pos);
226
+ }
227
+
228
+ // helper functions
229
+ function spawnRandomEdges()
230
+ {
231
+ // edge list along bottom
232
+ const edgePoints = [];
233
+ edgePoints.push(vec2(40,0));
234
+ for (let i=40, y=0; i--;)
235
+ edgePoints.push(vec2(i, y=clamp(y+rand(-2,2),0,5)));
236
+ edgePoints.push(vec2(0,0));
237
+ const o = new Box2dObject(vec2(), vec2(), 0, 0, BLACK, box2dBodyTypeStatic);
238
+ o.addEdgeList(edgePoints);
239
+ }
240
+ function spawnRope(startPos, count, angle=PI, color=WHITE, size=vec2(.3,1))
241
+ {
242
+ let lastObject = groundObject;
243
+ for (let i=0; i<count; ++i)
244
+ {
245
+ const pos = startPos.add(size.multiply(vec2(0,i+.5)).rotate(-angle));
246
+ const o = spawnBox(pos, size, color, box2dBodyTypeDynamic, false, angle);
247
+ o.setFilterData(2, 2);
248
+ const anchorPos = pos.add(vec2(0,-size.y/2).rotate(-angle));
249
+ box2dCreateRevoluteJoint(lastObject, o, anchorPos);
250
+ lastObject = o;
251
+ }
252
+ const endPos = lastObject.localToWorld(vec2(0,-size.y/2));
253
+ box2dCreateRopeJoint(groundObject, lastObject, startPos, endPos);
254
+ return lastObject;
255
+ }
256
+ function spawnPyramid(pos, count)
257
+ {
258
+ for (let i=count+1;i--;)
259
+ for (let j=i;j--;)
260
+ spawnBox(pos.add(vec2(j-i/2+.5,count-i+.5)), 1, randColor());
261
+ }
262
+ function spawnDominoes(pos, count, size=vec2(.5,2))
263
+ {
264
+ for (let i=count; i--;)
265
+ spawnBox(pos.add(vec2(i*size.y*.9,size.y/2)), size, randColor());
266
+ }
267
+ function spawnCar(pos)
268
+ {
269
+ // car object
270
+ const car = new Box2dObject(pos, vec2(), 0, 0, randColor());
271
+ const carPoints = [
272
+ vec2(-1.5,-.5),
273
+ vec2(1.5, -.5),
274
+ vec2(1.5, 0),
275
+ vec2(0, .9),
276
+ vec2(-1.15,.9),
277
+ vec2(-1.5, .2),
278
+ ];
279
+ car.addPoly(carPoints);
280
+
281
+ // wheel settings
282
+ const frequencyHz = 4;
283
+ const dampingRatio = .7;
284
+ const wheelDensity = 1;
285
+ const wheelFriction = 2;
286
+ const wheelRestitution = 0;
287
+ const wheelSize = .8;
288
+
289
+ // back wheel
290
+ const wheel1Pos = pos.add(vec2(-1, -.65));
291
+ const wheel1 = new Box2dObject(wheel1Pos, vec2(wheelSize), tile(4));
292
+ wheel1.addCircle(wheelSize,vec2(),wheelDensity,wheelFriction,wheelRestitution);
293
+ const joint1 = box2dCreateWheelJoint(car,wheel1);
294
+ joint1.SetSpringDampingRatio(dampingRatio);
295
+ joint1.SetSpringFrequencyHz(frequencyHz);
296
+ joint1.SetMaxMotorTorque(50);
297
+ joint1.EnableMotor(true);
298
+ carWheelJoint = joint1;
299
+
300
+ // front wheel
301
+ const wheel2Pos = pos.add(vec2(1, -.6));
302
+ const wheel2 = new Box2dObject(wheel2Pos, vec2(wheelSize), tile(4));
303
+ wheel2.addCircle(wheelSize,vec2(),wheelDensity,wheelFriction,wheelRestitution);
304
+ const joint2 = box2dCreateWheelJoint(car,wheel2);
305
+ joint2.SetSpringDampingRatio(dampingRatio);
306
+ joint2.SetSpringFrequencyHz(frequencyHz);
307
+ }
308
+ function spawnMobile(anchor, w, h, depth)
309
+ {
310
+ // tall box
311
+ const pos = anchor.add(vec2(0,-h/2));
312
+ const o = spawnBox(pos, vec2(h/4, h), randColor(), box2dBodyTypeDynamic, false);
313
+ if (--depth)
314
+ {
315
+ // long box on bottom
316
+ o.addBox(vec2(w, h/4), vec2(0, -h/2));
317
+
318
+ // spawn smaller mobiles attached to each side
319
+ for(let i=2; i--;)
320
+ {
321
+ const a = anchor.add(vec2( w/2*(i?1:-1), -h));
322
+ const o2 = spawnMobile(a, w/2, h, depth);
323
+ box2dCreateRevoluteJoint(o, o2, a);
324
+ }
325
+ }
326
+ return o;
327
+ }
328
+ }
329
+
330
+ ///////////////////////////////////////////////////////////////////////////////
331
+ // Spawn object functions
332
+
333
+ function spawnBox(pos, size=1, color=WHITE, type=box2dBodyTypeDynamic, applyTexture=true, angle=0)
334
+ {
335
+ size = typeof size == 'number' ? vec2(size) : size; // square
336
+ const o = new Box2dObject(pos, size, applyTexture && tile(3), angle, color, type);
337
+ o.addBox(size);
338
+ return o;
339
+ }
340
+
341
+ function spawnCircle(pos, diameter=1, color=WHITE, type=box2dBodyTypeDynamic, applyTexture=true, angle=0)
342
+ {
343
+ const size = vec2(diameter);
344
+ const o = new Box2dObject(pos, size, applyTexture && tile(2), angle, color, type);
345
+ o.addCircle(diameter);
346
+ return o;
347
+ }
348
+
349
+ function spawnRandomPoly(pos, diameter=1, color=WHITE, type=box2dBodyTypeDynamic, angle=0)
350
+ {
351
+ const o = new Box2dObject(pos, vec2(), 0, angle, color, type);
352
+ o.addRandomPoly(diameter);
353
+ return o;
354
+ }
355
+
356
+ function spawnRandomObject(pos, scale=1, type=box2dBodyTypeDynamic, angle=0)
357
+ {
358
+ if (randInt(2))
359
+ {
360
+ const size = vec2(scale*rand(.5,1), scale*rand(.5,1));
361
+ return spawnBox(pos, size, randColor(), type, true, angle);
362
+ }
363
+ else
364
+ {
365
+ const diameter = scale*rand(.5,1);
366
+ return spawnCircle(pos, diameter, randColor(), type, true, angle);
367
+ }
368
+ }
369
+
370
+ ///////////////////////////////////////////////////////////////////////////////
371
+ // Effects
372
+
373
+ const sound_click = new Sound([,.1]);
374
+ const sound_explosion = new Sound([,.2,72,.01,.01,.2,4,,,,,,,1,,.5,.1,.5,.02]);
375
+
376
+ function explosion(pos, radius=3, strength=300)
377
+ {
378
+ sound_explosion.play(pos);
379
+ const objects = box2dCircleCastAll(pos, (radius*2));
380
+ const newColor = randColor();
381
+ for (const o of objects)
382
+ {
383
+ const p = percent(o.pos.distance(pos), 2*radius, radius);
384
+ const force = o.pos.subtract(pos).normalize(p*radius*strength);
385
+ o.applyForce(force);
386
+ o.color = newColor;
387
+ }
388
+
389
+ // smoke
390
+ new ParticleEmitter(
391
+ pos, 0, // pos, angle
392
+ radius/2, .2, 50*radius, PI,// emitSize, emitTime, emitRate, emiteCone
393
+ tile(1), // tileInfo
394
+ hsl(0,0,0), hsl(0,0,0), // colorStartA, colorStartB
395
+ hsl(0,0,0,0), hsl(0,0,0,0), // colorEndA, colorEndB
396
+ 1, 1, 2, .1, .1, // time, sizeStart, sizeEnd, speed, angleSpeed
397
+ .9, 1, -.5, PI, .1, // damp, angleDamp, gravity, particleCone, fade
398
+ 1, 0, 0, 0, 1e8 // randomness, collide, additive, colorLinear, renderOrder
399
+ );
400
+
401
+ // fire
402
+ new ParticleEmitter(
403
+ pos, 0, // pos, angle
404
+ radius, .1, 100*radius, PI, // emitSize, emitTime, emitRate, emiteCone
405
+ tile(1), // tileInfo
406
+ hsl(0,1,.5), hsl(.15,1,.5), // colorStartA, colorStartB
407
+ hsl(0,1,.5,0), hsl(.1, 1,.5,0), // colorEndA, colorEndB
408
+ .7, 1, .5, .1, .1, // time, sizeStart, sizeEnd, speed, angleSpeed
409
+ .9, 1, 0, PI, .05, // damp, angleDamp, gravity, particleCone, fade
410
+ 1, 0, 1, 0, 1e9 // randomness, collide, additive, colorLinear, renderOrder
411
+ );
412
+ }
Binary file
@@ -38,7 +38,7 @@ function gameInit()
38
38
  new Wall(vec2(levelSize.x+.5,levelSize.y/2), vec2(1,100)) // left
39
39
  new Wall(vec2(levelSize.x/2,levelSize.y+.5), vec2(100,1)) // right
40
40
 
41
- initPostProcess(); // set up a post processing shader
41
+ setupPostProcess(); // set up a post processing shader
42
42
  }
43
43
 
44
44
  ///////////////////////////////////////////////////////////////////////////////
@@ -80,7 +80,7 @@ function gameRenderPost()
80
80
 
81
81
  ///////////////////////////////////////////////////////////////////////////////
82
82
  // an example shader that can be used to apply a post processing effect
83
- function initPostProcess()
83
+ function setupPostProcess()
84
84
  {
85
85
  const televisionShader = `
86
86
  // Simple TV Shader Code
@@ -130,7 +130,7 @@ function initPostProcess()
130
130
  }`;
131
131
 
132
132
  const includeOverlay = true;
133
- glInitPostProcess(televisionShader, includeOverlay);
133
+ initPostProcess(televisionShader, includeOverlay);
134
134
  }
135
135
 
136
136
  ///////////////////////////////////////////////////////////////////////////////
@@ -5,6 +5,7 @@
5
5
  <link rel=icon type=image/png href=../favicon.png>
6
6
  </head><body>
7
7
 
8
- <script src=../../dist/littlejs.js?196></script>
9
- <script src=gameObjects.js?196></script>
10
- <script src=game.js?196></script>
8
+ <script src=../../dist/littlejs.js?197></script>
9
+ <script src=../../plugins/postProcess.js></script>
10
+ <script src=gameObjects.js?197></script>
11
+ <script src=game.js?197></script>
@@ -5,5 +5,5 @@
5
5
  <link rel=icon type=image/png href=../favicon.png>
6
6
  </head><body>
7
7
 
8
- <script src=../../dist/littlejs.js?196></script>
9
- <script src=game.js?196></script>
8
+ <script src=../../dist/littlejs.js?197></script>
9
+ <script src=game.js?197></script>
@@ -68,7 +68,7 @@ function closureCompilerStep(filename)
68
68
 
69
69
  const filenameTemp = filename + '.tmp';
70
70
  fs.copyFileSync(filename, filenameTemp);
71
- child_process.execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=ADVANCED --language_out=ECMASCRIPT_2021 --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
71
+ child_process.execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=ADVANCED --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
72
72
  fs.rmSync(filenameTemp);
73
73
  };
74
74
 
@@ -6,7 +6,7 @@
6
6
  </head><body>
7
7
 
8
8
  <!-- LittleJS Engine -->
9
- <script src=../../dist/littlejs.js?196></script>
9
+ <script src=../../dist/littlejs.js?197></script>
10
10
 
11
11
  <!-- Add your game scripts here -->
12
- <script src=game.js?196></script>
12
+ <script src=game.js?197></script>
@@ -42,6 +42,7 @@ Build
42
42
  `${BUILD_FOLDER}/index.js`,
43
43
  sourceFiles,
44
44
  [closureCompilerStep, uglifyBuildStep, roadrollerBuildStep, htmlBuildStep, zipBuildStep]
45
+ //[closureCompilerSimpleStep, htmlBuildStep] // for build debugging
45
46
  );
46
47
 
47
48
  console.log(``);
@@ -73,7 +74,17 @@ function closureCompilerStep(filename)
73
74
 
74
75
  const filenameTemp = filename + '.tmp';
75
76
  fs.copyFileSync(filename, filenameTemp);
76
- child_process.execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=ADVANCED --language_out=ECMASCRIPT_2021 --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
77
+ child_process.execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=ADVANCED --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
78
+ fs.rmSync(filenameTemp);
79
+ };
80
+
81
+ function closureCompilerSimpleStep(filename)
82
+ {
83
+ console.log(`Running closure compiler in simple mode...`);
84
+
85
+ const filenameTemp = filename + '.tmp';
86
+ fs.copyFileSync(filename, filenameTemp);
87
+ child_process.execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=SIMPLE --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
77
88
  fs.rmSync(filenameTemp);
78
89
  };
79
90
 
@@ -89,6 +100,13 @@ function roadrollerBuildStep(filename)
89
100
  child_process.execSync(`npx roadroller ${filename} -o ${filename}`, {stdio: 'inherit'});
90
101
  };
91
102
 
103
+ function roadrollerExtremeBuildStep(filename)
104
+ {
105
+ // this takes over a minute to run but might be a little smaller
106
+ console.log(`Running roadroller extreme...`);
107
+ child_process.execSync(`npx roadroller ${filename} -o ${filename} --optimize 2`, {stdio: 'inherit'});
108
+ };
109
+
92
110
  function htmlBuildStep(filename)
93
111
  {
94
112
  console.log(`Building html...`);