littlejsengine 1.13.1 → 1.14.2
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 +15 -11
- package/copyToGithub.bat +28 -0
- package/dist/littlejs.d.ts +430 -304
- package/dist/littlejs.esm.js +1745 -982
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +1716 -965
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +1673 -922
- package/examples/box2d/game.js +2 -2
- package/examples/box2d/gameObjects.js +2 -2
- package/examples/box2d/scenes.js +1 -1
- package/examples/breakout/game.js +30 -25
- package/examples/breakoutTutorial/README.md +44 -41
- package/examples/breakoutTutorial/game.js +2 -2
- package/examples/electron/build.bat +7 -0
- package/examples/electron/build.js +124 -0
- package/examples/electron/electron.js +35 -0
- package/examples/electron/game.js +140 -0
- package/examples/electron/index.html +13 -0
- package/examples/electron/package.json +12 -0
- package/examples/electron/tiles.png +0 -0
- package/examples/empty/game.js +1 -0
- package/examples/htmlMenu/game.js +1 -1
- package/examples/index.html +332 -160
- package/examples/module/game.js +5 -2
- package/examples/particles/index.html +12 -3
- package/examples/platformer/gameEffects.js +20 -19
- package/examples/platformer/gameLevel.js +6 -1
- package/examples/shorts/base.html +1 -1
- package/examples/shorts/blending.js +9 -5
- package/examples/shorts/box2d.js +1 -1
- package/examples/shorts/box2dCar.js +1 -1
- package/examples/shorts/clock.js +1 -1
- package/examples/shorts/colors.js +2 -2
- package/examples/shorts/flappyGame.js +2 -1
- package/examples/shorts/helloWorld.js +1 -1
- package/examples/shorts/maze.js +1 -1
- package/examples/shorts/music.js +106 -0
- package/examples/shorts/nineSlice.js +9 -9
- package/examples/shorts/parallax.js +71 -0
- package/examples/shorts/piano.js +9 -10
- package/examples/shorts/postProcess.js +25 -8
- package/examples/shorts/raycasting.js +2 -2
- package/examples/shorts/shapes.js +7 -15
- package/examples/shorts/slidingPuzzle.js +2 -2
- package/examples/shorts/song.mp3 +0 -0
- package/examples/shorts/starfield.js +5 -7
- package/examples/shorts/systemFont.js +1 -1
- package/examples/shorts/uiSystem.js +16 -8
- package/examples/starter/build.js +9 -8
- package/examples/starter/game.js +5 -2
- package/examples/starter/index.html +2 -2
- package/examples/stress/index.html +13 -8
- package/examples/style.css +19 -6
- package/examples/typescript/build.js +1 -1
- package/examples/typescript/game.js +2 -2
- package/examples/typescript/game.ts +5 -2
- package/examples/uiSystem/game.js +13 -12
- package/package.json +2 -2
- package/plugins/box2d.js +24 -97
- package/plugins/drawUtilities.js +29 -23
- package/plugins/newgrounds.js +6 -6
- package/plugins/pluginExport.js +1 -1
- package/plugins/postProcess.js +7 -0
- package/plugins/uiSystem.js +106 -82
- package/plugins/zzfxm.js +10 -10
- package/reference.md +90 -54
- package/src/engine.js +28 -23
- package/src/engineAudio.js +285 -110
- package/src/engineBuild.js +9 -9
- package/src/engineDebug.js +28 -28
- package/src/engineDraw.js +346 -202
- package/src/engineExport.js +28 -16
- package/src/engineInput.js +58 -68
- package/src/engineMedals.js +29 -29
- package/src/engineObject.js +28 -25
- package/src/engineParticles.js +67 -60
- package/src/engineRelease.js +1 -1
- package/src/engineSettings.js +70 -16
- package/src/engineTileLayer.js +34 -34
- package/src/engineUtilities.js +69 -62
- package/src/engineWebGL.js +467 -65
- /package/examples/shorts/{playSound.js → sound.js} +0 -0
package/examples/box2d/game.js
CHANGED
|
@@ -136,8 +136,8 @@ function gameUpdatePost()
|
|
|
136
136
|
///////////////////////////////////////////////////////////////////////////////
|
|
137
137
|
function gameRender()
|
|
138
138
|
{
|
|
139
|
-
// draw a grey square in the background without using
|
|
140
|
-
LJS.drawRect(vec2(20,8), vec2(100), hsl(0,0,.8), 0,
|
|
139
|
+
// draw a grey square in the background without using WebGL
|
|
140
|
+
LJS.drawRect(vec2(20,8), vec2(100), hsl(0,0,.8), 0, false);
|
|
141
141
|
|
|
142
142
|
if (Scenes.scene == 5)
|
|
143
143
|
{
|
|
@@ -20,7 +20,7 @@ const restitution = .2;
|
|
|
20
20
|
|
|
21
21
|
export function spawnBox(pos, size=1, color=LJS.WHITE, type=LJS.box2d.bodyTypeDynamic, applyTexture=true, angle=0)
|
|
22
22
|
{
|
|
23
|
-
size = typeof size
|
|
23
|
+
size = typeof size === 'number' ? vec2(size) : size; // square
|
|
24
24
|
const o = new LJS.Box2dObject(pos, size, applyTexture && Game.spriteAtlas.squareOutline, angle, color, type);
|
|
25
25
|
o.drawSize = size.scale(1.02); // slightly enlarge to cover gaps
|
|
26
26
|
o.addBox(size, vec2(), 0, density, friction, restitution);
|
|
@@ -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.
|
|
311
|
+
LJS.drawPoly(poly, LJS.BLACK)
|
|
312
312
|
}
|
|
313
313
|
getNode(x, y)
|
|
314
314
|
{
|
package/examples/box2d/scenes.js
CHANGED
|
@@ -122,38 +122,43 @@ function setupPostProcess()
|
|
|
122
122
|
p=fract(p*.3197);
|
|
123
123
|
return fract(1.+sin(51.*p.x+73.*p.y)*13753.3);
|
|
124
124
|
}
|
|
125
|
-
|
|
126
|
-
{
|
|
127
|
-
vec2 i=floor(p),f=fract(p),u=f*f*(3.-2.*f);
|
|
128
|
-
return mix(mix(hash(i),hash(i+vec2(1,0)),u.x),mix(hash(i+vec2(0,1)),hash(i+1.),u.x),u.y);
|
|
129
|
-
}
|
|
125
|
+
|
|
130
126
|
void mainImage(out vec4 c, vec2 p)
|
|
131
127
|
{
|
|
132
|
-
//
|
|
128
|
+
// setup the shader
|
|
129
|
+
vec2 uv = p;
|
|
133
130
|
p /= iResolution.xy;
|
|
134
|
-
|
|
135
|
-
// apply fuzz as horizontal offset
|
|
136
|
-
const float fuzz = .0005;
|
|
137
|
-
const float fuzzScale = 800.;
|
|
138
|
-
const float fuzzSpeed = 9.;
|
|
139
|
-
p.x += fuzz*(noise(vec2(p.y*fuzzScale, iTime*fuzzSpeed))*2.-1.);
|
|
140
|
-
|
|
141
|
-
// init output color
|
|
142
131
|
c = texture(iChannel0, p);
|
|
143
132
|
|
|
144
|
-
//
|
|
145
|
-
const float
|
|
146
|
-
|
|
147
|
-
c
|
|
148
|
-
|
|
149
|
-
// tv static noise
|
|
150
|
-
const float staticNoise = .1;
|
|
151
|
-
c += staticNoise * hash(p + mod(iTime, 1e3));
|
|
133
|
+
// static noise
|
|
134
|
+
const float staticAlpha = .1;
|
|
135
|
+
const float staticScale = .002;
|
|
136
|
+
c += staticAlpha * hash(floor(p/staticScale) + mod(iTime*500., 1e3));
|
|
152
137
|
|
|
153
138
|
// scan lines
|
|
154
|
-
const float scanlineScale =
|
|
155
|
-
const float scanlineAlpha = .
|
|
156
|
-
c *= 1.
|
|
139
|
+
const float scanlineScale = 2.;
|
|
140
|
+
const float scanlineAlpha = .3;
|
|
141
|
+
c *= 1. - scanlineAlpha*cos(p.y*2.*iResolution.y/scanlineScale);
|
|
142
|
+
|
|
143
|
+
{
|
|
144
|
+
// bloom effect
|
|
145
|
+
const float blurSize = .002;
|
|
146
|
+
const float bloomIntensity = .2;
|
|
147
|
+
|
|
148
|
+
// 5-tap Gaussian blur
|
|
149
|
+
vec4 bloom = vec4(0);
|
|
150
|
+
bloom += texture(iChannel0, p + vec2(-2.*blurSize, 0)) * .12;
|
|
151
|
+
bloom += texture(iChannel0, p + vec2( -blurSize, 0)) * .24;
|
|
152
|
+
bloom += texture(iChannel0, p) * .28;
|
|
153
|
+
bloom += texture(iChannel0, p + vec2( blurSize, 0)) * .24;
|
|
154
|
+
bloom += texture(iChannel0, p + vec2( 2.*blurSize, 0)) * .12;
|
|
155
|
+
bloom += texture(iChannel0, p + vec2(0, -2.*blurSize)) * .12;
|
|
156
|
+
bloom += texture(iChannel0, p + vec2(0, -blurSize)) * .24;
|
|
157
|
+
bloom += texture(iChannel0, p) * .28;
|
|
158
|
+
bloom += texture(iChannel0, p + vec2(0, blurSize)) * .24;
|
|
159
|
+
bloom += texture(iChannel0, p + vec2(0, 2.*blurSize)) * .12;
|
|
160
|
+
c += bloom * bloomIntensity;
|
|
161
|
+
}
|
|
157
162
|
|
|
158
163
|
// black vignette around edges
|
|
159
164
|
const float vignette = 2.;
|
|
@@ -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
|

|
|
@@ -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),
|
|
87
|
-
drawRect(cameraPos, levelSize,
|
|
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
|
-
|
|
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 =
|
|
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
|

|
|
@@ -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,
|
|
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,
|
|
426
|
-
this.size, .1, 200,
|
|
427
|
-
undefined,
|
|
428
|
-
color, color,
|
|
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,
|
|
432
|
-
.1, .5, false, true //
|
|
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,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
|
+
});
|