littlejsengine 1.13.4 → 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.
Files changed (53) hide show
  1. package/README.md +2 -1
  2. package/copyToGithub.bat +28 -0
  3. package/dist/littlejs.d.ts +346 -240
  4. package/dist/littlejs.esm.js +1370 -723
  5. package/dist/littlejs.esm.min.js +1 -1
  6. package/dist/littlejs.js +1350 -709
  7. package/dist/littlejs.min.js +1 -1
  8. package/dist/littlejs.release.js +1333 -692
  9. package/examples/box2d/game.js +1 -1
  10. package/examples/box2d/gameObjects.js +1 -1
  11. package/examples/breakout/game.js +30 -25
  12. package/examples/electron/index.html +2 -2
  13. package/examples/index.html +207 -96
  14. package/examples/platformer/gameEffects.js +19 -18
  15. package/examples/platformer/gameLevel.js +6 -1
  16. package/examples/shorts/base.html +1 -1
  17. package/examples/shorts/flappyGame.js +2 -1
  18. package/examples/shorts/helloWorld.js +1 -1
  19. package/examples/shorts/music.js +106 -0
  20. package/examples/shorts/parallax.js +71 -0
  21. package/examples/shorts/piano.js +7 -8
  22. package/examples/shorts/postProcess.js +25 -8
  23. package/examples/shorts/shapes.js +1 -9
  24. package/examples/shorts/song.mp3 +0 -0
  25. package/examples/shorts/uiSystem.js +15 -8
  26. package/examples/starter/index.html +2 -2
  27. package/examples/stress/index.html +8 -3
  28. package/examples/style.css +14 -4
  29. package/examples/uiSystem/game.js +11 -11
  30. package/package.json +1 -1
  31. package/plugins/box2d.js +10 -8
  32. package/plugins/drawUtilities.js +5 -5
  33. package/plugins/newgrounds.js +6 -6
  34. package/plugins/pluginExport.js +1 -1
  35. package/plugins/uiSystem.js +103 -79
  36. package/plugins/zzfxm.js +10 -10
  37. package/reference.md +90 -54
  38. package/src/engine.js +22 -22
  39. package/src/engineAudio.js +284 -109
  40. package/src/engineBuild.js +9 -9
  41. package/src/engineDebug.js +26 -26
  42. package/src/engineDraw.js +148 -97
  43. package/src/engineExport.js +22 -16
  44. package/src/engineInput.js +57 -67
  45. package/src/engineMedals.js +25 -25
  46. package/src/engineObject.js +25 -22
  47. package/src/engineParticles.js +59 -59
  48. package/src/engineRelease.js +1 -1
  49. package/src/engineSettings.js +20 -13
  50. package/src/engineTileLayer.js +34 -34
  51. package/src/engineUtilities.js +62 -55
  52. package/src/engineWebGL.js +447 -65
  53. /package/examples/shorts/{playSound.js → sound.js} +0 -0
@@ -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 webgl texture
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 webgl
156
+ // cleanup neighbors and rebuild WebGL
157
157
  if (cleanup)
158
158
  {
159
159
  for (let i=-1;i<=1;++i)
@@ -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(vec2(), vec2(), 0, renderOrder, canvasSize);
224
- this.canvasSize = canvasSize;
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 topColor = GameLevel.levelColor.mutate(.2).lerp(GameLevel.sky.skyColor, .8 - depth*.15);
229
- const bottomColor = GameLevel.levelColor.subtract(LJS.CLEAR_WHITE).mutate(.2);
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/canvasSize.y;
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 = canvasSize.y/2;
241
+ const startGroundLevel = h/2;
243
242
  let y = startGroundLevel, groundSlope = LJS.rand(-slopeRange, slopeRange);
244
- for (let x=canvasSize.x; 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
- // random change slope
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, canvasSize.y, x, y, 1, canvasSize.y - y);
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,canvasSize.y);
257
+ this.context.clearRect(0,0,1,h);
259
258
 
260
- // make webgl texture
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 = GameLevel.levelSize.scale(.5);
270
- const cameraDeltaFromCenter = LJS.cameraPos.subtract(levelCenter).divide(levelCenter.scale(-1).divide(parallax));
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 = this.canvasSize.scale(scale);
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
- new GameEffects.ParallaxLayer(i);
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,5 +1,5 @@
1
1
  <!DOCTYPE html><meta charset=utf-8><body>
2
- <script src=../../dist/littlejs.js?1133></script>
2
+ <script src=../../dist/littlejs.js?1134></script>
3
3
  <script src=../../dist/box2d.wasm.js></script>
4
4
 
5
5
  <!-- LittleJS Engine Source
@@ -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=50, y=-h/2-6+rand(9), spacing=15, gap=5;
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
  }
@@ -1,7 +1,7 @@
1
1
  function gameRender()
2
2
  {
3
3
  // draw background rect
4
- drawRect(cameraPos, vec2(30), hsl(0,0,.2));
4
+ drawRect(cameraPos, vec2(50), hsl(0,0,.2));
5
5
 
6
6
  // draw text to the overlay canvas
7
7
  drawTextOverlay('Hello World', vec2(0,3), 3);
@@ -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
+ }
@@ -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
+ }
@@ -13,19 +13,18 @@ class PianoKey extends EngineObject
13
13
  }
14
14
  press()
15
15
  {
16
- if (!this.isDown)
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.isDown)
23
- pianoSound.stop(.2);
24
- this.isDown = false;
21
+ if (this.soundInstance)
22
+ this.soundInstance.stop(.2);
23
+ this.soundInstance = 0;
25
24
  }
26
25
  render()
27
26
  {
28
- const color = this.isDown ? RED : this.color;
27
+ const color = this.soundInstance ? RED : this.color;
29
28
  drawRect(this.pos, this.drawSize, color);
30
29
  }
31
30
  }
@@ -42,7 +41,7 @@ function gameInit()
42
41
  function gameUpdate()
43
42
  {
44
43
  // update state of piano keys
45
- const pressedKey = keys.find(k=>k.isDown);
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
- float noise(vec2 p)
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 = .005;
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 = .3;
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.;
@@ -2,15 +2,7 @@ function gameRender()
2
2
  {
3
3
  // polygon shapes
4
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(0,1).rotate(angle)));
11
- }
12
- drawPoly(points, hsl(j/4+time/9,1,.5)); // draw a regular polygon
13
- }
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
8
  drawCircle(vec2(0,5), 1+wave(.5), hsl(.15,1,.5));
Binary file
@@ -11,26 +11,33 @@ function gameInit()
11
11
  uiSystem.defaultCornerRadius = 8;
12
12
 
13
13
  // setup example menu
14
- uiMenu = new UIObject(mainCanvasSize.scale(.5));
15
- const uiBackground = new UIObject(vec2(), vec2(400));
16
- uiMenu.addChild(uiBackground);
14
+ uiBackground = new UIObject(mainCanvasSize.scale(.5), vec2(1e5));
15
+ uiBackground.color = hsl(0,0,.8);
16
+ const uiMenu = new UIObject(vec2(), vec2(450));
17
+ uiBackground.addChild(uiMenu);
17
18
 
18
19
  // example text
19
- const textTitle = new UIText(vec2(0,-100), vec2(400, 60), 'LittleJS UI\nSystem Demo');
20
+ const textTitle = new UIText(vec2(0,-120), vec2(400, 60), 'LittleJS UI\nSystem Demo');
20
21
  uiMenu.addChild(textTitle);
21
22
 
22
23
  // example button
23
- const button1 = new UIButton(vec2(70,40), vec2(100), 'Test');
24
- button1.textHeight = 40;
24
+ const button1 = new UIButton(vec2(70,0), vec2(140, 80), 'Test');
25
+ button1.textHeight = 60;
25
26
  uiMenu.addChild(button1);
26
27
  button1.onClick = ()=> uiBackground.color = randColor();
27
28
 
28
29
  // example checkbox
29
- const checkbox = new UICheckbox(vec2(-70,40), vec2(50));
30
+ const checkbox = new UICheckbox(vec2(-70,0), vec2(50));
31
+ checkbox.onChange = ()=> button1.disabled = checkbox.checked;
30
32
  uiMenu.addChild(checkbox);
31
33
 
34
+ // example scrollbar
35
+ const scrollbar = new UIScrollbar(vec2(0,90), vec2(300, 50), soundVolume, 'Volume');
36
+ uiMenu.addChild(scrollbar);
37
+ scrollbar.onChange = ()=> setSoundVolume(scrollbar.value);
38
+
32
39
  // exit button
33
- const button2 = new UIButton(vec2(0,140), vec2(300, 50), 'Exit Menu');
40
+ const button2 = new UIButton(vec2(0,170), vec2(300, 50), 'Exit Menu');
34
41
  button2.textHeight = 40;
35
42
  uiMenu.addChild(button2);
36
43
  button2.onClick = ()=> uiMenu.visible = false;
@@ -7,7 +7,7 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- LittleJS Engine -->
10
- <script src=../../dist/littlejs.js?1133></script>
10
+ <script src=../../dist/littlejs.js?1136></script>
11
11
 
12
12
  <!-- LittleJS Engine Source
13
13
  <script src=../../src/engineDebug.js></script>
@@ -31,4 +31,4 @@
31
31
  -->
32
32
 
33
33
  <!-- Add your game scripts here -->
34
- <script src=game.js?1133></script>
34
+ <script src=game.js?1136></script>
@@ -21,7 +21,7 @@ import * as LJS from '../../dist/littlejs.esm.min.js';
21
21
  const {vec2, rgb} = LJS;
22
22
 
23
23
  // keep our own list of simple sprites and track fps
24
- let sprites, tileLayer, timeMS, fpsDisplay, statsDisplay, spriteColor, spriteAdditiveColor;
24
+ let sprites, tileLayer, timeMS, fpsDisplay, statsDisplay, spriteColor, spriteAdditiveColor, musicInstance;
25
25
 
26
26
  ///////////////////////////////////////////////////////////////////////////////
27
27
 
@@ -59,8 +59,13 @@ function gameInit()
59
59
  ///////////////////////////////////////////////////////////////////////////////
60
60
  function gameUpdate()
61
61
  {
62
- if (LJS.mouseWasPressed(0) && !music.getSource())
63
- music.play();
62
+ if (LJS.mouseWasPressed(0))
63
+ {
64
+ if (!musicInstance)
65
+ musicInstance = music.play();
66
+ else if (!musicInstance.isPlaying())
67
+ musicInstance.start();
68
+ }
64
69
 
65
70
  // mouse click = change color
66
71
  if (LJS.mouseWasPressed(0) || LJS.mouseIsDown(2))
@@ -30,22 +30,27 @@ iframe
30
30
  #selectExample
31
31
  {
32
32
  flex-grow: 1;
33
+ min-height: 100px;
34
+ }
35
+ #divTextareas
36
+ {
37
+ flex-grow: 1;
38
+ display: flex;
39
+ flex-direction: column;
40
+ min-height: 300px;
33
41
  }
34
42
  .CodeMirror,
35
43
  #textareaCode
36
44
  {
37
45
  flex-grow: 1;
38
- padding: 5px;
39
46
  resize: none;
40
47
  color: #fff;
41
48
  background: #000;
42
- font-size: 20px;
43
49
  }
44
50
  #textareaConsole,
45
51
  #textareaError
46
52
  {
47
53
  flex-grow: .3;
48
- padding: 5px;
49
54
  resize: none;
50
55
  display: none;
51
56
  color:#f22;
@@ -79,9 +84,10 @@ iframe
79
84
  {
80
85
  margin: 0px;
81
86
  text-align: center;
82
- font-size: 20px;
87
+ font-size: 15px;
83
88
  display: inline-block;
84
89
  align-self: center;
90
+ font-style: italic;
85
91
  }
86
92
  select
87
93
  {
@@ -117,6 +123,10 @@ input[type='checkbox']:disabled
117
123
  {
118
124
  background-color: #f004 !important;
119
125
  }
126
+ .nowrap
127
+ {
128
+ white-space:nowrap;
129
+ }
120
130
 
121
131
  /* LittleJS CodeMirror Theme */
122
132
  .cm-s-littlejs.CodeMirror { background: #080808; color: #aef; }
@@ -54,26 +54,26 @@ function createUI()
54
54
  // example tile image
55
55
  const tileTest = new LJS.UITile(vec2(150,-130), vec2(110), tile(3,128))
56
56
  uiMenu.addChild(tileTest);
57
-
58
- // example checkbox
59
- const checkbox = new LJS.UICheckbox(vec2(-140,-20), vec2(40));
60
- uiMenu.addChild(checkbox);
61
- checkbox.onChange = ()=> console.log('Checkbox clicked');
62
-
63
- // text attached to checkbox
64
- const checkboxText = new LJS.UIText(vec2(170,0), vec2(300, 40), 'Test Checkbox');
65
- checkbox.addChild(checkboxText);
66
-
67
57
  // example scrollbar
68
58
  const scrollbar = new LJS.UIScrollbar(vec2(0,60), vec2(350, 50));
69
59
  uiMenu.addChild(scrollbar);
70
- scrollbar.onChange = ()=> console.log('New scrollbar value:', scrollbar.value);
60
+ scrollbar.onChange = ()=> scrollbar.text = scrollbar.value.toFixed(2)
61
+ scrollbar.onChange();
71
62
 
72
63
  // example button
73
64
  const button1 = new LJS.UIButton(vec2(0,140), vec2(350, 50), 'Test Button');
74
65
  uiMenu.addChild(button1);
75
66
  button1.onClick = ()=> console.log('Button 1 clicked');
76
67
 
68
+ // example checkbox
69
+ const checkbox = new LJS.UICheckbox(vec2(-140,-20), vec2(40));
70
+ uiMenu.addChild(checkbox);
71
+ checkbox.onChange = ()=> button1.disabled = checkbox.checked;
72
+
73
+ // text attached to checkbox
74
+ const checkboxText = new LJS.UIText(vec2(170,0), vec2(300, 40), 'Test Checkbox');
75
+ checkbox.addChild(checkboxText);
76
+
77
77
  // exit button
78
78
  const button2 = new LJS.UIButton(vec2(0,220), vec2(350, 50), 'Exit Menu');
79
79
  uiMenu.addChild(button2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "littlejsengine",
3
- "version": "1.13.4",
3
+ "version": "1.14.2",
4
4
  "description": "LittleJS - Tiny and Fast HTML5 Game Engine",
5
5
  "main": "dist/littlejs.esm.js",
6
6
  "types": "dist/littlejs.d.ts",