littlejsengine 1.14.19 → 1.14.28

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 (70) hide show
  1. package/dist/littlejs.d.ts +217 -38
  2. package/dist/littlejs.esm.js +879 -324
  3. package/dist/littlejs.esm.min.js +1 -1
  4. package/dist/littlejs.js +861 -324
  5. package/dist/littlejs.min.js +1 -1
  6. package/dist/littlejs.release.js +799 -325
  7. package/examples/box2d/gameObjects.js +6 -10
  8. package/examples/box2d/scenes.js +2 -2
  9. package/examples/breakout/gameObjects.js +1 -1
  10. package/examples/electron/game.js +1 -41
  11. package/examples/electron/index.html +2 -2
  12. package/examples/htmlMenu/game.js +1 -1
  13. package/examples/index.html +19 -10
  14. package/examples/module/game.js +5 -7
  15. package/examples/particles/index.html +6 -9
  16. package/examples/platformer/gameCharacter.js +4 -3
  17. package/examples/platformer/gameEffects.js +7 -2
  18. package/examples/platformer/gameObjects.js +6 -11
  19. package/examples/shorts/animation.js +2 -2
  20. package/examples/shorts/base.html +4 -1
  21. package/examples/shorts/box2d.js +2 -2
  22. package/examples/shorts/box2dCar.js +18 -7
  23. package/examples/shorts/box2dPool.js +108 -0
  24. package/examples/shorts/cameraDrag.js +22 -0
  25. package/examples/shorts/debugDraw.js +37 -0
  26. package/examples/shorts/flappyGame.js +1 -0
  27. package/examples/shorts/fps.js +90 -0
  28. package/examples/shorts/helloWorld.js +1 -1
  29. package/examples/shorts/hillGlideGame.js +1 -3
  30. package/examples/shorts/input.js +59 -0
  31. package/examples/shorts/landerGame.js +1 -3
  32. package/examples/shorts/medals.js +15 -9
  33. package/examples/shorts/music.js +15 -17
  34. package/examples/shorts/musicPlayer.js +24 -24
  35. package/examples/shorts/platformer.js +0 -2
  36. package/examples/shorts/postProcess.js +1 -1
  37. package/examples/shorts/sequencer.js +3 -3
  38. package/examples/shorts/slidingPuzzle.js +1 -1
  39. package/examples/shorts/spaceGame.js +1 -3
  40. package/examples/shorts/spriteAtlas.js +6 -8
  41. package/examples/shorts/starfield.js +1 -1
  42. package/examples/shorts/tileRaycast.js +39 -0
  43. package/examples/shorts/tiles.png +0 -0
  44. package/examples/shorts/tiltedView.js +1 -4
  45. package/examples/shorts/timers.js +1 -2
  46. package/examples/shorts/topDown.js +0 -2
  47. package/examples/starter/game.js +5 -7
  48. package/examples/starter/index.html +2 -2
  49. package/examples/typescript/game.js +3 -2
  50. package/examples/typescript/game.ts +5 -7
  51. package/examples/uiSystem/game.js +2 -2
  52. package/package.json +1 -1
  53. package/plugins/box2d.js +170 -50
  54. package/plugins/pluginExport.js +2 -0
  55. package/plugins/uiSystem.js +55 -27
  56. package/src/engine.js +19 -16
  57. package/src/engineAudio.js +27 -15
  58. package/src/engineDebug.js +64 -0
  59. package/src/engineDraw.js +88 -32
  60. package/src/engineExport.js +16 -0
  61. package/src/engineInput.js +35 -25
  62. package/src/engineMedals.js +2 -2
  63. package/src/engineObject.js +55 -10
  64. package/src/engineParticles.js +36 -20
  65. package/src/engineRelease.js +2 -1
  66. package/src/engineSettings.js +20 -1
  67. package/src/engineTileLayer.js +64 -59
  68. package/src/engineUtilities.js +213 -59
  69. package/src/engineWebGL.js +13 -8
  70. package/examples/shorts/raycasting.js +0 -79
@@ -0,0 +1,108 @@
1
+ const hitSound = new Sound([,,2e3,,,.01]);
2
+ const maxHitDistance = 6;
3
+
4
+ class Ball extends Box2dObject
5
+ {
6
+ constructor(position, number=0)
7
+ {
8
+ const color = hsl(number/9, 1, number? .5 : 1);
9
+ super(position, vec2(), 0, 0, color);
10
+ this.number = number;
11
+
12
+ // setup pool ball physics
13
+ const friction = 0, restitution = .95;
14
+ this.addCircle(1, vec2(), 1, friction, restitution);
15
+ this.setLinearDamping(.4);
16
+ this.setBullet(true);
17
+ this.setFixedRotation(true);
18
+ }
19
+ beginContact()
20
+ {
21
+ const volume = clamp(this.getSpeed()/20);
22
+ hitSound.play(this.pos, clamp(this.getSpeed()/20));
23
+ }
24
+ canHit() { return this == cueBall && this.getSpeed() < 1; }
25
+ getHitOffset()
26
+ {
27
+ // hit from cue ball to mouse position
28
+ const deltaPos = mousePos.subtract(this.pos);
29
+ const length = min(deltaPos.length(), maxHitDistance);
30
+ return deltaPos.normalize(length);
31
+ }
32
+ update()
33
+ {
34
+ if (this.canHit() && mouseWasPressed(0))
35
+ {
36
+ // hit the cue ball
37
+ const accel = this.getHitOffset().scale(8);
38
+ this.applyAcceleration(accel);
39
+ hitSound.play(cueBall.pos);
40
+ }
41
+ if (this.pocketed)
42
+ this.destroy();
43
+ }
44
+ render()
45
+ {
46
+ super.render();
47
+
48
+ // draw white circle and ball number
49
+ drawCircle(this.pos, .6, WHITE);
50
+ const textPos = this.pos.add(vec2(0,-.06));
51
+ if (this.number)
52
+ drawTextOverlay(this.number, textPos, .5, BLACK);
53
+ if (this.canHit())
54
+ {
55
+ // draw the aim line
56
+ const offset = this.getHitOffset();
57
+ const endPos = this.pos.add(offset);
58
+ const width = offset.length()/maxHitDistance;
59
+ drawLine(this.pos, endPos, width, hsl(0,1,.5,.5),
60
+ vec2(), 0, false, false, overlayContext);
61
+ }
62
+ }
63
+ }
64
+
65
+ class Pocket extends Box2dStaticObject
66
+ {
67
+ constructor(pos, size)
68
+ {
69
+ super(pos, size, 0, 0, BLACK);
70
+
71
+ // create a sensor circle for pocket
72
+ this.addCircle(size.x);
73
+ this.setSensor(true);
74
+ }
75
+ render()
76
+ {
77
+ // add ball size to pocket size for drawing
78
+ drawCircle(this.pos, this.size.x + 1, BLACK);
79
+ }
80
+ beginContact(other) { other.pocketed = 1; }
81
+ }
82
+
83
+ async function gameInit()
84
+ {
85
+ // setup box2d
86
+ await box2dInit();
87
+ canvasClearColor = hsl(.4,.5,.5);
88
+
89
+ // create table walls
90
+ const groundObject = new Box2dStaticObject;
91
+ groundObject.color = hsl(.1,1,.2);
92
+ groundObject.addBox(vec2(100,3), vec2( 0, 8.5));
93
+ groundObject.addBox(vec2(100,3), vec2( 0,-8.5));
94
+ groundObject.addBox(vec2(3,100), vec2( 15,0));
95
+ groundObject.addBox(vec2(3,100), vec2(-15,0));
96
+
97
+ // create pockets
98
+ for (let j=0; j<2; ++j)
99
+ for (let i=0; i<3; ++i)
100
+ new Pocket(vec2(i-1, j-.5).scale(13), vec2(.5));
101
+
102
+ // create balls
103
+ let number = 1;
104
+ for (let i=5; i--;)
105
+ for (let j=i+1; j--;)
106
+ new Ball(vec2(6+i*.9, j-i/2), number++);
107
+ cueBall = new Ball(vec2(-6, 0));
108
+ }
@@ -0,0 +1,22 @@
1
+ function gameInit()
2
+ {
3
+ // create some objects
4
+ for (let i=500; i--;)
5
+ {
6
+ const pos = randInCircle(100);
7
+ const size = vec2(rand(2,9),rand(2,9));
8
+ const color = randColor();
9
+ const angle = rand(PI);
10
+ new EngineObject(pos, size, 0, angle, color);
11
+ }
12
+ }
13
+
14
+ function gameUpdate()
15
+ {
16
+ // drag camera with mouse
17
+ if (mouseIsDown(0))
18
+ cameraPos = cameraPos.subtract(mouseDelta);
19
+
20
+ // zoom camera with mouse wheel
21
+ cameraScale = clamp(cameraScale*(1-mouseWheel/5), 1, 1e3);
22
+ }
@@ -0,0 +1,37 @@
1
+ class BounceObject extends EngineObject
2
+ {
3
+ constructor(pos, size, tile)
4
+ {
5
+ super(pos, size, tile);
6
+ this.velocity = vec2(.1);
7
+ }
8
+
9
+ update()
10
+ {
11
+ // show debug info
12
+ debugText('Debug Text', this.pos.add(vec2(0,3)), 1, WHITE);
13
+ debugRect(this.pos, this.size, RED);
14
+ const trianglePoints = [vec2(-2,-1), vec2(0,2), vec2(2,-1)];
15
+ debugPoly(mousePos, trianglePoints, YELLOW);
16
+ debugLine(this.pos, mousePos, BLUE);
17
+
18
+ // bounce off screen edges
19
+ const cameraSize = getCameraSize();
20
+ if (abs(this.pos.x) > cameraSize.x/2)
21
+ {
22
+ debugCircle(this.pos, 3, GREEN, 1);
23
+ this.velocity.x = -this.velocity.x;
24
+ }
25
+ if (abs(this.pos.y) > cameraSize.y/2)
26
+ {
27
+ debugCircle(this.pos, 3, GREEN, 1);
28
+ this.velocity.y = -this.velocity.y;
29
+ }
30
+ }
31
+ }
32
+
33
+ function gameInit()
34
+ {
35
+ canvasClearColor = GRAY;
36
+ new BounceObject(vec2(), vec2(5), tile(3,128));
37
+ }
@@ -4,6 +4,7 @@ class Wall extends EngineObject
4
4
  {
5
5
  super(pos, size, 0, 0, hsl(.3,.5,.3));
6
6
  this.setCollision(); // make object collide
7
+ this.mass = 0;
7
8
  }
8
9
  update()
9
10
  {
@@ -0,0 +1,90 @@
1
+ let playerPos = vec2(), playerAngle = 0;
2
+ setTileFixBleedScale(0);
3
+
4
+ // a simple function to create the level
5
+ const levelTest = (p)=> (floor(p.x)**3&floor(p.y)**2)%30>5;
6
+
7
+ function gameUpdate()
8
+ {
9
+ // update camera angle with mouse pointer lock
10
+ if (mouseWasPressed(0))
11
+ pointerLockRequest();
12
+ if (keyWasPressed('Escape'))
13
+ pointerLockExit()
14
+ if (pointerLockIsActive() || isTouchDevice)
15
+ playerAngle += mouseDelta.x * .03;
16
+
17
+ // update player movement, prevent walking through walls
18
+ const velocity = keyDirection().rotate(playerAngle).scale(.05);
19
+ const normal = vec2();
20
+ let newPos = playerPos.add(velocity);
21
+ if (lineTest(playerPos, newPos, levelTest, normal))
22
+ {
23
+ // adjust velocity to slide along wall
24
+ const d = velocity.dot(normal);
25
+ newPos = newPos.subtract(vec2(d*normal.x, d*normal.y));
26
+ if (!levelTest(newPos))
27
+ playerPos = newPos;
28
+ }
29
+ else
30
+ playerPos = newPos;
31
+ }
32
+
33
+ function gameRender()
34
+ {
35
+ {
36
+ // draw horizontal slizes to create floor and ceiling
37
+ const h = 9;
38
+ let pos = vec2(), size = vec2(39, .15), color = rgb();
39
+ for (let y=-h; y<h; y+=.1)
40
+ {
41
+ const p = 1.01 - abs(y/h)
42
+ color.setHSLA(.1, y>0?0:.5, .7-p*.7);
43
+ pos.y = y;
44
+ drawRect(pos, size, color);
45
+ }
46
+ }
47
+ {
48
+ // draw vertical slices to create the walls
49
+ // create objects in advance for optimal performance
50
+ const w = 15;
51
+ const maxDistance = 50;
52
+ const pos = vec2(), endPos = vec2(), size = vec2(.15);
53
+ const tileInfo = new TileInfo(vec2(), vec2(0,16));
54
+ const normal = vec2(), light = vec2().setAngle(2);
55
+ const color = rgb();
56
+ for (pos.x=-w; pos.x<w; pos.x+=.1)
57
+ {
58
+ // cast ray for this slice
59
+ const angle = playerAngle + pos.x/w/2;
60
+ endPos.setAngle(angle, maxDistance);
61
+ endPos.x += playerPos.x;
62
+ endPos.y += playerPos.y;
63
+ const p = lineTest(playerPos, endPos, levelTest, normal);
64
+ if (!p) continue;
65
+
66
+ // get texture coordinate
67
+ const t = mod(p.x+p.y, 1);
68
+ tileInfo.pos.x = 161 + 14*t;
69
+
70
+ // apply fog and lighting
71
+ const d = p.distance(playerPos)/maxDistance;
72
+ const l = max(0, normal.dot(light));
73
+ size.y = .5/d;
74
+ color.setHSLA(.6, 1-d, .7-d+l*.3);
75
+
76
+ // draw the section the wall
77
+ drawTile(pos, size, tileInfo, color);
78
+ }
79
+ }
80
+
81
+ // draw instructions and pointer lock status
82
+ const instructions = pointerLockIsActive() ?
83
+ 'Mouse Control Active - ESC To Exit' :
84
+ 'Click To Enable Mouse Control';
85
+ const textPos = vec2(mainCanvasSize.x/2, 50);
86
+ const textSize = 30;
87
+ const textColor = pointerLockIsActive() ? GREEN : WHITE;
88
+ if (!isTouchDevice)
89
+ drawTextScreen(instructions, textPos, textSize, textColor);
90
+ }
@@ -7,5 +7,5 @@ function gameRender()
7
7
  drawTextOverlay('LittleJS Engine', vec2(0,3), 3);
8
8
 
9
9
  // draw a tile
10
- drawTile(vec2(Math.sin(time)*3,-2), vec2(7), tile(3,128));
10
+ drawTile(vec2(sin(time)*3,-2), vec2(7), tile(3,128));
11
11
  }
@@ -9,8 +9,6 @@ class Player extends EngineObject
9
9
 
10
10
  update()
11
11
  {
12
- super.update();
13
-
14
12
  // check ground height
15
13
  const h = getGroundHeight(this.pos.x);
16
14
  if (this.pos.y < h + this.size.y/2)
@@ -35,7 +33,7 @@ class Player extends EngineObject
35
33
 
36
34
  function getGroundHeight(x)
37
35
  {
38
- return Math.sin(x/4)*2 + Math.sin(x/17);
36
+ return sin(x/4)*2 + sin(x/17);
39
37
  }
40
38
 
41
39
  function gameInit()
@@ -0,0 +1,59 @@
1
+ function gameUpdate()
2
+ {
3
+ if (isUsingGamepad)
4
+ {
5
+ debugText('Gamepad Mode', vec2(0,4));
6
+
7
+ // analog sticks
8
+ for (let i=2; i--;)
9
+ {
10
+ const stick = gamepadStick(i);
11
+ const pos = vec2(i?2:-2, 1);
12
+ debugCircle(pos, 2, WHITE);
13
+ debugLine(pos, pos.add(stick), GREEN);
14
+ }
15
+
16
+ // buttons
17
+ for (let i=16; i--;)
18
+ {
19
+ const pos = vec2(-1.5 + i%4, -2 - (i/4|0));
20
+ if (gamepadIsDown(i))
21
+ debugCircle(pos, 1, RED, 0, 1);
22
+ debugCircle(pos, 1, WHITE);
23
+ }
24
+ }
25
+ else if (isTouchDevice)
26
+ {
27
+ debugText('Touch Mode', vec2(0,4));
28
+
29
+ // touch input routed to mouse
30
+ if (mouseIsDown(0))
31
+ debugCircle(mousePos, 4, RED, 0, 1);
32
+ debugCircle(mousePos, 4, WHITE);
33
+ }
34
+ else
35
+ {
36
+ debugText('Mouse and Keyboard Mode', vec2(0,4));
37
+
38
+ // keyboard key (space bar)
39
+ debugRect(vec2(), vec2(2), WHITE);
40
+ if (keyIsDown('Space'))
41
+ debugRect(vec2(), vec2(2), RED, 0, 0, 1);
42
+
43
+ // keyboard direction (arrow keys or WASD)
44
+ const inputDirection = keyDirection();
45
+ debugLine(vec2(), inputDirection, GREEN);
46
+
47
+ // mouse pos
48
+ debugPoint(mousePos, mouseIsDown(0) ? RED : YELLOW);
49
+
50
+ // mouse buttons
51
+ for (let i=3; i--;)
52
+ {
53
+ const pos = vec2(-1 + i, -3);
54
+ if (mouseIsDown(i))
55
+ debugCircle(pos, 1, RED, 0, 1);
56
+ debugCircle(pos, 1, WHITE);
57
+ }
58
+ }
59
+ }
@@ -9,12 +9,10 @@ class Player extends EngineObject
9
9
 
10
10
  update()
11
11
  {
12
- super.update();
13
-
14
12
  // space ship controls
15
13
  const moveInput = keyDirection();
16
14
  this.applyAngularAcceleration(moveInput.x * .002);
17
- const accel = vec2(0, moveInput.y*.002).rotate(this.angle);
15
+ const accel = this.getUp(moveInput.y*.002);
18
16
  this.applyAcceleration(accel);
19
17
  }
20
18
 
@@ -4,19 +4,25 @@ const medal_leftClick = new Medal(1, 'Lefty', 'Left clicked!', '🐁');
4
4
  const medal_rightClick = new Medal(2, 'Righty', 'Right clicked!', '🐭');
5
5
  const medal_spacePressed = new Medal(3, 'Space', 'Pressed spacebar!', '🚀');
6
6
 
7
- // setup medals
8
- const saveName = 'Medals Example';
9
- medalsInit(saveName);
7
+ function gameInit()
8
+ {
9
+ // setup medals
10
+ const saveName = 'Medals Example';
11
+ medalsInit(saveName);
12
+
13
+ // clear unlocked medals for testing
14
+ medalsForEach(medal=> medal.unlocked = false);
10
15
 
11
- // clear medals for testing
12
- medalsForEach(medal=> medal.unlocked = false);
13
- medal_openedExample.unlock();
16
+ // unlock the example medal
17
+ medal_openedExample.unlock();
14
18
 
15
- // set background color
16
- canvasClearColor = hsl(.5,.3,.2);
19
+ // set background color
20
+ canvasClearColor = hsl(.5,.3,.2);
21
+ }
17
22
 
18
23
  function gameUpdate()
19
24
  {
25
+ // unlock example medals based on input
20
26
  if (mouseWasPressed(0))
21
27
  medal_leftClick.unlock();
22
28
  if (mouseWasPressed(2))
@@ -25,7 +31,7 @@ function gameUpdate()
25
31
  medal_spacePressed.unlock();
26
32
  }
27
33
 
28
- function gameRender()
34
+ function gameRenderPost()
29
35
  {
30
36
  const size = 80;
31
37
  let pos = mainCanvasSize.scale(.5).subtract(vec2(0,40));
@@ -1,7 +1,5 @@
1
- let musicPlayer, playButton, stopButton, infoText;
2
- let musicSound = new SoundWave('song.mp3');
3
- let musicVolume = 1;
4
- let music;
1
+ const musicSound = new SoundWave('song.mp3');
2
+ let musicVolume = 1, musicInstance;
5
3
 
6
4
  function gameInit()
7
5
  {
@@ -13,7 +11,8 @@ function gameInit()
13
11
  canvasClearColor = hsl(.9,.3,.2);
14
12
 
15
13
  // setup music player UI
16
- musicPlayer = new UIObject(mainCanvasSize.scale(.5), vec2(500, 220));
14
+ const center = mainCanvasSize.scale(.5);
15
+ musicPlayer = new UIObject(center, vec2(500, 220));
17
16
 
18
17
  // infomation text
19
18
  infoText = new UIText(vec2(0, -70), vec2(400, 50));
@@ -26,8 +25,7 @@ function gameInit()
26
25
  volumeSlider.onChange = () =>
27
26
  {
28
27
  musicVolume = volumeSlider.value;
29
- if (music)
30
- music.setVolume(musicVolume);
28
+ musicInstance?.setVolume(musicVolume);
31
29
  };
32
30
 
33
31
  // play button
@@ -39,17 +37,17 @@ function gameInit()
39
37
  return;
40
38
 
41
39
  // handle play/pause toggle
42
- if (!music)
43
- music = musicSound.playMusic(musicVolume);
44
- else if (music.isPaused())
45
- music.resume();
40
+ if (!musicInstance)
41
+ musicInstance = musicSound.playMusic(musicVolume);
42
+ else if (musicInstance.isPaused())
43
+ musicInstance.resume();
46
44
  else
47
- music.pause();
45
+ musicInstance.pause();
48
46
  };
49
47
 
50
48
  // stop button
51
49
  stopButton = new UIButton(vec2(90, 50), vec2(140, 50), 'Stop');
52
- stopButton.onClick = ()=> music && music.stop();
50
+ stopButton.onClick = ()=> musicInstance?.stop();
53
51
  musicPlayer.addChild(stopButton);
54
52
  }
55
53
 
@@ -69,10 +67,10 @@ function gameUpdate()
69
67
  else
70
68
  {
71
69
  // update ui text
72
- const isPlaying = music && music.isPlaying();
70
+ const isPlaying = musicInstance?.isPlaying();
73
71
  playButton.text = isPlaying ? 'Pause' : 'Play';
74
- const current = music ? music.getCurrentTime() : 0;
75
- const duration = musicSound.getDuration();
76
- infoText.text = formatTime(current) +' / '+ formatTime(duration);
72
+ const current = formatTime(musicInstance?.getCurrentTime());
73
+ const duration = formatTime(musicSound.getDuration());
74
+ infoText.text = current + ' / ' + duration;
77
75
  }
78
76
  }
@@ -1,6 +1,5 @@
1
- let musicPlayer, playButton, stopButton, progressBar;
2
- let musicSound, music;
3
- let musicVolume = 1;
1
+
2
+ let musicVolume = 1, musicSound, musicInstance;
4
3
 
5
4
  function gameInit()
6
5
  {
@@ -13,7 +12,8 @@ function gameInit()
13
12
  canvasClearColor = hsl(.9,.3,.2);
14
13
 
15
14
  // setup music player UI
16
- musicPlayer = new UIObject(mainCanvasSize.scale(.5), vec2(500, 300));
15
+ const center = mainCanvasSize.scale(.5);
16
+ musicPlayer = new UIObject(center, vec2(500, 300));
17
17
  const title = new UIText(vec2(0, -100), vec2(500, 40),
18
18
  'LittleJS Music Player');
19
19
  musicPlayer.addChild(title);
@@ -21,7 +21,7 @@ function gameInit()
21
21
  // drop zone text
22
22
  const dropZoneText = new UIText(vec2(0, -60), vec2(450, 20),
23
23
  'Drag & Drop Audio Files Here!');
24
- dropZoneText.textColor = hsl(.9, .3, .8, .7);
24
+ dropZoneText.textColor = GRAY;
25
25
  musicPlayer.addChild(dropZoneText);
26
26
 
27
27
  // volume slider
@@ -31,8 +31,7 @@ function gameInit()
31
31
  volumeSlider.onChange = () =>
32
32
  {
33
33
  musicVolume = volumeSlider.value;
34
- if (music)
35
- music.setVolume(musicVolume);
34
+ musicInstance?.setVolume(musicVolume);
36
35
  };
37
36
 
38
37
  // play button
@@ -44,17 +43,17 @@ function gameInit()
44
43
  return;
45
44
 
46
45
  // handle play/pause toggle
47
- if (!music)
48
- music = musicSound.playMusic(musicVolume);
49
- else if (music.isPaused())
50
- music.resume();
46
+ if (!musicInstance)
47
+ musicInstance = musicSound.playMusic(musicVolume);
48
+ else if (musicInstance.isPaused())
49
+ musicInstance.resume();
51
50
  else
52
- music.pause();
51
+ musicInstance.pause();
53
52
  };
54
53
 
55
54
  // stop button
56
55
  stopButton = new UIButton(vec2(90, 50), vec2(140, 50), 'Stop');
57
- stopButton.onClick = ()=> music && music.stop();
56
+ stopButton.onClick = ()=> musicInstance?.stop();
58
57
  musicPlayer.addChild(stopButton);
59
58
 
60
59
  // progress bar and scrollbar for seeking
@@ -63,14 +62,14 @@ function gameInit()
63
62
  progressBar.onChange = ()=>
64
63
  {
65
64
  // control music seek position
66
- const wasPlaying = music && music.isPlaying();
67
- if (!music)
68
- music = musicSound.playMusic(musicVolume, true, true);
65
+ const wasPlaying = musicInstance?.isPlaying();
66
+ if (!musicInstance)
67
+ musicInstance = musicSound.playMusic(musicVolume, 1, 1);
69
68
  progressBar.value = min(progressBar.value, .999); // prevent wrap
70
69
  const seekTime = progressBar.value * musicSound.getDuration();
71
- music.start(seekTime);
70
+ musicInstance.start(seekTime);
72
71
  if (!wasPlaying)
73
- music.pause();
72
+ musicInstance.pause();
74
73
  };
75
74
  musicPlayer.addChild(progressBar);
76
75
 
@@ -93,8 +92,8 @@ function gameInit()
93
92
  dropZoneText.text = file.name;
94
93
 
95
94
  // reset UI
96
- music && music.stop();
97
- music = undefined;
95
+ musicInstance?.stop();
96
+ musicInstance = undefined;
98
97
  progressBar.value = 0;
99
98
  }
100
99
  uiSystem.setupDragAndDrop(onDrop, onDragEnter, onDragLeave);
@@ -124,12 +123,13 @@ function gameUpdate()
124
123
  else
125
124
  {
126
125
  // update ui text
127
- const isPlaying = music && music.isPlaying();
126
+ const isPlaying = musicInstance?.isPlaying();
128
127
  playButton.text = isPlaying ? 'Pause' : 'Play';
129
- const current = music ? music.getCurrentTime() : 0;
128
+ const current = musicInstance?.getCurrentTime() || 0;
130
129
  const duration = musicSound.getDuration();
131
- progressBar.text = formatTime(current) +' / '+ formatTime(duration);
132
- if (!progressBar.mouseIsHeld)
130
+ progressBar.text = formatTime(current) +
131
+ ' / ' + formatTime(duration);
132
+ if (!progressBar.isActiveObject())
133
133
  progressBar.value = current / duration;
134
134
  }
135
135
  }
@@ -8,8 +8,6 @@ class Player extends EngineObject
8
8
 
9
9
  update()
10
10
  {
11
- super.update();
12
-
13
11
  // apply movement controls
14
12
  const moveInput = keyDirection();
15
13
  this.velocity.x += moveInput.x * (this.groundObject ? .1: .01);
@@ -6,7 +6,7 @@ function gameInit()
6
6
  function gameRender()
7
7
  {
8
8
  drawRect(vec2(), vec2(99), GRAY);
9
- drawTile(vec2(Math.sin(time)*3, 0), vec2(12), tile(3,128));
9
+ drawTile(vec2(sin(time)*3, 0), vec2(12), tile(3,128));
10
10
  }
11
11
 
12
12
  const tvShader = `
@@ -34,7 +34,7 @@ class UISequencerButton extends UIButton
34
34
  this.hue = track*.15;
35
35
  if (track >= pianoStart)
36
36
  {
37
- const octave = Math.floor((track-pianoStart) / scale.length);
37
+ const octave = floor((track-pianoStart) / scale.length);
38
38
  const scaleNote = (track-pianoStart) % scale.length;
39
39
  this.semitone = scale[scaleNote] + 12*octave;
40
40
  this.sound = sound_piano;
@@ -93,7 +93,7 @@ function gameInit()
93
93
  tempoSlider.onChange = ()=>
94
94
  {
95
95
  tempo = lerp(minTempo, maxTempo, tempoSlider.value);
96
- tempo = Math.floor(tempo/10) * 10; // round to nearest 10th
96
+ tempo = floor(tempo/10) * 10; // round to nearest 10th
97
97
  tempoSlider.text = `${tempo} BPM`;
98
98
  };
99
99
  tempoSlider.onChange();
@@ -108,7 +108,7 @@ function gameUpdate()
108
108
  const lastStepTime = stepTime;
109
109
  const lastStep = currentStep;
110
110
  stepTime += timeDelta*tempo/60;
111
- currentStep = Math.floor(stepTime) % stepCount;
111
+ currentStep = floor(stepTime) % stepCount;
112
112
  if (currentStep == lastStep && lastStepTime)
113
113
  return;
114
114
 
@@ -20,7 +20,7 @@ class PuzzlePiece extends EngineObject
20
20
  const deltaX = emptyGridPos.x - this.gridPos.x;
21
21
  const deltaY = emptyGridPos.y - this.gridPos.y;
22
22
  if (mouseWasPressed(0))
23
- if (isOverlapping(this.pos, this.size, mousePos))
23
+ if (this.isOverlapping(mousePos))
24
24
  if (abs(deltaX) + abs(deltaY) === 1)
25
25
  {
26
26
  // swap with empty space when clicked on
@@ -10,8 +10,6 @@ class Player extends EngineObject
10
10
 
11
11
  update()
12
12
  {
13
- super.update();
14
-
15
13
  // space ship controls
16
14
  const moveInput = keyDirection();
17
15
  this.applyAngularAcceleration(moveInput.x * .005);
@@ -23,7 +21,7 @@ class Player extends EngineObject
23
21
  // shoot bullet
24
22
  const pos = this.pos.add(vec2(0,1).rotate(cameraAngle));
25
23
  const bullet = new EngineObject(pos, vec2(.2,.5), 0, this.angle);
26
- bullet.velocity = vec2(0,.5).rotate(this.angle);
24
+ bullet.velocity = this.getUp(.5);
27
25
  bullet.velocity = bullet.velocity.add(this.velocity);
28
26
  this.shootTimer.set(.1);
29
27
  }