littlejsengine 1.14.19 → 1.14.23

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 (51) hide show
  1. package/dist/littlejs.d.ts +118 -18
  2. package/dist/littlejs.esm.js +506 -199
  3. package/dist/littlejs.esm.min.js +1 -1
  4. package/dist/littlejs.js +493 -199
  5. package/dist/littlejs.min.js +1 -1
  6. package/dist/littlejs.release.js +468 -200
  7. package/examples/electron/game.js +1 -41
  8. package/examples/electron/index.html +2 -2
  9. package/examples/htmlMenu/game.js +1 -1
  10. package/examples/index.html +12 -6
  11. package/examples/module/game.js +5 -7
  12. package/examples/particles/index.html +6 -9
  13. package/examples/platformer/gameCharacter.js +1 -1
  14. package/examples/platformer/gameEffects.js +7 -2
  15. package/examples/platformer/gameObjects.js +3 -3
  16. package/examples/shorts/animation.js +2 -2
  17. package/examples/shorts/base.html +4 -1
  18. package/examples/shorts/cameraDrag.js +22 -0
  19. package/examples/shorts/debugDraw.js +38 -0
  20. package/examples/shorts/fps.js +90 -0
  21. package/examples/shorts/helloWorld.js +1 -1
  22. package/examples/shorts/hillGlideGame.js +1 -1
  23. package/examples/shorts/landerGame.js +1 -1
  24. package/examples/shorts/postProcess.js +1 -1
  25. package/examples/shorts/sequencer.js +3 -3
  26. package/examples/shorts/spaceGame.js +1 -1
  27. package/examples/shorts/spriteAtlas.js +6 -6
  28. package/examples/shorts/starfield.js +1 -1
  29. package/examples/shorts/tileRaycast.js +39 -0
  30. package/examples/shorts/tiles.png +0 -0
  31. package/examples/shorts/tiltedView.js +1 -1
  32. package/examples/starter/game.js +5 -7
  33. package/examples/starter/index.html +2 -2
  34. package/examples/typescript/game.js +3 -2
  35. package/examples/typescript/game.ts +5 -7
  36. package/examples/uiSystem/game.js +2 -2
  37. package/package.json +1 -1
  38. package/src/engine.js +3 -3
  39. package/src/engineAudio.js +13 -13
  40. package/src/engineDebug.js +27 -0
  41. package/src/engineDraw.js +68 -20
  42. package/src/engineExport.js +13 -0
  43. package/src/engineInput.js +14 -16
  44. package/src/engineObject.js +31 -6
  45. package/src/engineParticles.js +36 -15
  46. package/src/engineRelease.js +2 -1
  47. package/src/engineSettings.js +20 -1
  48. package/src/engineTileLayer.js +62 -59
  49. package/src/engineUtilities.js +206 -58
  50. package/src/engineWebGL.js +13 -8
  51. package/examples/shorts/raycasting.js +0 -79
@@ -16,13 +16,6 @@ setTileFixBleedScale(.5);
16
16
  // sound effects
17
17
  const sound_click = new Sound([1,.5]);
18
18
 
19
- // medals
20
- const medal_example = new Medal(0, 'Example Medal', 'Welcome to LittleJS!');
21
- medalsInit('Hello World');
22
-
23
- // game variables
24
- let particleEmitter;
25
-
26
19
  ///////////////////////////////////////////////////////////////////////////////
27
20
  function gameInit()
28
21
  {
@@ -58,23 +51,6 @@ function gameInit()
58
51
  // setup camera
59
52
  setCameraPos(vec2(16,8));
60
53
  setCameraScale(32);
61
-
62
- // enable gravity
63
- setGravity(vec2(0,-.01));
64
-
65
- // create particle emitter
66
- particleEmitter = new ParticleEmitter(
67
- vec2(16,9), 0, // emitPos, emitAngle
68
- 0, 0, 500, PI, // emitSize, emitTime, rate, cone
69
- tile(0, 16), // tileIndex, tileSize
70
- hsl(1,1,1), hsl(0,0,0), // colorStartA, colorStartB
71
- hsl(0,0,0,0), hsl(0,0,0,0), // colorEndA, colorEndB
72
- 1, .2, .2, .1, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
73
- .99, 1, 1, PI, // damping, angleDamping, gravityScale, cone
74
- .05, .5, true, true // fadeRate, randomness, collide, additive
75
- );
76
- particleEmitter.restitution = .3; // bounce when it collides
77
- particleEmitter.trailScale = 2; // stretch as it moves
78
54
  }
79
55
 
80
56
  ///////////////////////////////////////////////////////////////////////////////
@@ -84,15 +60,6 @@ function gameUpdate()
84
60
  {
85
61
  // play sound when mouse is pressed
86
62
  sound_click.play(mousePos);
87
-
88
- // change particle color and set to fade out
89
- particleEmitter.colorStartA = randColor();
90
- particleEmitter.colorStartB = randColor();
91
- particleEmitter.colorEndA = particleEmitter.colorStartA.scale(1,0);
92
- particleEmitter.colorEndB = particleEmitter.colorStartB.scale(1,0);
93
-
94
- // unlock medals
95
- medal_example.unlock();
96
63
  }
97
64
 
98
65
  if (mouseWheel)
@@ -101,13 +68,6 @@ function gameUpdate()
101
68
  cameraScale -= sign(mouseWheel)*cameraScale/5;
102
69
  cameraScale = clamp(cameraScale, 10, 300);
103
70
  }
104
-
105
- // move particles to mouse location if on screen
106
- if (mousePosScreen.x)
107
- {
108
- particleEmitter.pos = mousePos;
109
- particleEmitter.velocity = mouseDelta.scale(.3*timeDelta);
110
- }
111
71
  }
112
72
 
113
73
  ///////////////////////////////////////////////////////////////////////////////
@@ -130,7 +90,7 @@ function gameRender()
130
90
  function gameRenderPost()
131
91
  {
132
92
  // draw to overlay canvas for hud rendering
133
- drawTextScreen('LittleJS Demo',
93
+ drawTextScreen('LittleJS Electron Demo',
134
94
  vec2(mainCanvasSize.x/2, 70), 80, // position, size
135
95
  hsl(0,0,1), 6, hsl(0,0,0)); // color, outline size and color
136
96
  }
@@ -7,7 +7,7 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- LittleJS Engine -->
10
- <script src=../../dist/littlejs.js?11417></script>
10
+ <script src=../../dist/littlejs.js?1.14.24></script>
11
11
 
12
12
  <!-- Add your game scripts here -->
13
- <script src=game.js?11417></script>
13
+ <script src=game.js?1.14.24></script>
@@ -64,7 +64,7 @@ function gameRender()
64
64
  for (let i=0; i<1e3; ++i)
65
65
  {
66
66
  const time = LJS.time;
67
- const pos = vec2(30*Math.sin(i+time/9),20*Math.sin(i*i+time/9));
67
+ const pos = vec2(30*LJS.sin(i+time/9),20*LJS.sin(i*i+time/9));
68
68
  LJS.drawTile(pos, vec2(2), tile(3,128), hsl(i/9,1,.4), time+i, !(i%2), hsl(i/9,1,.1,0));
69
69
  }
70
70
  }
@@ -89,9 +89,9 @@ const exampleList =
89
89
  new ExampleInfo('Empty', 'empty.js', 'Empty example template', false, 'beginner, text'),
90
90
  new ExampleInfo('Texture', 'texture.js', 'Texture display and manipulation', false, 'sprites, loading, tiles'),
91
91
  new ExampleInfo('Animation', 'animation.js', 'Sprite animation system', false, 'frames, loop, tiles, sprites'),
92
- new ExampleInfo('Shapes', 'shapes.js', 'Draw geometric shapes and primitives', false, 'circle, ellipses, rectangles, polygon, lines'),
93
- new ExampleInfo('Colors', 'colors.js', 'Color manipulation and HSL', false, 'hue, saturation, blending, rectangles'),
94
- new ExampleInfo('Starfield', 'starfield.js', 'Animated parallax starfield', false, 'space, movement, depth, rectangles'),
92
+ new ExampleInfo('Shapes', 'shapes.js', 'Draw geometric shapes and primitives', false, 'circle, ellipse, rectangle, polygon, lines'),
93
+ new ExampleInfo('Colors', 'colors.js', 'Color manipulation and HSL', false, 'hue, saturation, blending, rectangle'),
94
+ new ExampleInfo('Starfield', 'starfield.js', 'Animated parallax starfield', false, 'space, movement, depth, rectangle'),
95
95
  new ExampleInfo('Sprite Atlas', 'spriteAtlas.js', 'Sprite atlas and tile rendering', false, 'sheet, frames, tiles'),
96
96
  new ExampleInfo('Blending', 'blending.js', 'Additive blending and transparency', false, 'alpha, color, tiles, smooth'),
97
97
  new ExampleInfo('Tile Layer', 'tileLayer.js', 'Tile layer rendering system', false, 'level, map, grid, particles'),
@@ -103,7 +103,10 @@ const exampleList =
103
103
  new ExampleInfo('Parallax', 'parallax.js', 'Parallax scrolling mountains', false, 'generative, canvas, background'),
104
104
  new ExampleInfo('Maze Generator', 'maze.js', 'Procedural maze generation', false, 'generative, level, tiles, map, grid'),
105
105
  new ExampleInfo('Medals', 'medals.js', 'Achievement system', false, 'unlock, progress, newgrounds'),
106
- new ExampleInfo('Clock', 'clock.js', 'Animated analog clock', false, 'time, rotation, lines, rectangles'),
106
+ new ExampleInfo('Tile Raycast', 'tileRaycast.js', 'Example of the tile layer raycast collision', false, 'level, map, grid'),
107
+ new ExampleInfo('Debug Drawing', 'debugDraw.js', 'Debug drawing system', false, 'debug, circle, line, rectangle'),
108
+ new ExampleInfo('Camera Mouse Drag', 'cameraDrag.js', 'Example of how to control camera with mose', false, 'ui, input, control'),
109
+ new ExampleInfo('Clock', 'clock.js', 'Animated analog clock', false, 'time, rotation, lines, rectangle'),
107
110
  new ExampleInfo('Piano', 'piano.js', 'Interactive piano keyboard', false, 'music, sound, audio, notes, ui, instrument'),
108
111
  new ExampleInfo('Step Sequencer', 'sequencer.js', 'Simple music loop creation tool', false, 'music, sound, audio, notes, ui, instrument'),
109
112
  new ExampleInfo('Music Player', 'musicPlayer.js', 'Advanced music player with audio seeking and drag and drop', false, 'music, sound, audio, streaming, volume, ui'),
@@ -118,7 +121,7 @@ const exampleList =
118
121
  new ExampleInfo('Hill Glide Game', 'hillGlideGame.js', 'Tiny wings style sliding game', false, 'objects, physics, speed'),
119
122
  new ExampleInfo('Sliding Puzzle', 'slidingPuzzle.js', '15 tile sliding puzzle', false, 'objects, numbers, ui'),
120
123
  new ExampleInfo('Space Game', 'spaceGame.js', 'Spaceship shooter with parallax', false, 'objects, weapons, stars, camera, rotation'),
121
- new ExampleInfo('Raycasting 3D Game', 'raycasting.js', 'Pseudo 3D raycasting demo', false, '3D, maze, camera'),
124
+ new ExampleInfo('3D FPS Game', 'fps.js', 'Pseudo 3D raycasting demo', false, '3D, FPS, maze, camera'),
122
125
  new ExampleInfo('--- PLUGINS ---'),
123
126
  new ExampleInfo('Box2d Demo', 'box2d.js', 'Box2D physics plugin', false, 'objects, mouse'),
124
127
  new ExampleInfo('Box2d Car', 'box2dCar.js', 'Drivable car with Box2D physics', false, 'objects, vehicle, suspension, wheels'),
@@ -551,7 +554,10 @@ function setCode(code, filename)
551
554
  {
552
555
  // setup frame controls
553
556
  setFrameControlsEnabled();
554
- iframeContent.setGLEnable(checkboxWebGL.checked);
557
+ if (iframeContent.glCanEnable())
558
+ iframeContent.setGLEnable(checkboxWebGL.checked);
559
+ else
560
+ checkboxWebGL.disabled = true;
555
561
  checkboxWebGL.onchange = ()=> iframeContent.setGLEnable(checkboxWebGL.checked);
556
562
  })
557
563
  }
@@ -69,16 +69,17 @@ function gameInit()
69
69
  // create particle emitter
70
70
  particleEmitter = new LJS.ParticleEmitter(
71
71
  vec2(16,9), 0, // emitPos, emitAngle
72
- 1, 0, 500, Math.PI, // emitSize, emitTime, rate, cone
72
+ 0, 0, 500, 3.14, // emitSize, emitTime, rate, cone
73
73
  tile(0, 16), // tileIndex, tileSize
74
74
  hsl(1,1,1), hsl(0,0,0), // colorStartA, colorStartB
75
75
  hsl(0,0,0,0), hsl(0,0,0,0), // colorEndA, colorEndB
76
- 1, .2, .2, .1, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
77
- .99, 1, 1, Math.PI, // damping, angleDamping, gravityScale, cone
78
- .05, .5, true, true // fadeRate, randomness, collide, additive
76
+ 1, .2, .2, .1, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
77
+ .99, 1, 1, 3.14, // damping, angleDamping, gravityScale, cone
78
+ .05, .5, true, true // fadeRate, randomness, collide, additive
79
79
  );
80
80
  particleEmitter.restitution = .3; // bounce when it collides
81
81
  particleEmitter.trailScale = 2; // stretch as it moves
82
+ particleEmitter.velocityInheritance = .3; // inherit emitter velocity
82
83
  }
83
84
 
84
85
  ///////////////////////////////////////////////////////////////////////////////
@@ -101,10 +102,7 @@ function gameUpdate()
101
102
 
102
103
  // move particles to mouse location if on screen
103
104
  if (LJS.mousePosScreen.x)
104
- {
105
105
  particleEmitter.pos = LJS.mousePos;
106
- particleEmitter.velocity = LJS.mouseDelta.scale(.3*LJS.timeDelta);
107
- }
108
106
  }
109
107
 
110
108
  ///////////////////////////////////////////////////////////////////////////////
@@ -298,12 +298,10 @@ function getCode()
298
298
  {
299
299
  const expand = inputExpand.checked;
300
300
  let code = '';
301
-
302
- // https://www.codingem.com/javascript-how-to-limit-decimal-places/
303
- Number.prototype.round = function(n) {
304
- const d = Math.pow(10, n);
305
- return Math.round((this + Number.EPSILON) * d) / d;
306
- }
301
+
302
+ // limit float precision to prevent long strings
303
+ const trimFloat = (n, decimals=3)=>
304
+ Number(Number(n).toFixed(decimals));
307
305
 
308
306
  code = 'new ParticleEmitter(';
309
307
  if (expand)
@@ -325,13 +323,12 @@ function getCode()
325
323
  else if (type == 'color')
326
324
  {
327
325
  const c = particleSystem[name];
328
- const p = 3;
329
- value = `new Color(${c.r.round(p)}, ${c.g.round(p)}, ${c.b.round(p)}, ${c.a.round(p)})`;
326
+ value = `new Color(${trimFloat(c.r)}, ${trimFloat(c.g)}, ${trimFloat(c.b)}, ${trimFloat(c.a)})`;
330
327
  }
331
328
  else if (type == 'checkbox')
332
329
  value = particleSystem[name] ? 1 : 0;
333
330
  else
334
- value = particleSystem[name].round(3);
331
+ value = trimFloat(particleSystem[name]);
335
332
  if (expand)
336
333
  code += ' ';
337
334
  code += value;
@@ -238,7 +238,7 @@ export class Character extends GameObjects.GameObject
238
238
  if (!this.isDead())
239
239
  {
240
240
  // bounce pos with walk cycle
241
- bodyPos = bodyPos.add(vec2(0,.05*Math.sin(this.walkCyclePercent*LJS.PI)));
241
+ bodyPos = bodyPos.add(vec2(0,.05*LJS.sin(this.walkCyclePercent*LJS.PI)));
242
242
 
243
243
  // make bottom flush
244
244
  bodyPos = bodyPos.add(vec2(0,(this.drawSize.y-this.size.y)/2));
@@ -15,6 +15,9 @@ import * as LJS from '../../dist/littlejs.esm.js';
15
15
  import * as GameLevel from './gameLevel.js';
16
16
  const {vec2, hsl, rgb} = LJS;
17
17
 
18
+ // use low graphics mode on mobile devices
19
+ const lowGraphicsMode = LJS.isTouchDevice;
20
+
18
21
  ///////////////////////////////////////////////////////////////////////////////
19
22
  // sound effects
20
23
 
@@ -33,7 +36,9 @@ export const sound_score = new LJS.Sound([,,783,,.03,.02,1,2,,,940,.03,,,
33
36
 
34
37
  export const persistentParticleDestroyCallback = (particle)=>
35
38
  {
36
- // copy particle to tile layer on death
39
+ if (lowGraphicsMode) return;
40
+
41
+ // draw particle to tile layer on death
37
42
  LJS.ASSERT(!particle.tileInfo, 'quick draw to tile layer uses canvas 2d so must be untextured');
38
43
  if (particle.groundObject)
39
44
  {
@@ -193,7 +198,7 @@ export class Sky extends LJS.EngineObject
193
198
  // draw stars
194
199
  LJS.setBlendMode(true);
195
200
  const random = new LJS.RandomGenerator(this.seed);
196
- for (let i=1e3; i--;)
201
+ for (let i= lowGraphicsMode ? 500 : 1e3; i--;)
197
202
  {
198
203
  const size = random.float(.5,2)**2;
199
204
  const speed = random.float() < .9 ? random.float(5) : random.float(9,99);
@@ -106,7 +106,7 @@ export class Coin extends LJS.EngineObject
106
106
 
107
107
  // make it appear to spin
108
108
  const t = LJS.time+this.pos.x/4+this.pos.y/4;
109
- const spinSize = vec2(.5+.5*Math.sin(t*2*LJS.PI), 1);
109
+ const spinSize = vec2(.5+.5*LJS.sin(t*2*LJS.PI), 1);
110
110
  if (spinSize.x > .1)
111
111
  LJS.drawTile(this.pos, spinSize, this.tileInfo, this.color);
112
112
  }
@@ -174,7 +174,7 @@ export class Enemy extends GameObject
174
174
  {
175
175
  // bounce by changing size
176
176
  const bounceTime = this.bounceTime*6;
177
- this.drawSize = vec2(1-.1*Math.sin(bounceTime), 1+.1*Math.sin(bounceTime));
177
+ this.drawSize = vec2(1-.1*LJS.sin(bounceTime), 1+.1*LJS.sin(bounceTime));
178
178
 
179
179
  // make bottom flush
180
180
  let bodyPos = this.pos;
@@ -221,7 +221,7 @@ export class Grenade extends GameObject
221
221
 
222
222
  // draw additive flash exploding
223
223
  LJS.setBlendMode(true);
224
- const flash = Math.cos(this.getAliveTime()*2*LJS.PI);
224
+ const flash = LJS.cos(this.getAliveTime()*2*LJS.PI);
225
225
  LJS.drawTile(this.pos, vec2(2), Game.spriteAtlas.circle, hsl(0,1,.5,.2-.2*flash));
226
226
  LJS.setBlendMode(false);
227
227
  }
@@ -4,13 +4,13 @@ function gameRender()
4
4
  {
5
5
  {
6
6
  // animate by changing frames
7
- const pos = vec2(-5, 2*abs(Math.sin(time*2*PI)));
7
+ const pos = vec2(-5, 2*abs(sin(time*2*PI)));
8
8
  const frame = (time*4)%2|0;
9
9
  drawTile(pos, vec2(7), tile(3).frame(frame), RED);
10
10
  }
11
11
  {
12
12
  // animate with stretch and squash
13
- const s = Math.sin(time*9)*.5;
13
+ const s = sin(time*9)*.5;
14
14
  const size = vec2(7-s,7+s);
15
15
  const pos = vec2(5,size.y-7);
16
16
  drawTile(pos, size, tile(5), GREEN);
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html><meta charset=utf-8><body>
2
- <script src=../../dist/littlejs.js?11417></script>
2
+ <script src=../../dist/littlejs.js?1.14.24></script>
3
3
  <script src=../../dist/box2d.wasm.js></script>
4
4
 
5
5
  <!-- LittleJS Engine Source
@@ -44,4 +44,7 @@ function gameUpdatePost() {}
44
44
  function gameRender() {}
45
45
  function gameRenderPost() {}
46
46
 
47
+ // check if WebGL can be enabled
48
+ function glCanEnable() { return glCanBeEnabled; }
49
+
47
50
  </script>
@@ -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,38 @@
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
+ super.update();
12
+
13
+ // show debug info
14
+ debugText('Debug Text', this.pos.add(vec2(0,3)), 1, WHITE);
15
+ debugRect(this.pos, this.size, RED);
16
+ debugPoly(mousePos, [vec2(-2,-1), vec2(0,2), vec2(2,-1)], YELLOW);
17
+ debugLine(this.pos, mousePos, BLUE);
18
+
19
+ // bounce off screen edges
20
+ const cameraSize = getCameraSize();
21
+ if (abs(this.pos.x) > cameraSize.x/2)
22
+ {
23
+ debugCircle(this.pos, 3, GREEN, 1);
24
+ this.velocity.x = -this.velocity.x;
25
+ }
26
+ if (abs(this.pos.y) > cameraSize.y/2)
27
+ {
28
+ debugCircle(this.pos, 3, GREEN, 1);
29
+ this.velocity.y = -this.velocity.y;
30
+ }
31
+ }
32
+ }
33
+
34
+ function gameInit()
35
+ {
36
+ canvasClearColor = GRAY;
37
+ new BounceObject(vec2(), vec2(5), tile(3,128));
38
+ }
@@ -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 * .003;
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
  }
@@ -35,7 +35,7 @@ class Player extends EngineObject
35
35
 
36
36
  function getGroundHeight(x)
37
37
  {
38
- return Math.sin(x/4)*2 + Math.sin(x/17);
38
+ return sin(x/4)*2 + sin(x/17);
39
39
  }
40
40
 
41
41
  function gameInit()
@@ -14,7 +14,7 @@ class Player extends EngineObject
14
14
  // space ship controls
15
15
  const moveInput = keyDirection();
16
16
  this.applyAngularAcceleration(moveInput.x * .002);
17
- const accel = vec2(0, moveInput.y*.002).rotate(this.angle);
17
+ const accel = this.getRight(moveInput.y*.002);
18
18
  this.applyAcceleration(accel);
19
19
  }
20
20
 
@@ -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
 
@@ -23,7 +23,7 @@ class Player extends EngineObject
23
23
  // shoot bullet
24
24
  const pos = this.pos.add(vec2(0,1).rotate(cameraAngle));
25
25
  const bullet = new EngineObject(pos, vec2(.2,.5), 0, this.angle);
26
- bullet.velocity = vec2(0,.5).rotate(this.angle);
26
+ bullet.velocity = this.getUp(.5);
27
27
  bullet.velocity = bullet.velocity.add(this.velocity);
28
28
  this.shootTimer.set(.1);
29
29
  }
@@ -18,12 +18,12 @@ function gameInit()
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
22
- let angle = 0; // world space angle
23
- let size = vec2(9); // world space size
24
- let mirror = 0; // should tile be mirrored?
25
- let color = hsl(0,0,1); // color to multiply by
26
- let additive = hsl(0,0,0,0); // color to add to
21
+ let pos = vec2(sin(time)*5,-3);// world position
22
+ let angle = 0; // world space angle
23
+ let size = vec2(9); // world space size
24
+ let mirror = 0; // should tile be mirrored?
25
+ let color = hsl(0,0,1); // color to multiply by
26
+ let additive = hsl(0,0,0,0); // color to add to
27
27
  drawTile(pos, size, spriteAtlas.iconBig, color, angle, mirror, additive);
28
28
 
29
29
  // draw more sprites from the atlas
@@ -9,7 +9,7 @@ function gameRender()
9
9
  pos.x = offset%70 - 35;
10
10
  pos.y = i/110 - 9;
11
11
  size.x = size.y = i%.11 + .07;
12
- color.set(1,1,1,Math.sin(i)**4);
12
+ color.set(1,1,1,sin(i)**4);
13
13
  drawRect(pos, size, color);
14
14
  }
15
15
  }
@@ -0,0 +1,39 @@
1
+ function gameInit()
2
+ {
3
+ // create tile layer
4
+ const pos = vec2();
5
+ const tileLayer = new TileCollisionLayer(pos, vec2(28,16), 0);
6
+ cameraPos = tileLayer.size.scale(.5); // setup camera
7
+ for (pos.x = tileLayer.size.x; pos.x--;)
8
+ for (pos.y = tileLayer.size.y; pos.y--;)
9
+ {
10
+ // create random solid tiles away from level center
11
+ if (rand() < .7 || cameraPos.distanceSquared(pos) < 9)
12
+ continue;
13
+
14
+ // set tile data
15
+ const data = new TileLayerData(1);
16
+ tileLayer.setData(pos, data);
17
+ tileLayer.setCollisionData(pos);
18
+ }
19
+ tileLayer.redraw();
20
+ }
21
+
22
+ function gameRenderPost()
23
+ {
24
+ // cast ray from camera center to mouse
25
+ drawLine(cameraPos, mousePos, .1, CYAN);
26
+ const normal = vec2();
27
+ const hit = tileCollisionRaycast(cameraPos, mousePos, 0, normal);
28
+ if (hit)
29
+ {
30
+ // draw hit tile
31
+ const tilePos = hit.floor().add(vec2(.5));
32
+ drawRect(tilePos, vec2(1), RED);
33
+
34
+ // draw hit point and normal
35
+ drawRect(hit, vec2(.2), GREEN);
36
+ drawLine(cameraPos, hit, .1, RED);
37
+ drawLine(hit, hit.add(normal), .1, YELLOW);
38
+ }
39
+ }
Binary file
@@ -10,7 +10,7 @@ class GameObject extends EngineObject
10
10
  {
11
11
  // adjust draw postion to be at the bottom of the object
12
12
  const drawSize = this.drawSize || this.size;
13
- const offset = vec2(0,drawSize.y/2).rotate(this.angle);
13
+ const offset = this.getUp(drawSize.y/2);
14
14
  const pos = this.pos.add(offset);
15
15
  drawTile(pos, drawSize, this.tileInfo, this.color, this.angle);
16
16
  }