littlejsengine 1.14.10 → 1.14.16

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 (76) hide show
  1. package/dist/littlejs.d.ts +264 -120
  2. package/dist/littlejs.esm.js +603 -288
  3. package/dist/littlejs.esm.min.js +1 -1
  4. package/dist/littlejs.js +600 -287
  5. package/dist/littlejs.min.js +1 -1
  6. package/dist/littlejs.release.js +521 -232
  7. package/examples/box2d/gameObjects.js +2 -2
  8. package/examples/breakout/gameObjects.js +2 -2
  9. package/examples/breakoutTutorial/README.md +32 -32
  10. package/examples/breakoutTutorial/game.js +1 -1
  11. package/examples/electron/game.js +3 -3
  12. package/examples/electron/index.html +2 -2
  13. package/examples/electron/package.json +1 -8
  14. package/examples/index.html +59 -51
  15. package/examples/module/game.js +3 -3
  16. package/examples/platformer/gameCharacter.js +6 -2
  17. package/examples/platformer/gameEffects.js +4 -4
  18. package/examples/platformer/gameLevel.js +1 -1
  19. package/examples/platformer/gameObjects.js +11 -9
  20. package/examples/puzzle/game.js +1 -1
  21. package/examples/shorts/animation.js +1 -1
  22. package/examples/shorts/base.html +1 -1
  23. package/examples/shorts/blending.js +8 -14
  24. package/examples/shorts/box2d.js +7 -3
  25. package/examples/shorts/box2dCar.js +2 -1
  26. package/examples/shorts/empty.js +30 -0
  27. package/examples/shorts/helloWorld.js +1 -1
  28. package/examples/shorts/hillGlideGame.js +10 -4
  29. package/examples/shorts/landerGame.js +30 -3
  30. package/examples/shorts/medals.js +4 -4
  31. package/examples/shorts/music.js +29 -55
  32. package/examples/shorts/musicPlayer.js +134 -0
  33. package/examples/shorts/nineSlice.js +34 -15
  34. package/examples/shorts/parallax.js +4 -3
  35. package/examples/shorts/particles.js +16 -16
  36. package/examples/shorts/piano.js +15 -21
  37. package/examples/shorts/pongGame.js +6 -4
  38. package/examples/shorts/raycasting.js +13 -5
  39. package/examples/shorts/sequencer.js +122 -0
  40. package/examples/shorts/shapes.js +7 -4
  41. package/examples/shorts/slidingPuzzle.js +16 -6
  42. package/examples/shorts/sound.js +18 -9
  43. package/examples/shorts/spaceGame.js +12 -8
  44. package/examples/shorts/spriteAtlas.js +7 -7
  45. package/examples/shorts/starfield.js +1 -1
  46. package/examples/shorts/systemFont.js +2 -2
  47. package/examples/shorts/texture.js +2 -2
  48. package/examples/shorts/tileLayer.js +10 -10
  49. package/examples/shorts/tiltedView.js +14 -3
  50. package/examples/shorts/timers.js +10 -0
  51. package/examples/shorts/topDown.js +4 -1
  52. package/examples/shorts/uiSystem.js +8 -5
  53. package/examples/starter/game.js +3 -3
  54. package/examples/starter/index.html +2 -2
  55. package/examples/typescript/game.js +3 -3
  56. package/examples/typescript/game.ts +3 -3
  57. package/examples/uiSystem/game.js +6 -6
  58. package/package.json +4 -2
  59. package/plugins/box2d.js +18 -3
  60. package/plugins/newgrounds.js +11 -9
  61. package/plugins/postProcess.js +5 -2
  62. package/plugins/uiSystem.js +120 -34
  63. package/plugins/zzfxm.js +5 -1
  64. package/reference.md +1 -3
  65. package/src/engine.js +52 -21
  66. package/src/engineAudio.js +31 -14
  67. package/src/engineDebug.js +80 -55
  68. package/src/engineDraw.js +60 -31
  69. package/src/engineExport.js +3 -1
  70. package/src/engineMedals.js +10 -2
  71. package/src/engineObject.js +14 -10
  72. package/src/engineParticles.js +59 -46
  73. package/src/engineRelease.js +1 -0
  74. package/src/engineSettings.js +7 -7
  75. package/src/engineTileLayer.js +49 -18
  76. package/src/engineUtilities.js +79 -34
@@ -23,7 +23,7 @@ class ParallaxLayer extends CanvasLayer
23
23
  const w = canvasSize.x, h = canvasSize.y;
24
24
  for (let i = h; i--;)
25
25
  {
26
- // draw a 1 pixel gradient line on the left side of the canvas
26
+ // draw a 1 pixel gradient line on the left side
27
27
  const p = i/h;
28
28
  this.context.fillStyle = topColor.lerp(bottomColor, p);
29
29
  this.context.fillRect(0, i, 1, 1);
@@ -34,7 +34,8 @@ class ParallaxLayer extends CanvasLayer
34
34
  const levelness = .005; // how much the mountains level out
35
35
  const slopeRange = 1; // max slope of the mountains
36
36
  const startGroundLevel = h/2;
37
- let y = startGroundLevel, groundSlope = rand(-slopeRange, slopeRange);
37
+ let y = startGroundLevel;
38
+ let groundSlope = rand(-slopeRange, slopeRange);
38
39
  for (let x=w; x--;)
39
40
  {
40
41
  // pull slope towards start ground level
@@ -45,7 +46,7 @@ class ParallaxLayer extends CanvasLayer
45
46
  groundSlope = rand(-slopeRange, slopeRange);
46
47
 
47
48
  // draw 1 pixel wide vertical slice of mountain
48
- this.context.drawImage(this.canvas, 0, 0, 1, h, x, y, 1, h - y);
49
+ this.context.drawImage(this.canvas, 0,0,1,h,x,y,1,h-y);
49
50
  }
50
51
 
51
52
  // remove gradient sliver from left side
@@ -4,25 +4,25 @@ function gameInit()
4
4
 
5
5
  // fire
6
6
  new ParticleEmitter(
7
- vec2(-5,-2), 0, // pos, angle
8
- 2, 0, 200, PI, // emitSize, emitTime, emitRate, emitCone
9
- tile(0), // tileInfo
10
- rgb(1,.5,.1), rgb(1,.1,.1), // colorStartA, colorStartB
11
- rgb(1,.5,.1,0), rgb(1,.1,.1,0), // colorEndA, colorEndB
12
- .7, 2, 0, .2, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
13
- .9, 1, -1, PI, .05, // damp, angleDamp, gravity, particleCone, fade
14
- .5, 0, 1, 0 // randomness, collide, additive, colorLinear
7
+ vec2(-5,-2), 0, // pos, angle
8
+ 2, 0, 200, PI, // emitSize, emitTime, rate, cone
9
+ tile(0), // tileInfo
10
+ rgb(1,.5,.1), rgb(1,.1,.1), // colorStartA, colorStartB
11
+ rgb(1,.5,.1,0), rgb(1,.1,.1,0),// colorEndA, colorEndB
12
+ .7, 2, 0, .2, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
13
+ .9, 1, -1, PI, .05,// damp, angleDamp, gravity, particleCone, fade
14
+ .5, 0, 1, 0 // randomness, collide, additive, colorLinear
15
15
  );
16
16
 
17
17
  // smoke
18
18
  new ParticleEmitter(
19
- vec2(-5,-2), 0, // pos, angle
20
- 3, 0, 100, PI, // emitSize, emitTime, emitRate, emitCone
21
- tile(0), // tileInfo
22
- hsl(0,0,0,.5), hsl(0,0,1,.5), // colorStartA, colorStartB
23
- hsl(0,0,0,0), hsl(0,0,1,0), // colorEndA, colorEndB
24
- 1, 1, 5, .2, .01, // time, sizeStart, sizeEnd, speed, angleSpeed
25
- .85, 1, -1, PI, .3, // damp, angleDamp, gravity, particleCone, fade
26
- .5, 0, 0, 1 // randomness, collide, additive, colorLinear
19
+ vec2(5,-2), 0, // pos, angle
20
+ 3, 0, 100, PI, // emitSize, emitTime, rate, cone
21
+ tile(0), // tileInfo
22
+ hsl(0,0,0,.5), hsl(0,0,1,.5),// colorStartA, colorStartB
23
+ hsl(0,0,0,0), hsl(0,0,1,0), // colorEndA, colorEndB
24
+ 1, 1, 5, .2, .01, // time, sizeStart, sizeEnd, speed, angleSpeed
25
+ .85, 1, -1, PI, .3,// damp, angleDamp, gravity, particleCone, fade
26
+ .5, 0, 0, 1 // randomness, collide, additive, colorLinear
27
27
  );
28
28
  }
@@ -2,29 +2,21 @@ const pianoSound = new Sound([,0,220,,9]);
2
2
 
3
3
  class PianoKey extends UIButton
4
4
  {
5
- constructor(pos, size, semitone, isWhite)
5
+ constructor(pos, size, semitone, color, hoverColor)
6
6
  {
7
7
  const keySize = 65;
8
8
  size = size.scale(keySize);
9
9
  pos = pos.scale(keySize).add(vec2(0,size.y/2-keySize*2));
10
10
  pos = pos.add(mainCanvasSize.scale(.5));
11
- super(pos, size, '', hsl(0,0,isWhite ? 1 : .3));
12
- this.semitone = semitone;
11
+ super(pos, size, '', color);
12
+
13
13
  this.dragActivate = true;
14
- this.hoverColor = hsl(0,1,isWhite ? .9 : .3);
14
+ this.semitone = semitone;
15
+ this.hoverColor = hoverColor;
15
16
  this.activeColor = RED;
16
17
  }
17
- onPress()
18
- {
19
- if (!this.soundInstance)
20
- this.soundInstance = pianoSound.playNote(this.semitone);
21
- }
22
- onRelease()
23
- {
24
- if (this.soundInstance)
25
- this.soundInstance.stop(.2);
26
- this.soundInstance = 0;
27
- }
18
+ onPress() { this.sound = pianoSound.playNote(this.semitone); }
19
+ onRelease() { this.sound.stop(.2); }
28
20
  }
29
21
 
30
22
  function gameInit()
@@ -35,16 +27,18 @@ function gameInit()
35
27
  // create piano keyboard
36
28
  for (let i=15; i--;)
37
29
  {
38
- const pos = vec2(i-7,0);
39
- const size = vec2(1,4);
30
+ // white keys
31
+ const pos = vec2(i-7, 0);
32
+ const size = vec2(1, 4);
40
33
  const semitone = [0,2,4,5,7,9,11][i%7]+(i/7|0)*12;
41
- new PianoKey(pos, size, semitone, true);
34
+ new PianoKey(pos, size, semitone, WHITE, hsl(0,1,.9));
42
35
  }
43
36
  for (let i=10; i--;)
44
37
  {
45
- const pos = vec2([1,2,4,5,6][i%5]+(i/5|0)*7-7.5,0)
46
- const size = vec2(1,2);
38
+ // black keys
39
+ const pos = vec2([1,2,4,5,6][i%5]+(i/5|0)*7-7.5, 0)
40
+ const size = vec2(1, 2);
47
41
  const semitone = [1,3,6,8,10][i%5]+(i/5|0)*12;
48
- new PianoKey(pos, size, semitone);
42
+ new PianoKey(pos, size, semitone, hsl(0,0,.3), hsl(0,1,.3));
49
43
  }
50
44
  }
@@ -18,10 +18,12 @@ function gameInit()
18
18
  canvasFixedSize = vec2(1280, 720); // use a 720p fixed size canvas
19
19
 
20
20
  // create objects
21
- paddle = new PhysicsObject(vec2(0,1), vec2(6,1)); // create player's paddle
22
- new PhysicsObject(vec2(-.5,levelSize.y/2), vec2(1,100)); // left wall
23
- new PhysicsObject(vec2(levelSize.x+.5,levelSize.y/2), vec2(1,100)); // right wall
24
- new PhysicsObject(vec2(levelSize.x/2,levelSize.y+.5), vec2(100,1)); // top wall
21
+ paddle = new PhysicsObject(vec2(0,1), vec2(6,1)); // player
22
+
23
+ const w = levelSize.x, h = levelSize.y;
24
+ new PhysicsObject(vec2(-.5,h/2), vec2(1,100)); // left wall
25
+ new PhysicsObject(vec2(w+.5,h/2), vec2(1,100)); // right wall
26
+ new PhysicsObject(vec2(w/2,h+.5), vec2(100,1)); // top wall
25
27
  }
26
28
 
27
29
  function gameUpdate()
@@ -31,7 +31,10 @@ function gameUpdate()
31
31
  playerAngle += mouseDelta.x * .003;
32
32
 
33
33
  // update player movement, prevent walking through walls
34
- const velocity = keyDirection().scale(.1).rotate(playerAngle);
34
+ let velocity = keyDirection();
35
+ if (velocity.y && mouseIsDown(0))
36
+ velocity.y = 1; // forward movement with mouse
37
+ velocity = velocity.rotate(playerAngle).scale(.1);
35
38
  const newPos = playerPos.add(velocity);
36
39
  if (!levelTest(newPos.x, newPos.y))
37
40
  playerPos = newPos;
@@ -42,7 +45,7 @@ function gameRender()
42
45
  {
43
46
  // draw horizontal slizes to create floor and ceiling
44
47
  const h = 9;
45
- let pos = vec2(), size = vec2(39, .15), color = WHITE;
48
+ let pos = vec2(), size = vec2(39, .15), color = rgb();
46
49
  for (let y=-h; y<h; y+=.1)
47
50
  {
48
51
  const p = 1.01-abs(y/h)
@@ -54,7 +57,7 @@ function gameRender()
54
57
  {
55
58
  // draw vertical slices to create the walls
56
59
  const w = 20;
57
- const pos = vec2(), size = vec2(.15), color = WHITE;
60
+ const pos = vec2(), size = vec2(.15), color = rgb();
58
61
  for (let x=-w; x<w; x+=.1)
59
62
  {
60
63
  const p = raycast(playerPos, playerAngle + x/w);
@@ -65,7 +68,12 @@ function gameRender()
65
68
  }
66
69
  }
67
70
  // draw instructions and pointer lock status
68
- const instructions = pointerLockIsActive() ? 'Mouse Control Active - ESC To Exit' : 'Click To Enable Mouse Control';
71
+ const instructions = pointerLockIsActive() ?
72
+ 'Mouse Control Active - ESC To Exit' :
73
+ 'Click To Enable Mouse Control';
74
+ const textPos = vec2(mainCanvasSize.x/2, 50);
75
+ const textSize = 24;
76
+ const textColor = pointerLockIsActive() ? GREEN : WHITE;
69
77
  if (!isTouchDevice)
70
- drawTextScreen(instructions, vec2(mainCanvasSize.x/2, 50), 24, pointerLockIsActive() ? GREEN : WHITE);
78
+ drawTextScreen(instructions, textPos, textSize, textColor);
71
79
  }
@@ -0,0 +1,122 @@
1
+ const stepCount = 8, trackCount = 12, sequencer = [];
2
+ let currentStep = 0, stepTime = 0, tempo = 240;
3
+ let isPlaying = false, eraseMode = false;
4
+
5
+ // sound sequencer instruments
6
+ const sound_piano = new Sound([.4,0,220,,.1]);
7
+ const sound_drumKick = new Sound([,,99,,,.02,,,,,,,,2]);
8
+ const sound_drumHat = new Sound([,,1e3,,,.01,4,,,,,,,,,,,,,,4e3]);
9
+
10
+ // musical note scales
11
+ const majorScale = [0,2,4,5,7,9,11];
12
+ const minorScale = [0,2,3,5,7,8,10];
13
+ const pentatonicScale = [0,3,5,7,10];
14
+ const scale = majorScale;
15
+
16
+ class UISequencerButton extends UIButton
17
+ {
18
+ constructor(step, track)
19
+ {
20
+ const size = vec2(68, 35);
21
+ let pos = vec2(step, trackCount-1-track);
22
+ pos = pos.multiply(size);
23
+ pos = pos.add(vec2(240, 40));
24
+ super(pos, size);
25
+
26
+ this.step = step;
27
+ this.track = track;
28
+ this.cornerRadius = 0;
29
+ this.dragActivate = true;
30
+ this.isOn = false;
31
+
32
+ // set instrument and color based on track
33
+ const pianoStart = 2;
34
+ this.hue = track*.15;
35
+ if (track >= pianoStart)
36
+ {
37
+ const octave = Math.floor((track-pianoStart) / scale.length);
38
+ const scaleNote = (track-pianoStart) % scale.length;
39
+ this.semitone = scale[scaleNote] + 12*octave;
40
+ this.sound = sound_piano;
41
+ this.hue = .6 - scaleNote/40 + octave*.2;
42
+ }
43
+ else
44
+ this.sound = [sound_drumKick, sound_drumHat][track];
45
+ }
46
+ onPress()
47
+ {
48
+ // set the button on/off and update sequencer table
49
+ if (mouseWasPressed(0))
50
+ eraseMode = this.isOn;
51
+ this.isOn = !eraseMode;
52
+ eraseMode || this.playSound();
53
+ const index = this.step + this.track*stepCount;
54
+ sequencer[index] = eraseMode ? 0 : this;
55
+ }
56
+ render()
57
+ {
58
+ this.activeColor = eraseMode ? RED : WHITE;
59
+ this.color = this.isActiveObject() ? BLACK :
60
+ hsl(this.hue, this.isOn ? 1 : .5, this.isOn ? .5 : .1);
61
+ if (isPlaying && this.step == currentStep)
62
+ this.color = this.color.lerp(WHITE, .5);
63
+ super.render();
64
+ }
65
+ playSound() { this.sound.playNote(this.semitone); }
66
+ }
67
+
68
+ function gameInit()
69
+ {
70
+ // initialize UI system
71
+ new UISystemPlugin;
72
+ uiSystem.defaultCornerRadius = 8;
73
+ canvasClearColor = hsl(0,0,.3);
74
+
75
+ // create sequencer buttons
76
+ for (let step=stepCount; step--;)
77
+ for (let track=trackCount; track--;)
78
+ new UISequencerButton(step, track);
79
+
80
+ // create play/stop button
81
+ const playButton = new UIButton(vec2(660,500), vec2(180,60), 'PLAY');
82
+ playButton.onClick = ()=>
83
+ {
84
+ isPlaying = !isPlaying;
85
+ currentStep = stepTime = 0;
86
+ playButton.text = isPlaying ? 'STOP' : 'PLAY';
87
+ };
88
+
89
+ // create tempo slider
90
+ const minTempo = 120, maxTempo = 480;
91
+ const tempoPercent = percent(tempo, minTempo, maxTempo);
92
+ const tempoSlider = new UIScrollbar(vec2(380,500), vec2(340,40), tempoPercent);
93
+ tempoSlider.onChange = ()=>
94
+ {
95
+ tempo = lerp(minTempo, maxTempo, tempoSlider.value);
96
+ tempo = Math.floor(tempo/10) * 10; // round to nearest 10th
97
+ tempoSlider.text = `${tempo} BPM`;
98
+ };
99
+ tempoSlider.onChange();
100
+ }
101
+
102
+ function gameUpdate()
103
+ {
104
+ if (!isPlaying)
105
+ return;
106
+
107
+ // update step time based on tempo
108
+ const lastStepTime = stepTime;
109
+ const lastStep = currentStep;
110
+ stepTime += timeDelta*tempo/60;
111
+ currentStep = Math.floor(stepTime) % stepCount;
112
+ if (currentStep == lastStep && lastStepTime)
113
+ return;
114
+
115
+ // play sounds when step changes
116
+ for (let i=trackCount; i--;)
117
+ {
118
+ const index = currentStep + i*stepCount;
119
+ const noteButton = sequencer[index];
120
+ noteButton && noteButton.playSound();
121
+ }
122
+ }
@@ -7,12 +7,15 @@ function gameRender()
7
7
 
8
8
  // polygon shapes
9
9
  drawRectGradient(vec2(-6,0), vec2(5,4), RED, BLUE)
10
- drawRegularPoly(vec2(0,0), vec2(4), 3, PURPLE, .2, WHITE, time);
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, GREEN, true, vec2(6, 0));
10
+ drawRegularPoly(vec2(0,0), vec2(4), 3, PURPLE, .3, WHITE, time);
11
+ let starPath = []
12
+ for (let i=10; i--;)
13
+ starPath.push(vec2(0,2*(i%2?.4:1)).rotate(i/10*PI*2));
14
+ drawPoly(starPath, BLUE, .1, GREEN, vec2(6, 0));
13
15
 
14
16
  // rects and lines
15
17
  drawRect(vec2(0,-5), vec2(4,3), ORANGE, time);
16
18
  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, MAGENTA);
19
+ const zPath = [vec2(5,-3), vec2(-5,-3), vec2(5,-7), vec2(-5,-7)];
20
+ drawLineList(zPath, .4, MAGENTA);
18
21
  }
@@ -6,27 +6,37 @@ class PuzzlePiece extends EngineObject
6
6
  {
7
7
  constructor(gridPos, size)
8
8
  {
9
- const color = rgb(gridPos.x/(gridSize.x-1), gridPos.y/(gridSize.y-1), 1);
9
+ const x = gridPos.x, y = gridPos.y;
10
+ const color = rgb(x/(gridSize.x-1), y/(gridSize.y-1), 1);
10
11
  super(gridPos.multiply(size), size, 0, 0, color);
11
12
  this.gridPos = gridPos;
12
- this.text = gridPos.x + gridPos.y*gridSize.x;
13
+ this.text = x + y*gridSize.x;
14
+ this.moveTimer = new Timer;
15
+ this.lastPos = this.pos;
13
16
  }
14
17
 
15
18
  update()
16
19
  {
17
- if (mouseWasPressed(0) && isOverlapping(this.pos, this.size, mousePos))
18
- if (abs(this.gridPos.x-emptyGridPos.x) + abs(this.gridPos.y-emptyGridPos.y) == 1)
20
+ const deltaX = emptyGridPos.x - this.gridPos.x;
21
+ const deltaY = emptyGridPos.y - this.gridPos.y;
22
+ if (mouseWasPressed(0))
23
+ if (isOverlapping(this.pos, this.size, mousePos))
24
+ if (abs(deltaX) + abs(deltaY) === 1)
19
25
  {
20
26
  // swap with empty space when clicked on
27
+ this.lastPos = this.pos;
21
28
  this.pos = emptyGridPos.multiply(this.size);
22
29
  [emptyGridPos, this.gridPos] = [this.gridPos, emptyGridPos];
30
+ this.moveTimer.set(.2);
23
31
  }
24
32
  }
25
33
 
26
34
  render()
27
35
  {
28
- super.render();
29
- drawTextOverlay(this.text, this.pos, 2.5, BLACK);
36
+ const movePercent = this.moveTimer.getPercent();
37
+ const pos = this.lastPos.lerp(this.pos, movePercent);
38
+ drawRect(pos, this.size, this.color);
39
+ drawTextOverlay(this.text, pos, 2.5, BLACK);
30
40
  }
31
41
  }
32
42
 
@@ -14,13 +14,22 @@ function gameInit()
14
14
  button.textHeight = 100;
15
15
  button.onClick = ()=> sound.play();
16
16
  }
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]));
17
+ makeSoundButton(vec2(-1, 1),'💰',
18
+ new Sound([,,1675,,.06,.24,1,1.82,,,837,.06]));
19
+ makeSoundButton(vec2( 0, 1),'🥊',
20
+ new Sound([,,925,.04,.3,.6,1,.3,,6.27,-184,.09,.17]));
21
+ makeSoundButton(vec2( 1, 1),'✨',
22
+ new Sound([,,539,0,.04,.29,1,1.92,,,567,.02,.02,,,,.04]));
23
+ makeSoundButton(vec2(-1, 0),'🐁',
24
+ new Sound([,.2,1e3,.02,,.01,2,,18,,475,.01,.01]));
25
+ makeSoundButton(vec2( 0, 0),'🎹',
26
+ new Sound([1.5,.5,270,,.1,,1,1.5,,,,,,,,.1,.01]));
27
+ makeSoundButton(vec2( 1, 0),'🏌️',
28
+ new Sound([,,150,.05,,.05,,1.3,,,,,,3]));
29
+ makeSoundButton(vec2(-1,-1),'🌊',
30
+ new Sound([,.2,40,.5,,1.5,,11,,,,,,199]));
31
+ makeSoundButton(vec2( 0,-1),'🛰️',
32
+ new Sound([,.5,847,.02,.3,.9,1,1.67,,,-294,.04,.13,,,,.1]));
33
+ makeSoundButton(vec2( 1,-1),'⚡',
34
+ new Sound([,,471,,.09,.47,4,1.06,-6.7,,,,,.9,61,.1,,.82,.1]));
26
35
  }
@@ -15,13 +15,16 @@ class Player extends EngineObject
15
15
  // space ship controls
16
16
  const moveInput = keyDirection();
17
17
  this.applyAngularAcceleration(moveInput.x * .005);
18
- this.applyAcceleration(vec2().setAngle(this.angle, moveInput.y*.02));
19
- if (!this.shootTimer.active() && (keyIsDown('Space') || mouseIsDown(0)))
18
+ const accel = vec2().setAngle(this.angle, moveInput.y*.02);
19
+ this.applyAcceleration(accel);
20
+ if (!this.shootTimer.active())
21
+ if (keyIsDown('Space') || mouseIsDown(0))
20
22
  {
21
23
  // shoot bullet
22
24
  const pos = this.pos.add(vec2(0,1).rotate(cameraAngle));
23
- const bullet = new EngineObject(pos, vec2(.2,.5), 0, this.angle, YELLOW);
24
- bullet.velocity = this.velocity.add(vec2(0,.5).rotate(this.angle));
25
+ const bullet = new EngineObject(pos, vec2(.2,.5), 0, this.angle);
26
+ bullet.velocity = vec2(0,.5).rotate(this.angle);
27
+ bullet.velocity = bullet.velocity.add(this.velocity);
25
28
  this.shootTimer.set(.1);
26
29
  }
27
30
 
@@ -42,14 +45,15 @@ function gameRender()
42
45
  const range = 32, halfRange = range/2;
43
46
 
44
47
  // precreate variables to avoid overhead
45
- const pos = vec2(), size = vec2(), color = WHITE;
48
+ const pos = vec2(), size = vec2(), color = rgb();
49
+ const x = cameraPos.x, y = cameraPos.y;
46
50
  for (let i=1e3; i--;)
47
51
  {
48
52
  // use math to generate random star positions
49
53
  const parallax = i%.13-1;
50
- pos.x = mod(i**2.1 + cameraPos.x*parallax, range) + cameraPos.x - halfRange;
51
- pos.y = mod(i**3.1 + cameraPos.y*parallax, range) + cameraPos.y - halfRange;
52
- size.x = size.y = i%.07+.03;
54
+ pos.x = mod(i**2.1 + x*parallax, range) + x - halfRange;
55
+ pos.y = mod(i**3.1 + y*parallax, range) + y - halfRange;
56
+ size.x = size.y = i%.07 + .03;
53
57
  color.a = .1+i%.9;
54
58
  drawRect(pos, size, color);
55
59
  }
@@ -1,5 +1,4 @@
1
1
  let spriteAtlas;
2
- canvasClearColor = GRAY;
3
2
 
4
3
  function gameInit()
5
4
  {
@@ -13,18 +12,19 @@ function gameInit()
13
12
  circleBig: gameTile(2, 128),
14
13
  iconBig: gameTile(3, 128),
15
14
  };
15
+ canvasClearColor = GRAY;
16
16
  }
17
17
 
18
18
  function gameRender()
19
19
  {
20
20
  // draw a sprite from the atlas
21
- let pos = vec2(Math.sin(time)*5,-3);// world position to draw
22
- let angle = 0; // world space angle to draw the tile
23
- let size = vec2(9); // world size of the tile
21
+ let pos = vec2(Math.sin(time)*5,-3);// world position
22
+ let angle = 0; // world space angle
23
+ let size = vec2(9); // world space size
24
24
  let mirror = 0; // should tile be mirrored?
25
- let color = hsl(0,0,1); // color to multiply the tile by
26
- let additiveColor = hsl(0,0,0,0); // color to add to
27
- drawTile(pos, size, spriteAtlas.iconBig, color, angle, mirror, additiveColor);
25
+ let color = hsl(0,0,1); // color to multiply by
26
+ let additive = hsl(0,0,0,0); // color to add to
27
+ drawTile(pos, size, spriteAtlas.iconBig, color, angle, mirror, additive);
28
28
 
29
29
  // draw more sprites from the atlas
30
30
  drawTile(vec2(-7,4), vec2(5), spriteAtlas.crate);
@@ -1,7 +1,7 @@
1
1
  function gameRender()
2
2
  {
3
3
  // precreate variables to avoid overhead
4
- const pos = vec2(), size = vec2(), color = WHITE;
4
+ const pos = vec2(), size = vec2(), color = rgb();
5
5
  for (let i=2e3; i--;)
6
6
  {
7
7
  // use math to generate random star positions
@@ -2,7 +2,7 @@ function gameRender()
2
2
  {
3
3
  // draw text with built in font image system font
4
4
  const font = new FontImage;
5
- font.drawText('System Font Test', cameraPos.add(vec2(0,3)), .2, true);
5
+ font.drawText('System Font Test', cameraPos.add(vec2(0,3)), .2);
6
6
 
7
7
  // show every character in the system font
8
8
  let s = '';
@@ -12,5 +12,5 @@ function gameRender()
12
12
  s += '\n';
13
13
  s += String.fromCharCode(i);
14
14
  }
15
- font.drawText(s, cameraPos, .1, true);
15
+ font.drawText(s, cameraPos, .1);
16
16
  }
@@ -4,8 +4,8 @@ function gameRender()
4
4
  let pos = vec2(0,0); // world position to draw
5
5
  let size = vec2(15); // world size of the tile
6
6
  let color = hsl(0,0,1); // color to multiply the tile by
7
- let tilePos = vec2(0,0); // top left corner of tile in pixels
8
- let tileSize = vec2(256); // size of tile in pixels
7
+ let tilePos = vec2(0,0); // top left corner in pixels
8
+ let tileSize = vec2(256); // source size in pixels
9
9
  let tileInfo = new TileInfo(tilePos, tileSize); // tile info
10
10
  drawRect(pos, size, GRAY); // draw background
11
11
  drawTile(pos, size, tileInfo, color);
@@ -30,19 +30,19 @@ function gameUpdate()
30
30
  {
31
31
  if (mouseWasPressed(0))
32
32
  {
33
- // create particle emitter
33
+ // create particle emitter to test the collision
34
34
  const hue = rand();
35
35
  const particleEmitter = new ParticleEmitter(
36
- mousePos, 0, // emitPos, emitAngle
37
- 0, 0.1, 500, PI, // emitSize, emitTime, emitRate, emitCone
38
- tile(0, 16), // tileIndex, tileSize
39
- hsl(hue,1,.5), hsl(hue,1,1), // colorStartA, colorStartB
40
- hsl(hue,1,.5,0), hsl(hue,1,1,0), // colorEndA, colorEndB
41
- 2, .2, .2, .2, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
42
- .99, 1, 1, PI, // damping, angleDamping, gravityScale, cone
43
- .05, .8, true, false // fadeRate, randomness, collide, additive
36
+ mousePos, 0,
37
+ 0, 0.1, 500, PI,
38
+ tile(0, 16),
39
+ hsl(hue,1,.5), hsl(hue,1,1),
40
+ hsl(hue,1,.5,0), hsl(hue,1,1,0),
41
+ 2, .2, .2, .2, .05,
42
+ .99, 1, 1, PI,
43
+ .05, .8, true
44
44
  );
45
45
  particleEmitter.restitution = .5; // bounce when it collides
46
- particleEmitter.trailScale = 2; // stretch in direction of motion
46
+ particleEmitter.trailScale = 2; // stretch as it moves
47
47
  }
48
48
  }
@@ -9,7 +9,8 @@ class GameObject extends EngineObject
9
9
  render()
10
10
  {
11
11
  // adjust draw postion to be at the bottom of the object
12
- const pos = this.pos.add(vec2(0,this.size.y/2).rotate(this.angle));
12
+ const offset = vec2(0,this.size.y/2).rotate(this.angle);
13
+ const pos = this.pos.add(offset);
13
14
  drawTile(pos, this.size, this.tileInfo, this.color, this.angle);
14
15
  }
15
16
  }
@@ -37,9 +38,19 @@ function gameInit()
37
38
 
38
39
  // create background objects
39
40
  for (let i=1; i<300; ++i)
40
- new EngineObject(randInCircle(90), vec2(rand(59),rand(59)), 0, 0, hsl(.4,.2,rand(.4,.5),.8), -1e5);
41
+ {
42
+ const pos = randInCircle(90);
43
+ const size = vec2(rand(59), rand(59));
44
+ const color = hsl(.4,.2,rand(.4,.5),.8);
45
+ new EngineObject(pos, size, 0, 0, color, -1e5);
46
+ }
41
47
 
42
48
  // create world objects
43
49
  for (let i=1; i<1e3; ++i)
44
- new GameObject(randInCircle(7+i,7), vec2(rand(1,2),rand(4,9)), 0, 0, hsl(.1,.5,rand(.2,.3)));
50
+ {
51
+ const pos = randInCircle(7+i,7);
52
+ const size = vec2(rand(1,2),rand(4,9));
53
+ const color = hsl(.1,.5,rand(.2,.3));
54
+ new GameObject(pos, size, 0, 0, color);
55
+ }
45
56
  }
@@ -1,4 +1,5 @@
1
1
  let timerButton, timerSlider;
2
+ let timerSound = new Sound([2,0,999,,,,,1.5,,.3,-99,.1,1.63,,,.11]);
2
3
 
3
4
  function gameInit()
4
5
  {
@@ -13,13 +14,16 @@ function gameInit()
13
14
  timerButton.timer = new Timer;
14
15
  timerButton.onClick = ()=>
15
16
  {
17
+ timerButton.isSet = true;
16
18
  if (timerButton.timer.isSet())
17
19
  {
20
+ timerSound.play(0, .5, 2);
18
21
  timerButton.timer.unset();
19
22
  timerButton.text = 'Start';
20
23
  }
21
24
  else
22
25
  {
26
+ timerSound.play(0, .5, .5);
23
27
  timerButton.timer.set(3);
24
28
  timerButton.text = 'Stop';
25
29
  }
@@ -30,6 +34,12 @@ function gameInit()
30
34
  timerSlider.interactive = false;
31
35
  timerSlider.update = ()=>
32
36
  {
37
+ if (timerButton.isSet && timerButton.timer.elapsed())
38
+ {
39
+ timerSound.play();
40
+ timerButton.isSet = 0;
41
+ }
42
+
33
43
  // update the timer display
34
44
  const t = timerButton.timer.get();
35
45
  const timeText = t.toFixed(2) + 's';
@@ -30,7 +30,10 @@ function gameInit()
30
30
  // create collision objects
31
31
  for (let i=300; i--;)
32
32
  {
33
- const o = new EngineObject(randInCircle(15+i,7), vec2(rand(4,9),rand(4,9)), 0, 0, hsl(0,0,rand(.1,.3)));
33
+ const pos = randInCircle(15+i,7);
34
+ const size = vec2(rand(4,9),rand(4,9));
35
+ const color = hsl(.1,.5,rand(.2,.3));
36
+ const o = new EngineObject(pos, size, 0, 0, color);
34
37
  o.setCollision(); // make object collide
35
38
  o.mass = 0; // make object have static physics
36
39
  }