littlejsengine 1.14.11 → 1.14.19
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/dist/littlejs.d.ts +303 -137
- package/dist/littlejs.esm.js +936 -463
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +934 -462
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +859 -417
- package/examples/box2d/game.js +3 -2
- package/examples/box2d/gameObjects.js +2 -2
- package/examples/box2d/tiles.png +0 -0
- package/examples/breakout/game.js +5 -5
- package/examples/breakout/gameObjects.js +2 -2
- package/examples/breakoutTutorial/README.md +32 -32
- package/examples/breakoutTutorial/game.js +1 -1
- package/examples/electron/game.js +4 -4
- package/examples/electron/index.html +2 -2
- package/examples/electron/package.json +1 -8
- package/examples/index.html +67 -56
- package/examples/module/game.js +4 -4
- package/examples/platformer/gameEffects.js +5 -5
- package/examples/platformer/gameLevel.js +1 -1
- package/examples/platformer/gameObjects.js +4 -4
- package/examples/puzzle/game.js +1 -1
- package/examples/shorts/animation.js +1 -1
- package/examples/shorts/base.html +1 -1
- package/examples/shorts/blending.js +8 -14
- package/examples/shorts/box2d.js +7 -3
- package/examples/shorts/box2dCar.js +2 -1
- package/examples/shorts/empty.js +30 -0
- package/examples/shorts/helloWorld.js +1 -1
- package/examples/shorts/hillGlideGame.js +10 -4
- package/examples/shorts/landerGame.js +11 -8
- package/examples/shorts/medals.js +4 -4
- package/examples/shorts/music.js +29 -56
- package/examples/shorts/musicPlayer.js +135 -0
- package/examples/shorts/nineSlice.js +34 -15
- package/examples/shorts/parallax.js +5 -4
- package/examples/shorts/particles.js +15 -15
- package/examples/shorts/piano.js +15 -21
- package/examples/shorts/pongGame.js +6 -4
- package/examples/shorts/raycasting.js +9 -4
- package/examples/shorts/sequencer.js +122 -0
- package/examples/shorts/shader.js +29 -0
- package/examples/shorts/shapes.js +7 -4
- package/examples/shorts/slidingPuzzle.js +4 -2
- package/examples/shorts/sound.js +18 -9
- package/examples/shorts/spaceGame.js +12 -8
- package/examples/shorts/spriteAtlas.js +7 -7
- package/examples/shorts/starfield.js +1 -1
- package/examples/shorts/systemFont.js +2 -2
- package/examples/shorts/texture.js +2 -2
- package/examples/shorts/tileLayer.js +10 -10
- package/examples/shorts/tiltedView.js +24 -5
- package/examples/shorts/timers.js +10 -0
- package/examples/shorts/topDown.js +4 -1
- package/examples/shorts/uiSystem.js +8 -5
- package/examples/starter/game.js +4 -4
- package/examples/starter/index.html +2 -2
- package/examples/style.css +1 -0
- package/examples/typescript/game.js +4 -4
- package/examples/typescript/game.ts +4 -4
- package/examples/uiSystem/game.js +4 -3
- package/package.json +4 -2
- package/plugins/box2d.js +17 -2
- package/plugins/newgrounds.js +7 -5
- package/plugins/postProcess.js +76 -53
- package/plugins/uiSystem.js +192 -53
- package/plugins/zzfxm.js +5 -1
- package/reference.md +1 -1
- package/src/engine.js +60 -23
- package/src/engineAudio.js +44 -17
- package/src/engineDebug.js +75 -45
- package/src/engineDraw.js +94 -59
- package/src/engineExport.js +2 -1
- package/src/engineMedals.js +10 -2
- package/src/engineObject.js +14 -10
- package/src/engineParticles.js +60 -47
- package/src/engineSettings.js +7 -7
- package/src/engineTileLayer.js +73 -56
- package/src/engineUtilities.js +67 -20
- package/src/engineWebGL.js +134 -63
package/examples/module/game.js
CHANGED
|
@@ -69,16 +69,16 @@ function gameInit()
|
|
|
69
69
|
// create particle emitter
|
|
70
70
|
particleEmitter = new LJS.ParticleEmitter(
|
|
71
71
|
vec2(16,9), 0, // emitPos, emitAngle
|
|
72
|
-
1, 0, 500, Math.PI, // emitSize, emitTime,
|
|
72
|
+
1, 0, 500, Math.PI, // emitSize, emitTime, rate, cone
|
|
73
73
|
tile(0, 16), // tileIndex, tileSize
|
|
74
74
|
hsl(1,1,1), hsl(0,0,0), // colorStartA, colorStartB
|
|
75
75
|
hsl(0,0,0,0), hsl(0,0,0,0), // colorEndA, colorEndB
|
|
76
|
-
|
|
76
|
+
1, .2, .2, .1, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
77
77
|
.99, 1, 1, Math.PI, // damping, angleDamping, gravityScale, cone
|
|
78
78
|
.05, .5, true, true // fadeRate, randomness, collide, additive
|
|
79
79
|
);
|
|
80
80
|
particleEmitter.restitution = .3; // bounce when it collides
|
|
81
|
-
particleEmitter.trailScale = 2;
|
|
81
|
+
particleEmitter.trailScale = 2; // stretch as it moves
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -90,7 +90,7 @@ function gameUpdate()
|
|
|
90
90
|
sound_click.play(LJS.mousePos);
|
|
91
91
|
|
|
92
92
|
// change particle color and set to fade out
|
|
93
|
-
particleEmitter.colorStartA =
|
|
93
|
+
particleEmitter.colorStartA = LJS.randColor();
|
|
94
94
|
particleEmitter.colorStartB = LJS.randColor();
|
|
95
95
|
particleEmitter.colorEndA = particleEmitter.colorStartA.scale(1,0);
|
|
96
96
|
particleEmitter.colorEndB = particleEmitter.colorStartB.scale(1,0);
|
|
@@ -48,13 +48,13 @@ export function makeDebris(pos, color = hsl(), amount = 50, size=.2, restitution
|
|
|
48
48
|
{
|
|
49
49
|
const color2 = color.lerp(hsl(), .5);
|
|
50
50
|
const emitter = new LJS.ParticleEmitter(
|
|
51
|
-
pos, 0, 1, .1, amount/.1, 3.14, // pos, angle,
|
|
51
|
+
pos, 0, 1, .1, amount/.1, 3.14, // pos, angle, size, time, rate, cone
|
|
52
52
|
0, // tileInfo
|
|
53
53
|
color, color2, // colorStartA, colorStartB
|
|
54
54
|
color, color2, // colorEndA, colorEndB
|
|
55
55
|
3, size,size, .1, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
56
56
|
1, .95, .4, 3.14, 0, // damp, angleDamp, gravity, particleCone, fade
|
|
57
|
-
.5, 1 // randomness, collide
|
|
57
|
+
.5, 1 // randomness, collide
|
|
58
58
|
);
|
|
59
59
|
emitter.restitution = restitution;
|
|
60
60
|
emitter.particleDestroyCallback = persistentParticleDestroyCallback;
|
|
@@ -109,7 +109,7 @@ export function explosion(pos, radius=3)
|
|
|
109
109
|
// smoke
|
|
110
110
|
new LJS.ParticleEmitter(
|
|
111
111
|
pos, 0, // pos, angle
|
|
112
|
-
radius/2, .2, 50*radius, 3.14,// emitSize, emitTime,
|
|
112
|
+
radius/2, .2, 50*radius, 3.14,// emitSize, emitTime, rate, cone
|
|
113
113
|
0, // tileInfo
|
|
114
114
|
hsl(0,0,0), hsl(0,0,0), // colorStartA, colorStartB
|
|
115
115
|
hsl(0,0,0,0), hsl(0,0,0,0), // colorEndA, colorEndB
|
|
@@ -121,7 +121,7 @@ export function explosion(pos, radius=3)
|
|
|
121
121
|
// fire
|
|
122
122
|
new LJS.ParticleEmitter(
|
|
123
123
|
pos, 0, // pos, angle
|
|
124
|
-
radius/2, .1, 100*radius, 3.14, // emitSize, emitTime,
|
|
124
|
+
radius/2, .1, 100*radius, 3.14, // emitSize, emitTime, rate, cone
|
|
125
125
|
0, // tileInfo
|
|
126
126
|
rgb(1,.5,.1), rgb(1,.1,.1), // colorStartA, colorStartB
|
|
127
127
|
rgb(1,.5,.1,0), rgb(1,.1,.1,0), // colorEndA, colorEndB
|
|
@@ -255,7 +255,7 @@ export class ParallaxLayer extends LJS.CanvasLayer
|
|
|
255
255
|
this.context.clearRect(0,0,1,h);
|
|
256
256
|
|
|
257
257
|
// make WebGL texture
|
|
258
|
-
this.useWebGL(
|
|
258
|
+
this.useWebGL();
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
render()
|
|
@@ -50,7 +50,7 @@ function loadLevelData()
|
|
|
50
50
|
{
|
|
51
51
|
// load the level data
|
|
52
52
|
const tileMapData = Game.gameLevelData;
|
|
53
|
-
tileLayers = LJS.
|
|
53
|
+
tileLayers = LJS.tileLayersLoad(tileMapData, tile(0,16,1), 0, 1);
|
|
54
54
|
levelSize = tileLayers[0].size;
|
|
55
55
|
playerStartPos = vec2(0, levelSize.y); // default player start
|
|
56
56
|
foregroundTileLayer = tileLayers[0];
|
|
@@ -247,13 +247,13 @@ export class Weapon extends LJS.EngineObject
|
|
|
247
247
|
|
|
248
248
|
// shell effect
|
|
249
249
|
this.addChild(this.shellEmitter = new LJS.ParticleEmitter(
|
|
250
|
-
vec2(), 0, 0, 0, 0, .1, // pos, angle,
|
|
250
|
+
vec2(), 0, 0, 0, 0, .1, // pos, angle, size, time, rate, cone
|
|
251
251
|
0, // tileInfo
|
|
252
252
|
rgb(1,.8,.5), rgb(.9,.7,.5), // colorStartA, colorStartB
|
|
253
253
|
rgb(1,.8,.5), rgb(.9,.7,.5), // colorEndA, colorEndB
|
|
254
254
|
3, .1, .1, .15, .1, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
255
255
|
1, .95, 1, 0, 0, // damp, angleDamp, gravity, particleCone, fade
|
|
256
|
-
.1, 1 // randomness, collide
|
|
256
|
+
.1, 1 // randomness, collide
|
|
257
257
|
), vec2(.1,0), -.8);
|
|
258
258
|
this.shellEmitter.restitution = .5;
|
|
259
259
|
this.shellEmitter.particleDestroyCallback = GameEffects.persistentParticleDestroyCallback;
|
|
@@ -368,13 +368,13 @@ export class Bullet extends LJS.EngineObject
|
|
|
368
368
|
|
|
369
369
|
// spark effects
|
|
370
370
|
const emitter = new LJS.ParticleEmitter(
|
|
371
|
-
this.pos, 0, 0, .1, 100, .5, // pos, angle,
|
|
371
|
+
this.pos, 0, 0, .1, 100, .5, // pos, angle, size, time, rate, cone
|
|
372
372
|
0, // tileInfo
|
|
373
373
|
rgb(1,1,0), rgb(1,0,0), // colorStartA, colorStartB
|
|
374
374
|
rgb(1,1,0), rgb(1,0,0), // colorEndA, colorEndB
|
|
375
375
|
.2, .2, 0, .1, .1, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
376
376
|
1, 1, .5, 3.14, .1, // damp, angleDamp, gravityScale, particleCone, fade,
|
|
377
|
-
.5, 1, 1 // randomness, collide, additive
|
|
377
|
+
.5, 1, 1 // randomness, collide, additive
|
|
378
378
|
);
|
|
379
379
|
emitter.trailScale = 1;
|
|
380
380
|
emitter.restitution = .3;
|
package/examples/puzzle/game.js
CHANGED
|
@@ -309,7 +309,7 @@ function clearMatches()
|
|
|
309
309
|
const color2 = color1.lerp(hsl(), .5);
|
|
310
310
|
new LJS.ParticleEmitter(
|
|
311
311
|
pos.add(vec2(.5)), 0, // pos, angle
|
|
312
|
-
.5, .1, 200, 3.14, // emitSize, emitTime,
|
|
312
|
+
.5, .1, 200, 3.14, // emitSize, emitTime, rate, cone
|
|
313
313
|
0, // tileInfo
|
|
314
314
|
color1, color2, // colorStartA, colorStartB
|
|
315
315
|
color1.scale(1,0), color2.scale(1,0),// colorEndA, colorEndB
|
|
@@ -1,20 +1,14 @@
|
|
|
1
|
-
// use smooth blending
|
|
2
|
-
setCanvasPixelated(false);
|
|
3
|
-
setTilesPixelated(false);
|
|
4
|
-
|
|
5
1
|
function gameRender()
|
|
6
2
|
{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// additive blend
|
|
3
|
+
// additive blending
|
|
10
4
|
setBlendMode(1);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
drawCircle(vec2(-8,-2), 7, rgb(0,0,.5));
|
|
6
|
+
drawCircle(vec2(-6, 2), 7, rgb(0,1,0));
|
|
7
|
+
drawCircle(vec2(-4,-2), 7, rgb(1,0,0));
|
|
14
8
|
|
|
15
|
-
// alpha
|
|
9
|
+
// alpha blending
|
|
16
10
|
setBlendMode(0);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
drawCircle(vec2(4,-2), 7, hsl(time/9 ,1,.5));
|
|
12
|
+
drawCircle(vec2(8,-2), 7, hsl(time/9+1/3,1,.5,.5));
|
|
13
|
+
drawCircle(vec2(6, 2), 7, hsl(time/9+2/3,1,.5,.5));
|
|
20
14
|
}
|
package/examples/shorts/box2d.js
CHANGED
|
@@ -7,13 +7,16 @@ async function gameInit()
|
|
|
7
7
|
canvasClearColor = hsl(0,0,.9);
|
|
8
8
|
|
|
9
9
|
// create ground object
|
|
10
|
-
groundObject = new Box2dObject(vec2(-8), vec2(), 0, 0,
|
|
10
|
+
groundObject = new Box2dObject(vec2(-8), vec2(), 0, 0,
|
|
11
|
+
GRAY, box2d.bodyTypeStatic);
|
|
11
12
|
groundObject.addBox(vec2(100,2));
|
|
12
13
|
|
|
13
14
|
// add some random objects
|
|
14
15
|
for (let i=50; i--;)
|
|
15
16
|
{
|
|
16
|
-
const
|
|
17
|
+
const pos = randInCircle(5);
|
|
18
|
+
const color = randColor();
|
|
19
|
+
const o = new Box2dObject(pos, vec2(), 0, 0, color);
|
|
17
20
|
randInt(2) ? o.addCircle(rand(1,2)) : o.addRandomPoly(rand(1,2));
|
|
18
21
|
}
|
|
19
22
|
}
|
|
@@ -36,7 +39,8 @@ function gameUpdate()
|
|
|
36
39
|
// grab object
|
|
37
40
|
const object = box2d.pointCast(mousePos);
|
|
38
41
|
if (object)
|
|
39
|
-
mouseJoint = new Box2dTargetJoint(object,
|
|
42
|
+
mouseJoint = new Box2dTargetJoint(object,
|
|
43
|
+
groundObject, mousePos);
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
46
|
|
|
@@ -3,7 +3,8 @@ async function gameInit()
|
|
|
3
3
|
// setup box2d and create the objects
|
|
4
4
|
await box2dInit();
|
|
5
5
|
gravity.y = -20;
|
|
6
|
-
groundObject = new Box2dObject(vec2(-8), vec2(), 0, 0,
|
|
6
|
+
groundObject = new Box2dObject(vec2(-8), vec2(), 0, 0,
|
|
7
|
+
GRAY, box2d.bodyTypeStatic);
|
|
7
8
|
groundObject.addBox(vec2(100,6));
|
|
8
9
|
new CarObject(vec2(0,-2));
|
|
9
10
|
canvasClearColor = hsl(0,0,.9);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
function gameInit()
|
|
2
|
+
{
|
|
3
|
+
// called once after the engine starts up
|
|
4
|
+
// setup the game
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function gameUpdate()
|
|
8
|
+
{
|
|
9
|
+
// called every frame at 60 frames per second
|
|
10
|
+
// handle input and update the game state
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function gameUpdatePost()
|
|
14
|
+
{
|
|
15
|
+
// called after physics and objects are updated
|
|
16
|
+
// setup camera and prepare for render
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function gameRender()
|
|
20
|
+
{
|
|
21
|
+
// called before objects are rendered
|
|
22
|
+
// draw any background effects that appear behind objects
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function gameRenderPost()
|
|
26
|
+
{
|
|
27
|
+
// called after objects are rendered
|
|
28
|
+
// draw effects or hud that appear above all objects
|
|
29
|
+
drawTextScreen('LittleJS Engine', mainCanvasSize.scale(.5), 80);
|
|
30
|
+
}
|
|
@@ -4,7 +4,7 @@ function gameRender()
|
|
|
4
4
|
drawRectGradient(cameraPos, getCameraSize(), BLACK, WHITE);
|
|
5
5
|
|
|
6
6
|
// draw text to the overlay canvas
|
|
7
|
-
drawTextOverlay('
|
|
7
|
+
drawTextOverlay('LittleJS Engine', vec2(0,3), 3);
|
|
8
8
|
|
|
9
9
|
// draw a tile
|
|
10
10
|
drawTile(vec2(Math.sin(time)*3,-2), vec2(7), tile(3,128));
|
|
@@ -2,7 +2,7 @@ class Player extends EngineObject
|
|
|
2
2
|
{
|
|
3
3
|
constructor(pos)
|
|
4
4
|
{
|
|
5
|
-
super(pos, vec2(2), tile(9), 0,
|
|
5
|
+
super(pos, vec2(2), tile(9), 0, RED);
|
|
6
6
|
this.damping = 1; // disable damping
|
|
7
7
|
this.clampSpeed = false; // disable speed clamping
|
|
8
8
|
}
|
|
@@ -11,12 +11,14 @@ class Player extends EngineObject
|
|
|
11
11
|
{
|
|
12
12
|
super.update();
|
|
13
13
|
|
|
14
|
+
// check ground height
|
|
14
15
|
const h = getGroundHeight(this.pos.x);
|
|
15
16
|
if (this.pos.y < h + this.size.y/2)
|
|
16
17
|
{
|
|
17
18
|
// clamp to ground and reflect velocity
|
|
18
19
|
this.pos.y = h + this.size.y/2;
|
|
19
|
-
const
|
|
20
|
+
const h2 = getGroundHeight(this.pos.x+.1);
|
|
21
|
+
const n = vec2((h-h2)/.1, 1).normalize();
|
|
20
22
|
this.velocity = this.velocity.reflect(n,0);
|
|
21
23
|
}
|
|
22
24
|
|
|
@@ -40,13 +42,17 @@ function gameInit()
|
|
|
40
42
|
{
|
|
41
43
|
gravity.y = -.01;
|
|
42
44
|
new Player(vec2(0,5));
|
|
43
|
-
canvasClearColor = hsl(.
|
|
45
|
+
canvasClearColor = hsl(.6,1,.8);
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
function gameRender()
|
|
47
49
|
{
|
|
50
|
+
// draw ground as a series of thin rectangles
|
|
48
51
|
const h = 100, w = 20;
|
|
49
|
-
const pos = vec2()
|
|
52
|
+
const pos = vec2();
|
|
53
|
+
const sizeTop = vec2(.4);
|
|
54
|
+
const size = vec2(.2,h);
|
|
55
|
+
const color = rgb();
|
|
50
56
|
for (let x=cameraPos.x-w; x<cameraPos.x+w; x+=.1)
|
|
51
57
|
{
|
|
52
58
|
pos.x = x;
|
|
@@ -14,7 +14,8 @@ class Player extends EngineObject
|
|
|
14
14
|
// space ship controls
|
|
15
15
|
const moveInput = keyDirection();
|
|
16
16
|
this.applyAngularAcceleration(moveInput.x * .002);
|
|
17
|
-
|
|
17
|
+
const accel = vec2(0, moveInput.y*.002).rotate(this.angle);
|
|
18
|
+
this.applyAcceleration(accel);
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
// explode when it collides
|
|
@@ -25,16 +26,16 @@ class Player extends EngineObject
|
|
|
25
26
|
if (this.velocity.length() < .05)
|
|
26
27
|
return true;
|
|
27
28
|
|
|
29
|
+
// explode!
|
|
28
30
|
this.destroy();
|
|
29
31
|
new ParticleEmitter(
|
|
30
|
-
this.pos, 0,
|
|
31
|
-
1, .1, 300, 3.14, // emitSize, emitTime,
|
|
32
|
-
0, // tileInfo
|
|
32
|
+
this.pos, 0, // pos, angle
|
|
33
|
+
1, .1, 300, 3.14, 0, // emitSize, emitTime, rate, cone, tile
|
|
33
34
|
rgb(1,.5,.1), rgb(1,.1,.1), // colorStartA, colorStartB
|
|
34
35
|
rgb(1,.5,.1,0), rgb(1,.1,.1,0), // colorEndA, colorEndB
|
|
35
|
-
.7, .8, .2, .2, .05, // time,
|
|
36
|
-
.9, 1, -.2, 3.14, .05, // damp, angleDamp, gravity,
|
|
37
|
-
1, 0, 1
|
|
36
|
+
.7, .8, .2, .2, .05, // time, start, end, speed, angleSpeed
|
|
37
|
+
.9, 1, -.2, 3.14, .05, // damp, angleDamp, gravity, cone, fade
|
|
38
|
+
1, 0, 1 // randomness, collide, additive
|
|
38
39
|
);
|
|
39
40
|
}
|
|
40
41
|
}
|
|
@@ -49,7 +50,9 @@ function gameInit()
|
|
|
49
50
|
for (let i=0, y=0; i<20; ++i)
|
|
50
51
|
{
|
|
51
52
|
y = (y + rand(1,-1)*4) * .5;
|
|
52
|
-
const
|
|
53
|
+
const pos = vec2(i*2-20, y-54);
|
|
54
|
+
const color = hsl(0, 0, .5+i%.29);
|
|
55
|
+
const o = new EngineObject(pos, vec2(2, 99), 0, 0, color);
|
|
53
56
|
o.setCollision(); // make object collide
|
|
54
57
|
o.mass = 0; // make object have static physics
|
|
55
58
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// create example medals
|
|
2
|
-
const medal_openedExample = new Medal(0, '
|
|
3
|
-
const medal_leftClick
|
|
4
|
-
const medal_rightClick
|
|
5
|
-
const medal_spacePressed
|
|
2
|
+
const medal_openedExample = new Medal(0, 'Open', 'Opened this example!');
|
|
3
|
+
const medal_leftClick = new Medal(1, 'Lefty', 'Left clicked!', '🐁');
|
|
4
|
+
const medal_rightClick = new Medal(2, 'Righty', 'Right clicked!', '🐭');
|
|
5
|
+
const medal_spacePressed = new Medal(3, 'Space', 'Pressed spacebar!', '🚀');
|
|
6
6
|
|
|
7
7
|
// setup medals
|
|
8
8
|
const saveName = 'Medals Example';
|
package/examples/shorts/music.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
let playButton, stopButton,
|
|
1
|
+
let musicPlayer, playButton, stopButton, infoText;
|
|
2
2
|
let musicSound = new SoundWave('song.mp3');
|
|
3
3
|
let musicVolume = 1;
|
|
4
|
-
let
|
|
4
|
+
let music;
|
|
5
5
|
|
|
6
6
|
function gameInit()
|
|
7
7
|
{
|
|
@@ -10,27 +10,28 @@ function gameInit()
|
|
|
10
10
|
uiSystem.defaultSoundPress = new Sound([.5,0,220]);
|
|
11
11
|
uiSystem.defaultSoundClick = new Sound([.5,0,440]);
|
|
12
12
|
uiSystem.defaultCornerRadius = 20;
|
|
13
|
-
canvasClearColor = hsl(.9,.3,.2);
|
|
13
|
+
canvasClearColor = hsl(.9,.3,.2);
|
|
14
14
|
|
|
15
15
|
// setup music player UI
|
|
16
|
-
|
|
16
|
+
musicPlayer = new UIObject(mainCanvasSize.scale(.5), vec2(500, 220));
|
|
17
17
|
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
musicPlayer.addChild(
|
|
18
|
+
// infomation text
|
|
19
|
+
infoText = new UIText(vec2(0, -70), vec2(400, 50));
|
|
20
|
+
musicPlayer.addChild(infoText);
|
|
21
21
|
|
|
22
22
|
// volume slider
|
|
23
|
-
const volumeSlider = new UIScrollbar(vec2(0, -
|
|
23
|
+
const volumeSlider = new UIScrollbar(vec2(0, -20), vec2(400, 30),
|
|
24
|
+
musicVolume, 'Music Volume');
|
|
24
25
|
musicPlayer.addChild(volumeSlider);
|
|
25
26
|
volumeSlider.onChange = () =>
|
|
26
27
|
{
|
|
27
28
|
musicVolume = volumeSlider.value;
|
|
28
|
-
if (
|
|
29
|
-
|
|
29
|
+
if (music)
|
|
30
|
+
music.setVolume(musicVolume);
|
|
30
31
|
};
|
|
31
32
|
|
|
32
33
|
// play button
|
|
33
|
-
playButton = new UIButton(vec2(-90,
|
|
34
|
+
playButton = new UIButton(vec2(-90, 50), vec2(140, 50), 'Play');
|
|
34
35
|
musicPlayer.addChild(playButton);
|
|
35
36
|
playButton.onClick = ()=>
|
|
36
37
|
{
|
|
@@ -38,68 +39,40 @@ function gameInit()
|
|
|
38
39
|
return;
|
|
39
40
|
|
|
40
41
|
// handle play/pause toggle
|
|
41
|
-
if (!
|
|
42
|
-
|
|
43
|
-
else if (
|
|
44
|
-
|
|
42
|
+
if (!music)
|
|
43
|
+
music = musicSound.playMusic(musicVolume);
|
|
44
|
+
else if (music.isPaused())
|
|
45
|
+
music.resume();
|
|
45
46
|
else
|
|
46
|
-
|
|
47
|
+
music.pause();
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
// stop button
|
|
50
|
-
stopButton = new UIButton(vec2(90,
|
|
51
|
-
stopButton.onClick = ()=>
|
|
52
|
-
{
|
|
53
|
-
if (!musicInstance)
|
|
54
|
-
return;
|
|
55
|
-
|
|
56
|
-
// stop sound
|
|
57
|
-
musicInstance.stop();
|
|
58
|
-
};
|
|
51
|
+
stopButton = new UIButton(vec2(90, 50), vec2(140, 50), 'Stop');
|
|
52
|
+
stopButton.onClick = ()=> music && music.stop();
|
|
59
53
|
musicPlayer.addChild(stopButton);
|
|
60
|
-
|
|
61
|
-
// progress bar and scrollbar for seeking
|
|
62
|
-
progressBar = new UIScrollbar(vec2(0, 100), vec2(400, 30), 0, 'Progress');
|
|
63
|
-
progressBar.disabledColor = RED;
|
|
64
|
-
progressBar.onChange = ()=>
|
|
65
|
-
{
|
|
66
|
-
// control music seek position
|
|
67
|
-
const wasPlaying = musicInstance && musicInstance.isPlaying();
|
|
68
|
-
if (!musicInstance)
|
|
69
|
-
musicInstance = musicSound.playMusic(musicVolume, true, true);
|
|
70
|
-
progressBar.value = min(progressBar.value, .999); // prevent looping around
|
|
71
|
-
const seekTime = progressBar.value * musicSound.getDuration();
|
|
72
|
-
musicInstance.start(seekTime);
|
|
73
|
-
if (!wasPlaying)
|
|
74
|
-
musicInstance.pause();
|
|
75
|
-
};
|
|
76
|
-
musicPlayer.addChild(progressBar);
|
|
77
54
|
}
|
|
78
55
|
|
|
79
56
|
function gameUpdate()
|
|
80
57
|
{
|
|
81
|
-
// disable buttons while loading
|
|
82
|
-
const isDisabled = !musicSound.isLoaded()
|
|
83
|
-
playButton.disabled
|
|
84
|
-
stopButton.disabled = isDisabled
|
|
85
|
-
progressBar.disabled = isDisabled
|
|
58
|
+
// disable buttons while loading
|
|
59
|
+
const isDisabled = !musicSound.isLoaded();
|
|
60
|
+
playButton.disabled = stopButton.disabled = isDisabled;
|
|
86
61
|
|
|
87
62
|
// update ui
|
|
88
|
-
if (
|
|
63
|
+
if (isDisabled)
|
|
89
64
|
{
|
|
90
65
|
// update loading progress
|
|
91
|
-
const loadingPercent = musicSound.loadedPercent * 100;
|
|
92
|
-
|
|
66
|
+
const loadingPercent = musicSound.loadedPercent * 100|0;
|
|
67
|
+
infoText.text = `Loading: ${loadingPercent}%`;
|
|
93
68
|
}
|
|
94
69
|
else
|
|
95
70
|
{
|
|
96
71
|
// update ui text
|
|
97
|
-
|
|
98
|
-
|
|
72
|
+
const isPlaying = music && music.isPlaying();
|
|
73
|
+
playButton.text = isPlaying ? 'Pause' : 'Play';
|
|
74
|
+
const current = music ? music.getCurrentTime() : 0;
|
|
99
75
|
const duration = musicSound.getDuration();
|
|
100
|
-
|
|
101
|
-
progressBar.value = currentTime / duration;
|
|
102
|
-
const timeText = `${formatTime(currentTime)} / ${formatTime(duration)}`;
|
|
103
|
-
progressBar.text = audioIsRunning() ? timeText : 'Click to Enable Audio';
|
|
76
|
+
infoText.text = formatTime(current) +' / '+ formatTime(duration);
|
|
104
77
|
}
|
|
105
78
|
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
let musicPlayer, playButton, stopButton, progressBar;
|
|
2
|
+
let musicSound, music;
|
|
3
|
+
let musicVolume = 1;
|
|
4
|
+
|
|
5
|
+
function gameInit()
|
|
6
|
+
{
|
|
7
|
+
// setup ui system plugin
|
|
8
|
+
new UISystemPlugin;
|
|
9
|
+
uiSystem.defaultSoundPress = new Sound([.5,0,220]);
|
|
10
|
+
uiSystem.defaultSoundClick = new Sound([.5,0,440]);
|
|
11
|
+
uiSystem.defaultCornerRadius = 20;
|
|
12
|
+
uiSystem.defaultGradientColor = WHITE;
|
|
13
|
+
canvasClearColor = hsl(.9,.3,.2);
|
|
14
|
+
|
|
15
|
+
// setup music player UI
|
|
16
|
+
musicPlayer = new UIObject(mainCanvasSize.scale(.5), vec2(500, 300));
|
|
17
|
+
const title = new UIText(vec2(0, -100), vec2(500, 40),
|
|
18
|
+
'LittleJS Music Player');
|
|
19
|
+
musicPlayer.addChild(title);
|
|
20
|
+
|
|
21
|
+
// drop zone text
|
|
22
|
+
const dropZoneText = new UIText(vec2(0, -60), vec2(450, 20),
|
|
23
|
+
'Drag & Drop Audio Files Here!');
|
|
24
|
+
dropZoneText.textColor = hsl(.9, .3, .8, .7);
|
|
25
|
+
musicPlayer.addChild(dropZoneText);
|
|
26
|
+
|
|
27
|
+
// volume slider
|
|
28
|
+
const volumeSlider = new UIScrollbar(vec2(0, -20), vec2(400, 30),
|
|
29
|
+
musicVolume, 'Music Volume');
|
|
30
|
+
musicPlayer.addChild(volumeSlider);
|
|
31
|
+
volumeSlider.onChange = () =>
|
|
32
|
+
{
|
|
33
|
+
musicVolume = volumeSlider.value;
|
|
34
|
+
if (music)
|
|
35
|
+
music.setVolume(musicVolume);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// play button
|
|
39
|
+
playButton = new UIButton(vec2(-90, 50), vec2(140, 50), 'Play');
|
|
40
|
+
musicPlayer.addChild(playButton);
|
|
41
|
+
playButton.onClick = ()=>
|
|
42
|
+
{
|
|
43
|
+
if (!musicSound.isLoaded())
|
|
44
|
+
return;
|
|
45
|
+
|
|
46
|
+
// handle play/pause toggle
|
|
47
|
+
if (!music)
|
|
48
|
+
music = musicSound.playMusic(musicVolume);
|
|
49
|
+
else if (music.isPaused())
|
|
50
|
+
music.resume();
|
|
51
|
+
else
|
|
52
|
+
music.pause();
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// stop button
|
|
56
|
+
stopButton = new UIButton(vec2(90, 50), vec2(140, 50), 'Stop');
|
|
57
|
+
stopButton.onClick = ()=> music && music.stop();
|
|
58
|
+
musicPlayer.addChild(stopButton);
|
|
59
|
+
|
|
60
|
+
// progress bar and scrollbar for seeking
|
|
61
|
+
progressBar = new UIScrollbar(vec2(0, 120), vec2(400, 30), 0);
|
|
62
|
+
progressBar.disabledColor = RED;
|
|
63
|
+
progressBar.onChange = ()=>
|
|
64
|
+
{
|
|
65
|
+
// control music seek position
|
|
66
|
+
const wasPlaying = music && music.isPlaying();
|
|
67
|
+
if (!music)
|
|
68
|
+
music = musicSound.playMusic(musicVolume, true, true);
|
|
69
|
+
progressBar.value = min(progressBar.value, .999); // prevent wrap
|
|
70
|
+
const seekTime = progressBar.value * musicSound.getDuration();
|
|
71
|
+
music.start(seekTime);
|
|
72
|
+
if (!wasPlaying)
|
|
73
|
+
music.pause();
|
|
74
|
+
};
|
|
75
|
+
musicPlayer.addChild(progressBar);
|
|
76
|
+
|
|
77
|
+
{
|
|
78
|
+
// setup drag and drop for audio files
|
|
79
|
+
function onDragEnter() { musicPlayer.color = RED; };
|
|
80
|
+
function onDragLeave() { musicPlayer.color = WHITE; };
|
|
81
|
+
function onDrop(e)
|
|
82
|
+
{
|
|
83
|
+
musicPlayer.color = WHITE
|
|
84
|
+
|
|
85
|
+
// get the dropped file
|
|
86
|
+
const file = e.dataTransfer.files[0];
|
|
87
|
+
if (!file || !file.type.startsWith('audio'))
|
|
88
|
+
return;
|
|
89
|
+
|
|
90
|
+
// create new sound from dropped file
|
|
91
|
+
const fileURL = URL.createObjectURL(file);
|
|
92
|
+
musicSound = new SoundWave(fileURL, musicVolume);
|
|
93
|
+
dropZoneText.text = file.name;
|
|
94
|
+
|
|
95
|
+
// reset UI
|
|
96
|
+
music && music.stop();
|
|
97
|
+
music = undefined;
|
|
98
|
+
progressBar.value = 0;
|
|
99
|
+
}
|
|
100
|
+
uiSystem.setupDragAndDrop(onDrop, onDragEnter, onDragLeave);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function gameUpdate()
|
|
105
|
+
{
|
|
106
|
+
// disable buttons while loading
|
|
107
|
+
const isDisabled = !musicSound || !musicSound.isLoaded();
|
|
108
|
+
playButton.disabled = isDisabled
|
|
109
|
+
stopButton.disabled = isDisabled
|
|
110
|
+
progressBar.disabled = isDisabled
|
|
111
|
+
|
|
112
|
+
// update ui
|
|
113
|
+
if (!musicSound)
|
|
114
|
+
{
|
|
115
|
+
// waiting for file
|
|
116
|
+
progressBar.text = 'No File Loaded';
|
|
117
|
+
}
|
|
118
|
+
else if (isDisabled)
|
|
119
|
+
{
|
|
120
|
+
// update loading progress
|
|
121
|
+
const loadingPercent = musicSound.loadedPercent * 100|0;
|
|
122
|
+
progressBar.text = `Loading: ${loadingPercent}%`;
|
|
123
|
+
}
|
|
124
|
+
else
|
|
125
|
+
{
|
|
126
|
+
// update ui text
|
|
127
|
+
const isPlaying = music && music.isPlaying();
|
|
128
|
+
playButton.text = isPlaying ? 'Pause' : 'Play';
|
|
129
|
+
const current = music ? music.getCurrentTime() : 0;
|
|
130
|
+
const duration = musicSound.getDuration();
|
|
131
|
+
progressBar.text = formatTime(current) +' / '+ formatTime(duration);
|
|
132
|
+
if (!progressBar.mouseIsHeld)
|
|
133
|
+
progressBar.value = current / duration;
|
|
134
|
+
}
|
|
135
|
+
}
|