littlejsengine 1.13.1 → 1.13.4

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 (66) hide show
  1. package/README.md +15 -12
  2. package/dist/littlejs.d.ts +94 -74
  3. package/dist/littlejs.esm.js +422 -306
  4. package/dist/littlejs.esm.min.js +1 -1
  5. package/dist/littlejs.js +416 -306
  6. package/dist/littlejs.min.js +1 -1
  7. package/dist/littlejs.release.js +414 -304
  8. package/examples/box2d/game.js +1 -1
  9. package/examples/box2d/gameObjects.js +1 -1
  10. package/examples/box2d/scenes.js +1 -1
  11. package/examples/breakoutTutorial/README.md +44 -41
  12. package/examples/breakoutTutorial/game.js +2 -2
  13. package/examples/electron/build.bat +7 -0
  14. package/examples/electron/build.js +124 -0
  15. package/examples/electron/electron.js +35 -0
  16. package/examples/electron/game.js +140 -0
  17. package/examples/electron/index.html +13 -0
  18. package/examples/electron/package.json +12 -0
  19. package/examples/electron/tiles.png +0 -0
  20. package/examples/empty/game.js +1 -0
  21. package/examples/htmlMenu/game.js +1 -1
  22. package/examples/index.html +154 -93
  23. package/examples/module/game.js +5 -2
  24. package/examples/particles/index.html +12 -3
  25. package/examples/platformer/gameEffects.js +3 -3
  26. package/examples/shorts/base.html +1 -1
  27. package/examples/shorts/blending.js +9 -5
  28. package/examples/shorts/box2d.js +1 -1
  29. package/examples/shorts/box2dCar.js +1 -1
  30. package/examples/shorts/clock.js +1 -1
  31. package/examples/shorts/colors.js +2 -2
  32. package/examples/shorts/maze.js +1 -1
  33. package/examples/shorts/nineSlice.js +9 -9
  34. package/examples/shorts/piano.js +2 -2
  35. package/examples/shorts/raycasting.js +2 -2
  36. package/examples/shorts/shapes.js +9 -9
  37. package/examples/shorts/slidingPuzzle.js +2 -2
  38. package/examples/shorts/starfield.js +5 -7
  39. package/examples/shorts/systemFont.js +1 -1
  40. package/examples/shorts/uiSystem.js +1 -0
  41. package/examples/starter/build.js +9 -8
  42. package/examples/starter/game.js +5 -2
  43. package/examples/starter/index.html +2 -2
  44. package/examples/stress/index.html +5 -5
  45. package/examples/style.css +5 -2
  46. package/examples/typescript/build.js +1 -1
  47. package/examples/typescript/game.js +2 -2
  48. package/examples/typescript/game.ts +5 -2
  49. package/examples/uiSystem/game.js +2 -1
  50. package/package.json +2 -2
  51. package/plugins/box2d.js +19 -94
  52. package/plugins/drawUtilities.js +24 -18
  53. package/plugins/postProcess.js +7 -0
  54. package/plugins/uiSystem.js +4 -4
  55. package/src/engine.js +7 -2
  56. package/src/engineAudio.js +1 -1
  57. package/src/engineDebug.js +2 -2
  58. package/src/engineDraw.js +243 -150
  59. package/src/engineExport.js +6 -0
  60. package/src/engineInput.js +2 -2
  61. package/src/engineMedals.js +4 -4
  62. package/src/engineObject.js +3 -3
  63. package/src/engineParticles.js +8 -1
  64. package/src/engineSettings.js +55 -8
  65. package/src/engineUtilities.js +7 -7
  66. package/src/engineWebGL.js +25 -5
@@ -137,7 +137,7 @@ function gameUpdatePost()
137
137
  function gameRender()
138
138
  {
139
139
  // draw a grey square in the background without using webgl
140
- LJS.drawRect(vec2(20,8), vec2(100), hsl(0,0,.8), 0, 0);
140
+ LJS.drawRect(vec2(20,8), vec2(100), hsl(0,0,.8), 0, false);
141
141
 
142
142
  if (Scenes.scene == 5)
143
143
  {
@@ -308,7 +308,7 @@ export class SoftBodyObject extends LJS.Box2dObject
308
308
  for (let y = 0; y < sy.y; ++y) poly.push(this.getNode(sx-1, y).pos);
309
309
  for (let x = sx; x--;) poly.push(this.getNode(x, sy-1).pos);
310
310
  for (let y = sy; y--;) poly.push(this.getNode(0, y).pos);
311
- LJS.box2d.drawPoly(vec2(), 0, poly, LJS.BLACK)
311
+ LJS.drawPoly(poly, LJS.BLACK)
312
312
  }
313
313
  getNode(x, y)
314
314
  {
@@ -181,7 +181,7 @@ export function loadScene(_scene)
181
181
  if (scene == 10)
182
182
  {
183
183
  sceneName = 'Softbodies';
184
- for(let i=3;i--;)
184
+ for (let i=3;i--;)
185
185
  new GameObjects.SoftBodyObject(vec2(20, 3+i*7), vec2(6-i), vec2(9-i), LJS.randColor());
186
186
  }
187
187
  }
@@ -21,11 +21,11 @@ The first step is to make a 2D grid of brick objects in gameInit. As a placehold
21
21
 
22
22
  ```javascript
23
23
  // create bricks
24
- for(let x=0; x<=20; x++)
25
- for(let y=0; y<=20; y++)
24
+ for (let x=0; x<=20; x++)
25
+ for (let y=0; y<=20; y++)
26
26
  {
27
- const brick = new EngineObject(vec2(x,y)); // create a brick
28
- brick.color = randColor(); // give brick a random color
27
+ const brick = new LJS.EngineObject(vec2(x,y)); // create a brick
28
+ brick.color = LJS.randColor(); // give brick a random color
29
29
  }
30
30
  ```
31
31
 
@@ -42,11 +42,11 @@ Let’s make the bricks more rectangular by passing vec2(2,1) to the size parame
42
42
  ```javascript
43
43
  // create bricks
44
44
  const levelSize = vec2(20, 20);
45
- for(let x=0; x<=levelSize.x; x+=2)
46
- for(let y=0; y<=levelSize.y; y+=1)
45
+ for (let x=0; x<=levelSize.x; x+=2)
46
+ for (let y=0; y<=levelSize.y; y+=1)
47
47
  {
48
- const brick = new EngineObject(vec2(x,y), vec2(2,1)); // create a brick
49
- brick.color = randColor(); // give brick a random color
48
+ const brick = new LJS.EngineObject(vec2(x,y), vec2(2,1)); // create a brick
49
+ brick.color = LJS.randColor(); // give brick a random color
50
50
  }
51
51
  ```
52
52
 
@@ -57,13 +57,13 @@ You can also change the camera zoom by using camaraScale which controls the numb
57
57
  For this example the camera will just remain stationary, but in other types of games it is very useful!
58
58
 
59
59
  ```javascript
60
- setCameraPos(levelSize.scale(.5)); // center camera in level
60
+ LJS.setCameraPos(levelSize.scale(.5)); // center camera in level
61
61
  ```
62
62
 
63
63
  We’ll also start with a blank slate by commenting out the default “Hello World!” text in gameRenderPost.
64
64
 
65
65
  ```javascript
66
- // drawTextScreen('Hello World!', mainCanvasSize.scale(.5), 80);
66
+ // LJS.drawTextScreen('Hello World!', LJS.mainCanvasSize.scale(.5), 80);
67
67
  ```
68
68
 
69
69
  ![LittleJS Screenshot](images/2.png)
@@ -77,14 +77,14 @@ For this example we will use a fixed size canvas. This will let the drawing canv
77
77
  To enable it we will set canvasFixedSize in gameInit to use 720p resolution.
78
78
 
79
79
  ```javascript
80
- setCanvasFixedSize(vec2(1280, 720)); // use a 720p fixed size canvas
80
+ LJS.setCanvasFixedSize(vec2(1280, 720)); // use a 720p fixed size canvas
81
81
  ```
82
82
 
83
83
  Before we tweak the level size, let’s add this bit of code to gameRender to show the size of the level. This will cause some rects to be drawn each frame before the engine objects. To create color objects we pass in RGB values between 0 and 1.
84
84
 
85
85
  ```javascript
86
- drawRect(cameraPos, vec2(100), new Color(.5,.5,.5)); // draw background
87
- drawRect(cameraPos, levelSize, new Color(.1,.1,.1)); // draw level boundary
86
+ LJS.drawRect(LJS.cameraPos, vec2(100), rgb(.5,.5,.5)); // draw background
87
+ LJS.drawRect(LJS.cameraPos, levelSize, rgb(.1,.1,.1)); // draw level boundary
88
88
  ```
89
89
 
90
90
  We also need to make levelSize a global by moving it to the top so it can be accessed from other functions.
@@ -98,11 +98,11 @@ Now we can see the boundaries of our level and tweak the size to fill the canvas
98
98
  We can also adjust the for loop where the bricks are created to make them only fill the top middle part of the level.
99
99
 
100
100
  ```javascript
101
- for(let x=2; x<=levelSize.x-2; x+=2)
102
- for(let y=12; y<=levelSize.y-2; y+=1)
101
+ for (let x=2; x<=levelSize.x-2; x+=2)
102
+ for (let y=12; y<=levelSize.y-2; y+=1)
103
103
  {
104
- const brick = new EngineObject(vec2(x,y), vec2(2,1)); // create a brick
105
- brick.color = randColor(); // give brick a random color
104
+ const brick = new LJS.EngineObject(vec2(x,y), vec2(2,1)); // create a brick
105
+ brick.color = LJS.randColor(); // give brick a random color
106
106
  }
107
107
  ```
108
108
 
@@ -115,11 +115,11 @@ Now that looks almost like a breakout game!
115
115
  For the player’s paddle, let’s create a new class of object that extends the built in EngineObject. This will allow us to control movement with the mouse. In this Paddle class we will just add some new code to the update function which is automatically called each frame by the engine.
116
116
 
117
117
  ```javascript
118
- class Paddle extends EngineObject
118
+ class Paddle extends LJS.EngineObject
119
119
  {
120
120
  update()
121
121
  {
122
- this.pos.x = mousePos.x; // move paddle to mouse
122
+ this.pos.x = LJS.mousePos.x; // move paddle to mouse
123
123
  }
124
124
  }
125
125
  ```
@@ -149,7 +149,7 @@ You can also add this code to the paddle update that will keep the paddle from f
149
149
 
150
150
  ```javascript
151
151
  // clamp paddle to level size
152
- this.pos.x = clamp(this.pos.x, this.size.x/2, levelSize.x - this.size.x/2);
152
+ this.pos.x = LJS.clamp(this.pos.x, this.size.x/2, levelSize.x - this.size.x/2);
153
153
  ```
154
154
 
155
155
  ## Create the Ball
@@ -158,7 +158,7 @@ The final missing piece is of course that ball that moves around and bounces off
158
158
  We can create a Ball class the same way we created the paddle. In this case we will also apply some velocity to ball so it starts moving right away.
159
159
 
160
160
  ```javascript
161
- class Ball extends EngineObject
161
+ class Ball extends LJS.EngineObject
162
162
  {
163
163
  constructor(pos)
164
164
  {
@@ -172,7 +172,10 @@ class Ball extends EngineObject
172
172
  Then we just need to create the ball in gameInit, passing in the camera position for it’s location.
173
173
 
174
174
  ```javascript
175
- new Ball(cameraPos); // create a ball
175
+ {
176
+ // create a ball
177
+ ball = new Ball(LJS.cameraPos);
178
+ }
176
179
  ```
177
180
 
178
181
  ## Make the Ball Collide
@@ -210,7 +213,7 @@ super(pos, vec2(.5)); // set object position and size
210
213
  Next, let’s make the ball bounce when it hits the top or sides of the screen. To do this, we will make a Wall object class that works similar to the paddle but without an update function.
211
214
 
212
215
  ```javascript
213
- class Wall extends EngineObject
216
+ class Wall extends LJS.EngineObject
214
217
  {
215
218
  constructor(pos, size)
216
219
  {
@@ -236,7 +239,7 @@ new Wall(vec2(levelSize.x/2,levelSize.y+.5), vec2(100,1)) // top
236
239
  Now we have white walls around the outside that block the ball. These walls should be invisible so we will set their color to be transparent by adding another line to the Wall constructor.
237
240
 
238
241
  ```javascript
239
- this.color = new Color(0,0,0,0); // make object invisible
242
+ this.color = rgb(0,0,0,0); // make object invisible
240
243
  ```
241
244
 
242
245
  ## Debug Display
@@ -268,7 +271,7 @@ if (!ball || ball.pos.y < -1)
268
271
  ball.destroy();
269
272
 
270
273
  // create a ball
271
- ball = new Ball(cameraPos);
274
+ ball = new Ball(LJS.cameraPos);
272
275
  }
273
276
  ```
274
277
 
@@ -279,7 +282,7 @@ Don’t forget to destroy the old ball before creating the new one! Though it do
279
282
  Still, the ball doesn’t collide with the bricks much less breaks them and it wouldn’t be breakout without that. So we need to make the brick collide with the ball, just like the walls, so let’s start with Brick class that is the same as Wall.
280
283
 
281
284
  ```javascript
282
- class Brick extends EngineObject
285
+ class Brick extends LJS.EngineObject
283
286
  {
284
287
  constructor(pos, size)
285
288
  {
@@ -333,7 +336,7 @@ Then increment it in the Brick.collideWithObject function.
333
336
  And change that drawTextScreen code we had commented out in gameRenderPost to display the score. We can adjust the position and size of the text to fit at the top of the screen.
334
337
 
335
338
  ```javascript
336
- drawTextScreen("Score " + score, vec2(mainCanvasSize.x/2, 70), 50); // show score
339
+ LJS.drawTextScreen("Score " + score, vec2(LJS.mainCanvasSize.x/2, 70), 50); // show score
337
340
  ```
338
341
 
339
342
  ![LittleJS Screenshot](images/9.png)
@@ -347,7 +350,7 @@ We will start with the ball bounce sound. [You can use the official ZzFX sound d
347
350
  To make a sound effect with this system we will create a global object for each sound.
348
351
 
349
352
  ```javascript
350
- const sound_bounce = new Sound([,,1e3,,.03,.02,1,2,,,940,.03,,,,,.2,.6,,.06], 0);
353
+ const sound_bounce = new LJS.Sound([,,1e3,,.03,.02,1,2,,,940,.03,,,,,.2,.6,,.06], 0);
351
354
  ```
352
355
 
353
356
  You can use the sound I chose or copy the code for your own sound from ZzFX. There is a checkbox for LittleJS style sounds to make exporting a little easier.
@@ -366,7 +369,7 @@ Let’s also make a brick break sound. You can use the ZzFX sound designer again
366
369
  Create a global object for this sound the same way we did for the bounce sound. You can replace it with your own generated sound or use mine.
367
370
 
368
371
  ```javascript
369
- const sound_break = new Sound([,,90,,.01,.03,4,,,,,,,9,50,.2,,.2,.01], 0);
372
+ const sound_break = new LJS.Sound([,,90,,.01,.03,4,,,,,,,9,50,.2,,.2,.01], 0);
370
373
  ```
371
374
 
372
375
  Then in the Brick’s collideWithObject function just add some code to play that sound.
@@ -384,7 +387,7 @@ Let’s improve the gameplay by letting the player click to start, instead of cr
384
387
  We can also add a special sound that plays on startup. Try making an interesting start from the ZzFX sound designer, maybe using the Powerup preset.
385
388
 
386
389
  ```javascript
387
- const sound_start = new Sound([,0,500,,.04,.3,1,2,,,570,.02,.02,,,,.04]);
390
+ const sound_start = new LJS.Sound([,0,500,,.04,.3,1,2,,,570,.02,.02,,,,.04]);
388
391
  ```
389
392
 
390
393
  We can modify the gameUpdate to wait for player input from the mouse and play the sound when the ball is created.
@@ -396,9 +399,9 @@ if (ball && ball.pos.y < -1) // if ball is below level
396
399
  ball.destroy();
397
400
  ball = 0;
398
401
  }
399
- if (!ball && mouseWasPressed(0)) // if there is no ball and left mouse is pressed
402
+ if (!ball && LJS.mouseWasPressed(0)) // if there is no ball and left mouse is pressed
400
403
  {
401
- ball = new Ball(cameraPos); // create the ball
404
+ ball = new Ball(LJS.cameraPos); // create the ball
402
405
  sound_start.play(); // play start sound
403
406
  }
404
407
  ```
@@ -413,7 +416,7 @@ Make sure you replace the first parameter, vec2(), with this.pos so the effect a
413
416
 
414
417
  ```javascript
415
418
  // create explosion effect
416
- new ParticleEmitter(this.pos, 0, 0, 0.1, 100, 3.14, 0, new Color(1, 1, 1, 1), new Color(1, 1, 1, 1), new Color(1, 1, 1, 0), new Color(1, 1, 1, 0), 0.5, 0.1, 1, 0.1, 0.05, 1, 1, 0, 3.14, 0.1, 0.2, 0, 0, 1);
419
+ new LJS.ParticleEmitter(this.pos, 0, 0, 0.1, 100, 3.14, 0, rgb(1, 1, 1, 1), rgb(1, 1, 1, 1), rgb(1, 1, 1, 0), rgb(1, 1, 1, 0), 0.5, 0.1, 1, 0.1, 0.05, 1, 1, 0, 3.14, 0.1, 0.2, 0, 0, 1);
417
420
  ```
418
421
 
419
422
  Now you should see this simple particle effect play wherever a brick breaks. You can continue tweaking the parameters to make your own effect or use the one I made which also uses this.color to change the particle’s color so it matches the brick.
@@ -421,15 +424,15 @@ Now you should see this simple particle effect play wherever a brick breaks. You
421
424
  ```javascript
422
425
  // create explosion effect
423
426
  const color = this.color;
424
- new ParticleEmitter(
425
- this.pos, 0, // pos, angle
426
- this.size, .1, 200, PI, // emitSize, emitTime, emitRate, emiteCone
427
- undefined, // tileInfo
428
- color, color, // colorStartA, colorStartB
427
+ new LJS.ParticleEmitter(
428
+ this.pos, 0, // pos, angle
429
+ this.size, .1, 200, 3.14,// emitSize, emitTime, emitRate, emitCone
430
+ undefined, // tileInfo
431
+ color, color, // colorStartA, colorStartB
429
432
  color.scale(1,0), color.scale(1,0), // colorEndA, colorEndB
430
433
  .2, .5, 1, .1, .1, // time, sizeStart, sizeEnd, speed, angleSpeed
431
- .99, .95, .4, PI, // damping, angleDamping, gravityScale, cone
432
- .1, .5, false, true // fadeRate, randomness, collide, additive
434
+ .99, .95, .4, 3.14, // damp, angleDamp, gravity, cone
435
+ .1, .5, false, true // fade, randomness, collide, additive
433
436
  );
434
437
  ```
435
438
 
@@ -459,7 +462,7 @@ collideWithObject(o)
459
462
  this.velocity = this.velocity.rotate(.3 * deltaX);
460
463
 
461
464
  // make sure ball is moving upwards with a minimum speed
462
- this.velocity.y = max(-this.velocity.y, .2);
465
+ this.velocity.y = LJS.max(-this.velocity.y, .2);
463
466
 
464
467
  // prevent default collision code
465
468
  return false;
@@ -138,8 +138,8 @@ function gameInit()
138
138
  LJS.setCanvasFixedSize(vec2(1280, 720)); // use a 720p fixed size canvas
139
139
 
140
140
  // create bricks
141
- for(let x=2; x<=levelSize.x-2; x+=2)
142
- for(let y=12; y<=levelSize.y-2; y+=1)
141
+ for (let x=2; x<=levelSize.x-2; x+=2)
142
+ for (let y=12; y<=levelSize.y-2; y+=1)
143
143
  new Brick(vec2(x,y), vec2(2,1)); // create a brick
144
144
 
145
145
  // create player paddle
@@ -0,0 +1,7 @@
1
+ rem LittleJS Build Script
2
+ call node build.js
3
+ if %errorlevel% neq 0 (
4
+ echo Build failed with error level %errorlevel%
5
+ pause
6
+ exit /b %errorlevel%
7
+ )
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * LittleJS Build System
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const PROGRAM_TITLE = 'Little JS Electron Project';
10
+ const PROGRAM_NAME = 'game';
11
+ const BUILD_FOLDER = 'build';
12
+ const USE_ROADROLLER = false; // enable for extra compression
13
+ const sourceFiles =
14
+ [
15
+ '../../dist/littlejs.release.js',
16
+ 'game.js',
17
+ // add your game's files here
18
+ ];
19
+ const dataFiles =
20
+ [
21
+ 'tiles.png',
22
+ // add your game's data files here
23
+ ];
24
+
25
+ console.log(`Building ${PROGRAM_NAME}...`);
26
+ const startTime = Date.now();
27
+ const fs = require('node:fs');
28
+ const child_process = require('node:child_process');
29
+
30
+ // rebuild engine
31
+ //child_process.execSync(`npm run build`, { stdio: 'inherit' });
32
+
33
+ // remove old files and setup build folder
34
+ fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
35
+ fs.rmSync(`${PROGRAM_NAME}.zip`, { force: true });
36
+ fs.mkdirSync(BUILD_FOLDER);
37
+
38
+ // copy data files
39
+ for (const file of dataFiles)
40
+ fs.copyFileSync(file, `${BUILD_FOLDER}/${file}`);
41
+
42
+ Build
43
+ (
44
+ `${BUILD_FOLDER}/index.js`,
45
+ sourceFiles,
46
+ USE_ROADROLLER ?
47
+ [closureCompilerStep, uglifyBuildStep, roadrollerBuildStep, htmlBuildStep, electronBuildStep] :
48
+ [closureCompilerStep, uglifyBuildStep, htmlBuildStep, electronBuildStep]
49
+ );
50
+
51
+ console.log('');
52
+ console.log(`Build Completed in ${((Date.now() - startTime)/1e3).toFixed(2)} seconds!`);
53
+
54
+ ///////////////////////////////////////////////////////////////////////////////
55
+
56
+ // A single build with its own source files, build steps, and output file
57
+ // - each build step is a callback that accepts a single filename
58
+ function Build(outputFile, files=[], buildSteps=[])
59
+ {
60
+ // copy files into a buffer
61
+ let buffer = '';
62
+ for (const file of files)
63
+ buffer += fs.readFileSync(file) + '\n';
64
+
65
+ // output file
66
+ fs.writeFileSync(outputFile, buffer, {flag: 'w+'});
67
+
68
+ // execute build steps in order
69
+ for (const buildStep of buildSteps)
70
+ buildStep(outputFile);
71
+ }
72
+
73
+ function closureCompilerStep(filename)
74
+ {
75
+ console.log('Running closure compiler...');
76
+
77
+ // use closer compiler to minify the code
78
+ const filenameTemp = filename + '.tmp';
79
+ fs.copyFileSync(filename, filenameTemp);
80
+ 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'});
81
+ fs.rmSync(filenameTemp);
82
+ };
83
+
84
+ function uglifyBuildStep(filename)
85
+ {
86
+ console.log('Running uglify...');
87
+ child_process.execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
88
+ };
89
+
90
+ function roadrollerBuildStep(filename)
91
+ {
92
+ console.log('Running roadroller...');
93
+ child_process.execSync(`npx roadroller ${filename} -o ${filename}`, {stdio: 'inherit'});
94
+ };
95
+
96
+ function htmlBuildStep(filename)
97
+ {
98
+ console.log('Building html...');
99
+
100
+ // create html file
101
+ let buffer = '';
102
+ buffer += '<!DOCTYPE html>';
103
+ buffer += '<head>';
104
+ buffer += `<title>${PROGRAM_TITLE}</title>`;
105
+ buffer += '<meta charset=utf-8>';
106
+ buffer += '</head>';
107
+ buffer += '<body>';
108
+ buffer += '<script src="index.js"></script>';
109
+
110
+ // output html file
111
+ fs.writeFileSync(`${BUILD_FOLDER}/index.html`, buffer, {flag: 'w+'});
112
+ };
113
+
114
+ function electronBuildStep(filename)
115
+ {
116
+ console.log('Building executable with electron...');
117
+
118
+ // copy elecron files to build folder
119
+ fs.copyFileSync('electron.js', `${BUILD_FOLDER}/electron.js`);
120
+ fs.copyFileSync('package.json', `${BUILD_FOLDER}/package.json`);
121
+
122
+ // run electron packager
123
+ child_process.execSync(`npx electron-packager ./${BUILD_FOLDER} --overwrite`, {stdio: 'inherit'});
124
+ };
@@ -0,0 +1,35 @@
1
+ const { app, BrowserWindow } = require('electron');
2
+
3
+ function createWindow()
4
+ {
5
+ // create the browser window
6
+ const mainWindow = new BrowserWindow({width: 800, height: 600});
7
+
8
+ // hide the toolbar menu
9
+ mainWindow.setMenu(null);
10
+
11
+ // load the index.html of the app
12
+ mainWindow.loadFile('index.html');
13
+
14
+ // go fullscreen
15
+ //mainWindow.setFullScreen(true);
16
+
17
+ // open the dev tools debugging
18
+ //mainWindow.webContents.openDevTools()
19
+ }
20
+
21
+ // wait until the app is ready and create the window
22
+ app.whenReady().then(createWindow);
23
+
24
+ // quit when all windows are closed (except macOS convention)
25
+ app.on('window-all-closed', ()=>
26
+ {
27
+ if (process.platform != 'darwin')
28
+ app.quit();
29
+ });
30
+
31
+ app.on('activate', ()=>
32
+ {
33
+ if (BrowserWindow.getAllWindows().length == 0)
34
+ createWindow();
35
+ });
@@ -0,0 +1,140 @@
1
+ /*
2
+ Little JS Starter Project
3
+ - A simple starter project for LittleJS
4
+ - Demos all the main engine features
5
+ - Builds to a zip file
6
+ */
7
+
8
+ 'use strict';
9
+
10
+ // show the LittleJS splash screen
11
+ setShowSplashScreen(true);
12
+
13
+ // fix texture bleeding by shrinking tile slightly
14
+ setTileFixBleedScale(.5);
15
+
16
+ // sound effects
17
+ const sound_click = new Sound([1,.5]);
18
+
19
+ // medals
20
+ const medal_example = new Medal(0, 'Example Medal', 'Welcome to LittleJS!');
21
+ medalsInit('Hello World');
22
+
23
+ // game variables
24
+ let particleEmitter;
25
+
26
+ ///////////////////////////////////////////////////////////////////////////////
27
+ function gameInit()
28
+ {
29
+ // create tile collision and visible tile layer
30
+ const pos = vec2();
31
+ const tileLayer = new TileCollisionLayer(pos, vec2(32,16));
32
+
33
+ // get level data from the tiles image
34
+ const tileImage = textureInfos[0].image;
35
+ mainContext.drawImage(tileImage,0,0);
36
+ const imageData = mainContext.getImageData(0,0,tileImage.width,tileImage.height).data;
37
+ for (pos.x = tileLayer.size.x; pos.x--;)
38
+ for (pos.y = tileLayer.size.y; pos.y--;)
39
+ {
40
+ // check if this pixel is set
41
+ const i = pos.x + tileImage.width*(15 + tileLayer.size.y - pos.y);
42
+ if (!imageData[4*i])
43
+ continue;
44
+
45
+ // set tile data
46
+ const tileIndex = 1;
47
+ const direction = randInt(4)
48
+ const mirror = randBool();
49
+ const color = randColor();
50
+ const data = new TileLayerData(tileIndex, direction, mirror, color);
51
+ tileLayer.setData(pos, data);
52
+ tileLayer.setCollisionData(pos);
53
+ }
54
+
55
+ // draw tile layer with new data
56
+ tileLayer.redraw();
57
+
58
+ // setup camera
59
+ setCameraPos(vec2(16,8));
60
+ setCameraScale(32);
61
+
62
+ // enable gravity
63
+ setGravity(vec2(0,-.01));
64
+
65
+ // create particle emitter
66
+ particleEmitter = new ParticleEmitter(
67
+ vec2(16,9), 0, // emitPos, emitAngle
68
+ 0, 0, 500, PI, // emitSize, emitTime, emitRate, emitCone
69
+ tile(0, 16), // tileIndex, tileSize
70
+ hsl(1,1,1), hsl(0,0,0), // colorStartA, colorStartB
71
+ hsl(0,0,0,0), hsl(0,0,0,0), // colorEndA, colorEndB
72
+ 2, .2, .2, .1, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
73
+ .99, 1, 1, PI, // damping, angleDamping, gravityScale, cone
74
+ .05, .5, true, true // fadeRate, randomness, collide, additive
75
+ );
76
+ particleEmitter.restitution = .3; // bounce when it collides
77
+ particleEmitter.trailScale = 2; // stretch in direction of motion
78
+ }
79
+
80
+ ///////////////////////////////////////////////////////////////////////////////
81
+ function gameUpdate()
82
+ {
83
+ if (mouseWasPressed(0))
84
+ {
85
+ // play sound when mouse is pressed
86
+ sound_click.play(mousePos);
87
+
88
+ // change particle color and set to fade out
89
+ particleEmitter.colorStartA = hsl();
90
+ particleEmitter.colorStartB = randColor();
91
+ particleEmitter.colorEndA = particleEmitter.colorStartA.scale(1,0);
92
+ particleEmitter.colorEndB = particleEmitter.colorStartB.scale(1,0);
93
+
94
+ // unlock medals
95
+ medal_example.unlock();
96
+ }
97
+
98
+ if (mouseWheel)
99
+ {
100
+ // zoom in and out with mouse wheel
101
+ cameraScale -= sign(mouseWheel)*cameraScale/5;
102
+ cameraScale = clamp(cameraScale, 10, 300);
103
+ }
104
+
105
+ // move particles to mouse location if on screen
106
+ if (mousePosScreen.x)
107
+ {
108
+ particleEmitter.pos = mousePos;
109
+ particleEmitter.velocity = mouseDelta.scale(.3*timeDelta);
110
+ }
111
+ }
112
+
113
+ ///////////////////////////////////////////////////////////////////////////////
114
+ function gameUpdatePost()
115
+ {
116
+
117
+ }
118
+
119
+ ///////////////////////////////////////////////////////////////////////////////
120
+ function gameRender()
121
+ {
122
+ // draw a grey square in the background
123
+ drawRect(vec2(16,8), vec2(20,14), hsl(0,0,.6));
124
+
125
+ // draw the logo as a tile
126
+ drawTile(vec2(21,5), vec2(4.5), tile(3,128));
127
+ }
128
+
129
+ ///////////////////////////////////////////////////////////////////////////////
130
+ function gameRenderPost()
131
+ {
132
+ // draw to overlay canvas for hud rendering
133
+ drawTextScreen('LittleJS Demo',
134
+ vec2(mainCanvasSize.x/2, 70), 80, // position, size
135
+ hsl(0,0,1), 6, hsl(0,0,0)); // color, outline size and color
136
+ }
137
+
138
+ ///////////////////////////////////////////////////////////////////////////////
139
+ // Startup LittleJS Engine
140
+ engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html><head>
2
+ <title>LittleJS Starter Project</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
+
9
+ <!-- LittleJS Engine -->
10
+ <script src=../../dist/littlejs.js?1133></script>
11
+
12
+ <!-- Add your game scripts here -->
13
+ <script src=game.js?1133></script>
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "littlejsgame",
3
+ "version": "1.0.0",
4
+ "main": "electron.js",
5
+ "scripts": {
6
+ "build": "node build.js"
7
+ },
8
+ "devDependencies": {
9
+ "electron": "^38.2.0",
10
+ "electron-packager": "^17.1.2"
11
+ }
12
+ }
Binary file
@@ -8,6 +8,7 @@
8
8
 
9
9
  // import LittleJS module
10
10
  import * as LJS from '../../dist/littlejs.esm.js';
11
+ const {vec2, rgb} = LJS;
11
12
 
12
13
  ///////////////////////////////////////////////////////////////////////////////
13
14
  function gameInit()
@@ -61,7 +61,7 @@ function gameRender()
61
61
  {
62
62
  // test game rendering
63
63
  LJS.drawRect(vec2(), vec2(1e3), hsl(0,0,.2));
64
- for(let i=0; i<1e3; ++i)
64
+ for (let i=0; i<1e3; ++i)
65
65
  {
66
66
  const time = LJS.time;
67
67
  const pos = vec2(30*Math.sin(i+time/9),20*Math.sin(i*i+time/9));