littlejsengine 1.13.1 → 1.14.2
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/README.md +15 -11
- package/copyToGithub.bat +28 -0
- package/dist/littlejs.d.ts +430 -304
- package/dist/littlejs.esm.js +1745 -982
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +1716 -965
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +1673 -922
- package/examples/box2d/game.js +2 -2
- package/examples/box2d/gameObjects.js +2 -2
- package/examples/box2d/scenes.js +1 -1
- package/examples/breakout/game.js +30 -25
- package/examples/breakoutTutorial/README.md +44 -41
- package/examples/breakoutTutorial/game.js +2 -2
- package/examples/electron/build.bat +7 -0
- package/examples/electron/build.js +124 -0
- package/examples/electron/electron.js +35 -0
- package/examples/electron/game.js +140 -0
- package/examples/electron/index.html +13 -0
- package/examples/electron/package.json +12 -0
- package/examples/electron/tiles.png +0 -0
- package/examples/empty/game.js +1 -0
- package/examples/htmlMenu/game.js +1 -1
- package/examples/index.html +332 -160
- package/examples/module/game.js +5 -2
- package/examples/particles/index.html +12 -3
- package/examples/platformer/gameEffects.js +20 -19
- package/examples/platformer/gameLevel.js +6 -1
- package/examples/shorts/base.html +1 -1
- package/examples/shorts/blending.js +9 -5
- package/examples/shorts/box2d.js +1 -1
- package/examples/shorts/box2dCar.js +1 -1
- package/examples/shorts/clock.js +1 -1
- package/examples/shorts/colors.js +2 -2
- package/examples/shorts/flappyGame.js +2 -1
- package/examples/shorts/helloWorld.js +1 -1
- package/examples/shorts/maze.js +1 -1
- package/examples/shorts/music.js +106 -0
- package/examples/shorts/nineSlice.js +9 -9
- package/examples/shorts/parallax.js +71 -0
- package/examples/shorts/piano.js +9 -10
- package/examples/shorts/postProcess.js +25 -8
- package/examples/shorts/raycasting.js +2 -2
- package/examples/shorts/shapes.js +7 -15
- package/examples/shorts/slidingPuzzle.js +2 -2
- package/examples/shorts/song.mp3 +0 -0
- package/examples/shorts/starfield.js +5 -7
- package/examples/shorts/systemFont.js +1 -1
- package/examples/shorts/uiSystem.js +16 -8
- package/examples/starter/build.js +9 -8
- package/examples/starter/game.js +5 -2
- package/examples/starter/index.html +2 -2
- package/examples/stress/index.html +13 -8
- package/examples/style.css +19 -6
- package/examples/typescript/build.js +1 -1
- package/examples/typescript/game.js +2 -2
- package/examples/typescript/game.ts +5 -2
- package/examples/uiSystem/game.js +13 -12
- package/package.json +2 -2
- package/plugins/box2d.js +24 -97
- package/plugins/drawUtilities.js +29 -23
- package/plugins/newgrounds.js +6 -6
- package/plugins/pluginExport.js +1 -1
- package/plugins/postProcess.js +7 -0
- package/plugins/uiSystem.js +106 -82
- package/plugins/zzfxm.js +10 -10
- package/reference.md +90 -54
- package/src/engine.js +28 -23
- package/src/engineAudio.js +285 -110
- package/src/engineBuild.js +9 -9
- package/src/engineDebug.js +28 -28
- package/src/engineDraw.js +346 -202
- package/src/engineExport.js +28 -16
- package/src/engineInput.js +58 -68
- package/src/engineMedals.js +29 -29
- package/src/engineObject.js +28 -25
- package/src/engineParticles.js +67 -60
- package/src/engineRelease.js +1 -1
- package/src/engineSettings.js +70 -16
- package/src/engineTileLayer.js +34 -34
- package/src/engineUtilities.js +69 -62
- package/src/engineWebGL.js +467 -65
- /package/examples/shorts/{playSound.js → sound.js} +0 -0
package/examples/module/game.js
CHANGED
|
@@ -101,7 +101,10 @@ function gameUpdate()
|
|
|
101
101
|
|
|
102
102
|
// move particles to mouse location if on screen
|
|
103
103
|
if (LJS.mousePosScreen.x)
|
|
104
|
+
{
|
|
104
105
|
particleEmitter.pos = LJS.mousePos;
|
|
106
|
+
particleEmitter.velocity = LJS.mouseDelta.scale(.3*LJS.timeDelta);
|
|
107
|
+
}
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -113,8 +116,8 @@ function gameUpdatePost()
|
|
|
113
116
|
///////////////////////////////////////////////////////////////////////////////
|
|
114
117
|
function gameRender()
|
|
115
118
|
{
|
|
116
|
-
// draw a grey square in the background
|
|
117
|
-
LJS.drawRect(vec2(16,8), vec2(20,14), hsl(0,0,.6)
|
|
119
|
+
// draw a grey square in the background
|
|
120
|
+
LJS.drawRect(vec2(16,8), vec2(20,14), hsl(0,0,.6));
|
|
118
121
|
|
|
119
122
|
// draw the logo as a tile
|
|
120
123
|
LJS.drawTile(vec2(21,5), vec2(4.5), tile(3,128));
|
|
@@ -94,7 +94,7 @@ function gameInit()
|
|
|
94
94
|
if (type == 'color')
|
|
95
95
|
{
|
|
96
96
|
const color = particleSystem[name];
|
|
97
|
-
defaultValue = color.toString(
|
|
97
|
+
defaultValue = color.toString(false);
|
|
98
98
|
}
|
|
99
99
|
else if (type == 'alpha')
|
|
100
100
|
{
|
|
@@ -266,7 +266,7 @@ function updateSetting(setting, save=1)
|
|
|
266
266
|
if (type == 'color')
|
|
267
267
|
{
|
|
268
268
|
const color = particleSystem[name];
|
|
269
|
-
input.value = color.toString(
|
|
269
|
+
input.value = color.toString(false);
|
|
270
270
|
}
|
|
271
271
|
else if (type == 'alpha')
|
|
272
272
|
{
|
|
@@ -369,7 +369,16 @@ function gameUpdate()
|
|
|
369
369
|
|
|
370
370
|
if (document.activeElement == document.body)
|
|
371
371
|
{
|
|
372
|
-
|
|
372
|
+
if (LJS.mouseIsDown(0))
|
|
373
|
+
{
|
|
374
|
+
particleSystem.pos = LJS.mousePos;
|
|
375
|
+
particleSystem.velocity = LJS.mouseDelta.scale(.3*LJS.timeDelta);
|
|
376
|
+
}
|
|
377
|
+
else
|
|
378
|
+
{
|
|
379
|
+
particleSystem.pos = vec2();
|
|
380
|
+
particleSystem.velocity = vec2();
|
|
381
|
+
}
|
|
373
382
|
if (LJS.mouseWheel)
|
|
374
383
|
{
|
|
375
384
|
// zoom camera
|
|
@@ -82,7 +82,7 @@ export function explosion(pos, radius=3)
|
|
|
82
82
|
GameLevel.decorateTile(pos.add(vec2(x,y)).floor());
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
// update
|
|
85
|
+
// update WebGL texture
|
|
86
86
|
GameLevel.updateWebGL(GameLevel.foregroundTileLayer);
|
|
87
87
|
|
|
88
88
|
// kill/push objects
|
|
@@ -153,7 +153,7 @@ export function destroyTile(pos, makeSound = 1, cleanup = 1)
|
|
|
153
153
|
layer.setData(pos, new LJS.TileLayerData, true);
|
|
154
154
|
layer.setCollisionData(pos, GameLevel.tileType_empty);
|
|
155
155
|
|
|
156
|
-
// cleanup neighbors and rebuild
|
|
156
|
+
// cleanup neighbors and rebuild WebGL
|
|
157
157
|
if (cleanup)
|
|
158
158
|
{
|
|
159
159
|
for (let i=-1;i<=1;++i)
|
|
@@ -185,7 +185,7 @@ export class Sky extends LJS.EngineObject
|
|
|
185
185
|
// fill background with a gradient
|
|
186
186
|
const canvas = LJS.mainCanvas;
|
|
187
187
|
const gradientDelta = 5;
|
|
188
|
-
for(let y=0; y<canvas.height; y+=gradientDelta)
|
|
188
|
+
for (let y=0; y<canvas.height; y+=gradientDelta)
|
|
189
189
|
{
|
|
190
190
|
// draw horizontal lines to create a gradient
|
|
191
191
|
const color = this.skyColor.lerp(this.horizonColor, y/canvas.height);
|
|
@@ -216,21 +216,20 @@ export class Sky extends LJS.EngineObject
|
|
|
216
216
|
|
|
217
217
|
export class ParallaxLayer extends LJS.CanvasLayer
|
|
218
218
|
{
|
|
219
|
-
constructor(depth)
|
|
219
|
+
constructor(pos, topColor, bottomColor, depth)
|
|
220
220
|
{
|
|
221
221
|
const renderOrder = depth - 3e3;
|
|
222
222
|
const canvasSize = vec2(512, 256);
|
|
223
|
-
super(
|
|
224
|
-
this.
|
|
223
|
+
super(pos, vec2(), 0, renderOrder, canvasSize);
|
|
224
|
+
this.centerPos = pos;
|
|
225
225
|
this.depth = depth;
|
|
226
226
|
|
|
227
227
|
// create a gradient for the mountains
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
for(let i = canvasSize.y; i--;)
|
|
228
|
+
const w = canvasSize.x, h = canvasSize.y;
|
|
229
|
+
for (let i = h; i--;)
|
|
231
230
|
{
|
|
232
231
|
// draw a 1 pixel gradient line on the left side of the canvas
|
|
233
|
-
const p = i/
|
|
232
|
+
const p = i/h;
|
|
234
233
|
this.context.fillStyle = topColor.lerp(bottomColor, p);
|
|
235
234
|
this.context.fillRect(0, i, 1, 1);
|
|
236
235
|
}
|
|
@@ -239,40 +238,42 @@ export class ParallaxLayer extends LJS.CanvasLayer
|
|
|
239
238
|
const pointiness = .2; // how pointy the mountains are
|
|
240
239
|
const levelness = .005; // how much the mountains level out
|
|
241
240
|
const slopeRange = 1; // max slope of the mountains
|
|
242
|
-
const startGroundLevel =
|
|
241
|
+
const startGroundLevel = h/2;
|
|
243
242
|
let y = startGroundLevel, groundSlope = LJS.rand(-slopeRange, slopeRange);
|
|
244
|
-
for(let x=
|
|
243
|
+
for (let x=w; x--;)
|
|
245
244
|
{
|
|
246
245
|
// pull slope towards start ground level
|
|
247
246
|
y += groundSlope -= (y-startGroundLevel)*levelness;
|
|
248
247
|
|
|
249
|
-
//
|
|
248
|
+
// randomly change slope
|
|
250
249
|
if (LJS.rand() < pointiness)
|
|
251
250
|
groundSlope = LJS.rand(-slopeRange, slopeRange);
|
|
252
251
|
|
|
253
252
|
// draw 1 pixel wide vertical slice of mountain
|
|
254
|
-
this.context.drawImage(this.canvas, 0, 0, 1,
|
|
253
|
+
this.context.drawImage(this.canvas, 0, 0, 1, h, x, y, 1, h - y);
|
|
255
254
|
}
|
|
256
255
|
|
|
257
256
|
// remove gradient sliver from left side
|
|
258
|
-
this.context.clearRect(0,0,1,
|
|
257
|
+
this.context.clearRect(0,0,1,h);
|
|
259
258
|
|
|
260
|
-
// make
|
|
259
|
+
// make WebGL texture
|
|
261
260
|
this.useWebGL(LJS.glEnable);
|
|
262
261
|
}
|
|
263
262
|
|
|
264
263
|
render()
|
|
265
264
|
{
|
|
265
|
+
const canvasSize = vec2(this.canvas.width, this.canvas.height);
|
|
266
266
|
const depth = this.depth
|
|
267
267
|
const distance = 4 + depth;
|
|
268
268
|
const parallax = vec2(150, 30).scale(depth**2+1);
|
|
269
|
-
const levelCenter =
|
|
270
|
-
const cameraDeltaFromCenter = LJS.cameraPos.subtract(levelCenter)
|
|
269
|
+
const levelCenter = this.centerPos;
|
|
270
|
+
const cameraDeltaFromCenter = LJS.cameraPos.subtract(levelCenter)
|
|
271
|
+
.divide(levelCenter.scale(-1).divide(parallax));
|
|
271
272
|
const scale = distance/LJS.cameraScale;
|
|
272
273
|
const positonOffset = vec2(0, 2-depth);
|
|
273
274
|
const cameraOffset = cameraDeltaFromCenter.scale(1/LJS.cameraScale);
|
|
274
275
|
this.pos = LJS.cameraPos.add(positonOffset).add(cameraOffset);
|
|
275
|
-
this.size =
|
|
276
|
+
this.size = canvasSize.scale(scale);
|
|
276
277
|
super.render();
|
|
277
278
|
}
|
|
278
279
|
}
|
|
@@ -39,7 +39,12 @@ export function buildLevel()
|
|
|
39
39
|
|
|
40
40
|
// create parallax layers
|
|
41
41
|
for (let i=3; i--;)
|
|
42
|
-
|
|
42
|
+
{
|
|
43
|
+
const pos = levelSize.scale(.5);
|
|
44
|
+
const topColor = levelColor.mutate(.2).lerp(sky.skyColor, .8 - i*.15);
|
|
45
|
+
const bottomColor = levelColor.subtract(LJS.CLEAR_WHITE).mutate(.2);
|
|
46
|
+
new GameEffects.ParallaxLayer(pos, topColor, bottomColor, i );
|
|
47
|
+
}
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
function loadLevelData()
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
+
// use smoother textures
|
|
2
|
+
setCanvasPixelated(false);
|
|
3
|
+
setTilesPixelated(false);
|
|
4
|
+
|
|
1
5
|
function gameRender()
|
|
2
6
|
{
|
|
3
7
|
const circleTile = tile(2, 128); // get the circle tile
|
|
4
8
|
|
|
5
9
|
// additive blend
|
|
6
10
|
setBlendMode(1);
|
|
7
|
-
drawTile(vec2(-
|
|
11
|
+
drawTile(vec2(-8,-2), vec2(7), circleTile, rgb(0,0,.5), 0, false, rgb(0,0,.5));
|
|
8
12
|
drawTile(vec2(-6, 2), vec2(7), circleTile, rgb(0,1,0));
|
|
9
|
-
drawTile(vec2(-
|
|
13
|
+
drawTile(vec2(-4,-2), vec2(7), circleTile, rgb(1,0,0));
|
|
10
14
|
|
|
11
15
|
// alpha blend
|
|
12
16
|
setBlendMode(0);
|
|
13
|
-
drawTile(vec2(4,-2), vec2(7), circleTile,
|
|
14
|
-
drawTile(vec2(
|
|
15
|
-
drawTile(vec2(
|
|
17
|
+
drawTile(vec2(4,-2), vec2(7), circleTile, hsl(time/9 ,1,.5), 0, false, hsl(1,1,.5));
|
|
18
|
+
drawTile(vec2(8,-2), vec2(7), circleTile, hsl(time/9+1/3,1,.5,.5));
|
|
19
|
+
drawTile(vec2(6, 2), vec2(7), circleTile, hsl(time/9+2/3,1,.5,.5));
|
|
16
20
|
}
|
package/examples/shorts/box2d.js
CHANGED
|
@@ -10,7 +10,7 @@ async function gameInit()
|
|
|
10
10
|
groundObject.addBox(vec2(100,2));
|
|
11
11
|
|
|
12
12
|
// add some random objects
|
|
13
|
-
for(let i=50; i--;)
|
|
13
|
+
for (let i=50; i--;)
|
|
14
14
|
{
|
|
15
15
|
const o = new Box2dObject(randInCircle(5), vec2(), 0, 0, randColor());
|
|
16
16
|
randInt(2) ? o.addCircle(rand(1,2)) : o.addRandomPoly(rand(1,2));
|
|
@@ -18,7 +18,7 @@ class CarObject extends Box2dObject
|
|
|
18
18
|
this.addBox(vec2(7,2));
|
|
19
19
|
const frequency = 4, maxTorque = 250;
|
|
20
20
|
this.wheels = [];
|
|
21
|
-
for(let i=2; i--;)
|
|
21
|
+
for (let i=2; i--;)
|
|
22
22
|
{
|
|
23
23
|
const wheelPos = pos.add(vec2(i?2:-2, -1));
|
|
24
24
|
const wheel = new Box2dObject(wheelPos, vec2(2), tile(7));
|
package/examples/shorts/clock.js
CHANGED
|
@@ -10,12 +10,12 @@ function gameRender()
|
|
|
10
10
|
// rgb and hsl color
|
|
11
11
|
drawRect(vec2(-8, 0), vec2(3), new Color(1,0,0));
|
|
12
12
|
drawRect(vec2(-4, 0), vec2(3), rgb(0,1,1));
|
|
13
|
-
drawRect(vec2(-0, 0), vec2(3), hsl(0,1,.5));
|
|
13
|
+
drawRect(vec2(-0, 0), vec2(3), hsl(0,1,.5, .5));
|
|
14
14
|
drawRect(vec2( 4, 0), vec2(3), hsl(.6,.5,.5));
|
|
15
15
|
drawRect(vec2( 8, 0), vec2(3), hsl(0,0,1));
|
|
16
16
|
|
|
17
17
|
// color lerpping
|
|
18
|
-
for(let i=5; i--;)
|
|
18
|
+
for (let i=5; i--;)
|
|
19
19
|
{
|
|
20
20
|
const color1 = RED;
|
|
21
21
|
const color2 = YELLOW;
|
|
@@ -28,6 +28,7 @@ class Player extends EngineObject
|
|
|
28
28
|
if (mouseWasPressed(0) || keyWasPressed('Space'))
|
|
29
29
|
this.velocity = vec2(0,.2);
|
|
30
30
|
this.angle = -this.velocity.y*2;
|
|
31
|
+
this.pos.y = max(-50, this.pos.y);
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
collideWithObject(object)
|
|
@@ -44,7 +45,7 @@ function gameInit()
|
|
|
44
45
|
gravity.y = -.01;
|
|
45
46
|
for (let i=100; i--;)
|
|
46
47
|
{
|
|
47
|
-
const h=
|
|
48
|
+
const h=100, y=-h/2-6+rand(9), spacing=15, gap=5;
|
|
48
49
|
new Wall(vec2(14 + i*spacing,y+h + gap), vec2(3,h));
|
|
49
50
|
new Wall(vec2(14 + i*spacing,y), vec2(3,h));
|
|
50
51
|
}
|
package/examples/shorts/maze.js
CHANGED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Music player variables
|
|
2
|
+
let musicSound = new SoundWave('song.mp3');
|
|
3
|
+
let musicVolume = .8;
|
|
4
|
+
let musicInstance;
|
|
5
|
+
|
|
6
|
+
// UI elements
|
|
7
|
+
let playButton, stopButton, progressBar;
|
|
8
|
+
|
|
9
|
+
function gameInit()
|
|
10
|
+
{
|
|
11
|
+
// load ui system plugin
|
|
12
|
+
new UISystemPlugin;
|
|
13
|
+
uiSystem.defaultSoundPress = new Sound([.3,0,220]);
|
|
14
|
+
uiSystem.defaultSoundClick = new Sound([.3,0,440]);
|
|
15
|
+
uiSystem.defaultCornerRadius = 20;
|
|
16
|
+
|
|
17
|
+
// setup music player UI
|
|
18
|
+
const musicPlayer = new UIObject(mainCanvasSize.scale(.5), vec2(500, 300));
|
|
19
|
+
|
|
20
|
+
// title
|
|
21
|
+
const title = new UIText(vec2(0, -100), vec2(500, 40), 'LittleJS Music Player');
|
|
22
|
+
musicPlayer.addChild(title);
|
|
23
|
+
|
|
24
|
+
// volume slider
|
|
25
|
+
const volumeSlider = new UIScrollbar(vec2(0, -40), vec2(400, 30), musicVolume, 'Music Volume');
|
|
26
|
+
musicPlayer.addChild(volumeSlider);
|
|
27
|
+
volumeSlider.onChange = () =>
|
|
28
|
+
{
|
|
29
|
+
musicVolume = volumeSlider.value;
|
|
30
|
+
if (musicInstance)
|
|
31
|
+
musicInstance.setVolume(musicVolume);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// play button
|
|
35
|
+
playButton = new UIButton(vec2(-90, 30), vec2(140, 50), 'Play');
|
|
36
|
+
musicPlayer.addChild(playButton);
|
|
37
|
+
playButton.onClick = ()=>
|
|
38
|
+
{
|
|
39
|
+
if (!musicSound.isLoaded())
|
|
40
|
+
return;
|
|
41
|
+
|
|
42
|
+
// handle play/pause toggle
|
|
43
|
+
if (!musicInstance)
|
|
44
|
+
musicInstance = musicSound.playMusic(musicVolume);
|
|
45
|
+
else if (musicInstance.isPaused())
|
|
46
|
+
musicInstance.resume();
|
|
47
|
+
else
|
|
48
|
+
musicInstance.pause();
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// stop button
|
|
52
|
+
stopButton = new UIButton(vec2(90, 30), vec2(140, 50), 'Stop');
|
|
53
|
+
musicPlayer.addChild(stopButton);
|
|
54
|
+
stopButton.onClick = ()=>
|
|
55
|
+
{
|
|
56
|
+
if (!musicInstance)
|
|
57
|
+
return;
|
|
58
|
+
|
|
59
|
+
// stop sound
|
|
60
|
+
musicInstance.stop();
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// progress bar and scrollbar for seeking
|
|
64
|
+
progressBar = new UIScrollbar(vec2(0, 100), vec2(400, 30), 0, 'Progress');
|
|
65
|
+
musicPlayer.addChild(progressBar);
|
|
66
|
+
progressBar.onChange = ()=>
|
|
67
|
+
{
|
|
68
|
+
// control music seek position
|
|
69
|
+
const wasPlaying = musicInstance && musicInstance.isPlaying();
|
|
70
|
+
if (!musicInstance)
|
|
71
|
+
musicInstance = musicSound.playMusic(musicVolume, true, true);
|
|
72
|
+
progressBar.value = min(progressBar.value, .999); // prevent looping around
|
|
73
|
+
const seekTime = progressBar.value * musicSound.getDuration();
|
|
74
|
+
musicInstance.start(seekTime);
|
|
75
|
+
if (!wasPlaying)
|
|
76
|
+
musicInstance.pause();
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function gameUpdate()
|
|
81
|
+
{
|
|
82
|
+
// disable buttons while loading or waiting for interaction
|
|
83
|
+
const isDisabled = !musicSound.isLoaded() || !audioIsRunning();
|
|
84
|
+
playButton.disabled = isDisabled
|
|
85
|
+
stopButton.disabled = isDisabled
|
|
86
|
+
progressBar.disabled = isDisabled
|
|
87
|
+
|
|
88
|
+
// update ui
|
|
89
|
+
if (!musicSound.isLoaded())
|
|
90
|
+
{
|
|
91
|
+
// update loading progress
|
|
92
|
+
const loadingPercent = musicSound.loadedPercent * 100;
|
|
93
|
+
progressBar.text = `Loading: ${(loadingPercent).toFixed(2)}%`;
|
|
94
|
+
}
|
|
95
|
+
else
|
|
96
|
+
{
|
|
97
|
+
// update ui text
|
|
98
|
+
playButton.text = !musicInstance || !musicInstance.isPlaying() ? 'Play' : 'Pause';
|
|
99
|
+
const currentTime = musicInstance ? musicInstance.getCurrentTime() : 0;
|
|
100
|
+
const duration = musicSound.getDuration();
|
|
101
|
+
if (!progressBar.mouseIsHeld)
|
|
102
|
+
progressBar.value = currentTime / duration;
|
|
103
|
+
const timeText = `${formatTime(currentTime)} / ${formatTime(duration)}`;
|
|
104
|
+
progressBar.text = audioIsRunning() ? timeText : 'Click to Enable Audio';
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -4,18 +4,18 @@ function gameRender()
|
|
|
4
4
|
const threeSliceTile = tile(19);
|
|
5
5
|
|
|
6
6
|
// draw nine slice with thin border and color
|
|
7
|
-
drawNineSlice(vec2(-7,4), vec2(
|
|
7
|
+
drawNineSlice(vec2(-7,4), vec2(11+wave(.5,2), 6), nineSliceTile, hsl(.1,.5,.9), .5);
|
|
8
8
|
drawTextOverlay('Nine Slice\nThin Border', vec2(-7,4), 1, BLACK);
|
|
9
9
|
|
|
10
|
-
// draw nine slice in screen space with thick border
|
|
11
|
-
drawNineSliceScreen(vec2(700,150), vec2(250), nineSliceTile);
|
|
10
|
+
// draw nine slice in screen space with thick border and rotation
|
|
11
|
+
drawNineSliceScreen(vec2(700,150), vec2(250), nineSliceTile, 32, 2, time/2);
|
|
12
12
|
drawTextScreen('Nine Slice\nScreen Space', vec2(700,150), 30, BLACK);
|
|
13
13
|
|
|
14
|
-
// draw three slice with
|
|
15
|
-
drawThreeSlice(vec2(-7,-4), vec2(9, 7), threeSliceTile, WHITE, 2, hsl(
|
|
16
|
-
drawTextOverlay('Three Slice\
|
|
14
|
+
// draw three slice with variable border and additive color
|
|
15
|
+
drawThreeSlice(vec2(-7,-4), vec2(9, 7), threeSliceTile, WHITE, 2+wave(.2)*2, hsl(time/30,.5,.5));
|
|
16
|
+
drawTextOverlay('Three Slice\nVariable\n Border', vec2(-7,-4), 1, BLACK);
|
|
17
17
|
|
|
18
|
-
// draw three slice in screen space with
|
|
19
|
-
drawThreeSliceScreen(vec2(700,
|
|
20
|
-
drawTextScreen('Three Slice\nScreen Space', vec2(700,
|
|
18
|
+
// draw three slice in screen space with changing size
|
|
19
|
+
drawThreeSliceScreen(vec2(700,420), vec2(350-wave(.3,90),120+wave(.3,60)), threeSliceTile);
|
|
20
|
+
drawTextScreen('Three Slice\nScreen Space', vec2(700,420), 30, BLACK);
|
|
21
21
|
}
|
|
@@ -0,0 +1,71 @@
|
|
|
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 of the canvas
|
|
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, groundSlope = rand(-slopeRange, slopeRange);
|
|
38
|
+
for (let x=w; x--;)
|
|
39
|
+
{
|
|
40
|
+
// pull slope towards start ground level
|
|
41
|
+
y += groundSlope -= (y-startGroundLevel)*levelness;
|
|
42
|
+
|
|
43
|
+
// randomly change slope
|
|
44
|
+
if (rand() < pointiness)
|
|
45
|
+
groundSlope = rand(-slopeRange, slopeRange);
|
|
46
|
+
|
|
47
|
+
// draw 1 pixel wide vertical slice of mountain
|
|
48
|
+
this.context.drawImage(this.canvas, 0, 0, 1, h, x, y, 1, h - y);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// remove gradient sliver from left side
|
|
52
|
+
this.context.clearRect(0,0,1,h);
|
|
53
|
+
|
|
54
|
+
// make WebGL texture
|
|
55
|
+
this.useWebGL(glEnable);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
render()
|
|
59
|
+
{
|
|
60
|
+
const canvasSize = vec2(this.canvas.width, this.canvas.height);
|
|
61
|
+
const viewerPos = mousePos;
|
|
62
|
+
const depth = this.depth
|
|
63
|
+
const distance = 3 + depth;
|
|
64
|
+
const parallax = vec2(.2, .05).scale(depth**2+1);
|
|
65
|
+
const cameraDeltaFromCenter = viewerPos.multiply(parallax);
|
|
66
|
+
const positonOffset = vec2(0, 4-depth*3);
|
|
67
|
+
this.pos = cameraDeltaFromCenter.add(positonOffset)
|
|
68
|
+
this.size = canvasSize.scale(distance/cameraScale);
|
|
69
|
+
super.render();
|
|
70
|
+
}
|
|
71
|
+
}
|
package/examples/shorts/piano.js
CHANGED
|
@@ -13,19 +13,18 @@ class PianoKey extends EngineObject
|
|
|
13
13
|
}
|
|
14
14
|
press()
|
|
15
15
|
{
|
|
16
|
-
if (!this.
|
|
17
|
-
pianoSound.playNote(this.semitone);
|
|
18
|
-
this.isDown = true;
|
|
16
|
+
if (!this.soundInstance)
|
|
17
|
+
this.soundInstance = pianoSound.playNote(this.semitone);
|
|
19
18
|
}
|
|
20
19
|
release()
|
|
21
20
|
{
|
|
22
|
-
if (this.
|
|
23
|
-
|
|
24
|
-
this.
|
|
21
|
+
if (this.soundInstance)
|
|
22
|
+
this.soundInstance.stop(.2);
|
|
23
|
+
this.soundInstance = 0;
|
|
25
24
|
}
|
|
26
25
|
render()
|
|
27
26
|
{
|
|
28
|
-
const color = this.
|
|
27
|
+
const color = this.soundInstance ? RED : this.color;
|
|
29
28
|
drawRect(this.pos, this.drawSize, color);
|
|
30
29
|
}
|
|
31
30
|
}
|
|
@@ -33,16 +32,16 @@ class PianoKey extends EngineObject
|
|
|
33
32
|
function gameInit()
|
|
34
33
|
{
|
|
35
34
|
// create piano keyboard
|
|
36
|
-
for(let i=15; i--;)
|
|
35
|
+
for (let i=15; i--;)
|
|
37
36
|
keys.unshift(new PianoKey(vec2(i-7,0), vec2(1,4), [0,2,4,5,7,9,11][i%7]+(i/7|0)*12, 1));
|
|
38
|
-
for(let i=10; i--;)
|
|
37
|
+
for (let i=10; i--;)
|
|
39
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));
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
function gameUpdate()
|
|
43
42
|
{
|
|
44
43
|
// update state of piano keys
|
|
45
|
-
const pressedKey = keys.find(k=>k.
|
|
44
|
+
const pressedKey = keys.find(k=>k.soundInstance);
|
|
46
45
|
const newPressedKey = mouseIsDown(0) && keys.find(k=>isOverlapping(k.pos, k.size, mousePos));
|
|
47
46
|
if (newPressedKey != pressedKey)
|
|
48
47
|
{
|
|
@@ -6,7 +6,7 @@ function gameInit()
|
|
|
6
6
|
function gameRender()
|
|
7
7
|
{
|
|
8
8
|
drawRect(vec2(), vec2(99), GRAY);
|
|
9
|
-
drawTile(vec2(), vec2(12), tile(3,128));
|
|
9
|
+
drawTile(vec2(Math.sin(time)*3, 0), vec2(12), tile(3,128));
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
const tvShader = `
|
|
@@ -16,27 +16,44 @@ float hash(vec2 p)
|
|
|
16
16
|
p=fract(p*.3197);
|
|
17
17
|
return fract(1.+sin(51.*p.x+73.*p.y)*13753.3);
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
vec2 i=floor(p),f=fract(p),u=f*f*(3.-2.*f);
|
|
22
|
-
return mix(mix(hash(i),hash(i+vec2(1,0)),u.x),mix(hash(i+vec2(0,1)),hash(i+1.),u.x),u.y);
|
|
23
|
-
}
|
|
19
|
+
|
|
24
20
|
void mainImage(out vec4 c, vec2 p)
|
|
25
21
|
{
|
|
26
22
|
// setup the shader
|
|
23
|
+
vec2 uv = p;
|
|
27
24
|
p /= iResolution.xy;
|
|
28
25
|
c = texture(iChannel0, p);
|
|
29
26
|
|
|
30
27
|
// static noise
|
|
31
28
|
const float staticAlpha = .1;
|
|
32
|
-
const float staticScale = .
|
|
29
|
+
const float staticScale = .002;
|
|
33
30
|
c += staticAlpha * hash(floor(p/staticScale) + mod(iTime*500., 1e3));
|
|
34
31
|
|
|
35
32
|
// scan lines
|
|
36
33
|
const float scanlineScale = 2.;
|
|
37
|
-
const float scanlineAlpha = .
|
|
34
|
+
const float scanlineAlpha = .5;
|
|
38
35
|
c *= 1. - scanlineAlpha*cos(p.y*2.*iResolution.y/scanlineScale);
|
|
39
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
|
+
|
|
40
57
|
// black vignette around edges
|
|
41
58
|
const float vignette = 2.;
|
|
42
59
|
const float vignettePow = 6.;
|
|
@@ -42,7 +42,7 @@ function gameRender()
|
|
|
42
42
|
{
|
|
43
43
|
// draw horizontal slizes to create floor and ceiling
|
|
44
44
|
const h = 9;
|
|
45
|
-
let pos = vec2(), size = vec2(39, .
|
|
45
|
+
let pos = vec2(), size = vec2(39, .15), color = WHITE;
|
|
46
46
|
for (let y=-h; y<h; y+=.1)
|
|
47
47
|
{
|
|
48
48
|
const p = 1.01-abs(y/h)
|
|
@@ -54,7 +54,7 @@ function gameRender()
|
|
|
54
54
|
{
|
|
55
55
|
// draw vertical slices to create the walls
|
|
56
56
|
const w = 20;
|
|
57
|
-
const pos = vec2(), size = vec2(.
|
|
57
|
+
const pos = vec2(), size = vec2(.15), color = WHITE;
|
|
58
58
|
for (let x=-w; x<w; x+=.1)
|
|
59
59
|
{
|
|
60
60
|
const p = raycast(playerPos, playerAngle + x/w);
|
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
function gameRender()
|
|
2
2
|
{
|
|
3
3
|
// polygon shapes
|
|
4
|
-
for(let j=3; j<7; ++j)
|
|
5
|
-
|
|
6
|
-
let points = [];
|
|
7
|
-
for(let i=0; i<j; ++i)
|
|
8
|
-
{
|
|
9
|
-
let angle = i * Math.PI * 2 / j;
|
|
10
|
-
points.push(vec2(j*4-18,0).add(vec2(Math.sin(angle), Math.cos(angle))));
|
|
11
|
-
}
|
|
12
|
-
drawPoly(points, hsl(j/4,1,.5)); // draw a star
|
|
13
|
-
}
|
|
4
|
+
for (let j=3; j<7; ++j)
|
|
5
|
+
drawRegularPoly(vec2(j*4-18,0), vec2(1), j, hsl(j/4+time/9,1,.5), .2, WHITE, time);
|
|
14
6
|
|
|
15
7
|
// circles and ellipses
|
|
16
|
-
drawCircle(vec2(0,5), 1, hsl(.15,1,.5));
|
|
17
|
-
drawEllipse(vec2(-5,5), 2,
|
|
18
|
-
drawEllipse(vec2(5,5), .5,
|
|
8
|
+
drawCircle(vec2(0,5), 1+wave(.5), hsl(.15,1,.5));
|
|
9
|
+
drawEllipse(vec2(-5,5), vec2(2,1), hsl(0,1,.5));
|
|
10
|
+
drawEllipse(vec2(5,5), vec2(.5,2), hsl(.55,1,.5), .5);
|
|
19
11
|
|
|
20
12
|
// rects and lines
|
|
21
|
-
drawRect(vec2(0,-5), vec2(
|
|
22
|
-
drawLine(vec2(-5,-7), vec2(5,-3), 1, hsl(0,0,1));
|
|
13
|
+
drawRect(vec2(0,-5), vec2(4,3), hsl(.6,1,.5), time);
|
|
14
|
+
drawLine(vec2(-5,-7), vec2(5,-3), 1, hsl(0,0,1, .5));
|
|
23
15
|
drawLine(vec2(-5,-3), vec2(5,-7), .2, hsl(1,1,.5));
|
|
24
16
|
}
|