littlejsengine 1.18.4 → 1.18.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/COPYRIGHT.txt +38 -0
  2. package/FAQ.md +633 -0
  3. package/README.md +19 -1
  4. package/dist/littlejs.d.ts +349 -54
  5. package/dist/littlejs.esm.js +1469 -448
  6. package/dist/littlejs.esm.min.js +1 -1
  7. package/dist/littlejs.js +1438 -436
  8. package/dist/littlejs.min.js +1 -1
  9. package/dist/littlejs.release.js +1438 -436
  10. package/package.json +8 -1
  11. package/plugins/box2d.js +32 -7
  12. package/{src/engineMedals.js → plugins/medalSystem.js} +248 -196
  13. package/plugins/pathFinder.js +758 -0
  14. package/plugins/pluginExport.js +19 -0
  15. package/plugins/tween.js +1 -1
  16. package/plugins/tweenSystem.js +509 -0
  17. package/plugins/uiSystem.js +150 -11
  18. package/src/engine.js +2 -141
  19. package/src/engineAudio.js +8 -5
  20. package/src/engineBuild.mjs +4 -2
  21. package/src/engineDebug.js +1 -1
  22. package/src/engineDraw.js +21 -3
  23. package/src/engineExport.js +12 -12
  24. package/src/engineInput.js +1 -1
  25. package/src/engineLogo.js +146 -0
  26. package/src/engineMath.js +10 -3
  27. package/src/engineObject.js +11 -5
  28. package/src/engineParticles.js +6 -3
  29. package/src/engineRelease.js +1 -1
  30. package/src/engineSettings.js +0 -47
  31. package/src/engineUtilities.js +7 -2
  32. package/src/engineWebGL.js +34 -7
  33. package/src/jsconfig.json +3 -1
  34. package/.github/workflows/test.yml +0 -17
  35. package/AI.md +0 -173
  36. package/CLAUDE.md +0 -1
  37. package/examples/box2d/game.js +0 -192
  38. package/examples/box2d/gameObjects.js +0 -564
  39. package/examples/box2d/index.html +0 -9
  40. package/examples/box2d/scenes.js +0 -194
  41. package/examples/box2d/tiles.png +0 -0
  42. package/examples/breakout/game.js +0 -175
  43. package/examples/breakout/gameObjects.js +0 -147
  44. package/examples/breakout/index.html +0 -8
  45. package/examples/breakout/tiles.png +0 -0
  46. package/examples/breakoutTutorial/README.md +0 -521
  47. package/examples/breakoutTutorial/game.js +0 -191
  48. package/examples/breakoutTutorial/images/1.png +0 -0
  49. package/examples/breakoutTutorial/images/10.png +0 -0
  50. package/examples/breakoutTutorial/images/11.png +0 -0
  51. package/examples/breakoutTutorial/images/2.png +0 -0
  52. package/examples/breakoutTutorial/images/3.png +0 -0
  53. package/examples/breakoutTutorial/images/4.png +0 -0
  54. package/examples/breakoutTutorial/images/5.png +0 -0
  55. package/examples/breakoutTutorial/images/6.png +0 -0
  56. package/examples/breakoutTutorial/images/7.png +0 -0
  57. package/examples/breakoutTutorial/images/8.png +0 -0
  58. package/examples/breakoutTutorial/images/9.png +0 -0
  59. package/examples/breakoutTutorial/index.html +0 -8
  60. package/examples/electron/build.mjs +0 -127
  61. package/examples/electron/electron.js +0 -35
  62. package/examples/electron/game.js +0 -54
  63. package/examples/electron/index.html +0 -13
  64. package/examples/electron/package.json +0 -5
  65. package/examples/electron/tiles.png +0 -0
  66. package/examples/empty/game.js +0 -51
  67. package/examples/empty/index.html +0 -5
  68. package/examples/empty/tiles.png +0 -0
  69. package/examples/favicon.png +0 -0
  70. package/examples/games.jpg +0 -0
  71. package/examples/htmlMenu/game.js +0 -82
  72. package/examples/htmlMenu/index.html +0 -45
  73. package/examples/htmlMenu/tiles.png +0 -0
  74. package/examples/index.html +0 -62
  75. package/examples/logo.png +0 -0
  76. package/examples/logo2.png +0 -0
  77. package/examples/module/build.mjs +0 -124
  78. package/examples/module/game.js +0 -132
  79. package/examples/module/index.html +0 -10
  80. package/examples/module/tiles.png +0 -0
  81. package/examples/particles/index.html +0 -426
  82. package/examples/particles/tiles.png +0 -0
  83. package/examples/platformer/data/gameLevelData.tmx +0 -143
  84. package/examples/platformer/data/gameLevelData.tsx +0 -4
  85. package/examples/platformer/game.js +0 -147
  86. package/examples/platformer/gameCharacter.js +0 -309
  87. package/examples/platformer/gameEffects.js +0 -278
  88. package/examples/platformer/gameLevel.js +0 -205
  89. package/examples/platformer/gameLevelData.json +0 -171
  90. package/examples/platformer/gameObjects.js +0 -378
  91. package/examples/platformer/gamePlayer.js +0 -35
  92. package/examples/platformer/index.html +0 -9
  93. package/examples/platformer/tiles.png +0 -0
  94. package/examples/platformer/tilesLevel.png +0 -0
  95. package/examples/puzzle/game.js +0 -331
  96. package/examples/puzzle/index.html +0 -8
  97. package/examples/puzzle/tiles.png +0 -0
  98. package/examples/screenshot.jpg +0 -0
  99. package/examples/shorts/animation.js +0 -18
  100. package/examples/shorts/base.html +0 -54
  101. package/examples/shorts/blending.js +0 -14
  102. package/examples/shorts/box2d.js +0 -51
  103. package/examples/shorts/box2dCar.js +0 -59
  104. package/examples/shorts/box2dPool.js +0 -107
  105. package/examples/shorts/box2dTileLayer.js +0 -48
  106. package/examples/shorts/cameraDrag.js +0 -22
  107. package/examples/shorts/clock.js +0 -21
  108. package/examples/shorts/colors.js +0 -25
  109. package/examples/shorts/debugDraw.js +0 -37
  110. package/examples/shorts/empty.js +0 -30
  111. package/examples/shorts/flappyGame.js +0 -55
  112. package/examples/shorts/fontImage.js +0 -17
  113. package/examples/shorts/fps.js +0 -90
  114. package/examples/shorts/helloWorld.js +0 -11
  115. package/examples/shorts/hillGlideGame.js +0 -63
  116. package/examples/shorts/input.js +0 -64
  117. package/examples/shorts/landerGame.js +0 -57
  118. package/examples/shorts/maze.js +0 -48
  119. package/examples/shorts/medals.js +0 -51
  120. package/examples/shorts/music.js +0 -78
  121. package/examples/shorts/musicPlayer.js +0 -137
  122. package/examples/shorts/nineSlice.js +0 -40
  123. package/examples/shorts/parallax.js +0 -72
  124. package/examples/shorts/particles.js +0 -28
  125. package/examples/shorts/piano.js +0 -44
  126. package/examples/shorts/platformer.js +0 -45
  127. package/examples/shorts/pongGame.js +0 -41
  128. package/examples/shorts/postProcess.js +0 -62
  129. package/examples/shorts/sequencer.js +0 -124
  130. package/examples/shorts/shader.js +0 -29
  131. package/examples/shorts/shapes.js +0 -21
  132. package/examples/shorts/slidingPuzzle.js +0 -52
  133. package/examples/shorts/song.mp3 +0 -0
  134. package/examples/shorts/sound.js +0 -36
  135. package/examples/shorts/spaceGame.js +0 -58
  136. package/examples/shorts/spriteAtlas.js +0 -31
  137. package/examples/shorts/starfield.js +0 -15
  138. package/examples/shorts/texture.js +0 -16
  139. package/examples/shorts/textureWrapped.js +0 -12
  140. package/examples/shorts/tileLayer.js +0 -48
  141. package/examples/shorts/tileRaycast.js +0 -39
  142. package/examples/shorts/tiles.png +0 -0
  143. package/examples/shorts/tiltedView.js +0 -63
  144. package/examples/shorts/timers.js +0 -53
  145. package/examples/shorts/topDown.js +0 -38
  146. package/examples/shorts/tween.js +0 -24
  147. package/examples/shorts/uiSystem.js +0 -61
  148. package/examples/shorts/video.webm +0 -0
  149. package/examples/shorts/videoPlayer.js +0 -34
  150. package/examples/shorts.js +0 -743
  151. package/examples/starter/build.bat +0 -7
  152. package/examples/starter/build.mjs +0 -126
  153. package/examples/starter/game.js +0 -137
  154. package/examples/starter/index.html +0 -35
  155. package/examples/starter/tiles.png +0 -0
  156. package/examples/stress/index.html +0 -173
  157. package/examples/style.css +0 -150
  158. package/examples/tweenSystem/game.js +0 -171
  159. package/examples/tweenSystem/index.html +0 -10
  160. package/examples/tweenSystem/tiles.png +0 -0
  161. package/examples/typescript/build.mjs +0 -60
  162. package/examples/typescript/game.js +0 -100
  163. package/examples/typescript/game.ts +0 -132
  164. package/examples/typescript/index.html +0 -10
  165. package/examples/typescript/tiles.png +0 -0
  166. package/examples/typescript/tsconfig.json +0 -17
  167. package/examples/uiSystem/game.js +0 -139
  168. package/examples/uiSystem/index.html +0 -10
  169. package/examples/uiSystem/tiles.png +0 -0
  170. package/jsconfig.json +0 -12
  171. package/plugins/desktop.ini +0 -2
  172. package/reference.md +0 -448
  173. package/test/math.test.mjs +0 -774
  174. package/test/setup.mjs +0 -22
  175. package/test/smoke.test.mjs +0 -274
  176. package/test/tween.test.mjs +0 -576
  177. package/test/util.test.mjs +0 -80
@@ -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
- }
@@ -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
- }