littlejsengine 1.18.4 → 1.18.8
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/COPYRIGHT.txt +38 -0
- package/FAQ.md +633 -0
- package/README.md +19 -1
- package/dist/littlejs.d.ts +354 -55
- package/dist/littlejs.esm.js +1531 -489
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +1499 -476
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +1493 -470
- package/package.json +8 -1
- package/plugins/box2d.js +32 -7
- package/{src/engineMedals.js → plugins/medalSystem.js} +248 -196
- package/plugins/pathFinder.js +758 -0
- package/plugins/pluginExport.js +19 -0
- package/plugins/{tween.js → tweenSystem.js} +7 -7
- package/plugins/uiSystem.js +186 -25
- package/src/engine.js +2 -141
- package/src/engineAudio.js +3 -3
- package/src/engineBuild.mjs +4 -2
- package/src/engineDebug.js +7 -7
- package/src/engineDraw.js +26 -8
- package/src/engineExport.js +13 -13
- package/src/engineInput.js +8 -8
- package/src/engineLogo.js +146 -0
- package/src/engineMath.js +15 -6
- package/src/engineObject.js +11 -5
- package/src/engineParticles.js +6 -3
- package/src/engineRelease.js +1 -1
- package/src/engineSettings.js +0 -47
- package/src/engineUtilities.js +13 -8
- package/src/engineWebGL.js +34 -7
- package/src/jsconfig.json +3 -1
- package/.github/workflows/test.yml +0 -17
- package/AI.md +0 -173
- package/CLAUDE.md +0 -1
- package/examples/box2d/game.js +0 -192
- package/examples/box2d/gameObjects.js +0 -564
- package/examples/box2d/index.html +0 -9
- package/examples/box2d/scenes.js +0 -194
- package/examples/box2d/tiles.png +0 -0
- package/examples/breakout/game.js +0 -175
- package/examples/breakout/gameObjects.js +0 -147
- package/examples/breakout/index.html +0 -8
- package/examples/breakout/tiles.png +0 -0
- package/examples/breakoutTutorial/README.md +0 -521
- package/examples/breakoutTutorial/game.js +0 -191
- package/examples/breakoutTutorial/images/1.png +0 -0
- package/examples/breakoutTutorial/images/10.png +0 -0
- package/examples/breakoutTutorial/images/11.png +0 -0
- package/examples/breakoutTutorial/images/2.png +0 -0
- package/examples/breakoutTutorial/images/3.png +0 -0
- package/examples/breakoutTutorial/images/4.png +0 -0
- package/examples/breakoutTutorial/images/5.png +0 -0
- package/examples/breakoutTutorial/images/6.png +0 -0
- package/examples/breakoutTutorial/images/7.png +0 -0
- package/examples/breakoutTutorial/images/8.png +0 -0
- package/examples/breakoutTutorial/images/9.png +0 -0
- package/examples/breakoutTutorial/index.html +0 -8
- package/examples/electron/build.mjs +0 -127
- package/examples/electron/electron.js +0 -35
- package/examples/electron/game.js +0 -54
- package/examples/electron/index.html +0 -13
- package/examples/electron/package.json +0 -5
- package/examples/electron/tiles.png +0 -0
- package/examples/empty/game.js +0 -51
- package/examples/empty/index.html +0 -5
- package/examples/empty/tiles.png +0 -0
- package/examples/favicon.png +0 -0
- package/examples/games.jpg +0 -0
- package/examples/htmlMenu/game.js +0 -82
- package/examples/htmlMenu/index.html +0 -45
- package/examples/htmlMenu/tiles.png +0 -0
- package/examples/index.html +0 -62
- package/examples/logo.png +0 -0
- package/examples/logo2.png +0 -0
- package/examples/module/build.mjs +0 -124
- package/examples/module/game.js +0 -132
- package/examples/module/index.html +0 -10
- package/examples/module/tiles.png +0 -0
- package/examples/particles/index.html +0 -426
- package/examples/particles/tiles.png +0 -0
- package/examples/platformer/data/gameLevelData.tmx +0 -143
- package/examples/platformer/data/gameLevelData.tsx +0 -4
- package/examples/platformer/game.js +0 -147
- package/examples/platformer/gameCharacter.js +0 -309
- package/examples/platformer/gameEffects.js +0 -278
- package/examples/platformer/gameLevel.js +0 -205
- package/examples/platformer/gameLevelData.json +0 -171
- package/examples/platformer/gameObjects.js +0 -378
- package/examples/platformer/gamePlayer.js +0 -35
- package/examples/platformer/index.html +0 -9
- package/examples/platformer/tiles.png +0 -0
- package/examples/platformer/tilesLevel.png +0 -0
- package/examples/puzzle/game.js +0 -331
- package/examples/puzzle/index.html +0 -8
- package/examples/puzzle/tiles.png +0 -0
- package/examples/screenshot.jpg +0 -0
- package/examples/shorts/animation.js +0 -18
- package/examples/shorts/base.html +0 -54
- package/examples/shorts/blending.js +0 -14
- package/examples/shorts/box2d.js +0 -51
- package/examples/shorts/box2dCar.js +0 -59
- package/examples/shorts/box2dPool.js +0 -107
- package/examples/shorts/box2dTileLayer.js +0 -48
- package/examples/shorts/cameraDrag.js +0 -22
- package/examples/shorts/clock.js +0 -21
- package/examples/shorts/colors.js +0 -25
- package/examples/shorts/debugDraw.js +0 -37
- package/examples/shorts/empty.js +0 -30
- package/examples/shorts/flappyGame.js +0 -55
- package/examples/shorts/fontImage.js +0 -17
- package/examples/shorts/fps.js +0 -90
- package/examples/shorts/helloWorld.js +0 -11
- package/examples/shorts/hillGlideGame.js +0 -63
- package/examples/shorts/input.js +0 -64
- package/examples/shorts/landerGame.js +0 -57
- package/examples/shorts/maze.js +0 -48
- package/examples/shorts/medals.js +0 -51
- package/examples/shorts/music.js +0 -78
- package/examples/shorts/musicPlayer.js +0 -137
- package/examples/shorts/nineSlice.js +0 -40
- package/examples/shorts/parallax.js +0 -72
- package/examples/shorts/particles.js +0 -28
- package/examples/shorts/piano.js +0 -44
- package/examples/shorts/platformer.js +0 -45
- package/examples/shorts/pongGame.js +0 -41
- package/examples/shorts/postProcess.js +0 -62
- package/examples/shorts/sequencer.js +0 -124
- package/examples/shorts/shader.js +0 -29
- package/examples/shorts/shapes.js +0 -21
- package/examples/shorts/slidingPuzzle.js +0 -52
- package/examples/shorts/song.mp3 +0 -0
- package/examples/shorts/sound.js +0 -36
- package/examples/shorts/spaceGame.js +0 -58
- package/examples/shorts/spriteAtlas.js +0 -31
- package/examples/shorts/starfield.js +0 -15
- package/examples/shorts/texture.js +0 -16
- package/examples/shorts/textureWrapped.js +0 -12
- package/examples/shorts/tileLayer.js +0 -48
- package/examples/shorts/tileRaycast.js +0 -39
- package/examples/shorts/tiles.png +0 -0
- package/examples/shorts/tiltedView.js +0 -63
- package/examples/shorts/timers.js +0 -53
- package/examples/shorts/topDown.js +0 -38
- package/examples/shorts/tween.js +0 -24
- package/examples/shorts/uiSystem.js +0 -61
- package/examples/shorts/video.webm +0 -0
- package/examples/shorts/videoPlayer.js +0 -34
- package/examples/shorts.js +0 -743
- package/examples/starter/build.bat +0 -7
- package/examples/starter/build.mjs +0 -126
- package/examples/starter/game.js +0 -137
- package/examples/starter/index.html +0 -35
- package/examples/starter/tiles.png +0 -0
- package/examples/stress/index.html +0 -173
- package/examples/style.css +0 -150
- package/examples/tweenSystem/game.js +0 -171
- package/examples/tweenSystem/index.html +0 -10
- package/examples/tweenSystem/tiles.png +0 -0
- package/examples/typescript/build.mjs +0 -60
- package/examples/typescript/game.js +0 -100
- package/examples/typescript/game.ts +0 -132
- package/examples/typescript/index.html +0 -10
- package/examples/typescript/tiles.png +0 -0
- package/examples/typescript/tsconfig.json +0 -17
- package/examples/uiSystem/game.js +0 -139
- package/examples/uiSystem/index.html +0 -10
- package/examples/uiSystem/tiles.png +0 -0
- package/jsconfig.json +0 -12
- package/plugins/desktop.ini +0 -2
- package/reference.md +0 -448
- package/test/math.test.mjs +0 -774
- package/test/setup.mjs +0 -22
- package/test/smoke.test.mjs +0 -274
- package/test/tween.test.mjs +0 -576
- package/test/util.test.mjs +0 -80
package/examples/shorts/music.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
const musicSound = new Sound('song.mp3');
|
|
2
|
-
let musicVolume = .8, musicInstance;
|
|
3
|
-
|
|
4
|
-
function gameInit()
|
|
5
|
-
{
|
|
6
|
-
// setup ui system plugin
|
|
7
|
-
new UISystemPlugin;
|
|
8
|
-
uiSystem.defaultSoundPress = new Sound([.5,0,220]);
|
|
9
|
-
uiSystem.defaultSoundClick = new Sound([.5,0,440]);
|
|
10
|
-
uiSystem.defaultCornerRadius = 20;
|
|
11
|
-
uiSystem.defaultShadowColor = BLACK;
|
|
12
|
-
canvasClearColor = hsl(.9,.3,.2);
|
|
13
|
-
|
|
14
|
-
// setup music player UI
|
|
15
|
-
const center = mainCanvasSize.scale(.5);
|
|
16
|
-
musicPlayer = new UIObject(center, vec2(500, 220));
|
|
17
|
-
|
|
18
|
-
// information text
|
|
19
|
-
infoText = new UIText(vec2(0, -70), vec2(400, 50));
|
|
20
|
-
musicPlayer.addChild(infoText);
|
|
21
|
-
|
|
22
|
-
// volume slider
|
|
23
|
-
const volumeSlider = new UISlider(vec2(0, -20), vec2(400, 30),
|
|
24
|
-
musicVolume, 'Music Volume');
|
|
25
|
-
volumeSlider.fillMode = true;
|
|
26
|
-
musicPlayer.addChild(volumeSlider);
|
|
27
|
-
volumeSlider.onChange = ()=>
|
|
28
|
-
{
|
|
29
|
-
musicVolume = volumeSlider.value;
|
|
30
|
-
musicInstance?.setVolume(musicVolume);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
// play button
|
|
34
|
-
playButton = new UIButton(vec2(-90, 50), vec2(140, 50), 'Play');
|
|
35
|
-
musicPlayer.addChild(playButton);
|
|
36
|
-
playButton.onClick = ()=>
|
|
37
|
-
{
|
|
38
|
-
if (!musicSound.isLoaded())
|
|
39
|
-
return;
|
|
40
|
-
|
|
41
|
-
// handle play/pause toggle
|
|
42
|
-
if (!musicInstance)
|
|
43
|
-
musicInstance = musicSound.playMusic(musicVolume);
|
|
44
|
-
else if (musicInstance.isPaused())
|
|
45
|
-
musicInstance.resume();
|
|
46
|
-
else
|
|
47
|
-
musicInstance.pause();
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// stop button
|
|
51
|
-
stopButton = new UIButton(vec2(90, 50), vec2(140, 50), 'Stop');
|
|
52
|
-
stopButton.onClick = ()=> musicInstance?.stop();
|
|
53
|
-
musicPlayer.addChild(stopButton);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function gameUpdate()
|
|
57
|
-
{
|
|
58
|
-
// disable buttons while loading
|
|
59
|
-
const isDisabled = !musicSound.isLoaded();
|
|
60
|
-
playButton.disabled = stopButton.disabled = isDisabled;
|
|
61
|
-
|
|
62
|
-
// update ui
|
|
63
|
-
if (isDisabled)
|
|
64
|
-
{
|
|
65
|
-
// update loading progress
|
|
66
|
-
const loadingPercent = musicSound.loadedPercent * 100|0;
|
|
67
|
-
infoText.text = `Loading: ${loadingPercent}%`;
|
|
68
|
-
}
|
|
69
|
-
else
|
|
70
|
-
{
|
|
71
|
-
// update ui text
|
|
72
|
-
const isPlaying = musicInstance?.isPlaying();
|
|
73
|
-
playButton.text = isPlaying ? 'Pause' : 'Play';
|
|
74
|
-
const current = formatTime(musicInstance?.getCurrentTime());
|
|
75
|
-
const duration = formatTime(musicSound.getDuration());
|
|
76
|
-
infoText.text = current + ' / ' + duration;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
let musicVolume = .8, musicSound, musicInstance;
|
|
3
|
-
|
|
4
|
-
function gameInit()
|
|
5
|
-
{
|
|
6
|
-
// setup ui system plugin
|
|
7
|
-
new UISystemPlugin;
|
|
8
|
-
uiSystem.defaultSoundPress = new Sound([.5,0,220]);
|
|
9
|
-
uiSystem.defaultSoundClick = new Sound([.5,0,440]);
|
|
10
|
-
uiSystem.defaultCornerRadius = 20;
|
|
11
|
-
uiSystem.defaultGradientColor = WHITE;
|
|
12
|
-
uiSystem.defaultShadowColor = BLACK;
|
|
13
|
-
canvasClearColor = hsl(.9,.3,.2);
|
|
14
|
-
|
|
15
|
-
// setup music player UI
|
|
16
|
-
const center = mainCanvasSize.scale(.5);
|
|
17
|
-
musicPlayer = new UIObject(center, vec2(500, 300));
|
|
18
|
-
const title = new UIText(vec2(0, -100), vec2(500, 40),
|
|
19
|
-
'LittleJS Music Player');
|
|
20
|
-
musicPlayer.addChild(title);
|
|
21
|
-
|
|
22
|
-
// drop zone text
|
|
23
|
-
const dropZoneText = new UIText(vec2(0, -60), vec2(450, 20),
|
|
24
|
-
'Drag & Drop Audio Files Here!');
|
|
25
|
-
dropZoneText.textColor = GRAY;
|
|
26
|
-
musicPlayer.addChild(dropZoneText);
|
|
27
|
-
|
|
28
|
-
// volume slider
|
|
29
|
-
const volumeSlider = new UISlider(vec2(0, -20), vec2(400, 30),
|
|
30
|
-
musicVolume, 'Music Volume');
|
|
31
|
-
volumeSlider.fillMode = true;
|
|
32
|
-
musicPlayer.addChild(volumeSlider);
|
|
33
|
-
volumeSlider.onChange = ()=>
|
|
34
|
-
{
|
|
35
|
-
musicVolume = volumeSlider.value;
|
|
36
|
-
musicInstance?.setVolume(musicVolume);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
// play button
|
|
40
|
-
playButton = new UIButton(vec2(-90, 50), vec2(140, 50), 'Play');
|
|
41
|
-
musicPlayer.addChild(playButton);
|
|
42
|
-
playButton.onClick = ()=>
|
|
43
|
-
{
|
|
44
|
-
if (!musicSound.isLoaded())
|
|
45
|
-
return;
|
|
46
|
-
|
|
47
|
-
// handle play/pause toggle
|
|
48
|
-
if (!musicInstance)
|
|
49
|
-
musicInstance = musicSound.playMusic(musicVolume);
|
|
50
|
-
else if (musicInstance.isPaused())
|
|
51
|
-
musicInstance.resume();
|
|
52
|
-
else
|
|
53
|
-
musicInstance.pause();
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
// stop button
|
|
57
|
-
stopButton = new UIButton(vec2(90, 50), vec2(140, 50), 'Stop');
|
|
58
|
-
stopButton.onClick = ()=> musicInstance?.stop();
|
|
59
|
-
musicPlayer.addChild(stopButton);
|
|
60
|
-
|
|
61
|
-
// progress bar and slider for seeking
|
|
62
|
-
progressBar = new UISlider(vec2(0, 120), vec2(400, 30), 0);
|
|
63
|
-
progressBar.disabledColor = RED;
|
|
64
|
-
progressBar.onChange = ()=>
|
|
65
|
-
{
|
|
66
|
-
// control music seek position
|
|
67
|
-
const wasPlaying = musicInstance?.isPlaying();
|
|
68
|
-
if (!musicInstance)
|
|
69
|
-
musicInstance = musicSound.playMusic(musicVolume, 1, 1);
|
|
70
|
-
progressBar.value = min(progressBar.value, .999); // prevent wrap
|
|
71
|
-
const seekTime = progressBar.value * musicSound.getDuration();
|
|
72
|
-
musicInstance.start(seekTime);
|
|
73
|
-
if (!wasPlaying)
|
|
74
|
-
musicInstance.pause();
|
|
75
|
-
};
|
|
76
|
-
musicPlayer.addChild(progressBar);
|
|
77
|
-
|
|
78
|
-
{
|
|
79
|
-
// setup drag and drop for audio files
|
|
80
|
-
function onDragEnter() { musicPlayer.color = RED; };
|
|
81
|
-
function onDragLeave() { musicPlayer.color = WHITE; };
|
|
82
|
-
function onDrop(e)
|
|
83
|
-
{
|
|
84
|
-
musicPlayer.color = WHITE
|
|
85
|
-
|
|
86
|
-
// get the dropped file
|
|
87
|
-
const file = e.dataTransfer.files[0];
|
|
88
|
-
if (!file || !file.type.startsWith('audio'))
|
|
89
|
-
return;
|
|
90
|
-
|
|
91
|
-
// create new sound from dropped file
|
|
92
|
-
const fileURL = URL.createObjectURL(file);
|
|
93
|
-
musicSound = new Sound(fileURL, musicVolume);
|
|
94
|
-
dropZoneText.text = file.name;
|
|
95
|
-
|
|
96
|
-
// reset UI
|
|
97
|
-
musicInstance?.stop();
|
|
98
|
-
musicInstance = undefined;
|
|
99
|
-
progressBar.value = 0;
|
|
100
|
-
}
|
|
101
|
-
uiSystem.setupDragAndDrop(onDrop, onDragEnter, onDragLeave);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function gameUpdate()
|
|
106
|
-
{
|
|
107
|
-
// disable buttons while loading
|
|
108
|
-
const isDisabled = !musicSound || !musicSound.isLoaded();
|
|
109
|
-
playButton.disabled = isDisabled
|
|
110
|
-
stopButton.disabled = isDisabled
|
|
111
|
-
progressBar.disabled = isDisabled
|
|
112
|
-
|
|
113
|
-
// update ui
|
|
114
|
-
if (!musicSound)
|
|
115
|
-
{
|
|
116
|
-
// waiting for file
|
|
117
|
-
progressBar.text = 'No File Loaded';
|
|
118
|
-
}
|
|
119
|
-
else if (isDisabled)
|
|
120
|
-
{
|
|
121
|
-
// update loading progress
|
|
122
|
-
const loadingPercent = musicSound.loadedPercent * 100|0;
|
|
123
|
-
progressBar.text = `Loading: ${loadingPercent}%`;
|
|
124
|
-
}
|
|
125
|
-
else
|
|
126
|
-
{
|
|
127
|
-
// update ui text
|
|
128
|
-
const isPlaying = musicInstance?.isPlaying();
|
|
129
|
-
playButton.text = isPlaying ? 'Pause' : 'Play';
|
|
130
|
-
const current = musicInstance?.getCurrentTime() || 0;
|
|
131
|
-
const duration = musicSound.getDuration();
|
|
132
|
-
progressBar.text = formatTime(current) +
|
|
133
|
-
' / ' + formatTime(duration);
|
|
134
|
-
if (!progressBar.isActiveObject())
|
|
135
|
-
progressBar.value = current / duration;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
function gameRender()
|
|
2
|
-
{
|
|
3
|
-
const nineSliceTile = tile(16);
|
|
4
|
-
const threeSliceTile = tile(19);
|
|
5
|
-
|
|
6
|
-
{
|
|
7
|
-
// draw nine slice with thin border and color
|
|
8
|
-
const pos = vec2(-7,4);
|
|
9
|
-
const size = vec2(11+oscillate(.5,2), 6);
|
|
10
|
-
const color = hsl(.1,.5,.9);
|
|
11
|
-
const border = .5;
|
|
12
|
-
drawNineSlice(pos, size, nineSliceTile, color, border);
|
|
13
|
-
drawText('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 + oscillate(.2)*2;
|
|
29
|
-
const additive = hsl(time/30,.5,.5);
|
|
30
|
-
drawThreeSlice(pos, size, threeSliceTile, WHITE, border, additive);
|
|
31
|
-
drawText('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-oscillate(.3,90),120+oscillate(.3,60));
|
|
37
|
-
drawThreeSliceScreen(pos, size, threeSliceTile);
|
|
38
|
-
drawTextScreen('Three Slice\nScreen Space', pos, 30, BLACK);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
function gameInit()
|
|
2
|
-
{
|
|
3
|
-
// create parallax layers
|
|
4
|
-
const levelColor = hsl(rand(), .5, .5);
|
|
5
|
-
for (let i=3; i--;)
|
|
6
|
-
{
|
|
7
|
-
const topColor = levelColor.mutate(.3);
|
|
8
|
-
const bottomColor = levelColor.subtract(CLEAR_WHITE).mutate(.3);
|
|
9
|
-
new ParallaxLayer(topColor, bottomColor, i);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
class ParallaxLayer extends CanvasLayer
|
|
14
|
-
{
|
|
15
|
-
constructor(topColor, bottomColor, depth)
|
|
16
|
-
{
|
|
17
|
-
const renderOrder = depth;
|
|
18
|
-
const canvasSize = vec2(512, 256);
|
|
19
|
-
super(vec2(), vec2(), 0, renderOrder, canvasSize);
|
|
20
|
-
this.depth = depth;
|
|
21
|
-
|
|
22
|
-
// create a gradient for the mountains
|
|
23
|
-
const w = canvasSize.x, h = canvasSize.y;
|
|
24
|
-
for (let i = h; i--;)
|
|
25
|
-
{
|
|
26
|
-
// draw a 1 pixel gradient line on the left side
|
|
27
|
-
const p = i/h;
|
|
28
|
-
this.context.fillStyle = topColor.lerp(bottomColor, p);
|
|
29
|
-
this.context.fillRect(0, i, 1, 1);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// draw random mountains
|
|
33
|
-
const pointiness = .2; // how pointy the mountains are
|
|
34
|
-
const levelness = .005; // how much the mountains level out
|
|
35
|
-
const slopeRange = 1; // max slope of the mountains
|
|
36
|
-
const startGroundLevel = h/2;
|
|
37
|
-
let y = startGroundLevel;
|
|
38
|
-
let groundSlope = rand(-slopeRange, slopeRange);
|
|
39
|
-
for (let x=w; x--;)
|
|
40
|
-
{
|
|
41
|
-
// pull slope towards start ground level
|
|
42
|
-
y += groundSlope -= (y-startGroundLevel)*levelness;
|
|
43
|
-
|
|
44
|
-
// randomly change slope
|
|
45
|
-
if (rand() < pointiness)
|
|
46
|
-
groundSlope = rand(-slopeRange, slopeRange);
|
|
47
|
-
|
|
48
|
-
// draw 1 pixel wide vertical slice of mountain
|
|
49
|
-
this.context.drawImage(this.canvas, 0,0,1,h,x,y,1,h-y);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// remove gradient sliver from left side
|
|
53
|
-
this.context.clearRect(0,0,1,h);
|
|
54
|
-
|
|
55
|
-
// make WebGL texture
|
|
56
|
-
this.updateWebGL();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
render()
|
|
60
|
-
{
|
|
61
|
-
const canvasSize = vec2(this.canvas.width, this.canvas.height);
|
|
62
|
-
const viewerPos = mousePos;
|
|
63
|
-
const depth = this.depth
|
|
64
|
-
const distance = 3 + depth;
|
|
65
|
-
const parallax = vec2(.2, .05).scale(depth**2+1);
|
|
66
|
-
const cameraDeltaFromCenter = viewerPos.multiply(parallax);
|
|
67
|
-
const positionOffset = vec2(0, 4-depth*3);
|
|
68
|
-
this.pos = cameraDeltaFromCenter.add(positionOffset)
|
|
69
|
-
this.size = canvasSize.scale(distance/cameraScale);
|
|
70
|
-
super.render();
|
|
71
|
-
}
|
|
72
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
function gameInit()
|
|
2
|
-
{
|
|
3
|
-
gravity.y = -.01; // set default gravity
|
|
4
|
-
|
|
5
|
-
// fire
|
|
6
|
-
new ParticleEmitter(
|
|
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
|
-
);
|
|
16
|
-
|
|
17
|
-
// smoke
|
|
18
|
-
new ParticleEmitter(
|
|
19
|
-
vec2(5,-2), 0, // pos, angle
|
|
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
|
-
);
|
|
28
|
-
}
|
package/examples/shorts/piano.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
const pianoSound = new Sound([,0,220,,9]);
|
|
2
|
-
|
|
3
|
-
class PianoKey extends UIButton
|
|
4
|
-
{
|
|
5
|
-
constructor(pos, size, semitone, color, hoverColor)
|
|
6
|
-
{
|
|
7
|
-
const keySize = 65;
|
|
8
|
-
size = size.scale(keySize);
|
|
9
|
-
pos = pos.scale(keySize).add(vec2(0,size.y/2-keySize*2));
|
|
10
|
-
pos = pos.add(mainCanvasSize.scale(.5));
|
|
11
|
-
super(pos, size, '', color);
|
|
12
|
-
|
|
13
|
-
this.dragActivate = true;
|
|
14
|
-
this.semitone = semitone;
|
|
15
|
-
this.hoverColor = hoverColor;
|
|
16
|
-
this.activeColor = RED;
|
|
17
|
-
}
|
|
18
|
-
onPress() { this.sound = pianoSound.playNote(this.semitone); }
|
|
19
|
-
onRelease() { this.sound.stop(.2); }
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function gameInit()
|
|
23
|
-
{
|
|
24
|
-
// initialize UI system
|
|
25
|
-
new UISystemPlugin;
|
|
26
|
-
|
|
27
|
-
// create piano keyboard
|
|
28
|
-
for (let i=15; i--;)
|
|
29
|
-
{
|
|
30
|
-
// white keys
|
|
31
|
-
const pos = vec2(i-7, 0);
|
|
32
|
-
const size = vec2(1, 4);
|
|
33
|
-
const semitone = [0,2,4,5,7,9,11][i%7]+(i/7|0)*12;
|
|
34
|
-
new PianoKey(pos, size, semitone, WHITE, hsl(0,1,.9));
|
|
35
|
-
}
|
|
36
|
-
for (let i=10; i--;)
|
|
37
|
-
{
|
|
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);
|
|
41
|
-
const semitone = [1,3,6,8,10][i%5]+(i/5|0)*12;
|
|
42
|
-
new PianoKey(pos, size, semitone, hsl(0,0,.3), hsl(0,1,.3));
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
class Player extends EngineObject
|
|
2
|
-
{
|
|
3
|
-
constructor(pos)
|
|
4
|
-
{
|
|
5
|
-
super(pos, vec2(2,4), 0, 0, RED);
|
|
6
|
-
this.setCollision(); // make object collide
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
update()
|
|
10
|
-
{
|
|
11
|
-
// apply movement controls
|
|
12
|
-
const moveInput = keyDirection();
|
|
13
|
-
this.velocity.x += moveInput.x * (this.groundObject ? .1: .01);
|
|
14
|
-
if (this.groundObject && moveInput.y > 0)
|
|
15
|
-
this.velocity.y = .9; // jump
|
|
16
|
-
|
|
17
|
-
// move camera with player
|
|
18
|
-
cameraPos = vec2(this.pos.x, 9);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function gameInit()
|
|
23
|
-
{
|
|
24
|
-
// setup level
|
|
25
|
-
gravity.y = -.05;
|
|
26
|
-
new Player(vec2(5,6));
|
|
27
|
-
canvasClearColor = hsl(.6,.3,.5);
|
|
28
|
-
|
|
29
|
-
// create tile layer
|
|
30
|
-
const pos = vec2();
|
|
31
|
-
const tileLayer = new TileCollisionLayer(pos, vec2(256));
|
|
32
|
-
for (pos.x = tileLayer.size.x; pos.x--;)
|
|
33
|
-
for (pos.y = tileLayer.size.y; pos.y--;)
|
|
34
|
-
{
|
|
35
|
-
// check if tile should be solid
|
|
36
|
-
const levelHeight = pos.x<9 ? 2 : (pos.x/4|0)**3.1%7;
|
|
37
|
-
if (pos.y > levelHeight)
|
|
38
|
-
continue;
|
|
39
|
-
|
|
40
|
-
// set tile data
|
|
41
|
-
tileLayer.setData(pos, new TileLayerData(1));
|
|
42
|
-
tileLayer.setCollisionData(pos);
|
|
43
|
-
}
|
|
44
|
-
tileLayer.redraw(); // redraw tile layer with new data
|
|
45
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
let paddle, ball;
|
|
2
|
-
|
|
3
|
-
class PhysicsObject extends EngineObject
|
|
4
|
-
{
|
|
5
|
-
constructor(pos, size)
|
|
6
|
-
{
|
|
7
|
-
super(pos, size); // set object position and size
|
|
8
|
-
this.setCollision(); // make object collide
|
|
9
|
-
this.mass = 0; // make object have static physics
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function gameInit()
|
|
14
|
-
{
|
|
15
|
-
// setup level
|
|
16
|
-
const levelSize = vec2(38, 21); // size of play area
|
|
17
|
-
cameraPos = levelSize.scale(.5); // center camera in level
|
|
18
|
-
canvasFixedSize = vec2(1280, 720); // use a 720p fixed size canvas
|
|
19
|
-
|
|
20
|
-
// create objects
|
|
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
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function gameUpdate()
|
|
30
|
-
{
|
|
31
|
-
if (!ball || ball.pos.y < -1) // spawn ball
|
|
32
|
-
{
|
|
33
|
-
ball && ball.destroy(); // destroy old ball
|
|
34
|
-
ball = new PhysicsObject(cameraPos); // create a ball
|
|
35
|
-
ball.velocity = vec2(.2); // give ball some movement
|
|
36
|
-
ball.restitution = 1; // make ball bounce
|
|
37
|
-
ball.mass = 1; // make ball have dynamic physics
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
paddle.pos.x = mousePos.x; // move paddle to mouse
|
|
41
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
function gameInit()
|
|
2
|
-
{
|
|
3
|
-
new PostProcessPlugin(tvShader);
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
function gameRender()
|
|
7
|
-
{
|
|
8
|
-
drawRect(vec2(), vec2(99), GRAY);
|
|
9
|
-
drawTile(vec2(sin(time)*3, 0), vec2(12), tile(3,128));
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const tvShader = `
|
|
13
|
-
// Simple TV Shader Code
|
|
14
|
-
float hash(vec2 p)
|
|
15
|
-
{
|
|
16
|
-
p=fract(p*.3197);
|
|
17
|
-
return fract(1.+sin(51.*p.x+73.*p.y)*13753.3);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
void mainImage(out vec4 c, vec2 p)
|
|
21
|
-
{
|
|
22
|
-
// setup the shader
|
|
23
|
-
vec2 uv = p;
|
|
24
|
-
p /= iResolution.xy;
|
|
25
|
-
c = texture(iChannel0, p);
|
|
26
|
-
|
|
27
|
-
// static noise
|
|
28
|
-
const float staticAlpha = .1;
|
|
29
|
-
const float staticScale = .002;
|
|
30
|
-
c += staticAlpha * hash(floor(p/staticScale) + mod(iTime*500., 1e3));
|
|
31
|
-
|
|
32
|
-
// scan lines
|
|
33
|
-
const float scanlineScale = 2.;
|
|
34
|
-
const float scanlineAlpha = .5;
|
|
35
|
-
c *= 1. - scanlineAlpha*cos(p.y*2.*iResolution.y/scanlineScale);
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
// bloom effect
|
|
39
|
-
const float blurSize = .002;
|
|
40
|
-
const float bloomIntensity = .2;
|
|
41
|
-
|
|
42
|
-
// 5-tap Gaussian blur
|
|
43
|
-
vec4 bloom = vec4(0);
|
|
44
|
-
bloom += texture(iChannel0, p + vec2(-2.*blurSize, 0)) * .12;
|
|
45
|
-
bloom += texture(iChannel0, p + vec2( -blurSize, 0)) * .24;
|
|
46
|
-
bloom += texture(iChannel0, p) * .28;
|
|
47
|
-
bloom += texture(iChannel0, p + vec2( blurSize, 0)) * .24;
|
|
48
|
-
bloom += texture(iChannel0, p + vec2( 2.*blurSize, 0)) * .12;
|
|
49
|
-
bloom += texture(iChannel0, p + vec2(0, -2.*blurSize)) * .12;
|
|
50
|
-
bloom += texture(iChannel0, p + vec2(0, -blurSize)) * .24;
|
|
51
|
-
bloom += texture(iChannel0, p) * .28;
|
|
52
|
-
bloom += texture(iChannel0, p + vec2(0, blurSize)) * .24;
|
|
53
|
-
bloom += texture(iChannel0, p + vec2(0, 2.*blurSize)) * .12;
|
|
54
|
-
c += bloom * bloomIntensity;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// black vignette around edges
|
|
58
|
-
const float vignette = 2.;
|
|
59
|
-
const float vignettePow = 6.;
|
|
60
|
-
float dx = 2.*p.x-1., dy = 2.*p.y-1.;
|
|
61
|
-
c *= 1.-pow((dx*dx + dy*dy)/vignette, vignettePow);
|
|
62
|
-
}`;
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
const stepCount = 8, trackCount = 12, sequencer = [];
|
|
2
|
-
let currentStep = 0, stepTime = 0, tempo = 240;
|
|
3
|
-
let isPlaying = false, eraseMode = false;
|
|
4
|
-
|
|
5
|
-
// sound sequencer instruments
|
|
6
|
-
const sound_piano = new Sound([.3,0,220,,.1]);
|
|
7
|
-
const sound_drumKick = new Sound([,,99,,,.02,,,,,,,,2]);
|
|
8
|
-
const sound_drumHat = new Sound([,,1e3,,,.01,4,,,,,,,,,,,,,,4e3]);
|
|
9
|
-
|
|
10
|
-
// musical note scales
|
|
11
|
-
const majorScale = [0,2,4,5,7,9,11];
|
|
12
|
-
const minorScale = [0,2,3,5,7,8,10];
|
|
13
|
-
const pentatonicScale = [0,3,5,7,10];
|
|
14
|
-
const scale = majorScale;
|
|
15
|
-
|
|
16
|
-
class UISequencerButton extends UIButton
|
|
17
|
-
{
|
|
18
|
-
constructor(step, track)
|
|
19
|
-
{
|
|
20
|
-
const size = vec2(68, 35);
|
|
21
|
-
let pos = vec2(step, trackCount-1-track);
|
|
22
|
-
pos = pos.multiply(size);
|
|
23
|
-
pos = pos.add(vec2(240, 40));
|
|
24
|
-
super(pos, size);
|
|
25
|
-
|
|
26
|
-
this.step = step;
|
|
27
|
-
this.track = track;
|
|
28
|
-
this.cornerRadius = 0;
|
|
29
|
-
this.dragActivate = true;
|
|
30
|
-
this.isOn = false;
|
|
31
|
-
this.shadowColor = CLEAR_BLACK;
|
|
32
|
-
|
|
33
|
-
// set instrument and color based on track
|
|
34
|
-
const pianoStart = 2;
|
|
35
|
-
this.hue = track*.15;
|
|
36
|
-
if (track >= pianoStart)
|
|
37
|
-
{
|
|
38
|
-
const octave = floor((track-pianoStart) / scale.length);
|
|
39
|
-
const scaleNote = (track-pianoStart) % scale.length;
|
|
40
|
-
this.semitone = scale[scaleNote] + 12*octave;
|
|
41
|
-
this.sound = sound_piano;
|
|
42
|
-
this.hue = .6 - scaleNote/40 + octave*.2;
|
|
43
|
-
}
|
|
44
|
-
else
|
|
45
|
-
this.sound = [sound_drumKick, sound_drumHat][track];
|
|
46
|
-
}
|
|
47
|
-
onPress()
|
|
48
|
-
{
|
|
49
|
-
// set the button on/off and update sequencer table
|
|
50
|
-
if (mouseWasPressed(0))
|
|
51
|
-
eraseMode = this.isOn;
|
|
52
|
-
this.isOn = !eraseMode;
|
|
53
|
-
eraseMode || this.playSound();
|
|
54
|
-
const index = this.step + this.track*stepCount;
|
|
55
|
-
sequencer[index] = eraseMode ? 0 : this;
|
|
56
|
-
}
|
|
57
|
-
render()
|
|
58
|
-
{
|
|
59
|
-
this.activeColor = eraseMode ? RED : WHITE;
|
|
60
|
-
this.color = this.isActiveObject() ? BLACK :
|
|
61
|
-
hsl(this.hue, this.isOn ? 1 : .5, this.isOn ? .5 : .15);
|
|
62
|
-
if (isPlaying && this.step == currentStep)
|
|
63
|
-
this.color = this.color.lerp(WHITE, .5);
|
|
64
|
-
super.render();
|
|
65
|
-
}
|
|
66
|
-
playSound() { this.sound.playNote(this.semitone); }
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function gameInit()
|
|
70
|
-
{
|
|
71
|
-
// initialize UI system
|
|
72
|
-
new UISystemPlugin;
|
|
73
|
-
uiSystem.defaultCornerRadius = 8;
|
|
74
|
-
uiSystem.defaultShadowColor = BLACK;
|
|
75
|
-
canvasClearColor = GRAY;
|
|
76
|
-
|
|
77
|
-
// create sequencer buttons
|
|
78
|
-
for (let step=stepCount; step--;)
|
|
79
|
-
for (let track=trackCount; track--;)
|
|
80
|
-
new UISequencerButton(step, track);
|
|
81
|
-
|
|
82
|
-
// create play/stop button
|
|
83
|
-
const playButton = new UIButton(vec2(660,500), vec2(180,60), 'PLAY');
|
|
84
|
-
playButton.onClick = ()=>
|
|
85
|
-
{
|
|
86
|
-
isPlaying = !isPlaying;
|
|
87
|
-
currentStep = stepTime = 0;
|
|
88
|
-
playButton.text = isPlaying ? 'STOP' : 'PLAY';
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
// create tempo slider
|
|
92
|
-
const minTempo = 120, maxTempo = 480;
|
|
93
|
-
const tempoPercent = percent(tempo, minTempo, maxTempo);
|
|
94
|
-
const tempoSlider = new UISlider(vec2(380,500), vec2(340,40), tempoPercent);
|
|
95
|
-
tempoSlider.onChange = ()=>
|
|
96
|
-
{
|
|
97
|
-
tempo = lerp(minTempo, maxTempo, tempoSlider.value);
|
|
98
|
-
tempo = floor(tempo/10) * 10; // round to nearest 10th
|
|
99
|
-
tempoSlider.text = `${tempo} BPM`;
|
|
100
|
-
};
|
|
101
|
-
tempoSlider.onChange();
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function gameUpdate()
|
|
105
|
-
{
|
|
106
|
-
if (!isPlaying)
|
|
107
|
-
return;
|
|
108
|
-
|
|
109
|
-
// update step time based on tempo
|
|
110
|
-
const lastStepTime = stepTime;
|
|
111
|
-
const lastStep = currentStep;
|
|
112
|
-
stepTime += timeDelta*tempo/60;
|
|
113
|
-
currentStep = floor(stepTime) % stepCount;
|
|
114
|
-
if (currentStep == lastStep && lastStepTime)
|
|
115
|
-
return;
|
|
116
|
-
|
|
117
|
-
// play sounds when step changes
|
|
118
|
-
for (let i=trackCount; i--;)
|
|
119
|
-
{
|
|
120
|
-
const index = currentStep + i*stepCount;
|
|
121
|
-
const noteButton = sequencer[index];
|
|
122
|
-
noteButton && noteButton.playSound();
|
|
123
|
-
}
|
|
124
|
-
}
|