littlejsengine 1.14.11 → 1.14.16
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 +252 -109
- package/dist/littlejs.esm.js +559 -252
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +557 -251
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +482 -206
- package/examples/box2d/gameObjects.js +2 -2
- 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 +3 -3
- package/examples/electron/index.html +2 -2
- package/examples/electron/package.json +1 -8
- package/examples/index.html +10 -7
- package/examples/module/game.js +3 -3
- package/examples/platformer/gameEffects.js +4 -4
- 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 +134 -0
- package/examples/shorts/nineSlice.js +34 -15
- package/examples/shorts/parallax.js +4 -3
- 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/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 +14 -3
- 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 +3 -3
- package/examples/starter/index.html +2 -2
- package/examples/typescript/game.js +3 -3
- package/examples/typescript/game.ts +3 -3
- package/examples/uiSystem/game.js +3 -3
- package/package.json +4 -2
- package/plugins/box2d.js +17 -2
- package/plugins/newgrounds.js +7 -5
- package/plugins/postProcess.js +5 -2
- package/plugins/uiSystem.js +120 -34
- package/plugins/zzfxm.js +5 -1
- package/reference.md +1 -1
- package/src/engine.js +35 -12
- package/src/engineAudio.js +31 -14
- package/src/engineDebug.js +75 -45
- package/src/engineDraw.js +60 -31
- package/src/engineExport.js +2 -1
- package/src/engineMedals.js +10 -2
- package/src/engineObject.js +14 -10
- package/src/engineParticles.js +59 -46
- package/src/engineSettings.js +7 -7
- package/src/engineTileLayer.js +45 -20
- package/src/engineUtilities.js +67 -20
|
@@ -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,134 @@
|
|
|
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
|
+
canvasClearColor = hsl(.9,.3,.2);
|
|
13
|
+
|
|
14
|
+
// setup music player UI
|
|
15
|
+
musicPlayer = new UIObject(mainCanvasSize.scale(.5), vec2(500, 300));
|
|
16
|
+
const title = new UIText(vec2(0, -100), vec2(500, 40),
|
|
17
|
+
'LittleJS Music Player');
|
|
18
|
+
musicPlayer.addChild(title);
|
|
19
|
+
|
|
20
|
+
// drop zone text
|
|
21
|
+
const dropZoneText = new UIText(vec2(0, -60), vec2(450, 20),
|
|
22
|
+
'Drag & Drop Audio Files Here!');
|
|
23
|
+
dropZoneText.textColor = hsl(.9, .3, .8, .7);
|
|
24
|
+
musicPlayer.addChild(dropZoneText);
|
|
25
|
+
|
|
26
|
+
// volume slider
|
|
27
|
+
const volumeSlider = new UIScrollbar(vec2(0, -20), vec2(400, 30),
|
|
28
|
+
musicVolume, 'Music Volume');
|
|
29
|
+
musicPlayer.addChild(volumeSlider);
|
|
30
|
+
volumeSlider.onChange = () =>
|
|
31
|
+
{
|
|
32
|
+
musicVolume = volumeSlider.value;
|
|
33
|
+
if (music)
|
|
34
|
+
music.setVolume(musicVolume);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// play button
|
|
38
|
+
playButton = new UIButton(vec2(-90, 50), vec2(140, 50), 'Play');
|
|
39
|
+
musicPlayer.addChild(playButton);
|
|
40
|
+
playButton.onClick = ()=>
|
|
41
|
+
{
|
|
42
|
+
if (!musicSound.isLoaded())
|
|
43
|
+
return;
|
|
44
|
+
|
|
45
|
+
// handle play/pause toggle
|
|
46
|
+
if (!music)
|
|
47
|
+
music = musicSound.playMusic(musicVolume);
|
|
48
|
+
else if (music.isPaused())
|
|
49
|
+
music.resume();
|
|
50
|
+
else
|
|
51
|
+
music.pause();
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// stop button
|
|
55
|
+
stopButton = new UIButton(vec2(90, 50), vec2(140, 50), 'Stop');
|
|
56
|
+
stopButton.onClick = ()=> music && music.stop();
|
|
57
|
+
musicPlayer.addChild(stopButton);
|
|
58
|
+
|
|
59
|
+
// progress bar and scrollbar for seeking
|
|
60
|
+
progressBar = new UIScrollbar(vec2(0, 120), vec2(400, 30), 0);
|
|
61
|
+
progressBar.disabledColor = RED;
|
|
62
|
+
progressBar.onChange = ()=>
|
|
63
|
+
{
|
|
64
|
+
// control music seek position
|
|
65
|
+
const wasPlaying = music && music.isPlaying();
|
|
66
|
+
if (!music)
|
|
67
|
+
music = musicSound.playMusic(musicVolume, true, true);
|
|
68
|
+
progressBar.value = min(progressBar.value, .999); // prevent wrap
|
|
69
|
+
const seekTime = progressBar.value * musicSound.getDuration();
|
|
70
|
+
music.start(seekTime);
|
|
71
|
+
if (!wasPlaying)
|
|
72
|
+
music.pause();
|
|
73
|
+
};
|
|
74
|
+
musicPlayer.addChild(progressBar);
|
|
75
|
+
|
|
76
|
+
{
|
|
77
|
+
// setup drag and drop for audio files
|
|
78
|
+
function onDragEnter() { musicPlayer.color = RED; };
|
|
79
|
+
function onDragLeave() { musicPlayer.color = WHITE; };
|
|
80
|
+
function onDrop(e)
|
|
81
|
+
{
|
|
82
|
+
musicPlayer.color = WHITE
|
|
83
|
+
|
|
84
|
+
// get the dropped file
|
|
85
|
+
const file = e.dataTransfer.files[0];
|
|
86
|
+
if (!file || !file.type.startsWith('audio'))
|
|
87
|
+
return;
|
|
88
|
+
|
|
89
|
+
// create new sound from dropped file
|
|
90
|
+
const fileURL = URL.createObjectURL(file);
|
|
91
|
+
musicSound = new SoundWave(fileURL, musicVolume);
|
|
92
|
+
dropZoneText.text = file.name;
|
|
93
|
+
|
|
94
|
+
// reset UI
|
|
95
|
+
music && music.stop();
|
|
96
|
+
music = undefined;
|
|
97
|
+
progressBar.value = 0;
|
|
98
|
+
}
|
|
99
|
+
uiSystem.setupDragAndDrop(onDrop, onDragEnter, onDragLeave);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function gameUpdate()
|
|
104
|
+
{
|
|
105
|
+
// disable buttons while loading
|
|
106
|
+
const isDisabled = !musicSound || !musicSound.isLoaded();
|
|
107
|
+
playButton.disabled = isDisabled
|
|
108
|
+
stopButton.disabled = isDisabled
|
|
109
|
+
progressBar.disabled = isDisabled
|
|
110
|
+
|
|
111
|
+
// update ui
|
|
112
|
+
if (!musicSound)
|
|
113
|
+
{
|
|
114
|
+
// waiting for file
|
|
115
|
+
progressBar.text = 'No File Loaded';
|
|
116
|
+
}
|
|
117
|
+
else if (isDisabled)
|
|
118
|
+
{
|
|
119
|
+
// update loading progress
|
|
120
|
+
const loadingPercent = musicSound.loadedPercent * 100|0;
|
|
121
|
+
progressBar.text = `Loading: ${loadingPercent}%`;
|
|
122
|
+
}
|
|
123
|
+
else
|
|
124
|
+
{
|
|
125
|
+
// update ui text
|
|
126
|
+
const isPlaying = music && music.isPlaying();
|
|
127
|
+
playButton.text = isPlaying ? 'Pause' : 'Play';
|
|
128
|
+
const current = music ? music.getCurrentTime() : 0;
|
|
129
|
+
const duration = musicSound.getDuration();
|
|
130
|
+
progressBar.text = formatTime(current) +' / '+ formatTime(duration);
|
|
131
|
+
if (!progressBar.mouseIsHeld)
|
|
132
|
+
progressBar.value = current / duration;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -3,19 +3,38 @@ function gameRender()
|
|
|
3
3
|
const nineSliceTile = tile(16);
|
|
4
4
|
const threeSliceTile = tile(19);
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
6
|
+
{
|
|
7
|
+
// draw nine slice with thin border and color
|
|
8
|
+
const pos = vec2(-7,4);
|
|
9
|
+
const size = vec2(11+wave(.5,2), 6);
|
|
10
|
+
const color = hsl(.1,.5,.9);
|
|
11
|
+
const border = .5;
|
|
12
|
+
drawNineSlice(pos, size, nineSliceTile, color, border);
|
|
13
|
+
drawTextOverlay('Nine Slice\nThin Border', pos, 1, BLACK);
|
|
14
|
+
}
|
|
15
|
+
{
|
|
16
|
+
// draw nine slice in screen space with thick border and rotation
|
|
17
|
+
const pos = vec2(700,150);
|
|
18
|
+
const size = vec2(250);
|
|
19
|
+
const border = 32;
|
|
20
|
+
const angle = time/2;
|
|
21
|
+
drawNineSliceScreen(pos, size, nineSliceTile, border, 2, angle);
|
|
22
|
+
drawTextScreen('Nine Slice\nScreen Space', pos, 30, BLACK);
|
|
23
|
+
}
|
|
24
|
+
{
|
|
25
|
+
// draw three slice with variable border and additive color
|
|
26
|
+
const pos = vec2(-7,-4);
|
|
27
|
+
const size = vec2(9, 7);
|
|
28
|
+
const border = 2 + wave(.2)*2;
|
|
29
|
+
const additive = hsl(time/30,.5,.5);
|
|
30
|
+
drawThreeSlice(pos, size, threeSliceTile, WHITE, border, additive);
|
|
31
|
+
drawTextOverlay('Three Slice\nVariable\nBorder', pos, 1, BLACK);
|
|
32
|
+
}
|
|
33
|
+
{
|
|
34
|
+
// draw three slice in screen space with changing size
|
|
35
|
+
const pos = vec2(700,420);
|
|
36
|
+
const size = vec2(350-wave(.3,90),120+wave(.3,60));
|
|
37
|
+
drawThreeSliceScreen(pos, size, threeSliceTile);
|
|
38
|
+
drawTextScreen('Three Slice\nScreen Space', pos, 30, BLACK);
|
|
39
|
+
}
|
|
21
40
|
}
|
|
@@ -23,7 +23,7 @@ class ParallaxLayer extends CanvasLayer
|
|
|
23
23
|
const w = canvasSize.x, h = canvasSize.y;
|
|
24
24
|
for (let i = h; i--;)
|
|
25
25
|
{
|
|
26
|
-
// draw a 1 pixel gradient line on the left side
|
|
26
|
+
// draw a 1 pixel gradient line on the left side
|
|
27
27
|
const p = i/h;
|
|
28
28
|
this.context.fillStyle = topColor.lerp(bottomColor, p);
|
|
29
29
|
this.context.fillRect(0, i, 1, 1);
|
|
@@ -34,7 +34,8 @@ class ParallaxLayer extends CanvasLayer
|
|
|
34
34
|
const levelness = .005; // how much the mountains level out
|
|
35
35
|
const slopeRange = 1; // max slope of the mountains
|
|
36
36
|
const startGroundLevel = h/2;
|
|
37
|
-
let y = startGroundLevel
|
|
37
|
+
let y = startGroundLevel;
|
|
38
|
+
let groundSlope = rand(-slopeRange, slopeRange);
|
|
38
39
|
for (let x=w; x--;)
|
|
39
40
|
{
|
|
40
41
|
// pull slope towards start ground level
|
|
@@ -45,7 +46,7 @@ class ParallaxLayer extends CanvasLayer
|
|
|
45
46
|
groundSlope = rand(-slopeRange, slopeRange);
|
|
46
47
|
|
|
47
48
|
// draw 1 pixel wide vertical slice of mountain
|
|
48
|
-
this.context.drawImage(this.canvas, 0,
|
|
49
|
+
this.context.drawImage(this.canvas, 0,0,1,h,x,y,1,h-y);
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
// remove gradient sliver from left side
|
|
@@ -4,25 +4,25 @@ function gameInit()
|
|
|
4
4
|
|
|
5
5
|
// fire
|
|
6
6
|
new ParticleEmitter(
|
|
7
|
-
vec2(-5,-2), 0,
|
|
8
|
-
2, 0, 200, PI,
|
|
9
|
-
tile(0),
|
|
10
|
-
rgb(1,.5,.1), rgb(1,.1,.1),
|
|
11
|
-
rgb(1,.5,.1,0), rgb(1,.1,.1,0)
|
|
12
|
-
.7, 2, 0, .2, .05,
|
|
13
|
-
.9, 1, -1, PI, .05
|
|
14
|
-
.5, 0, 1, 0
|
|
7
|
+
vec2(-5,-2), 0, // pos, angle
|
|
8
|
+
2, 0, 200, PI, // emitSize, emitTime, rate, cone
|
|
9
|
+
tile(0), // tileInfo
|
|
10
|
+
rgb(1,.5,.1), rgb(1,.1,.1), // colorStartA, colorStartB
|
|
11
|
+
rgb(1,.5,.1,0), rgb(1,.1,.1,0),// colorEndA, colorEndB
|
|
12
|
+
.7, 2, 0, .2, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
13
|
+
.9, 1, -1, PI, .05,// damp, angleDamp, gravity, particleCone, fade
|
|
14
|
+
.5, 0, 1, 0 // randomness, collide, additive, colorLinear
|
|
15
15
|
);
|
|
16
16
|
|
|
17
17
|
// smoke
|
|
18
18
|
new ParticleEmitter(
|
|
19
19
|
vec2(5,-2), 0, // pos, angle
|
|
20
|
-
3, 0, 100, PI,
|
|
21
|
-
tile(0),
|
|
22
|
-
hsl(0,0,0,.5), hsl(0,0,1,.5)
|
|
23
|
-
hsl(0,0,0,0), hsl(0,0,1,0),
|
|
24
|
-
1, 1, 5, .2, .01,
|
|
25
|
-
.85, 1, -1, PI, .3
|
|
26
|
-
.5, 0, 0, 1
|
|
20
|
+
3, 0, 100, PI, // emitSize, emitTime, rate, cone
|
|
21
|
+
tile(0), // tileInfo
|
|
22
|
+
hsl(0,0,0,.5), hsl(0,0,1,.5),// colorStartA, colorStartB
|
|
23
|
+
hsl(0,0,0,0), hsl(0,0,1,0), // colorEndA, colorEndB
|
|
24
|
+
1, 1, 5, .2, .01, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
25
|
+
.85, 1, -1, PI, .3,// damp, angleDamp, gravity, particleCone, fade
|
|
26
|
+
.5, 0, 0, 1 // randomness, collide, additive, colorLinear
|
|
27
27
|
);
|
|
28
28
|
}
|
package/examples/shorts/piano.js
CHANGED
|
@@ -2,29 +2,21 @@ const pianoSound = new Sound([,0,220,,9]);
|
|
|
2
2
|
|
|
3
3
|
class PianoKey extends UIButton
|
|
4
4
|
{
|
|
5
|
-
constructor(pos, size, semitone,
|
|
5
|
+
constructor(pos, size, semitone, color, hoverColor)
|
|
6
6
|
{
|
|
7
7
|
const keySize = 65;
|
|
8
8
|
size = size.scale(keySize);
|
|
9
9
|
pos = pos.scale(keySize).add(vec2(0,size.y/2-keySize*2));
|
|
10
10
|
pos = pos.add(mainCanvasSize.scale(.5));
|
|
11
|
-
super(pos, size, '',
|
|
12
|
-
|
|
11
|
+
super(pos, size, '', color);
|
|
12
|
+
|
|
13
13
|
this.dragActivate = true;
|
|
14
|
-
this.
|
|
14
|
+
this.semitone = semitone;
|
|
15
|
+
this.hoverColor = hoverColor;
|
|
15
16
|
this.activeColor = RED;
|
|
16
17
|
}
|
|
17
|
-
onPress()
|
|
18
|
-
{
|
|
19
|
-
if (!this.soundInstance)
|
|
20
|
-
this.soundInstance = pianoSound.playNote(this.semitone);
|
|
21
|
-
}
|
|
22
|
-
onRelease()
|
|
23
|
-
{
|
|
24
|
-
if (this.soundInstance)
|
|
25
|
-
this.soundInstance.stop(.2);
|
|
26
|
-
this.soundInstance = 0;
|
|
27
|
-
}
|
|
18
|
+
onPress() { this.sound = pianoSound.playNote(this.semitone); }
|
|
19
|
+
onRelease() { this.sound.stop(.2); }
|
|
28
20
|
}
|
|
29
21
|
|
|
30
22
|
function gameInit()
|
|
@@ -35,16 +27,18 @@ function gameInit()
|
|
|
35
27
|
// create piano keyboard
|
|
36
28
|
for (let i=15; i--;)
|
|
37
29
|
{
|
|
38
|
-
|
|
39
|
-
const
|
|
30
|
+
// white keys
|
|
31
|
+
const pos = vec2(i-7, 0);
|
|
32
|
+
const size = vec2(1, 4);
|
|
40
33
|
const semitone = [0,2,4,5,7,9,11][i%7]+(i/7|0)*12;
|
|
41
|
-
new PianoKey(pos, size, semitone,
|
|
34
|
+
new PianoKey(pos, size, semitone, WHITE, hsl(0,1,.9));
|
|
42
35
|
}
|
|
43
36
|
for (let i=10; i--;)
|
|
44
37
|
{
|
|
45
|
-
|
|
46
|
-
const
|
|
38
|
+
// black keys
|
|
39
|
+
const pos = vec2([1,2,4,5,6][i%5]+(i/5|0)*7-7.5, 0)
|
|
40
|
+
const size = vec2(1, 2);
|
|
47
41
|
const semitone = [1,3,6,8,10][i%5]+(i/5|0)*12;
|
|
48
|
-
new PianoKey(pos, size, semitone);
|
|
42
|
+
new PianoKey(pos, size, semitone, hsl(0,0,.3), hsl(0,1,.3));
|
|
49
43
|
}
|
|
50
44
|
}
|
|
@@ -18,10 +18,12 @@ function gameInit()
|
|
|
18
18
|
canvasFixedSize = vec2(1280, 720); // use a 720p fixed size canvas
|
|
19
19
|
|
|
20
20
|
// create objects
|
|
21
|
-
paddle = new PhysicsObject(vec2(0,1), vec2(6,1)); //
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
new PhysicsObject(vec2(
|
|
21
|
+
paddle = new PhysicsObject(vec2(0,1), vec2(6,1)); // player
|
|
22
|
+
|
|
23
|
+
const w = levelSize.x, h = levelSize.y;
|
|
24
|
+
new PhysicsObject(vec2(-.5,h/2), vec2(1,100)); // left wall
|
|
25
|
+
new PhysicsObject(vec2(w+.5,h/2), vec2(1,100)); // right wall
|
|
26
|
+
new PhysicsObject(vec2(w/2,h+.5), vec2(100,1)); // top wall
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
function gameUpdate()
|
|
@@ -45,7 +45,7 @@ function gameRender()
|
|
|
45
45
|
{
|
|
46
46
|
// draw horizontal slizes to create floor and ceiling
|
|
47
47
|
const h = 9;
|
|
48
|
-
let pos = vec2(), size = vec2(39, .15), color =
|
|
48
|
+
let pos = vec2(), size = vec2(39, .15), color = rgb();
|
|
49
49
|
for (let y=-h; y<h; y+=.1)
|
|
50
50
|
{
|
|
51
51
|
const p = 1.01-abs(y/h)
|
|
@@ -57,7 +57,7 @@ function gameRender()
|
|
|
57
57
|
{
|
|
58
58
|
// draw vertical slices to create the walls
|
|
59
59
|
const w = 20;
|
|
60
|
-
const pos = vec2(), size = vec2(.15), color =
|
|
60
|
+
const pos = vec2(), size = vec2(.15), color = rgb();
|
|
61
61
|
for (let x=-w; x<w; x+=.1)
|
|
62
62
|
{
|
|
63
63
|
const p = raycast(playerPos, playerAngle + x/w);
|
|
@@ -68,7 +68,12 @@ function gameRender()
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
// draw instructions and pointer lock status
|
|
71
|
-
const instructions = pointerLockIsActive() ?
|
|
71
|
+
const instructions = pointerLockIsActive() ?
|
|
72
|
+
'Mouse Control Active - ESC To Exit' :
|
|
73
|
+
'Click To Enable Mouse Control';
|
|
74
|
+
const textPos = vec2(mainCanvasSize.x/2, 50);
|
|
75
|
+
const textSize = 24;
|
|
76
|
+
const textColor = pointerLockIsActive() ? GREEN : WHITE;
|
|
72
77
|
if (!isTouchDevice)
|
|
73
|
-
drawTextScreen(instructions,
|
|
78
|
+
drawTextScreen(instructions, textPos, textSize, textColor);
|
|
74
79
|
}
|