littlejsengine 1.14.5 → 1.14.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/dist/littlejs.d.ts +53 -19
- package/dist/littlejs.esm.js +183 -106
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +179 -104
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +178 -103
- package/examples/box2d/game.js +1 -3
- package/examples/box2d/gameObjects.js +2 -2
- package/examples/htmlMenu/game.js +1 -1
- package/examples/index.html +92 -51
- package/examples/puzzle/game.js +1 -2
- package/examples/shorts/animation.js +2 -2
- package/examples/shorts/box2d.js +1 -0
- package/examples/shorts/box2dCar.js +1 -0
- package/examples/shorts/flappyGame.js +2 -1
- package/examples/shorts/helloWorld.js +2 -2
- package/examples/shorts/hillGlideGame.js +6 -3
- package/examples/shorts/maze.js +1 -0
- package/examples/shorts/medals.js +3 -0
- package/examples/shorts/music.js +3 -5
- package/examples/shorts/piano.js +24 -25
- package/examples/shorts/platformer.js +1 -0
- package/examples/shorts/shapes.js +6 -6
- package/examples/shorts/sound.js +21 -32
- package/examples/shorts/spriteAtlas.js +1 -2
- package/examples/shorts/tileLayer.js +1 -0
- package/examples/shorts/tiltedView.js +1 -1
- package/examples/shorts/timers.js +34 -31
- package/examples/shorts/topDown.js +2 -1
- package/examples/shorts/uiSystem.js +15 -10
- package/examples/stress/index.html +1 -1
- package/examples/uiSystem/game.js +1 -1
- package/package.json +1 -1
- package/plugins/uiSystem.js +83 -58
- package/reference.md +1 -0
- package/src/engine.js +23 -6
- package/src/engineDebug.js +1 -1
- package/src/engineDraw.js +19 -12
- package/src/engineExport.js +4 -2
- package/src/engineInput.js +7 -0
- package/src/engineObject.js +4 -4
- package/src/engineSettings.js +11 -1
- package/src/engineTileLayer.js +2 -2
- package/src/engineUtilities.js +9 -2
- package/src/engineWebGL.js +20 -18
package/examples/box2d/game.js
CHANGED
|
@@ -56,6 +56,7 @@ async function gameInit()
|
|
|
56
56
|
// start up LittleJS Box2D plugin
|
|
57
57
|
await LJS.box2dInit();
|
|
58
58
|
//LJS.box2dSetDebug(true); // enable box2d debug draw
|
|
59
|
+
LJS.setCanvasClearColor(hsl(0,0,.8));
|
|
59
60
|
|
|
60
61
|
// create a table of all sprites
|
|
61
62
|
const gameTile = (i)=> LJS.tile(i, 496, 0, 8);
|
|
@@ -136,9 +137,6 @@ function gameUpdatePost()
|
|
|
136
137
|
///////////////////////////////////////////////////////////////////////////////
|
|
137
138
|
function gameRender()
|
|
138
139
|
{
|
|
139
|
-
// draw a grey square in the background
|
|
140
|
-
LJS.drawRect(vec2(20,8), vec2(100), hsl(0,0,.8));
|
|
141
|
-
|
|
142
140
|
if (Scenes.scene == 5)
|
|
143
141
|
{
|
|
144
142
|
// raycast test
|
|
@@ -18,7 +18,7 @@ const density = 1;
|
|
|
18
18
|
const friction = .5;
|
|
19
19
|
const restitution = .2;
|
|
20
20
|
|
|
21
|
-
export function spawnBox(pos, size=1, color=LJS.WHITE, type=LJS.box2d.bodyTypeDynamic, applyTexture=
|
|
21
|
+
export function spawnBox(pos, size=1, color=LJS.WHITE, type=LJS.box2d.bodyTypeDynamic, applyTexture=false, angle=0)
|
|
22
22
|
{
|
|
23
23
|
size = typeof size === 'number' ? vec2(size) : size; // square
|
|
24
24
|
const o = new LJS.Box2dObject(pos, size, applyTexture && Game.spriteAtlas.squareOutline, angle, color, type);
|
|
@@ -27,7 +27,7 @@ export function spawnBox(pos, size=1, color=LJS.WHITE, type=LJS.box2d.bodyTypeDy
|
|
|
27
27
|
return o;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export function spawnCircle(pos, diameter=1, color=LJS.WHITE, type=LJS.box2d.bodyTypeDynamic, applyTexture=
|
|
30
|
+
export function spawnCircle(pos, diameter=1, color=LJS.WHITE, type=LJS.box2d.bodyTypeDynamic, applyTexture=false, angle=0)
|
|
31
31
|
{
|
|
32
32
|
const size = vec2(diameter);
|
|
33
33
|
const o = new LJS.Box2dObject(pos, size, applyTexture && Game.spriteAtlas.circleOutline, angle, color, type);
|
|
@@ -32,6 +32,7 @@ function gameInit()
|
|
|
32
32
|
button_exitMenu.onclick = function() { setMenuVisible(false); }
|
|
33
33
|
input_test.onchange = function() { alert('New text: ' + this.value); }
|
|
34
34
|
input_rangeTest.onchange = function() { alert('New value: ' + this.value); }
|
|
35
|
+
LJS.setCanvasClearColor(hsl(0,0,.2));
|
|
35
36
|
|
|
36
37
|
// show menu for demo
|
|
37
38
|
setMenuVisible(true);
|
|
@@ -60,7 +61,6 @@ function gameUpdatePost()
|
|
|
60
61
|
function gameRender()
|
|
61
62
|
{
|
|
62
63
|
// test game rendering
|
|
63
|
-
LJS.drawRect(vec2(), vec2(1e3), hsl(0,0,.2));
|
|
64
64
|
for (let i=0; i<1e3; ++i)
|
|
65
65
|
{
|
|
66
66
|
const time = LJS.time;
|
package/examples/index.html
CHANGED
|
@@ -61,58 +61,62 @@ class ExampleInfo
|
|
|
61
61
|
this.filename = filename;
|
|
62
62
|
this.description = description;
|
|
63
63
|
this.largeExample = largeExample;
|
|
64
|
+
this.isHeading = !filename;
|
|
65
|
+
this.text = this.name;
|
|
66
|
+
if (this.description)
|
|
67
|
+
this.text += ' - ' + this.description;
|
|
64
68
|
}
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
const exampleList =
|
|
68
72
|
[
|
|
69
73
|
new ExampleInfo('--- SHORT EXAMPLES ---'),
|
|
70
|
-
new ExampleInfo('Hello World', 'helloWorld.js', 'Minimal starter example
|
|
71
|
-
new ExampleInfo('
|
|
72
|
-
new ExampleInfo('
|
|
73
|
-
new ExampleInfo('
|
|
74
|
-
new ExampleInfo('
|
|
75
|
-
new ExampleInfo('
|
|
76
|
-
new ExampleInfo('
|
|
77
|
-
new ExampleInfo('
|
|
78
|
-
new ExampleInfo('
|
|
79
|
-
new ExampleInfo('
|
|
80
|
-
new ExampleInfo('
|
|
81
|
-
new ExampleInfo('
|
|
82
|
-
new ExampleInfo('
|
|
83
|
-
new ExampleInfo('
|
|
84
|
-
new ExampleInfo('
|
|
85
|
-
new ExampleInfo('
|
|
86
|
-
new ExampleInfo('
|
|
87
|
-
new ExampleInfo('
|
|
88
|
-
new ExampleInfo('
|
|
74
|
+
new ExampleInfo('Hello World', 'helloWorld.js', 'Minimal starter example'),
|
|
75
|
+
new ExampleInfo('Texture', 'texture.js', 'Texture display and manipulation'),
|
|
76
|
+
new ExampleInfo('Animation', 'animation.js', 'Sprite animation system'),
|
|
77
|
+
new ExampleInfo('Shapes', 'shapes.js', 'Draw geometric shapes and primitives'),
|
|
78
|
+
new ExampleInfo('Colors', 'colors.js', 'Color manipulation and HSL'),
|
|
79
|
+
new ExampleInfo('Starfield', 'starfield.js', 'Animated parallax starfield'),
|
|
80
|
+
new ExampleInfo('Sprite Atlas', 'spriteAtlas.js', 'Sprite atlas and tile rendering'),
|
|
81
|
+
new ExampleInfo('Blending', 'blending.js', 'Additive blending and transparency'),
|
|
82
|
+
new ExampleInfo('Tile Layer', 'tileLayer.js', 'Tile layer rendering system'),
|
|
83
|
+
new ExampleInfo('Particles', 'particles.js', 'Particle system'),
|
|
84
|
+
new ExampleInfo('Timers', 'timers.js', 'Timer objects and UI'),
|
|
85
|
+
new ExampleInfo('Sound Effects', 'sound.js', 'ZzFX sound effect generator'),
|
|
86
|
+
new ExampleInfo('Music', 'music.js', 'Music playback and controls'),
|
|
87
|
+
new ExampleInfo('Font Image', 'systemFont.js', 'Bitmap font system with built-in system font'),
|
|
88
|
+
new ExampleInfo('Parallax', 'parallax.js', 'Parallax scrolling mountains'),
|
|
89
|
+
new ExampleInfo('Maze Generator', 'maze.js', 'Procedural maze generation'),
|
|
90
|
+
new ExampleInfo('Medals', 'medals.js', 'Achievement system'),
|
|
91
|
+
new ExampleInfo('Piano', 'piano.js', 'Interactive piano keyboard'),
|
|
92
|
+
new ExampleInfo('Clock', 'clock.js', 'Animated analog clock'),
|
|
89
93
|
new ExampleInfo('--- MINI GAMES ---'),
|
|
90
|
-
new ExampleInfo('
|
|
91
|
-
new ExampleInfo('
|
|
92
|
-
new ExampleInfo('
|
|
93
|
-
new ExampleInfo('
|
|
94
|
-
new ExampleInfo('
|
|
95
|
-
new ExampleInfo('
|
|
96
|
-
new ExampleInfo('Hill Glide Game', 'hillGlideGame.js', 'Tiny wings style
|
|
97
|
-
new ExampleInfo('
|
|
98
|
-
new ExampleInfo('
|
|
99
|
-
new ExampleInfo('Raycasting Game', 'raycasting.js', '
|
|
94
|
+
new ExampleInfo('Pong Game', 'pongGame.js', 'Classic paddle ball bouncing'),
|
|
95
|
+
new ExampleInfo('Platformer Game', 'platformer.js', 'Jump and run side view'),
|
|
96
|
+
new ExampleInfo('Top Down Game', 'topDown.js', 'Top-down style camera'),
|
|
97
|
+
new ExampleInfo('Tilted View Game', 'tiltedView.js', 'Pseudo-3D oblique view'),
|
|
98
|
+
new ExampleInfo('Flappy Game', 'flappyGame.js', 'Flappy bird style game'),
|
|
99
|
+
new ExampleInfo('Lander Game', 'landerGame.js', 'Lunar lander style game'),
|
|
100
|
+
new ExampleInfo('Hill Glide Game', 'hillGlideGame.js', 'Tiny wings style sliding game'),
|
|
101
|
+
new ExampleInfo('Sliding Puzzle', 'slidingPuzzle.js', '15 tile sliding puzzle'),
|
|
102
|
+
new ExampleInfo('Space Game', 'spaceGame.js', 'Spaceship shooter with parallax'),
|
|
103
|
+
new ExampleInfo('Raycasting 3D Game', 'raycasting.js', 'Wolfenstein-style raycasting'),
|
|
100
104
|
new ExampleInfo('--- PLUGINS ---'),
|
|
101
|
-
new ExampleInfo('Box2d Demo', 'box2d.js', 'Box2D physics plugin
|
|
102
|
-
new ExampleInfo('Box2d Car', 'box2dCar.js', 'Drivable car with Box2D
|
|
103
|
-
new ExampleInfo('Post Processing', 'postProcess.js', 'Shader effects and filters
|
|
104
|
-
new ExampleInfo('UI System Plugin', 'uiSystem.js', '
|
|
105
|
-
new ExampleInfo('Nine Slice', 'nineSlice.js', 'Scalable UI
|
|
105
|
+
new ExampleInfo('Box2d Demo', 'box2d.js', 'Box2D physics plugin'),
|
|
106
|
+
new ExampleInfo('Box2d Car', 'box2dCar.js', 'Drivable car with Box2D physics'),
|
|
107
|
+
new ExampleInfo('Post Processing', 'postProcess.js', 'Shader effects and filters'),
|
|
108
|
+
new ExampleInfo('UI System Plugin', 'uiSystem.js', 'Buttons, sliders, and checkboxes'),
|
|
109
|
+
new ExampleInfo('Nine Slice', 'nineSlice.js', 'Scalable UI panels'),
|
|
106
110
|
new ExampleInfo('--- FULL EXAMPLES ---'),
|
|
107
|
-
new ExampleInfo('Starter', 'starter', 'Clean project template
|
|
108
|
-
new ExampleInfo('Breakout Tutorial', 'breakoutTutorial', 'Step-by-step breakout
|
|
109
|
-
new ExampleInfo('Breakout Game', 'breakout', 'Complete breakout
|
|
110
|
-
new ExampleInfo('Platforming Game', 'platformer', 'Full platformer with levels
|
|
111
|
-
new ExampleInfo('Puzzle Game', 'puzzle', 'Match-3 puzzle
|
|
112
|
-
new ExampleInfo('Stress Test', 'stress', 'Performance
|
|
113
|
-
new ExampleInfo('Box2D Plugin', 'box2d', '
|
|
114
|
-
new ExampleInfo('HTML Menus', 'htmlMenu', 'HTML
|
|
115
|
-
new ExampleInfo('UI System Plugin', 'uiSystem', 'Complete UI system demo
|
|
111
|
+
new ExampleInfo('Starter', 'starter', 'Clean project template', true),
|
|
112
|
+
new ExampleInfo('Breakout Tutorial', 'breakoutTutorial', 'Step-by-step breakout tutorial', true),
|
|
113
|
+
new ExampleInfo('Breakout Game', 'breakout', 'Complete breakout game', true),
|
|
114
|
+
new ExampleInfo('Platforming Game', 'platformer', 'Full platformer with levels', true),
|
|
115
|
+
new ExampleInfo('Puzzle Game', 'puzzle', 'Match-3 puzzle game', true),
|
|
116
|
+
new ExampleInfo('Stress Test', 'stress', 'Performance and music test', true),
|
|
117
|
+
new ExampleInfo('Box2D Plugin', 'box2d', 'Full Box2D physics demo', true),
|
|
118
|
+
new ExampleInfo('HTML Menus', 'htmlMenu', 'HTML UI integration', true),
|
|
119
|
+
new ExampleInfo('UI System Plugin', 'uiSystem', 'Complete UI system demo', true),
|
|
116
120
|
];
|
|
117
121
|
|
|
118
122
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -222,7 +226,7 @@ function setExample()
|
|
|
222
226
|
|
|
223
227
|
// load the example
|
|
224
228
|
const example = exampleList[exampleIndex];
|
|
225
|
-
exampleInfo.innerText = example.
|
|
229
|
+
exampleInfo.innerText = example.text;
|
|
226
230
|
const filename = 'examples/' + example.filename;
|
|
227
231
|
exampleLink.href = 'https://github.com/KilledByAPixel/LittleJS/tree/main/' + filename;
|
|
228
232
|
exampleLink.innerText = 'View code on GitHub';
|
|
@@ -300,16 +304,48 @@ function filterExamples(reset=0)
|
|
|
300
304
|
|
|
301
305
|
// filter and add matching examples
|
|
302
306
|
const searchTerm = inputSearch.value.toLowerCase().trim();
|
|
307
|
+
|
|
308
|
+
// first pass: find which examples match
|
|
309
|
+
const matchingIndices = [];
|
|
303
310
|
for (let i = 0; i < exampleList.length; i++)
|
|
304
311
|
{
|
|
305
|
-
// check if search term matches name or description
|
|
306
312
|
const example = exampleList[i];
|
|
307
|
-
|
|
313
|
+
if (!example.filename)
|
|
314
|
+
continue;
|
|
315
|
+
|
|
316
|
+
// Check if search term matches name or description
|
|
308
317
|
if (example.name.toLowerCase().includes(searchTerm) ||
|
|
309
318
|
example.description.toLowerCase().includes(searchTerm))
|
|
319
|
+
matchingIndices.push(i);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// second pass: add headings and matching examples
|
|
323
|
+
let lastHeadingIndex = -1;
|
|
324
|
+
for (let i = 0; i < exampleList.length; i++)
|
|
325
|
+
{
|
|
326
|
+
const example = exampleList[i];
|
|
327
|
+
if (example.isHeading)
|
|
328
|
+
{
|
|
329
|
+
// check if there are any matches between this and the next
|
|
330
|
+
for (let j = i + 1; j < exampleList.length; j++)
|
|
331
|
+
{
|
|
332
|
+
if (exampleList[j].isHeading)
|
|
333
|
+
break; // hit next heading
|
|
334
|
+
if (matchingIndices.includes(j))
|
|
335
|
+
{
|
|
336
|
+
// only add heading if there are matches under it
|
|
337
|
+
lastHeadingIndex = i;
|
|
338
|
+
const o = new Option(example.text);
|
|
339
|
+
o.disabled = true;
|
|
340
|
+
selectExample.add(o);
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
else if (matchingIndices.includes(i))
|
|
310
346
|
{
|
|
311
|
-
|
|
312
|
-
o
|
|
347
|
+
// add matching example
|
|
348
|
+
const o = new Option(example.text);
|
|
313
349
|
o.originalIndex = i;
|
|
314
350
|
selectExample.add(o);
|
|
315
351
|
}
|
|
@@ -317,7 +353,7 @@ function filterExamples(reset=0)
|
|
|
317
353
|
|
|
318
354
|
if (!selectExample.options.length)
|
|
319
355
|
{
|
|
320
|
-
// show a message if no matches
|
|
356
|
+
// show a message if no matches were found
|
|
321
357
|
const o = new Option(`No examples found matching '${searchTerm}'`);
|
|
322
358
|
o.disabled = true;
|
|
323
359
|
selectExample.add(o);
|
|
@@ -387,7 +423,7 @@ function setCode(code, filename)
|
|
|
387
423
|
{
|
|
388
424
|
// try to extract line number from stack trace
|
|
389
425
|
// look for <anonymous> or injectedScript to find user code
|
|
390
|
-
const anonymousMatch = stack
|
|
426
|
+
const anonymousMatch = stack?.match(/(<anonymous>|injectedScript):(\d+)/);
|
|
391
427
|
return anonymousMatch ? parseInt(anonymousMatch[2]) : -1;
|
|
392
428
|
}
|
|
393
429
|
iframeContent.onerror = (message, source, lineno, colno, error) =>
|
|
@@ -484,7 +520,12 @@ function setCode(code, filename)
|
|
|
484
520
|
const errorLine = getErrorLine(error.stack);
|
|
485
521
|
if (errorLine >= 0)
|
|
486
522
|
setErrorLine(errorLine);
|
|
487
|
-
|
|
523
|
+
let message = error;
|
|
524
|
+
if (error.message)
|
|
525
|
+
message = error.message;
|
|
526
|
+
if (error.stack)
|
|
527
|
+
message += '\n' + error.stack;
|
|
528
|
+
setErrorMessage(message);
|
|
488
529
|
throw error;
|
|
489
530
|
})
|
|
490
531
|
.then(()=>
|
package/examples/puzzle/game.js
CHANGED
|
@@ -69,8 +69,7 @@ function gameInit()
|
|
|
69
69
|
{
|
|
70
70
|
// setup canvas
|
|
71
71
|
LJS.setCanvasFixedSize(vec2(1920, 1080)); // 1080p
|
|
72
|
-
LJS.
|
|
73
|
-
|
|
72
|
+
LJS.setCanvasClearColor(backgroundColor);
|
|
74
73
|
// load high score
|
|
75
74
|
bestScore = localStorage[highScoreKey] || 0;
|
|
76
75
|
|
package/examples/shorts/box2d.js
CHANGED
|
@@ -2,7 +2,7 @@ class Wall extends EngineObject
|
|
|
2
2
|
{
|
|
3
3
|
constructor(pos, size)
|
|
4
4
|
{
|
|
5
|
-
super(pos, size, 0, 0, hsl(.
|
|
5
|
+
super(pos, size, 0, 0, hsl(.3,.5,.3));
|
|
6
6
|
this.setCollision(); // make object collide
|
|
7
7
|
}
|
|
8
8
|
update()
|
|
@@ -50,4 +50,5 @@ function gameInit()
|
|
|
50
50
|
new Wall(vec2(14 + i*spacing,y), vec2(3,h));
|
|
51
51
|
}
|
|
52
52
|
new Player(vec2(-7,6));
|
|
53
|
+
canvasClearColor = hsl(.55,1,.8);
|
|
53
54
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
function gameRender()
|
|
2
2
|
{
|
|
3
|
-
// draw background
|
|
4
|
-
|
|
3
|
+
// draw background gradient
|
|
4
|
+
drawRectGradient(cameraPos, getCameraSize(), BLACK, WHITE);
|
|
5
5
|
|
|
6
6
|
// draw text to the overlay canvas
|
|
7
7
|
drawTextOverlay('Hello World', vec2(0,3), 3);
|
|
@@ -40,17 +40,20 @@ function gameInit()
|
|
|
40
40
|
{
|
|
41
41
|
gravity.y = -.01;
|
|
42
42
|
new Player(vec2(0,5));
|
|
43
|
+
canvasClearColor = hsl(.7,1,.8);
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
function gameRender()
|
|
46
47
|
{
|
|
47
48
|
const h = 100, w = 20;
|
|
48
|
-
const pos = vec2(), size = vec2(.2,h), color = WHITE;
|
|
49
|
+
const pos = vec2(), sizeTop = vec2(.4), size = vec2(.2,h), color = WHITE;
|
|
49
50
|
for (let x=cameraPos.x-w; x<cameraPos.x+w; x+=.1)
|
|
50
51
|
{
|
|
51
52
|
pos.x = x;
|
|
52
|
-
pos.y = getGroundHeight(x)
|
|
53
|
-
|
|
53
|
+
pos.y = getGroundHeight(x);
|
|
54
|
+
drawRect(pos, sizeTop, BLACK);
|
|
55
|
+
pos.y -= h/2;
|
|
56
|
+
color.setHSLA(.2+.2*wave(.2,1,x), .7, .5);
|
|
54
57
|
drawRect(pos, size, color);
|
|
55
58
|
}
|
|
56
59
|
}
|
package/examples/shorts/maze.js
CHANGED
package/examples/shorts/music.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
let playButton, stopButton, progressBar;
|
|
2
2
|
let musicSound = new SoundWave('song.mp3');
|
|
3
3
|
let musicVolume = 1;
|
|
4
4
|
let musicInstance;
|
|
5
5
|
|
|
6
|
-
// UI elements
|
|
7
|
-
let playButton, stopButton, progressBar;
|
|
8
|
-
|
|
9
6
|
function gameInit()
|
|
10
7
|
{
|
|
11
|
-
//
|
|
8
|
+
// setup ui system plugin
|
|
12
9
|
new UISystemPlugin;
|
|
13
10
|
uiSystem.defaultSoundPress = new Sound([.5,0,220]);
|
|
14
11
|
uiSystem.defaultSoundClick = new Sound([.5,0,440]);
|
|
15
12
|
uiSystem.defaultCornerRadius = 20;
|
|
13
|
+
canvasClearColor = hsl(.9,.3,.2); // background color
|
|
16
14
|
|
|
17
15
|
// setup music player UI
|
|
18
16
|
const musicPlayer = new UIObject(mainCanvasSize.scale(.5), vec2(500, 300));
|
package/examples/shorts/piano.js
CHANGED
|
@@ -1,51 +1,50 @@
|
|
|
1
|
-
const pianoSound = new Sound([,0,220,,9])
|
|
1
|
+
const pianoSound = new Sound([,0,220,,9]);
|
|
2
2
|
|
|
3
|
-
class PianoKey extends
|
|
3
|
+
class PianoKey extends UIButton
|
|
4
4
|
{
|
|
5
5
|
constructor(pos, size, semitone, isWhite)
|
|
6
6
|
{
|
|
7
|
-
const keySize =
|
|
7
|
+
const keySize = 65;
|
|
8
8
|
size = size.scale(keySize);
|
|
9
|
-
pos = pos.scale(keySize).add(vec2(0,
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
pos = pos.scale(keySize).add(vec2(0,size.y/2-keySize*2));
|
|
10
|
+
pos = pos.add(mainCanvasSize.scale(.5));
|
|
11
|
+
super(pos, size, '', hsl(0,0,isWhite ? 1 : .3));
|
|
12
12
|
this.semitone = semitone;
|
|
13
|
+
this.dragActivate = true;
|
|
14
|
+
this.hoverColor = hsl(0,1,isWhite ? .9 : .3);
|
|
15
|
+
this.activeColor = RED;
|
|
13
16
|
}
|
|
14
|
-
|
|
17
|
+
onPress()
|
|
15
18
|
{
|
|
16
19
|
if (!this.soundInstance)
|
|
17
20
|
this.soundInstance = pianoSound.playNote(this.semitone);
|
|
18
21
|
}
|
|
19
|
-
|
|
22
|
+
onRelease()
|
|
20
23
|
{
|
|
21
24
|
if (this.soundInstance)
|
|
22
25
|
this.soundInstance.stop(.2);
|
|
23
26
|
this.soundInstance = 0;
|
|
24
27
|
}
|
|
25
|
-
render()
|
|
26
|
-
{
|
|
27
|
-
const color = this.soundInstance ? RED : this.color;
|
|
28
|
-
drawRect(this.pos, this.drawSize, color);
|
|
29
|
-
}
|
|
30
28
|
}
|
|
31
29
|
|
|
32
30
|
function gameInit()
|
|
33
31
|
{
|
|
32
|
+
// initialize UI system
|
|
33
|
+
new UISystemPlugin;
|
|
34
|
+
|
|
34
35
|
// create piano keyboard
|
|
35
36
|
for (let i=15; i--;)
|
|
36
|
-
|
|
37
|
+
{
|
|
38
|
+
const pos = vec2(i-7,0);
|
|
39
|
+
const size = vec2(1,4);
|
|
40
|
+
const semitone = [0,2,4,5,7,9,11][i%7]+(i/7|0)*12;
|
|
41
|
+
new PianoKey(pos, size, semitone, true);
|
|
42
|
+
}
|
|
37
43
|
for (let i=10; i--;)
|
|
38
|
-
keys.unshift(new PianoKey(vec2([1,2,4,5,6][i%5]+(i/5|0)*7-7.5,0), vec2(1,2), [1,3,6,8,10][i%5]+(i/5|0)*12));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function gameUpdate()
|
|
42
|
-
{
|
|
43
|
-
// update state of piano keys
|
|
44
|
-
const pressedKey = keys.find(k=>k.soundInstance);
|
|
45
|
-
const newPressedKey = mouseIsDown(0) && keys.find(k=>isOverlapping(k.pos, k.size, mousePos));
|
|
46
|
-
if (newPressedKey != pressedKey)
|
|
47
44
|
{
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
const pos = vec2([1,2,4,5,6][i%5]+(i/5|0)*7-7.5,0)
|
|
46
|
+
const size = vec2(1,2);
|
|
47
|
+
const semitone = [1,3,6,8,10][i%5]+(i/5|0)*12;
|
|
48
|
+
new PianoKey(pos, size, semitone);
|
|
50
49
|
}
|
|
51
50
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
function gameRender()
|
|
2
2
|
{
|
|
3
3
|
// circles and ellipses
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
drawEllipse(vec2(6,5), vec2(
|
|
4
|
+
drawEllipse(vec2(-6,5), vec2(3,2), YELLOW, .5);
|
|
5
|
+
drawCircle(vec2(0,5), 2+wave(.5), RED);
|
|
6
|
+
drawEllipse(vec2(6,5), vec2(2,4), CLEAR_BLACK, .3, .5, CYAN)
|
|
7
7
|
|
|
8
8
|
// polygon shapes
|
|
9
9
|
drawRectGradient(vec2(-6,0), vec2(5,4), RED, BLUE)
|
|
10
|
-
drawRegularPoly(vec2(0,0), vec2(
|
|
10
|
+
drawRegularPoly(vec2(0,0), vec2(4), 3, PURPLE, .2, WHITE, time);
|
|
11
11
|
const starPath = [vec2(0,2), vec2(2,-2), vec2(-3,.5), vec2(3,.5), vec2(-2,-2), vec2(0,2)];
|
|
12
|
-
drawLineList(starPath, .2,
|
|
12
|
+
drawLineList(starPath, .2, GREEN, true, vec2(6, 0));
|
|
13
13
|
|
|
14
14
|
// rects and lines
|
|
15
15
|
drawRect(vec2(0,-5), vec2(4,3), ORANGE, time);
|
|
16
16
|
drawLine(vec2(-5,-7), vec2(5,-3), 1, hsl(0,0,1,.5));
|
|
17
|
-
drawLineList([vec2(5,-3), vec2(-5,-3), vec2(5,-7), vec2(-5,-7)], .2,
|
|
17
|
+
drawLineList([vec2(5,-3), vec2(-5,-3), vec2(5,-7), vec2(-5,-7)], .2, MAGENTA);
|
|
18
18
|
}
|
package/examples/shorts/sound.js
CHANGED
|
@@ -1,37 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
function gameInit()
|
|
2
2
|
{
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
this.icon = icon;
|
|
7
|
-
this.sound = sound;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
update()
|
|
11
|
-
{
|
|
12
|
-
// play sound when clicked
|
|
13
|
-
if (mouseWasPressed(0) && isOverlapping(this.pos, this.size, mousePos))
|
|
14
|
-
this.sound.play(this.pos);
|
|
15
|
-
}
|
|
3
|
+
// initialize UI system
|
|
4
|
+
new UISystemPlugin;
|
|
5
|
+
canvasClearColor = hsl(.6,.3,.2);
|
|
16
6
|
|
|
17
|
-
|
|
7
|
+
// create a grid of buttons with different sounds
|
|
8
|
+
const w = 200, h = 150, gap = 20;
|
|
9
|
+
function makeSoundButton(pos, icon, sound)
|
|
18
10
|
{
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
pos = pos.multiply(vec2(w+gap, h+gap));
|
|
12
|
+
pos = pos.add(mainCanvasSize.scale(.5));
|
|
13
|
+
const button = new UIButton(pos, vec2(w, h), icon);
|
|
14
|
+
button.textHeight = 100;
|
|
15
|
+
button.onClick = ()=> sound.play();
|
|
22
16
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
new SoundButton(vec2( 0, 0),'🎹', new Sound([1.5,.5,270,,.1,,1,1.5,,,,,,,,.1,.01]));
|
|
33
|
-
new SoundButton(vec2( 6, 0),'🏌️', new Sound([,,150,.05,,.05,,1.3,,,,,,3]));
|
|
34
|
-
new SoundButton(vec2(-6,-5),'🌊', new Sound([,.2,40,.5,,1.5,,11,,,,,,199]));
|
|
35
|
-
new SoundButton(vec2( 0,-5),'🛰️', new Sound([,.5,847,.02,.3,.9,1,1.67,,,-294,.04,.13,,,,.1]));
|
|
36
|
-
new SoundButton(vec2( 6,-5),'⚡', new Sound([,,471,,.09,.47,4,1.06,-6.7,,,,,.9,61,.1,,.82,.1]));
|
|
17
|
+
makeSoundButton(vec2(-1, 1),'💰', new Sound([,,1675,,.06,.24,1,1.82,,,837,.06]));
|
|
18
|
+
makeSoundButton(vec2( 0, 1),'🥊', new Sound([,,925,.04,.3,.6,1,.3,,6.27,-184,.09,.17]));
|
|
19
|
+
makeSoundButton(vec2( 1, 1),'✨', new Sound([,,539,0,.04,.29,1,1.92,,,567,.02,.02,,,,.04]));
|
|
20
|
+
makeSoundButton(vec2(-1, 0),'🐁', new Sound([,.2,1e3,.02,,.01,2,,18,,475,.01,.01]));
|
|
21
|
+
makeSoundButton(vec2( 0, 0),'🎹', new Sound([1.5,.5,270,,.1,,1,1.5,,,,,,,,.1,.01]));
|
|
22
|
+
makeSoundButton(vec2( 1, 0),'🏌️', new Sound([,,150,.05,,.05,,1.3,,,,,,3]));
|
|
23
|
+
makeSoundButton(vec2(-1,-1),'🌊', new Sound([,.2,40,.5,,1.5,,11,,,,,,199]));
|
|
24
|
+
makeSoundButton(vec2( 0,-1),'🛰️', new Sound([,.5,847,.02,.3,.9,1,1.67,,,-294,.04,.13,,,,.1]));
|
|
25
|
+
makeSoundButton(vec2( 1,-1),'⚡', new Sound([,,471,,.09,.47,4,1.06,-6.7,,,,,.9,61,.1,,.82,.1]));
|
|
37
26
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
let spriteAtlas;
|
|
2
|
+
canvasClearColor = GRAY;
|
|
2
3
|
|
|
3
4
|
function gameInit()
|
|
4
5
|
{
|
|
@@ -16,8 +17,6 @@ function gameInit()
|
|
|
16
17
|
|
|
17
18
|
function gameRender()
|
|
18
19
|
{
|
|
19
|
-
drawRect(vec2(0,0), vec2(100), GRAY); // draw background
|
|
20
|
-
|
|
21
20
|
// draw a sprite from the atlas
|
|
22
21
|
let pos = vec2(Math.sin(time)*5,-3);// world position to draw
|
|
23
22
|
let angle = 0; // world space angle to draw the tile
|
|
@@ -37,7 +37,7 @@ function gameInit()
|
|
|
37
37
|
|
|
38
38
|
// create background objects
|
|
39
39
|
for (let i=1; i<300; ++i)
|
|
40
|
-
new EngineObject(randInCircle(90), vec2(rand(59),rand(59)), 0, 0, hsl(.4,.
|
|
40
|
+
new EngineObject(randInCircle(90), vec2(rand(59),rand(59)), 0, 0, hsl(.4,.2,rand(.4,.5),.8), -1e5);
|
|
41
41
|
|
|
42
42
|
// create world objects
|
|
43
43
|
for (let i=1; i<1e3; ++i)
|