littlejsengine 1.9.11 → 1.10.4

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/README.md +9 -13
  2. package/dist/littlejs.d.ts +129 -10
  3. package/dist/littlejs.esm.js +220 -75
  4. package/dist/littlejs.esm.min.js +1 -1
  5. package/dist/littlejs.js +188 -73
  6. package/dist/littlejs.min.js +1 -1
  7. package/dist/littlejs.release.js +187 -72
  8. package/examples/box2d/game.js +4 -1
  9. package/examples/box2d/index.html +7 -6
  10. package/examples/breakout/game.js +1 -1
  11. package/examples/breakout/index.html +5 -4
  12. package/examples/breakoutTutorial/README.md +9 -7
  13. package/examples/breakoutTutorial/game.js +6 -6
  14. package/examples/breakoutTutorial/index.html +4 -3
  15. package/examples/electron/game.js +1 -1
  16. package/examples/electron/index.html +4 -3
  17. package/examples/empty/game.js +1 -1
  18. package/examples/empty/index.html +2 -1
  19. package/examples/htmlMenu/game.js +67 -0
  20. package/examples/htmlMenu/index.html +56 -0
  21. package/examples/htmlMenu/tiles.png +0 -0
  22. package/examples/index.html +33 -0
  23. package/examples/js13k/build/index.html +1 -0
  24. package/examples/js13k/build/index.js +1 -0
  25. package/examples/js13k/build/tiles.png +0 -0
  26. package/examples/js13k/game - Copy.zip +0 -0
  27. package/examples/js13k/game.js +1 -1
  28. package/examples/js13k/game.zip +0 -0
  29. package/examples/js13k/index.html +17 -14
  30. package/examples/module/game.js +1 -1
  31. package/examples/module/index.html +3 -2
  32. package/examples/particles/index.html +4 -3
  33. package/examples/platformer/game.js +7 -5
  34. package/examples/platformer/gameCharacter.js +12 -11
  35. package/examples/platformer/gameEffects.js +3 -4
  36. package/examples/platformer/gameLevel.js +18 -34
  37. package/examples/platformer/gameObjects.js +9 -15
  38. package/examples/platformer/index.html +10 -9
  39. package/examples/puzzle/game.js +1 -1
  40. package/examples/puzzle/index.html +4 -3
  41. package/examples/starter/build/index.html +2 -0
  42. package/examples/starter/build/index.js +1 -0
  43. package/examples/starter/build/tiles.png +0 -0
  44. package/examples/starter/game.js +4 -4
  45. package/examples/starter/game.zip +0 -0
  46. package/examples/starter/index.html +15 -14
  47. package/examples/stress/index.html +3 -2
  48. package/examples/typescript/build/build/littlejs.esm.js +4327 -0
  49. package/examples/typescript/build/dist/littlejs.esm.js +4425 -0
  50. package/examples/typescript/build/examples/typescript/build.js +24 -0
  51. package/examples/typescript/build/examples/typescript/game.js +100 -0
  52. package/examples/typescript/build/examples/typescript/test/build/littlejs.esm.js +3934 -0
  53. package/examples/typescript/build/examples/typescript/test/examples/typescript/build.js +86 -0
  54. package/examples/typescript/build/examples/typescript/test/examples/typescript/game.js +92 -0
  55. package/examples/typescript/game.js +1 -1
  56. package/examples/typescript/game.ts +1 -1
  57. package/examples/typescript/index.html +3 -2
  58. package/examples/uiSystem/game.js +134 -0
  59. package/examples/uiSystem/index.html +25 -0
  60. package/examples/uiSystem/tiles.png +0 -0
  61. package/jsconfig.json +11 -0
  62. package/package.json +1 -1
  63. package/plugins/box2d.js +2 -1
  64. package/plugins/postProcess.js +14 -8
  65. package/plugins/uiSystem.js +243 -0
  66. package/src/engine.js +42 -22
  67. package/src/engineAudio.js +10 -13
  68. package/src/engineDebug.js +1 -1
  69. package/src/engineDraw.js +102 -27
  70. package/src/engineExport.js +32 -2
  71. package/src/engineInput.js +1 -3
  72. package/src/engineObject.js +1 -0
  73. package/src/engineSettings.js +1 -1
  74. package/src/engineTileLayer.js +2 -1
  75. package/src/engineUtilities.js +2 -1
  76. package/src/engineWebGL.js +26 -4
@@ -54,7 +54,7 @@ class Ball extends EngineObject
54
54
  {
55
55
  // prevent colliding with paddle if moving upwards
56
56
  if (o == paddle && this.velocity.y > 0)
57
- return 0;
57
+ return false;
58
58
 
59
59
  // speed up
60
60
  const speed = min(1.04*this.velocity.length(), .5);
@@ -73,10 +73,10 @@ class Ball extends EngineObject
73
73
  this.velocity.y = max(-this.velocity.y, .2);
74
74
 
75
75
  // prevent default collision code
76
- return 0;
76
+ return false;
77
77
  }
78
78
 
79
- return 1; // allow object to collide
79
+ return true; // allow object to collide
80
80
  }
81
81
  }
82
82
 
@@ -114,15 +114,15 @@ class Brick extends EngineObject
114
114
  new ParticleEmitter(
115
115
  this.pos, 0, // pos, angle
116
116
  this.size, .1, 200, PI, // emitSize, emitTime, emitRate, emiteCone
117
- 0, // tileInfo
117
+ undefined, // tileInfo
118
118
  color, color, // colorStartA, colorStartB
119
119
  color.scale(1,0), color.scale(1,0), // colorEndA, colorEndB
120
120
  .2, .5, 1, .1, .1, // time, sizeStart, sizeEnd, speed, angleSpeed
121
121
  .99, .95, .4, PI, // damp, angleDamp, gravity, cone
122
- .1, .5, 0, 1 // fade, randomness, collide, additive
122
+ .1, .5, false, true // fade, randomness, collide, additive
123
123
  );
124
124
 
125
- return 1; // allow object to collide
125
+ return true; // allow object to collide
126
126
  }
127
127
  }
128
128
 
@@ -1,9 +1,10 @@
1
1
  <!DOCTYPE html><head>
2
- <title>Little JS Breakout Tutorial</title>
2
+ <title>LittleJS Breakout Tutorial</title>
3
+ <meta charset=utf-8>
3
4
  <meta name=apple-mobile-web-app-capable content=yes>
4
5
  <meta name=mobile-web-app-capable content=yes>
5
6
  <link rel=icon type=image/png href=../favicon.png>
6
7
  </head><body>
7
8
 
8
- <script src=../../dist/littlejs.js?198></script>
9
- <script src=game.js?198></script>
9
+ <script src=../../dist/littlejs.js?1100></script>
10
+ <script src=game.js?1100></script>
@@ -125,4 +125,4 @@ function gameRenderPost()
125
125
 
126
126
  ///////////////////////////////////////////////////////////////////////////////
127
127
  // Startup LittleJS Engine
128
- engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost);
128
+ engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
@@ -1,12 +1,13 @@
1
1
  <!DOCTYPE html><head>
2
- <title>Little JS Electron Demo</title>
2
+ <title>LittleJS Electron Demo</title>
3
+ <meta charset=utf-8>
3
4
  <meta name=apple-mobile-web-app-capable content=yes>
4
5
  <meta name=mobile-web-app-capable content=yes>
5
6
  <link rel=icon type=image/png href=../favicon.png>
6
7
  </head><body>
7
8
 
8
9
  <!-- LittleJS Engine -->
9
- <script src=../../dist/littlejs.js?198></script>
10
+ <script src=../../dist/littlejs.js?1100></script>
10
11
 
11
12
  <!-- Add your game scripts here -->
12
- <script src=game.js?198></script>
13
+ <script src=game.js?1100></script>
@@ -44,4 +44,4 @@ function gameRenderPost()
44
44
 
45
45
  ///////////////////////////////////////////////////////////////////////////////
46
46
  // Startup LittleJS Engine
47
- engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost);
47
+ engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
@@ -1,5 +1,6 @@
1
1
  <!DOCTYPE html><head>
2
- <title>Little JS Hello World Demo</title>
2
+ <title>LittleJS Hello World Demo</title>
3
+ <meta charset=utf-8>
3
4
  </head><body>
4
5
 
5
6
  <script src=../../dist/littlejs.js></script>
@@ -0,0 +1,67 @@
1
+ /*
2
+ Little JS HTML Menu Example Project
3
+ - Setup a simple html menu system
4
+ - Menu can be toggled
5
+ - Pauses game when menu is visible
6
+ - Shows several input types
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ // show the LittleJS splash screen
12
+ setShowSplashScreen(true);
13
+
14
+ // sound effects
15
+ const sound_click = new Sound([1,.5]);
16
+
17
+ ///////////////////////////////////////////////////////////////////////////////
18
+ function gameInit()
19
+ {
20
+ // show menu for demo
21
+ setMenuVisible(true);
22
+ }
23
+
24
+ ///////////////////////////////////////////////////////////////////////////////
25
+ function gameUpdate()
26
+ {
27
+ // play sound when mouse is pressed
28
+ if (mouseWasPressed(0))
29
+ sound_click.play(mousePos);
30
+ }
31
+
32
+ ///////////////////////////////////////////////////////////////////////////////
33
+ function gameUpdatePost()
34
+ {
35
+ // pause game when menu is visible
36
+ const menuVisible = getMenuVisible();
37
+ paused = menuVisible;
38
+
39
+ // toggle menu visibility
40
+ if (keyWasPressed('KeyM'))
41
+ setMenuVisible(!menuVisible);
42
+ }
43
+
44
+ ///////////////////////////////////////////////////////////////////////////////
45
+ function gameRender()
46
+ {
47
+ // test game rendering
48
+ drawRect(vec2(), vec2(1e3), hsl(0,0,.2));
49
+ for(let i=0; i<1e3; ++i)
50
+ {
51
+ const pos = vec2(30*Math.sin(i+time/9),20*Math.sin(i*i+time/9));
52
+ drawTile(pos, vec2(2), tile(3,128), hsl(i/9,1,.4), time+i, !(i%2), hsl(i/9,1,.1,0));
53
+ }
54
+ }
55
+
56
+ ///////////////////////////////////////////////////////////////////////////////
57
+ function gameRenderPost()
58
+ {
59
+ // draw to overlay canvas for hud rendering
60
+ drawTextScreen('LittleJS HTML Menu Example\nM = Toggle menu',
61
+ vec2(mainCanvasSize.x/2, 70), 60, // position, size
62
+ hsl(0,0,1), 6, hsl(0,0,0)); // color, outline size and color
63
+ }
64
+
65
+ ///////////////////////////////////////////////////////////////////////////////
66
+ // Startup LittleJS Engine
67
+ engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
@@ -0,0 +1,56 @@
1
+ <!DOCTYPE html><head>
2
+ <title>LittleJS HTML Menu Example</title>
3
+ <meta charset=utf-8>
4
+ <meta name=apple-mobile-web-app-capable content=yes>
5
+ <meta name=mobile-web-app-capable content=yes>
6
+ <link rel=icon type=image/png href=../favicon.png>
7
+ <style>
8
+ .topDiv
9
+ {
10
+ position: absolute;
11
+ z-index: 1;
12
+ width: 100%;
13
+ height: 100%;
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: center;
17
+ }
18
+ .menuDiv
19
+ {
20
+ gap: 20px;
21
+ padding: 30px;
22
+ display: flex;
23
+ align-items: center;
24
+ flex-direction: column;
25
+ border: 3px solid black;
26
+ background-color: white;
27
+ }
28
+ </style>
29
+
30
+ </head><body>
31
+
32
+ <!-- setup html menu system -->
33
+ <div class="topDiv">
34
+ <div id="menu" class="menuDiv">
35
+ <h1><i style="font-size:30px">Test Menu</i></h1>
36
+ This is an example menu using html elements.
37
+ <input value="Test Input" onchange="alert('New text: ' + this.value)">
38
+ <input type="range" onchange="alert('New value: ' + this.value)">
39
+ <button onclick="alert('Button was clicked!')">Test Button</button>
40
+ <button onclick="setMenuVisible(false)">Exit Menu</button>
41
+ </div>
42
+ </div>
43
+ <script>
44
+
45
+ // html menu system
46
+ const getMenuVisible =()=> menu.style.visibility != 'hidden';
47
+ const setMenuVisible =(visible)=> menu.style.visibility = visible ? '' : 'hidden';
48
+
49
+ // hide menu at start
50
+ setMenuVisible(false);
51
+
52
+ </script>
53
+
54
+ <!-- Add your game scripts here -->
55
+ <script src=../../dist/littlejs.js?1100></script>
56
+ <script src=game.js?1100></script>
Binary file
@@ -0,0 +1,33 @@
1
+ <head>
2
+ <title>LittleJS Examples</title>
3
+ <link rel=icon type=image/png href=../favicon.png>
4
+ <body>
5
+ <h1>All LittleJS Engine Examples</h1>
6
+ <p>
7
+ <img src=screenshot.jpg width=500>
8
+ </p>
9
+ <h2>Main Demos</h2>
10
+ <p>
11
+ <a href="starter">Starter</a> - Clean example with only a few things to get you started<br>
12
+ <a href="stress">Stress</a> - Max sprite/object test and music system demo<br>
13
+ <a href="platformer">Platformer</a> - Platformer/shooter with level data from Tiled Editor<br>
14
+ <a href="breakout">Breakout</a> - Block breaking game with post-processing effects<br>
15
+ <a href="breakoutTutorial">Breakout Tutorial</a> - Tutorial Breakout example<br>
16
+ <a href="puzzle">Puzzle</a> - Match 3 puzzle game with HD rendering and high score tracking<br>
17
+ <a href="particles">Particle Designer</a> - Particle system editor and visualizer<br>
18
+ <a href="js13k">JS13K Starter</a> - Special small size demo for JS13K Games<br>
19
+ <a href="empty">Empty</a> - A blank hello world project for LittleJS<br>
20
+ </p>
21
+ <h2>Plugin Demos</h2>
22
+ <p>
23
+ <a href="box2d">Box2D</a> - Box2D plugin demonstration and testbed<br>
24
+ <a href="uiSystem">UI System</a> - A simple hierarchical UI system using LittleJS rendering<br>
25
+ <a href="htmlMenu">HTML UI Menu</a> - Example using html to create an overlay menu<br>
26
+ </p>
27
+ <h2>Environment Demos</h2>
28
+ <p>
29
+ <a href="module">LittleJS using modules</a> - Loads LittleJS as a module<br>
30
+ <a href="typescript">LittleJS using TypeScript</a> - Uses LittleJS type definitions<br>
31
+ <a href="electron">LittleJS building with Electron</a> - Builds to an executable<br>
32
+ </p>
33
+ </body>
@@ -0,0 +1 @@
1
+ <body><script>const g=Math.PI;function n(t,i=0,e=1){return t<i?i:e<t?e:t}function aa(t,i,e){return(e-=i)?n((t-i)/e):0}function ba(t,i,e,a=q()){return 2*Math.abs(t.x-e.x)<i.x+a.x&&2*Math.abs(t.y-e.y)<i.y+a.y}function t(t=1,i=0){return i+Math.random()*(t-i)}function ca(i=1){return da(new v,t(2*g),i)}function ea(i=1){return 0<i?ca(i*t(0/i,1)**.5):new v}function ja(i=new w,e=new w(0,0,0,1),a=!1){return a?i.ma(e,t()):new w(t(i.r,e.r),t(i.j,e.j),t(i.b,e.b),t(i.a,e.a))}function q(t=0,i){return"number"==typeof t?new v(t,null==i?t:i):new v(t.x,t.y)}function da(t,i=0,e=1){return t.x=e*Math.sin(i),t.y=e*Math.cos(i),t}function ka(t){return t.x**2+t.y**2}function la(t,i){return(t.x-i.x)**2+(t.y-i.y)**2}function ma(t){var i=t.length();return 1<i?t.scale(1/i):t}function na(t){return Math.abs(t.x*t.y)}function pa(t,i){return 0<=t.x&&0<=t.y&&t.x<i.x&&t.y<i.y}class v{constructor(t=0,i=0){this.x=t,this.y=i}set(t=0,i=0){return this.x=t,this.y=i,this}v(){return new v(this.x,this.y)}add(t){return new v(this.x+t.x,this.y+t.y)}l(t){return new v(this.x-t.x,this.y-t.y)}multiply(t){return new v(this.x*t.x,this.y*t.y)}U(t){return new v(this.x/t.x,this.y/t.y)}scale(t){return new v(this.x*t,this.y*t)}length(){return ka(this)**.5}normalize(t=1){var i=this.length();return i?this.scale(t/i):new v(0,t)}angle(){return Math.atan2(this.x,this.y)}rotate(t){var i=Math.cos(t);return t=Math.sin(t),new v(this.x*i-this.y*t,this.x*t+this.y*i)}setDirection(t,i=1){return q(t%2?t-1?-i:i:0,t%2?0:t?-i:i)}direction(){return Math.abs(this.x)>Math.abs(this.y)?this.x<0?3:1:this.y<0?2:0}floor(){return new v(Math.floor(this.x),Math.floor(this.y))}ma(t,i){return this.add(t.l(this).scale(n(i)))}toString(){}}function qa(t){return(255*n(t.r)|0)+(255*n(t.j)<<8)+(255*n(t.b)<<16)+(255*n(t.a)<<24)}class w{constructor(t=1,i=1,e=1,a=1){this.r=t,this.j=i,this.b=e,this.a=a}set(t=1,i=1,e=1,a=1){return this.r=t,this.j=i,this.b=e,this.a=a,this}v(){return new w(this.r,this.j,this.b,this.a)}add(t){return new w(this.r+t.r,this.j+t.j,this.b+t.b,this.a+t.a)}l(t){return new w(this.r-t.r,this.j-t.j,this.b-t.b,this.a-t.a)}multiply(t){return new w(this.r*t.r,this.j*t.j,this.b*t.b,this.a*t.a)}U(t){return new w(this.r/t.r,this.j/t.j,this.b/t.b,this.a/t.a)}scale(t,i=t){return new w(this.r*t,this.j*t,this.b*t,this.a*i)}ma(t,i){return this.add(t.l(this).scale(n(i)))}toString(t=!0){var i=t=>((t=255*t|0)<16?"0":"")+t.toString(16);return"#"+i(this.r)+i(this.j)+i(this.b)+(t?i(this.a):"")}}class ra{constructor(){this.setTime=this.time=void 0}set(t=0){this.time=x+t,this.setTime=t}active(){return x<this.time}get(){return null!=this.time?x-this.time:0}toString(){}valueOf(){return this.get()}}function ua(t){var i,e=t.parent;e&&(i=e.o?-1:1,t.i=t.Ca.multiply(q(i,1)).rotate(-e.angle).add(e.i),t.angle=i*t.Ba+e.angle);for(const a of t.children)ua(a)}function va(t){if(!t.A){t.A=1,t.parent&&t.parent.removeChild(t);for(const i of t.children)va(i,i.parent=0)}}class wa{constructor(t=q(),i=q(1),e,a=0,s,h=0){this.i=t.v(),this.size=i,this.xa=void 0,this.s=e,this.angle=a,this.color=s,this.va=void 0,this.o=!1,this.h=xa,this.m=ya,this.K=za,this.u=Aa,this.X=Ba,this.B=1,this.P=h,this.g=q(),this.R=0,this.ua=x,this.children=[],this.ba=!0,this.parent=void 0,this.Ca=q(),this.Ba=0,this.la=this.ca=this.L=!1,y.push(this)}update(){var t;if(!this.parent&&(this.ba?(this.g.x=n(this.g.x,-z,z),this.g.y=n(this.g.y,-z,z)):(t=ka(this.g))>z*z&&(t=z/t**.5,this.g.x*=t,this.g.y*=t),t=this.i.v(),this.g.y+=Ca*this.B,this.i.x+=this.g.x*=this.m,this.i.y+=this.g.y*=this.m,this.angle+=this.R*=this.K,Da&&this.h)){var i,e,a,s,h,r,o=this.g.y<0;if(this.C&&(i=this.C.g?this.C.g.x:0,this.g.x=i+(this.g.x-i)*this.X,this.C=0),this.ca)for(var c of Ea)!this.la&&!c.la||c.A||c.parent||c==this||ba(this.i,this.size,c.i,c.size)&&(ba(t,this.size,c.i,c.size)?(i=(e=(i=t.l(c.i)).length())<.01?ca(.001):i.scale(.001/e),this.g=this.g.add(i),c.h&&(c.g=c.g.l(i))):(e=this.size.add(c.size),a=2*(t.y-c.i.y)>e.y+Ca,s=2*Math.abs(t.y-c.i.y)<e.y,h=2*Math.abs(t.x-c.i.x)<e.x,i=Math.max(this.u,c.u),!a&&!h&&s||(this.i.y=c.i.y+(e.y/2+.001)*Math.sign(t.y-c.i.y),c.C&&o||!c.h?(o&&(this.C=c),this.g.y*=-i):c.h&&(h=(this.h*this.g.y+c.h*c.g.y)/(this.h+c.h),r=c.g.y*(c.h-this.h)/(this.h+c.h)+2*this.g.y*this.h/(this.h+c.h),this.g.y=h+n(i)*(this.g.y*(this.h-c.h)/(this.h+c.h)+2*c.g.y*c.h/(this.h+c.h)-h),c.g.y=h+n(i)*(r-h))),!a&&s&&(this.i.x=c.i.x+(e.x/2+.001)*Math.sign(t.x-c.i.x),c.h?(e=(this.h*this.g.x+c.h*c.g.x)/(this.h+c.h),a=c.g.x*(c.h-this.h)/(this.h+c.h)+2*this.g.x*this.h/(this.h+c.h),this.g.x=e+n(i)*(this.g.x*(this.h-c.h)/(this.h+c.h)+2*c.g.x*c.h/(this.h+c.h)-e),c.g.x=e+n(i)*(a-e)):this.g.x*=-i)));this.L&&Fa(this.i,this.size,this)&&!Fa(t,this.size,this)&&(c=Fa(q(this.i.x,t.y),this.size,this),!Fa(q(t.x,this.i.y),this.size,this)&&c||(this.C=o,this.g.y*=-this.u,(o=(t.y-this.size.y/2|0)-(t.y-this.size.y/2))<0&&o>this.m*this.g.y+Ca*this.B&&(this.g.y=this.m?(o-Ca*this.B)/this.m:0),this.i.y=t.y),c)&&(this.i.x=t.x,this.g.x*=-this.u)}}H(){Ga(this.i,this.xa||this.size,this.s,this.color,this.angle,this.o,this.va)}removeChild(t){t.parent==this&&this.children.includes(t),this.children.splice(this.children.indexOf(t),1),t.parent=0}toString(){}}let B,C,D,Ha,E=q(),Na=[];function Oa(t=q(),i=Pa,e=0){var a;return F?new Qa:("number"==typeof i&&(i=q(i)),"number"==typeof t&&(t=q(t%(a=Na[e].size.x/i.x|0)*i.x,(t/a|0)*i.y)),new Qa(t,i,e))}class Qa{constructor(t=q(),i=Pa,e=0){this.i=t.v(),this.size=i.v(),this.$=e}offset(t){return new Qa(this.i.add(t),this.size,this.$)}frame(t){return this.offset(q(t*this.size.x,0))}}class Ra{constructor(t){var i;this.image=t,this.size=q(t.width,t.height),(i=Sa)&&(i=G.createTexture(),G.bindTexture(3553,i),t&&G.texImage2D(3553,0,6408,6408,5121,t),t=Ta?9728:9729,G.texParameteri(3553,10241,t),G.texParameteri(3553,10240,t)),this.ja=i,this.ya=q(Ua).U(this.size)}}function Va(t){return new v((t.x-I.x)*J+E.x/2-.5,(t.y-I.y)*-J+E.y/2-.5)}function Ga(t,i=q(1),h,n=new w,e=0,a,s=new w(0,0,0,0),r=Sa){const o=h&&Na[h.$];var c,u,l,b;r?o?(r=h.i.x/o.size.x,c=h.i.y/o.size.y,u=h.size.x/o.size.x,l=h.size.y/o.size.y,b=o.ya,Wa(o.ja),Xa(t.x,t.y,a?-i.x:i.x,i.y,e,r+b.x,c+b.y,r-b.x+u,c-b.y+l,qa(n),qa(s))):Xa(t.x,t.y,i.x,i.y,e,0,0,0,0,0,qa(n)):ab(t,i,e,a,t=>{var i,e,a,s;o?(i=h.i.x+Ua,e=h.i.y+Ua,a=h.size.x-2*Ua,s=h.size.y-2*Ua,t.globalAlpha=n.a,t.drawImage(o.image,i,e,a,s,-.5,-.5,1,1),t.globalAlpha=1):(t.fillStyle=n,t.fillRect(-.5,-.5,1,1))})}function ab(t,i,e,a,s){var h=C;t=Va(t),i=i.scale(J),h.save(),h.translate(t.x+.5,t.y+.5),h.rotate(e),h.scale(a?-i.x:i.x,-i.y),s(h),h.restore()}function bb(t){var i;Sa?cb=t:(i||=C).globalCompositeOperation=t?"lighter":"source-over"}function db(){var i=q(E.x/2,70),t=new w(0,0,0),e=eb,a=Ha;a.fillStyle=(new w).toString(),a.lineWidth=0,a.strokeStyle=t.toString(),a.textAlign="center",a.font="80px "+e,a.textBaseline="middle",a.lineJoin="round",i=i.v(),["LittleJS JS13K Demo"].forEach(t=>{a.fillText(t,i.x,i.y),i.y+=80})}function fb(t,i=0){return K[i]&&!!(1&K[i][t])}let gb=q(),hb=q(),ib=!1;function jb(t,i=0){return fb(t,i+1)}let K=[[]];function kb(){var t;F||(N&&lb||document.hasFocus()||(K=[[]]),t=hb,gb=new v((t.x-E.x/2+.5)/J+I.x,(t.y-E.y/2+.5)/-J+I.y),mb&&nb())}function ob(){if(!F)for(const t of K)for(const i in t)t[i]&=1}function pb(){function i(t){return qb?"KeyW"==t?"ArrowUp":"KeyS"==t?"ArrowDown":"KeyA"==t?"ArrowLeft":"KeyD"==t?"ArrowRight":t:t}F||(onkeydown=t=>{t.repeat||(ib=!1,K[0][t.code]=3,qb&&(K[0][i(t.code)]=3))},onkeyup=t=>{K[0][t.code]=4,qb&&(K[0][i(t.code)]=4)},onmousedown=t=>{ib=!1,K[0][t.button]=3,hb=rb(t),t.button&&t.preventDefault()},onmouseup=t=>K[0][t.button]=2&K[0][t.button]|4,onmousemove=t=>hb=rb(t),onwheel=t=>t.ctrlKey?0:Math.sign(t.deltaY),oncontextmenu=()=>!1,lb&&N&&!F&&sb())}function rb(t){var i;return!B||F?q():(i=B.getBoundingClientRect(),q(B.width,B.height).multiply(q(aa(t.x,i.left,i.right),aa(t.y,i.top,i.bottom))))}const tb=[];function nb(){var t=t=>{var i=t=>.3<t?aa(t,.3,.8):t<-.3?-aa(-t,.3,.8):0;return ma(q(i(t.x),i(-t.y)))};if(ub&&lb&&null!=Ab.time){(i=tb[0]||(tb[0]=[]))[0]=q(),Bb?i[0]=t(O):.3<ka(O)&&(i[0].x=Math.round(O.x),i[0].y=-Math.round(O.y),i[0]=ma(i[0]));for(var i=K[1]||(K[1]=[]),e=10;e--;){var a=3==e?2:2==e?3:e,s=jb(a,0);i[a]=Q[e]?s?1:3:s?4:0}}if(mb&&mb&&navigator&&navigator.getGamepads&&document.hasFocus())for(e=(i=navigator.getGamepads()).length;e--;){var s=i[e],h=K[e+1]||(K[e+1]=[]),a=tb[e]||(tb[e]=[]);if(s){for(var n=0;n<s.axes.length-1;n+=2)a[n>>1]=t(q(s.axes[n],s.axes[n+1]));for(n=s.buttons.length;n--;){var r=s.buttons[n],o=jb(n,e);h[n]=r.pressed?o?1:3:o?4:0,ib||=!e&&r.pressed}Cb&&ka(s=q((jb(15,e)&&1)-(jb(14,e)&&1),(jb(12,e)&&1)-(jb(13,e)&&1)))&&(a[0]=ma(s)),ub&&ib&&(Ab.time=void 0)}}}const lb=void 0!==window.ontouchstart;let Ab=new ra,Q,O;function sb(){function n(t){Db&&R&&"running"!=R.state&&new Eb([0]).play();var i=t.touches.length;return i?(hb=rb(q(t.touches[0].clientX,t.touches[0].clientY)),e?ib=!1:K[0][0]=3):e&&(K[0][0]=2&K[0][0]|4),e=i,document.hasFocus()&&t.preventDefault(),!0}let i=n;ub&&(i=function(t){if(O=q(),Q=[],ib=!0,!t.touches.length||(Ab.set(),!Fb)){var i=q(S,E.y-S),e=E.l(q(S,S)),a=E.scale(.5);for(const h of t.touches){var s=rb(q(h.clientX,h.clientY));la(s,i)**.5<S?O=ma(s.l(i).scale(2/S)):la(s,e)**.5<S?(s=s.l(e).direction(),Q[s]=1):la(s,a)**.5<S&&(Q[9]=1)}return n(t),!0}Q[9]=1},Q=[],O=q()),document.addEventListener("touchstart",t=>i(t),{passive:!1}),document.addEventListener("touchmove",t=>i(t),{passive:!1}),document.addEventListener("touchend",t=>i(t),{passive:!1}),onmousedown=onmouseup=()=>0;let e}function Gb(){if(N&&lb&&!F&&ub&&null!=Ab.time){var t=aa(Ab.get(),4,3);if(t&&!Fb){var i=Ha;if(i.save(),i.globalAlpha=t*Hb,i.strokeStyle="#fff",i.lineWidth=3,i.fillStyle=0<ka(O)?"#fff":"#000",i.beginPath(),t=q(S,E.y-S),Bb)i.arc(t.x,t.y,S/2,0,9),i.fill();else for(var e=10;e--;){var a=e*g/4;i.arc(t.x,t.y,.6*S,a+g/8,a+g/8),e%2&&i.arc(t.x,t.y,.33*S,a,a),1==e&&i.fill()}for(i.stroke(),t=q(E.x-S,E.y-S),e=4;e--;)a=t.add(q().setDirection(e,S/2)),i.fillStyle=Q[e]?"#fff":"#000",i.beginPath(),i.arc(a.x,a.y,S/4,0,9),i.fill(),i.stroke();i.restore()}}}let R,Ib;class Eb{constructor(t){var i=Jb,e=Kb;Db&&!F&&(this.Fa=i,this.Ja=e,this.O=0,t)&&(this.O=t[1]||.05,this.ta=[Lb(...t)],this.sampleRate=44100)}play(i,e=1,a=1,s=1,h=!1){if(Db&&!F&&this.ta){var n;if(i){if(n=this.Fa){var r=la(I,i);if(n*n<r)return;e*=aa(r**.5,n,n*this.Ja)}n=2*Va(i).x/B.width-1}return i=a+a*this.O*s*t(-1,1),this.za=R.createGain(),this.source=Mb(this.ta,e,i,n,h,this.sampleRate,this.za)}}stop(){this.source&&this.source.stop(),this.source=void 0}}let Nb=!1;function Mb(t,i=1,e=1,a=0,s=!1,h=44100,r){if(Db&&!F){var o,c=Nb;if(!(Nb="running"!=R.state)||(R.resume(),!c))return o=R.createBuffer(t.length,t[0].length,h),h=R.createBufferSource(),t.forEach((t,i)=>o.getChannelData(i).set(t)),h.buffer=o,h.playbackRate.value=e,h.loop=s,(r=r||R.createGain()).gain.value=i,r.connect(Ib),h.connect(new StereoPannerNode(R,{pan:n(a,-1,1)})).connect(r),h.start(),h}}function Lb(t=1,i,e=220,a=0,s=0,h=.1,r=0,o=1,c=0,u=0,l=0,b=0,f=0,d=0,y=0,x=0,v=0,m=1,w=0,p=0,q=0){let O=c*=500*(i=2*g)/44100/44100,S=e*=i/44100,z=[],G=0,k=0,M=0,B=1,U=0,J=0,D=0;var F=i*Math.abs(q)*2/44100,C=Math.cos(F),E=1+(A=Math.sin(F)/2/2),F=-2*C/E,A=(1-A)/E;let j=(1+Math.sign(q)*C)/2/E,P=-(Math.sign(q)+C)/E,T=0,K=0,I=0,R=0;for(u*=500*i/44100**3,y*=i/44100,l*=i/44100,b*=44100,f=44100*f|0,E=(a=44100*a+9)+(w*=44100)+(s*=44100)+(h*=44100)+(v*=44100)|0;M<E;z[M++]=D*t)++J%(100*x|0)||(D=r?1<r?2<r?3<r?Math.sin(G**3):n(Math.tan(G),1,-1):1-(2*G/i%2+2)%2:1-4*Math.abs(Math.round(G/i)-G/i):Math.sin(G),D=(f?1-p+p*Math.sin(i*M/f):1)*Math.sign(D)*Math.abs(D)**o*(M<a?M/a:M<a+w?1-(M-a)/w*(1-m):M<a+w+s?m:M<E-v?(E-M-v)/h*m:0),D=v?D/2+(v>M?0:(M<E-v?1:(E-M)/v)*z[M-v|0]/2/t):D,q&&(D=R=j*T+P*(T=K)+j*(K=D)-A*I-F*(I=R))),C=(e+=c+=u)*Math.cos(y*k++),G+=C+C*d*Math.sin(M**5),B&&++B>b&&(e+=l,S+=l,B=0),!f||++U%f||(e=S,c=O,B=B||1);return z}let Ob=[],T=q();function Fa(t,i=q(),e){var a=Math.max(t.x-i.x/2|0,0),s=Math.max(t.y-i.y/2|0,0),h=Math.min(t.x+i.x/2,T.x);for(t=Math.min(t.y+i.y/2,T.y);s<t;++s)for(i=a;i<h;++i){var n=Ob[s*T.x+i];if(n&&(!e||0<n))return!0}}class Pb{constructor(t,i=0,e=!1,a=new w){this.aa=t,this.direction=i,this.o=e,this.color=a}clear(){this.aa=this.direction=0,this.o=!1,this.color=new w}}class Qb extends wa{constructor(t,i=T){var e=q(1);for(super(t,i,Oa(),0,void 0,0),this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.scale=e,this.ka=!1,this.data=[],t=na(this.size);t--;)this.data.push(new Pb);F&&(this.qa=()=>{},this.H=()=>{},this.sa=()=>{},this.ra=()=>{},this.V=()=>{})}setData(t,i,e=!1){pa(t,this.size)&&(this.data[(0|t.y)*this.size.x+t.x|0]=i,e)&&this.V(t)}getData(t){return pa(t,this.size)&&this.data[(0|t.y)*this.size.x+t.x|0]}update(){}H(){Rb||this.ka||Sb();var t=Va(this.i.add(q(0,this.size.y*this.scale.y)));(this.ka?Ha:C).drawImage(this.canvas,t.x,t.y,J*this.size.x*this.scale.x,J*this.size.y*this.scale.y)}qa(){this.sa(!0);for(let i=this.size.x;i--;)for(let t=this.size.y;t--;)this.V(q(i,t),!1);this.ra()}sa(t=!1){this.Ga=[B,C,E,I,J],B=this.canvas,C=this.context,E=this.size.multiply(this.s.size),I=this.size.scale(.5),J=this.s.size.x,t&&(B.width=E.x,B.height=E.y),this.context.imageSmoothingEnabled=!Ta,Tb()}ra(){Sb(!0),[B,C,E,I,J]=this.Ga}V(t,i=!0){var e=this.s.size;i&&(i=t.multiply(e),this.context.clearRect(i.x,this.canvas.height-i.y,e.x,-e.y)),null!=(i=this.getData(t)).aa&&Ga(t=this.i.add(t).add(q(.5)),q(1),Oa(i.aa,e,this.s.$),i.color,i.direction*g/2,i.o)}}function Ub(i){var e="number"==typeof i.W?ea(i.W/2):q(t(-.5,.5),t(-.5,.5)).multiply(i.W).rotate(i.angle);let a=t(i.na,-i.na);i.Y||(e=i.i.add(e),a+=i.angle);const s=i.O;var h=(c=i=>i+i*t(s,-s))(i.Ea),n=c(i.Z),r=c(i.Ha),o=c(i.speed),c=c(i.wa)*(2*Math.floor(t(2,0))-1),u=t(i.ga,-i.ga),l=ja(i.S,i.T,i.pa),b=ja(i.da,i.ea,i.pa),u=i.Y?u:i.angle+u;(e=new Vb(e,i.s,a,l,b,h,n,r,i.G,i.J,i.I,i.Y&&i,i.Da)).g=da(q(),u,o),e.R=c,e.G=i.G,e.m=i.m,e.K=i.K,e.u=i.u,e.X=i.X,e.B=i.B,e.L=i.L,e.P=i.P,e.o=!!Math.floor(t(2,0)),i.oa&&i.oa(e)}class Wb extends wa{constructor(t,i,e=0,a=0,s=100,h=g,n,r=new w,o=new w,c=new w(1,1,1,0),u=new w(1,1,1,0),l=.5,b=.1,f=1,d=.1,y=.05,x=1,v=1,m=0,p=g,S=.1,z=.2,G=!1,M=!1,B=!0,D=M?1e9:0,F=!1){super(t,q(),n,i,void 0,D),this.W=e,this.ia=a,this.ha=s,this.ga=h,this.S=r,this.T=o,this.da=c,this.ea=u,this.pa=B,this.Ea=l,this.Z=b,this.Ha=f,this.speed=d,this.wa=y,this.m=x,this.K=v,this.B=m,this.na=p,this.G=S,this.O=z,this.L=G,this.J=M,this.Y=F,this.I=0,this.oa=this.Da=void 0,this.F=0}update(){if(this.parent&&super.update(),!this.ia||x-this.ua<=this.ia){if(this.ha*Xb){var t=1/this.ha/Xb;for(this.F+=Yb;0<this.F;this.F-=t)Ub(this)}}else va(this)}H(){}}class Vb extends wa{constructor(t,i,e,a,s,h,n,r,o,c,u,l,b){super(t,q(),i,e),this.N=a,this.M=s.l(a),this.Aa=h,this.Z=n,this.Ia=r-n,this.G=o,this.J=c,this.I=u,this.D=l,this.fa=b,this.ba=!1}H(){var t=Math.min((x-this.ua)/this.Aa,1),i=q(this.Z+t*this.Ia),e=this.G/2,e=new w(this.N.r+t*this.M.r,this.N.j+t*this.M.j,this.N.b+t*this.M.b,(this.N.a+t*this.M.a)*(t<e?t/e:1-e<t?(1-t)/e:1));this.J&&bb(!0);let a=this.i;var s,h,n=this.angle;this.D&&(a=this.D.i.add(a.rotate(-this.D.angle)),n+=this.D.angle),this.I?(s=this.g,(n=(s=this.D?s.rotate(-this.D.angle):s).length())&&(s=s.scale(1/n),h=n*this.I,i.y=Math.max(i.x,h),n=s.angle(),Ga(a.add(s.multiply(q(0,-h/2))),i,this.s,e,n,this.o))):Ga(a,i,this.s,e,n,this.o),this.J&&bb(),1==t&&(this.color=e,this.size=i,this.fa&&this.fa(this),this.A=1)}}let U,G,Zb,$b,ac,bc,V,cc,W,cb,dc;function ec(){var t;Sa&&!F&&(U=document.createElement("canvas"),G=U.getContext("webgl2"),Rb&&document.body.appendChild(U),t=G.createProgram(),G.attachShader(t,ic("#version 300 es\nprecision highp float;uniform mat4 m;in vec2 g;in vec4 p,u,c,a;in float r;out vec2 v;out vec4 d,e;void main(){vec2 s=(g-.5)*p.zw;gl_Position=m*vec4(p.xy+s*cos(r)-vec2(-s.y,s)*sin(r),1,1);v=mix(u.xw,u.zy,g);d=c;e=a;}",35633)),G.attachShader(t,ic("#version 300 es\nprecision highp float;uniform sampler2D s;in vec2 v;in vec4 d,e;out vec4 c;void main(){c=texture(s,v)*d+e;}",35632)),G.linkProgram(t),Zb=t,t=new ArrayBuffer(44e4),V=new Float32Array(t),cc=new Uint32Array(t),ac=G.createBuffer(),bc=G.createBuffer(),t=new Float32Array([W=0,0,1,0,0,1,1,1]),G.bindBuffer(34962,bc),G.bufferData(34962,t,35044))}function Tb(){var r,t,i;Sa&&!F&&(G.viewport(0,0,U.width=B.width,U.height=B.height),G.clear(16384),G.useProgram(Zb),G.activeTexture(33984),G.bindTexture(3553,$b=Na[0].ja),r=cb=dc=0,t=(t,i,e,a)=>{t=G.getAttribLocation(Zb,t);var s=e&&44,h=e&&1,n=1==e;G.enableVertexAttribArray(t),G.vertexAttribPointer(t,a,i,n,s,r),G.vertexAttribDivisor(t,h),r+=a*e},G.bindBuffer(34962,bc),t("g",5126,0,2),G.bindBuffer(34962,ac),G.bufferData(34962,44e4,35048),t("p",5126,4,4),t("u",5126,4,4),t("c",5121,1,4),t("a",5121,1,4),t("r",5126,4,1),t=q(2*J).U(E),i=q(-1).l(I.multiply(t)),G.uniformMatrix4fv(G.getUniformLocation(Zb,"m"),!1,[t.x,0,0,0,0,t.y,0,0,1,1,1,1,i.x,i.y,0,0]))}function Wa(t){F||t==$b||(jc(),G.bindTexture(3553,$b=t))}function ic(t,i){return i=G.createShader(i),G.shaderSource(i,t),G.compileShader(i),i}function jc(){var t;W&&(t=dc?1:771,G.blendFuncSeparate(770,t,1,t),G.enable(3042),G.bufferSubData(34962,0,V),G.drawArraysInstanced(5,0,4,W),W=0,dc=cb)}function Sb(t=!1){var i=C;Sa&&(W||t)&&(jc(),Rb&&!t||i.drawImage(U,0,0))}function Xa(t,i,e,a,s,h,n,r,o,c,u=0){(1e4<=W||dc!=cb)&&jc();var l=11*W;V[l++]=t,V[l++]=i,V[l++]=e,V[l++]=a,V[l++]=h,V[l++]=n,V[l++]=r,V[l++]=o,cc[l++]=c,cc[l++]=u,V[+l]=s,W++}const Yb=1/60;let y=[],Ea=[],kc=0,x=0,Fb=!1,lc=0,X=0;const mc=[],nc=[];function oc(){Ea=y.filter(t=>t.ca);for(const t of y)t.parent||(function t(i){if(!i.A){i.update();for(const e of i.children)t(e)}}(t),ua(t));y=y.filter(t=>!t.A)}let I=q(),J=32,pc=q(1920,1080),qc=q(),Ta=!0,eb="arial",F=!1,Sa=!0,Rb=!0,Pa=q(16),Ua=.5,Da=!0,xa=1,ya=1,za=1,Aa=0,Ba=.8,z=1,Ca=0,Xb=1,mb=!1,Cb=!(mb=!1),qb=!0,N=!1,ub=N=N=!1,Bb=!0,S=99,Hb=.3,Db=!0,rc=.3,Jb=40,Kb=.7;function sc(){var t=rc;rc=t,Db&&!F&&Ib&&(Ib.gain.value=t)}let Y;qb=N=!1;const tc=new Eb([1,.5]);!function(s,h,n,r,i=["tiles.png"]){function o(t=0){var i=t-lc;if(lc=t,X+=Fb?0:i,X=Math.min(X,50),c(),Fb){for(const e of y)e.parent||ua(e);kb(),h(),ob()}else{for(t=0,X<0&&-9<X&&(t=X,X=0);0<=X;X-=1e3/60)x=kc++/60,kb(),s(),mc.forEach(t=>t()),oc(),h(),ob();X+=t}if(!F){E=q(B.width,B.height),C.imageSmoothingEnabled=!Ta,Tb(),n(),y.sort((t,i)=>t.P-i.P);for(const a of y)a.A||a.H();r(),nc.forEach(t=>t()),Gb(),Sb()}requestAnimationFrame(o)}function c(){var t,i;F||(qc.x?(B.width=qc.x,B.height=qc.y,t=innerWidth/innerHeight,i=B.width/B.height,(U||B).style.width=B.style.width=D.style.width=t<i?"100%":"",(U||B).style.height=B.style.height=D.style.height=t<i?"":"100%"):(B.width=Math.min(innerWidth,pc.x),B.height=Math.min(innerHeight,pc.y)),D.width=B.width,D.height=B.height,E=q(B.width,B.height))}function e(){{T=q(32,16);for(var i=(Ob=[]).length=na(T);i--;)Ob[i]=0;i=q();var e=new Qb(i,T),a=Na[0].image,s=(C.drawImage(a,0,0),C.getImageData(0,0,a.width,a.height).data),h,n,r;for(i.x=T.x;i.x--;)for(i.y=T.y;i.y--;)s[4*(i.x+a.width*(15+T.y-i.y))]&&(h=Math.floor(t(4,0)),n=Math.floor(t(2,0)),r=ja(),e.setData(i,new Pb(1,h,n,r)),pa(i,T))&&(Ob[(0|i.y)*T.x+i.x|0]=1);e.qa(),I=q(16,8),Ca=-.01,(Y=new Wb(q(16,9),0,1,0,500,g,Oa(0,16),new w(1,1,1),new w(0,0,0),new w(0,0,0,0),new w(0,0,0,0),2,.2,.2,.1,.05,.99,1,1,g,.05,.5,1,1)).u=.3,Y.I=2}o()}F?e():(document.body.style.cssText="margin:0;overflow:hidden;background:#000;user-select:none;-webkit-user-select:none;"+(N?"touch-action:none;-webkit-touch-callout:none":""),document.body.appendChild(B=document.createElement("canvas")),C=B.getContext("2d"),pb(),Db&&!F&&(R=new AudioContext,(Ib=R.createGain()).connect(R.destination),sc()),ec(),document.body.appendChild(D=document.createElement("canvas")),Ha=D.getContext("2d"),(U||B).style.cssText=B.style.cssText=D.style.cssText="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)",c(),i=i.map((e,a)=>new Promise(t=>{const i=new Image;i.onerror=i.onload=()=>{Na[a]=new Ra(i),t()},i.src=e})),Promise.all(i).then(e))}(function(){K[0]&&2&K[0][0]&&(tc.play(gb),Y.S=new w,Y.T=ja(),Y.da=Y.S.scale(1,0),Y.ea=Y.T.scale(1,0)),hb.x&&(Y.i=gb)},function(){},function(){Ga(q(16,8),q(20,14),void 0,new w(.6,.6,.6),0,!1,void 0,0)},function(){db()});</script>
@@ -0,0 +1 @@
1
+ const g=Math.PI;function n(t,i=0,e=1){return t<i?i:e<t?e:t}function aa(t,i,e){return(e-=i)?n((t-i)/e):0}function ba(t,i,e,a=q()){return 2*Math.abs(t.x-e.x)<i.x+a.x&&2*Math.abs(t.y-e.y)<i.y+a.y}function t(t=1,i=0){return i+Math.random()*(t-i)}function ca(i=1){return da(new v,t(2*g),i)}function ea(i=1){return 0<i?ca(i*t(0/i,1)**.5):new v}function ja(i=new w,e=new w(0,0,0,1),a=!1){return a?i.ma(e,t()):new w(t(i.r,e.r),t(i.j,e.j),t(i.b,e.b),t(i.a,e.a))}function q(t=0,i){return"number"==typeof t?new v(t,null==i?t:i):new v(t.x,t.y)}function da(t,i=0,e=1){return t.x=e*Math.sin(i),t.y=e*Math.cos(i),t}function ka(t){return t.x**2+t.y**2}function la(t,i){return(t.x-i.x)**2+(t.y-i.y)**2}function ma(t){var i=t.length();return 1<i?t.scale(1/i):t}function na(t){return Math.abs(t.x*t.y)}function pa(t,i){return 0<=t.x&&0<=t.y&&t.x<i.x&&t.y<i.y}class v{constructor(t=0,i=0){this.x=t,this.y=i}set(t=0,i=0){return this.x=t,this.y=i,this}v(){return new v(this.x,this.y)}add(t){return new v(this.x+t.x,this.y+t.y)}l(t){return new v(this.x-t.x,this.y-t.y)}multiply(t){return new v(this.x*t.x,this.y*t.y)}U(t){return new v(this.x/t.x,this.y/t.y)}scale(t){return new v(this.x*t,this.y*t)}length(){return ka(this)**.5}normalize(t=1){var i=this.length();return i?this.scale(t/i):new v(0,t)}angle(){return Math.atan2(this.x,this.y)}rotate(t){var i=Math.cos(t);return t=Math.sin(t),new v(this.x*i-this.y*t,this.x*t+this.y*i)}setDirection(t,i=1){return q(t%2?t-1?-i:i:0,t%2?0:t?-i:i)}direction(){return Math.abs(this.x)>Math.abs(this.y)?this.x<0?3:1:this.y<0?2:0}floor(){return new v(Math.floor(this.x),Math.floor(this.y))}ma(t,i){return this.add(t.l(this).scale(n(i)))}toString(){}}function qa(t){return(255*n(t.r)|0)+(255*n(t.j)<<8)+(255*n(t.b)<<16)+(255*n(t.a)<<24)}class w{constructor(t=1,i=1,e=1,a=1){this.r=t,this.j=i,this.b=e,this.a=a}set(t=1,i=1,e=1,a=1){return this.r=t,this.j=i,this.b=e,this.a=a,this}v(){return new w(this.r,this.j,this.b,this.a)}add(t){return new w(this.r+t.r,this.j+t.j,this.b+t.b,this.a+t.a)}l(t){return new w(this.r-t.r,this.j-t.j,this.b-t.b,this.a-t.a)}multiply(t){return new w(this.r*t.r,this.j*t.j,this.b*t.b,this.a*t.a)}U(t){return new w(this.r/t.r,this.j/t.j,this.b/t.b,this.a/t.a)}scale(t,i=t){return new w(this.r*t,this.j*t,this.b*t,this.a*i)}ma(t,i){return this.add(t.l(this).scale(n(i)))}toString(t=!0){var i=t=>((t=255*t|0)<16?"0":"")+t.toString(16);return"#"+i(this.r)+i(this.j)+i(this.b)+(t?i(this.a):"")}}class ra{constructor(){this.setTime=this.time=void 0}set(t=0){this.time=x+t,this.setTime=t}active(){return x<this.time}get(){return null!=this.time?x-this.time:0}toString(){}valueOf(){return this.get()}}function ua(t){var i,e=t.parent;e&&(i=e.o?-1:1,t.i=t.Ca.multiply(q(i,1)).rotate(-e.angle).add(e.i),t.angle=i*t.Ba+e.angle);for(const a of t.children)ua(a)}function va(t){if(!t.A){t.A=1,t.parent&&t.parent.removeChild(t);for(const i of t.children)va(i,i.parent=0)}}class wa{constructor(t=q(),i=q(1),e,a=0,s,h=0){this.i=t.v(),this.size=i,this.xa=void 0,this.s=e,this.angle=a,this.color=s,this.va=void 0,this.o=!1,this.h=xa,this.m=ya,this.K=za,this.u=Aa,this.X=Ba,this.B=1,this.P=h,this.g=q(),this.R=0,this.ua=x,this.children=[],this.ba=!0,this.parent=void 0,this.Ca=q(),this.Ba=0,this.la=this.ca=this.L=!1,y.push(this)}update(){var t;if(!this.parent&&(this.ba?(this.g.x=n(this.g.x,-z,z),this.g.y=n(this.g.y,-z,z)):(t=ka(this.g))>z*z&&(t=z/t**.5,this.g.x*=t,this.g.y*=t),t=this.i.v(),this.g.y+=Ca*this.B,this.i.x+=this.g.x*=this.m,this.i.y+=this.g.y*=this.m,this.angle+=this.R*=this.K,Da&&this.h)){var i,e,a,s,h,r,o=this.g.y<0;if(this.C&&(i=this.C.g?this.C.g.x:0,this.g.x=i+(this.g.x-i)*this.X,this.C=0),this.ca)for(var c of Ea)!this.la&&!c.la||c.A||c.parent||c==this||ba(this.i,this.size,c.i,c.size)&&(ba(t,this.size,c.i,c.size)?(i=(e=(i=t.l(c.i)).length())<.01?ca(.001):i.scale(.001/e),this.g=this.g.add(i),c.h&&(c.g=c.g.l(i))):(e=this.size.add(c.size),a=2*(t.y-c.i.y)>e.y+Ca,s=2*Math.abs(t.y-c.i.y)<e.y,h=2*Math.abs(t.x-c.i.x)<e.x,i=Math.max(this.u,c.u),!a&&!h&&s||(this.i.y=c.i.y+(e.y/2+.001)*Math.sign(t.y-c.i.y),c.C&&o||!c.h?(o&&(this.C=c),this.g.y*=-i):c.h&&(h=(this.h*this.g.y+c.h*c.g.y)/(this.h+c.h),r=c.g.y*(c.h-this.h)/(this.h+c.h)+2*this.g.y*this.h/(this.h+c.h),this.g.y=h+n(i)*(this.g.y*(this.h-c.h)/(this.h+c.h)+2*c.g.y*c.h/(this.h+c.h)-h),c.g.y=h+n(i)*(r-h))),!a&&s&&(this.i.x=c.i.x+(e.x/2+.001)*Math.sign(t.x-c.i.x),c.h?(e=(this.h*this.g.x+c.h*c.g.x)/(this.h+c.h),a=c.g.x*(c.h-this.h)/(this.h+c.h)+2*this.g.x*this.h/(this.h+c.h),this.g.x=e+n(i)*(this.g.x*(this.h-c.h)/(this.h+c.h)+2*c.g.x*c.h/(this.h+c.h)-e),c.g.x=e+n(i)*(a-e)):this.g.x*=-i)));this.L&&Fa(this.i,this.size,this)&&!Fa(t,this.size,this)&&(c=Fa(q(this.i.x,t.y),this.size,this),!Fa(q(t.x,this.i.y),this.size,this)&&c||(this.C=o,this.g.y*=-this.u,(o=(t.y-this.size.y/2|0)-(t.y-this.size.y/2))<0&&o>this.m*this.g.y+Ca*this.B&&(this.g.y=this.m?(o-Ca*this.B)/this.m:0),this.i.y=t.y),c)&&(this.i.x=t.x,this.g.x*=-this.u)}}H(){Ga(this.i,this.xa||this.size,this.s,this.color,this.angle,this.o,this.va)}removeChild(t){t.parent==this&&this.children.includes(t),this.children.splice(this.children.indexOf(t),1),t.parent=0}toString(){}}let B,C,D,Ha,E=q(),Na=[];function Oa(t=q(),i=Pa,e=0){var a;return F?new Qa:("number"==typeof i&&(i=q(i)),"number"==typeof t&&(t=q(t%(a=Na[e].size.x/i.x|0)*i.x,(t/a|0)*i.y)),new Qa(t,i,e))}class Qa{constructor(t=q(),i=Pa,e=0){this.i=t.v(),this.size=i.v(),this.$=e}offset(t){return new Qa(this.i.add(t),this.size,this.$)}frame(t){return this.offset(q(t*this.size.x,0))}}class Ra{constructor(t){var i;this.image=t,this.size=q(t.width,t.height),(i=Sa)&&(i=G.createTexture(),G.bindTexture(3553,i),t&&G.texImage2D(3553,0,6408,6408,5121,t),t=Ta?9728:9729,G.texParameteri(3553,10241,t),G.texParameteri(3553,10240,t)),this.ja=i,this.ya=q(Ua).U(this.size)}}function Va(t){return new v((t.x-I.x)*J+E.x/2-.5,(t.y-I.y)*-J+E.y/2-.5)}function Ga(t,i=q(1),h,n=new w,e=0,a,s=new w(0,0,0,0),r=Sa){const o=h&&Na[h.$];var c,u,l,b;r?o?(r=h.i.x/o.size.x,c=h.i.y/o.size.y,u=h.size.x/o.size.x,l=h.size.y/o.size.y,b=o.ya,Wa(o.ja),Xa(t.x,t.y,a?-i.x:i.x,i.y,e,r+b.x,c+b.y,r-b.x+u,c-b.y+l,qa(n),qa(s))):Xa(t.x,t.y,i.x,i.y,e,0,0,0,0,0,qa(n)):ab(t,i,e,a,t=>{var i,e,a,s;o?(i=h.i.x+Ua,e=h.i.y+Ua,a=h.size.x-2*Ua,s=h.size.y-2*Ua,t.globalAlpha=n.a,t.drawImage(o.image,i,e,a,s,-.5,-.5,1,1),t.globalAlpha=1):(t.fillStyle=n,t.fillRect(-.5,-.5,1,1))})}function ab(t,i,e,a,s){var h=C;t=Va(t),i=i.scale(J),h.save(),h.translate(t.x+.5,t.y+.5),h.rotate(e),h.scale(a?-i.x:i.x,-i.y),s(h),h.restore()}function bb(t){var i;Sa?cb=t:(i||=C).globalCompositeOperation=t?"lighter":"source-over"}function db(){var i=q(E.x/2,70),t=new w(0,0,0),e=eb,a=Ha;a.fillStyle=(new w).toString(),a.lineWidth=0,a.strokeStyle=t.toString(),a.textAlign="center",a.font="80px "+e,a.textBaseline="middle",a.lineJoin="round",i=i.v(),["LittleJS JS13K Demo"].forEach(t=>{a.fillText(t,i.x,i.y),i.y+=80})}function fb(t,i=0){return K[i]&&!!(1&K[i][t])}let gb=q(),hb=q(),ib=!1;function jb(t,i=0){return fb(t,i+1)}let K=[[]];function kb(){var t;F||(N&&lb||document.hasFocus()||(K=[[]]),t=hb,gb=new v((t.x-E.x/2+.5)/J+I.x,(t.y-E.y/2+.5)/-J+I.y),mb&&nb())}function ob(){if(!F)for(const t of K)for(const i in t)t[i]&=1}function pb(){function i(t){return qb?"KeyW"==t?"ArrowUp":"KeyS"==t?"ArrowDown":"KeyA"==t?"ArrowLeft":"KeyD"==t?"ArrowRight":t:t}F||(onkeydown=t=>{t.repeat||(ib=!1,K[0][t.code]=3,qb&&(K[0][i(t.code)]=3))},onkeyup=t=>{K[0][t.code]=4,qb&&(K[0][i(t.code)]=4)},onmousedown=t=>{ib=!1,K[0][t.button]=3,hb=rb(t),t.button&&t.preventDefault()},onmouseup=t=>K[0][t.button]=2&K[0][t.button]|4,onmousemove=t=>hb=rb(t),onwheel=t=>t.ctrlKey?0:Math.sign(t.deltaY),oncontextmenu=()=>!1,lb&&N&&!F&&sb())}function rb(t){var i;return!B||F?q():(i=B.getBoundingClientRect(),q(B.width,B.height).multiply(q(aa(t.x,i.left,i.right),aa(t.y,i.top,i.bottom))))}const tb=[];function nb(){var t=t=>{var i=t=>.3<t?aa(t,.3,.8):t<-.3?-aa(-t,.3,.8):0;return ma(q(i(t.x),i(-t.y)))};if(ub&&lb&&null!=Ab.time){(i=tb[0]||(tb[0]=[]))[0]=q(),Bb?i[0]=t(O):.3<ka(O)&&(i[0].x=Math.round(O.x),i[0].y=-Math.round(O.y),i[0]=ma(i[0]));for(var i=K[1]||(K[1]=[]),e=10;e--;){var a=3==e?2:2==e?3:e,s=jb(a,0);i[a]=Q[e]?s?1:3:s?4:0}}if(mb&&mb&&navigator&&navigator.getGamepads&&document.hasFocus())for(e=(i=navigator.getGamepads()).length;e--;){var s=i[e],h=K[e+1]||(K[e+1]=[]),a=tb[e]||(tb[e]=[]);if(s){for(var n=0;n<s.axes.length-1;n+=2)a[n>>1]=t(q(s.axes[n],s.axes[n+1]));for(n=s.buttons.length;n--;){var r=s.buttons[n],o=jb(n,e);h[n]=r.pressed?o?1:3:o?4:0,ib||=!e&&r.pressed}Cb&&ka(s=q((jb(15,e)&&1)-(jb(14,e)&&1),(jb(12,e)&&1)-(jb(13,e)&&1)))&&(a[0]=ma(s)),ub&&ib&&(Ab.time=void 0)}}}const lb=void 0!==window.ontouchstart;let Ab=new ra,Q,O;function sb(){function n(t){Db&&R&&"running"!=R.state&&new Eb([0]).play();var i=t.touches.length;return i?(hb=rb(q(t.touches[0].clientX,t.touches[0].clientY)),e?ib=!1:K[0][0]=3):e&&(K[0][0]=2&K[0][0]|4),e=i,document.hasFocus()&&t.preventDefault(),!0}let i=n;ub&&(i=function(t){if(O=q(),Q=[],ib=!0,!t.touches.length||(Ab.set(),!Fb)){var i=q(S,E.y-S),e=E.l(q(S,S)),a=E.scale(.5);for(const h of t.touches){var s=rb(q(h.clientX,h.clientY));la(s,i)**.5<S?O=ma(s.l(i).scale(2/S)):la(s,e)**.5<S?(s=s.l(e).direction(),Q[s]=1):la(s,a)**.5<S&&(Q[9]=1)}return n(t),!0}Q[9]=1},Q=[],O=q()),document.addEventListener("touchstart",t=>i(t),{passive:!1}),document.addEventListener("touchmove",t=>i(t),{passive:!1}),document.addEventListener("touchend",t=>i(t),{passive:!1}),onmousedown=onmouseup=()=>0;let e}function Gb(){if(N&&lb&&!F&&ub&&null!=Ab.time){var t=aa(Ab.get(),4,3);if(t&&!Fb){var i=Ha;if(i.save(),i.globalAlpha=t*Hb,i.strokeStyle="#fff",i.lineWidth=3,i.fillStyle=0<ka(O)?"#fff":"#000",i.beginPath(),t=q(S,E.y-S),Bb)i.arc(t.x,t.y,S/2,0,9),i.fill();else for(var e=10;e--;){var a=e*g/4;i.arc(t.x,t.y,.6*S,a+g/8,a+g/8),e%2&&i.arc(t.x,t.y,.33*S,a,a),1==e&&i.fill()}for(i.stroke(),t=q(E.x-S,E.y-S),e=4;e--;)a=t.add(q().setDirection(e,S/2)),i.fillStyle=Q[e]?"#fff":"#000",i.beginPath(),i.arc(a.x,a.y,S/4,0,9),i.fill(),i.stroke();i.restore()}}}let R,Ib;class Eb{constructor(t){var i=Jb,e=Kb;Db&&!F&&(this.Fa=i,this.Ja=e,this.O=0,t)&&(this.O=t[1]||.05,this.ta=[Lb(...t)],this.sampleRate=44100)}play(i,e=1,a=1,s=1,h=!1){if(Db&&!F&&this.ta){var n;if(i){if(n=this.Fa){var r=la(I,i);if(n*n<r)return;e*=aa(r**.5,n,n*this.Ja)}n=2*Va(i).x/B.width-1}return i=a+a*this.O*s*t(-1,1),this.za=R.createGain(),this.source=Mb(this.ta,e,i,n,h,this.sampleRate,this.za)}}stop(){this.source&&this.source.stop(),this.source=void 0}}let Nb=!1;function Mb(t,i=1,e=1,a=0,s=!1,h=44100,r){if(Db&&!F){var o,c=Nb;if(!(Nb="running"!=R.state)||(R.resume(),!c))return o=R.createBuffer(t.length,t[0].length,h),h=R.createBufferSource(),t.forEach((t,i)=>o.getChannelData(i).set(t)),h.buffer=o,h.playbackRate.value=e,h.loop=s,(r=r||R.createGain()).gain.value=i,r.connect(Ib),h.connect(new StereoPannerNode(R,{pan:n(a,-1,1)})).connect(r),h.start(),h}}function Lb(t=1,i,e=220,a=0,s=0,h=.1,r=0,o=1,c=0,u=0,l=0,b=0,f=0,d=0,y=0,x=0,v=0,m=1,w=0,p=0,q=0){let O=c*=500*(i=2*g)/44100/44100,S=e*=i/44100,z=[],G=0,k=0,M=0,B=1,U=0,J=0,D=0;var F=i*Math.abs(q)*2/44100,C=Math.cos(F),E=1+(A=Math.sin(F)/2/2),F=-2*C/E,A=(1-A)/E;let j=(1+Math.sign(q)*C)/2/E,P=-(Math.sign(q)+C)/E,T=0,K=0,I=0,R=0;for(u*=500*i/44100**3,y*=i/44100,l*=i/44100,b*=44100,f=44100*f|0,E=(a=44100*a+9)+(w*=44100)+(s*=44100)+(h*=44100)+(v*=44100)|0;M<E;z[M++]=D*t)++J%(100*x|0)||(D=r?1<r?2<r?3<r?Math.sin(G**3):n(Math.tan(G),1,-1):1-(2*G/i%2+2)%2:1-4*Math.abs(Math.round(G/i)-G/i):Math.sin(G),D=(f?1-p+p*Math.sin(i*M/f):1)*Math.sign(D)*Math.abs(D)**o*(M<a?M/a:M<a+w?1-(M-a)/w*(1-m):M<a+w+s?m:M<E-v?(E-M-v)/h*m:0),D=v?D/2+(v>M?0:(M<E-v?1:(E-M)/v)*z[M-v|0]/2/t):D,q&&(D=R=j*T+P*(T=K)+j*(K=D)-A*I-F*(I=R))),C=(e+=c+=u)*Math.cos(y*k++),G+=C+C*d*Math.sin(M**5),B&&++B>b&&(e+=l,S+=l,B=0),!f||++U%f||(e=S,c=O,B=B||1);return z}let Ob=[],T=q();function Fa(t,i=q(),e){var a=Math.max(t.x-i.x/2|0,0),s=Math.max(t.y-i.y/2|0,0),h=Math.min(t.x+i.x/2,T.x);for(t=Math.min(t.y+i.y/2,T.y);s<t;++s)for(i=a;i<h;++i){var n=Ob[s*T.x+i];if(n&&(!e||0<n))return!0}}class Pb{constructor(t,i=0,e=!1,a=new w){this.aa=t,this.direction=i,this.o=e,this.color=a}clear(){this.aa=this.direction=0,this.o=!1,this.color=new w}}class Qb extends wa{constructor(t,i=T){var e=q(1);for(super(t,i,Oa(),0,void 0,0),this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.scale=e,this.ka=!1,this.data=[],t=na(this.size);t--;)this.data.push(new Pb);F&&(this.qa=()=>{},this.H=()=>{},this.sa=()=>{},this.ra=()=>{},this.V=()=>{})}setData(t,i,e=!1){pa(t,this.size)&&(this.data[(0|t.y)*this.size.x+t.x|0]=i,e)&&this.V(t)}getData(t){return pa(t,this.size)&&this.data[(0|t.y)*this.size.x+t.x|0]}update(){}H(){Rb||this.ka||Sb();var t=Va(this.i.add(q(0,this.size.y*this.scale.y)));(this.ka?Ha:C).drawImage(this.canvas,t.x,t.y,J*this.size.x*this.scale.x,J*this.size.y*this.scale.y)}qa(){this.sa(!0);for(let i=this.size.x;i--;)for(let t=this.size.y;t--;)this.V(q(i,t),!1);this.ra()}sa(t=!1){this.Ga=[B,C,E,I,J],B=this.canvas,C=this.context,E=this.size.multiply(this.s.size),I=this.size.scale(.5),J=this.s.size.x,t&&(B.width=E.x,B.height=E.y),this.context.imageSmoothingEnabled=!Ta,Tb()}ra(){Sb(!0),[B,C,E,I,J]=this.Ga}V(t,i=!0){var e=this.s.size;i&&(i=t.multiply(e),this.context.clearRect(i.x,this.canvas.height-i.y,e.x,-e.y)),null!=(i=this.getData(t)).aa&&Ga(t=this.i.add(t).add(q(.5)),q(1),Oa(i.aa,e,this.s.$),i.color,i.direction*g/2,i.o)}}function Ub(i){var e="number"==typeof i.W?ea(i.W/2):q(t(-.5,.5),t(-.5,.5)).multiply(i.W).rotate(i.angle);let a=t(i.na,-i.na);i.Y||(e=i.i.add(e),a+=i.angle);const s=i.O;var h=(c=i=>i+i*t(s,-s))(i.Ea),n=c(i.Z),r=c(i.Ha),o=c(i.speed),c=c(i.wa)*(2*Math.floor(t(2,0))-1),u=t(i.ga,-i.ga),l=ja(i.S,i.T,i.pa),b=ja(i.da,i.ea,i.pa),u=i.Y?u:i.angle+u;(e=new Vb(e,i.s,a,l,b,h,n,r,i.G,i.J,i.I,i.Y&&i,i.Da)).g=da(q(),u,o),e.R=c,e.G=i.G,e.m=i.m,e.K=i.K,e.u=i.u,e.X=i.X,e.B=i.B,e.L=i.L,e.P=i.P,e.o=!!Math.floor(t(2,0)),i.oa&&i.oa(e)}class Wb extends wa{constructor(t,i,e=0,a=0,s=100,h=g,n,r=new w,o=new w,c=new w(1,1,1,0),u=new w(1,1,1,0),l=.5,b=.1,f=1,d=.1,y=.05,x=1,v=1,m=0,p=g,S=.1,z=.2,G=!1,M=!1,B=!0,D=M?1e9:0,F=!1){super(t,q(),n,i,void 0,D),this.W=e,this.ia=a,this.ha=s,this.ga=h,this.S=r,this.T=o,this.da=c,this.ea=u,this.pa=B,this.Ea=l,this.Z=b,this.Ha=f,this.speed=d,this.wa=y,this.m=x,this.K=v,this.B=m,this.na=p,this.G=S,this.O=z,this.L=G,this.J=M,this.Y=F,this.I=0,this.oa=this.Da=void 0,this.F=0}update(){if(this.parent&&super.update(),!this.ia||x-this.ua<=this.ia){if(this.ha*Xb){var t=1/this.ha/Xb;for(this.F+=Yb;0<this.F;this.F-=t)Ub(this)}}else va(this)}H(){}}class Vb extends wa{constructor(t,i,e,a,s,h,n,r,o,c,u,l,b){super(t,q(),i,e),this.N=a,this.M=s.l(a),this.Aa=h,this.Z=n,this.Ia=r-n,this.G=o,this.J=c,this.I=u,this.D=l,this.fa=b,this.ba=!1}H(){var t=Math.min((x-this.ua)/this.Aa,1),i=q(this.Z+t*this.Ia),e=this.G/2,e=new w(this.N.r+t*this.M.r,this.N.j+t*this.M.j,this.N.b+t*this.M.b,(this.N.a+t*this.M.a)*(t<e?t/e:1-e<t?(1-t)/e:1));this.J&&bb(!0);let a=this.i;var s,h,n=this.angle;this.D&&(a=this.D.i.add(a.rotate(-this.D.angle)),n+=this.D.angle),this.I?(s=this.g,(n=(s=this.D?s.rotate(-this.D.angle):s).length())&&(s=s.scale(1/n),h=n*this.I,i.y=Math.max(i.x,h),n=s.angle(),Ga(a.add(s.multiply(q(0,-h/2))),i,this.s,e,n,this.o))):Ga(a,i,this.s,e,n,this.o),this.J&&bb(),1==t&&(this.color=e,this.size=i,this.fa&&this.fa(this),this.A=1)}}let U,G,Zb,$b,ac,bc,V,cc,W,cb,dc;function ec(){var t;Sa&&!F&&(U=document.createElement("canvas"),G=U.getContext("webgl2"),Rb&&document.body.appendChild(U),t=G.createProgram(),G.attachShader(t,ic("#version 300 es\nprecision highp float;uniform mat4 m;in vec2 g;in vec4 p,u,c,a;in float r;out vec2 v;out vec4 d,e;void main(){vec2 s=(g-.5)*p.zw;gl_Position=m*vec4(p.xy+s*cos(r)-vec2(-s.y,s)*sin(r),1,1);v=mix(u.xw,u.zy,g);d=c;e=a;}",35633)),G.attachShader(t,ic("#version 300 es\nprecision highp float;uniform sampler2D s;in vec2 v;in vec4 d,e;out vec4 c;void main(){c=texture(s,v)*d+e;}",35632)),G.linkProgram(t),Zb=t,t=new ArrayBuffer(44e4),V=new Float32Array(t),cc=new Uint32Array(t),ac=G.createBuffer(),bc=G.createBuffer(),t=new Float32Array([W=0,0,1,0,0,1,1,1]),G.bindBuffer(34962,bc),G.bufferData(34962,t,35044))}function Tb(){var r,t,i;Sa&&!F&&(G.viewport(0,0,U.width=B.width,U.height=B.height),G.clear(16384),G.useProgram(Zb),G.activeTexture(33984),G.bindTexture(3553,$b=Na[0].ja),r=cb=dc=0,t=(t,i,e,a)=>{t=G.getAttribLocation(Zb,t);var s=e&&44,h=e&&1,n=1==e;G.enableVertexAttribArray(t),G.vertexAttribPointer(t,a,i,n,s,r),G.vertexAttribDivisor(t,h),r+=a*e},G.bindBuffer(34962,bc),t("g",5126,0,2),G.bindBuffer(34962,ac),G.bufferData(34962,44e4,35048),t("p",5126,4,4),t("u",5126,4,4),t("c",5121,1,4),t("a",5121,1,4),t("r",5126,4,1),t=q(2*J).U(E),i=q(-1).l(I.multiply(t)),G.uniformMatrix4fv(G.getUniformLocation(Zb,"m"),!1,[t.x,0,0,0,0,t.y,0,0,1,1,1,1,i.x,i.y,0,0]))}function Wa(t){F||t==$b||(jc(),G.bindTexture(3553,$b=t))}function ic(t,i){return i=G.createShader(i),G.shaderSource(i,t),G.compileShader(i),i}function jc(){var t;W&&(t=dc?1:771,G.blendFuncSeparate(770,t,1,t),G.enable(3042),G.bufferSubData(34962,0,V),G.drawArraysInstanced(5,0,4,W),W=0,dc=cb)}function Sb(t=!1){var i=C;Sa&&(W||t)&&(jc(),Rb&&!t||i.drawImage(U,0,0))}function Xa(t,i,e,a,s,h,n,r,o,c,u=0){(1e4<=W||dc!=cb)&&jc();var l=11*W;V[l++]=t,V[l++]=i,V[l++]=e,V[l++]=a,V[l++]=h,V[l++]=n,V[l++]=r,V[l++]=o,cc[l++]=c,cc[l++]=u,V[+l]=s,W++}const Yb=1/60;let y=[],Ea=[],kc=0,x=0,Fb=!1,lc=0,X=0;const mc=[],nc=[];function oc(){Ea=y.filter(t=>t.ca);for(const t of y)t.parent||(function t(i){if(!i.A){i.update();for(const e of i.children)t(e)}}(t),ua(t));y=y.filter(t=>!t.A)}let I=q(),J=32,pc=q(1920,1080),qc=q(),Ta=!0,eb="arial",F=!1,Sa=!0,Rb=!0,Pa=q(16),Ua=.5,Da=!0,xa=1,ya=1,za=1,Aa=0,Ba=.8,z=1,Ca=0,Xb=1,mb=!1,Cb=!(mb=!1),qb=!0,N=!1,ub=N=N=!1,Bb=!0,S=99,Hb=.3,Db=!0,rc=.3,Jb=40,Kb=.7;function sc(){var t=rc;rc=t,Db&&!F&&Ib&&(Ib.gain.value=t)}let Y;qb=N=!1;const tc=new Eb([1,.5]);!function(s,h,n,r,i=["tiles.png"]){function o(t=0){var i=t-lc;if(lc=t,X+=Fb?0:i,X=Math.min(X,50),c(),Fb){for(const e of y)e.parent||ua(e);kb(),h(),ob()}else{for(t=0,X<0&&-9<X&&(t=X,X=0);0<=X;X-=1e3/60)x=kc++/60,kb(),s(),mc.forEach(t=>t()),oc(),h(),ob();X+=t}if(!F){E=q(B.width,B.height),C.imageSmoothingEnabled=!Ta,Tb(),n(),y.sort((t,i)=>t.P-i.P);for(const a of y)a.A||a.H();r(),nc.forEach(t=>t()),Gb(),Sb()}requestAnimationFrame(o)}function c(){var t,i;F||(qc.x?(B.width=qc.x,B.height=qc.y,t=innerWidth/innerHeight,i=B.width/B.height,(U||B).style.width=B.style.width=D.style.width=t<i?"100%":"",(U||B).style.height=B.style.height=D.style.height=t<i?"":"100%"):(B.width=Math.min(innerWidth,pc.x),B.height=Math.min(innerHeight,pc.y)),D.width=B.width,D.height=B.height,E=q(B.width,B.height))}function e(){{T=q(32,16);for(var i=(Ob=[]).length=na(T);i--;)Ob[i]=0;i=q();var e=new Qb(i,T),a=Na[0].image,s=(C.drawImage(a,0,0),C.getImageData(0,0,a.width,a.height).data),h,n,r;for(i.x=T.x;i.x--;)for(i.y=T.y;i.y--;)s[4*(i.x+a.width*(15+T.y-i.y))]&&(h=Math.floor(t(4,0)),n=Math.floor(t(2,0)),r=ja(),e.setData(i,new Pb(1,h,n,r)),pa(i,T))&&(Ob[(0|i.y)*T.x+i.x|0]=1);e.qa(),I=q(16,8),Ca=-.01,(Y=new Wb(q(16,9),0,1,0,500,g,Oa(0,16),new w(1,1,1),new w(0,0,0),new w(0,0,0,0),new w(0,0,0,0),2,.2,.2,.1,.05,.99,1,1,g,.05,.5,1,1)).u=.3,Y.I=2}o()}F?e():(document.body.style.cssText="margin:0;overflow:hidden;background:#000;user-select:none;-webkit-user-select:none;"+(N?"touch-action:none;-webkit-touch-callout:none":""),document.body.appendChild(B=document.createElement("canvas")),C=B.getContext("2d"),pb(),Db&&!F&&(R=new AudioContext,(Ib=R.createGain()).connect(R.destination),sc()),ec(),document.body.appendChild(D=document.createElement("canvas")),Ha=D.getContext("2d"),(U||B).style.cssText=B.style.cssText=D.style.cssText="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)",c(),i=i.map((e,a)=>new Promise(t=>{const i=new Image;i.onerror=i.onload=()=>{Na[a]=new Ra(i),t()},i.src=e})),Promise.all(i).then(e))}(function(){K[0]&&2&K[0][0]&&(tc.play(gb),Y.S=new w,Y.T=ja(),Y.da=Y.S.scale(1,0),Y.ea=Y.T.scale(1,0)),hb.x&&(Y.i=gb)},function(){},function(){Ga(q(16,8),q(20,14),void 0,new w(.6,.6,.6),0,!1,void 0,0)},function(){db()});
Binary file
Binary file
@@ -112,4 +112,4 @@ function gameRenderPost()
112
112
 
113
113
  ///////////////////////////////////////////////////////////////////////////////
114
114
  // Startup LittleJS Engine
115
- engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost);
115
+ engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
Binary file
@@ -1,18 +1,21 @@
1
- <head><title>LittleJS JS13K Project</title></head><body>
1
+ <head>
2
+ <title>LittleJS JS13K Project</title>
3
+ <meta charset=utf-8>
4
+ </head><body>
2
5
 
3
6
  <!-- LittleJS Engine -->
4
- <script src=../../src/engineDebug.js?198></script>
5
- <script src=../../src/engineUtilities.js?198></script>
6
- <script src=../../src/engineSettings.js?198></script>
7
- <script src=../../src/engineObject.js?198></script>
8
- <script src=../../src/engineDraw.js?198></script>
9
- <script src=../../src/engineInput.js?198></script>
10
- <script src=../../src/engineAudio.js?198></script>
11
- <script src=../../src/engineTileLayer.js?198></script>
12
- <script src=../../src/engineParticles.js?198></script>
13
- <script src=../../src/engineMedals.js?198></script>
14
- <script src=../../src/engineWebGL.js?198></script>
15
- <script src=../../src/engine.js?198></script>
7
+ <script src=../../src/engineDebug.js?1100></script>
8
+ <script src=../../src/engineUtilities.js?1100></script>
9
+ <script src=../../src/engineSettings.js?1100></script>
10
+ <script src=../../src/engineObject.js?1100></script>
11
+ <script src=../../src/engineDraw.js?1100></script>
12
+ <script src=../../src/engineInput.js?1100></script>
13
+ <script src=../../src/engineAudio.js?1100></script>
14
+ <script src=../../src/engineTileLayer.js?1100></script>
15
+ <script src=../../src/engineParticles.js?1100></script>
16
+ <script src=../../src/engineMedals.js?1100></script>
17
+ <script src=../../src/engineWebGL.js?1100></script>
18
+ <script src=../../src/engine.js?1100></script>
16
19
 
17
20
  <!-- Add your game scripts here -->
18
- <script src=game.js?198></script>
21
+ <script src=game.js?1100></script>
@@ -128,4 +128,4 @@ function gameRenderPost()
128
128
 
129
129
  ///////////////////////////////////////////////////////////////////////////////
130
130
  // Startup LittleJS Engine
131
- LittleJS.engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost);
131
+ LittleJS.engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
@@ -1,9 +1,10 @@
1
1
  <!DOCTYPE html><head>
2
- <title>Little JS Module Demo</title>
2
+ <title>LittleJS Module Demo</title>
3
+ <meta charset=utf-8>
3
4
  <meta name=apple-mobile-web-app-capable content=yes>
4
5
  <meta name=mobile-web-app-capable content=yes>
5
6
  <link rel=icon type=image/png href=../favicon.png>
6
7
  </head><body>
7
8
 
8
9
  <!-- Add your game scripts here -->
9
- <script src=game.js?198 type=module></script>
10
+ <script src=game.js?1100 type=module></script>
@@ -1,5 +1,6 @@
1
1
  <!DOCTYPE html><head>
2
- <title>Little JS Particle System Designer</title>
2
+ <title>LittleJS Particle System Designer</title>
3
+ <meta charset=utf-8>
3
4
  <meta name=apple-mobile-web-app-capable content=yes>
4
5
  <meta name=mobile-web-app-capable content=yes>
5
6
  <link rel=icon type=image/png href=../favicon.png>
@@ -9,7 +10,7 @@ button { margin:1px; }
9
10
  </style>
10
11
  </head><body>
11
12
 
12
- <script src=../../dist/littlejs.js?198></script>
13
+ <script src=../../dist/littlejs.js?1100></script>
13
14
  <script>
14
15
 
15
16
  'use strict';
@@ -390,6 +391,6 @@ function gameRenderPost()
390
391
 
391
392
  ///////////////////////////////////////////////////////////////////////////////
392
393
  // Startup LittleJS Engine
393
- engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost);
394
+ engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
394
395
 
395
396
  </script>
@@ -13,6 +13,12 @@ setShowSplashScreen(true);
13
13
 
14
14
  let spriteAtlas, score, deaths;
15
15
 
16
+ // enable touch gamepad on touch devices
17
+ touchGamepadEnable = true;
18
+
19
+ // fix texture bleeding by shrinking tile slightly
20
+ tileFixBleedScale = .1;
21
+
16
22
  ///////////////////////////////////////////////////////////////////////////////
17
23
  function gameInit()
18
24
  {
@@ -30,10 +36,6 @@ function gameInit()
30
36
  gun: tile(2,8),
31
37
  grenade: tile(3,8),
32
38
  };
33
-
34
- // enable touch gamepad on touch devices
35
- touchGamepadEnable = true;
36
-
37
39
  // setup level
38
40
  buildLevel();
39
41
 
@@ -81,7 +83,7 @@ function gameUpdate()
81
83
  function getCameraTarget()
82
84
  {
83
85
  // camera is above player
84
- const offset = 3*percent(mainCanvasSize.y, 300, 600);
86
+ const offset = 200/cameraScale*percent(mainCanvasSize.y, 300, 600);
85
87
  return player.pos.add(vec2(0, offset));
86
88
  }
87
89
 
@@ -31,6 +31,7 @@ class Character extends GameObject
31
31
  this.renderOrder = 10;
32
32
  this.walkCyclePercent = 0;
33
33
  this.health = 1;
34
+ this.climbingLadder = false;
34
35
  this.setCollision(true,false);
35
36
  }
36
37
 
@@ -102,9 +103,9 @@ class Character extends GameObject
102
103
  touchingLadder ||= collisionData == tileType_ladder;
103
104
  }
104
105
  if (!touchingLadder)
105
- this.climbingLadder = 0;
106
+ this.climbingLadder = false;
106
107
  else if (moveInput.y)
107
- this.climbingLadder = 1;
108
+ this.climbingLadder = true;
108
109
 
109
110
  if (this.weapon) // update weapon trigger
110
111
  this.weapon.triggerIsDown = this.holdingShoot && !this.dodgeTimer.active();
@@ -236,10 +237,10 @@ class Character extends GameObject
236
237
  damage(damage, damagingObject)
237
238
  {
238
239
  if (this.isDead() || this.getAliveTime() < 1 || this.dodgeTimer.active())
239
- return;
240
+ return 0;
240
241
 
241
242
  makeBlood(damagingObject ? damagingObject.pos : this.pos);
242
- super.damage(damage, damagingObject);
243
+ return super.damage(damage, damagingObject);
243
244
  }
244
245
 
245
246
  kill(damagingObject)
@@ -251,31 +252,31 @@ class Character extends GameObject
251
252
  sound_die.play(this.pos);
252
253
 
253
254
  this.health = 0;
254
- if (this.weapon)
255
- this.weapon.destroy();
256
255
  this.deadTimer.set();
257
256
  this.size = this.size.scale(.5);
258
257
  const fallDirection = damagingObject ? sign(damagingObject.velocity.x) : randSign();
259
258
  this.angleVelocity = fallDirection*rand(.22,.14);
260
259
  this.angleDamping = .9;
261
260
  this.renderOrder = -1; // move to back layer
261
+ if (this.weapon)
262
+ this.weapon.destroy();
262
263
  }
263
264
 
264
265
  collideWithTile(data, pos)
265
266
  {
266
267
  if (!data)
267
- return;
268
+ return false;
268
269
 
269
270
  if (data == tileType_ladder)
270
271
  {
271
272
  // handle ladder collisions
272
273
  if (pos.y + 1 > this.lastPos.y - this.size.y/2)
273
- return;
274
+ return false;
274
275
 
275
276
  if (getTileCollisionData(pos.add(vec2(0,1))) // above
276
277
  && !getTileCollisionData(pos.add(vec2(1,0))) // left
277
278
  && !getTileCollisionData(pos.add(vec2(1,0)))) // right
278
- return; // dont collide if something above it and nothing to left or right
279
+ return false; // dont collide if something above it and nothing to left or right
279
280
 
280
281
  // allow standing on top of ladders
281
282
  return !this.climbingLadder;
@@ -287,9 +288,9 @@ class Character extends GameObject
287
288
  {
288
289
  // break blocks above
289
290
  this.velocity.y = 0;
290
- return;
291
+ return false;
291
292
  }
292
293
 
293
- return 1;
294
+ return true;
294
295
  }
295
296
  }
@@ -129,13 +129,13 @@ function destroyTile(pos, makeSound = 1, cleanNeighbors = 1)
129
129
  // destroy tile
130
130
  const tileType = getTileCollisionData(pos);
131
131
  if (!tileType)
132
- return 1;
132
+ return true;
133
133
 
134
134
  const tileLayer = tileLayers[foregroundLayerIndex];
135
135
  const centerPos = pos.add(vec2(.5));
136
136
  const layerData = tileLayer.getData(pos);
137
137
  if (!layerData || tileType == tileType_solid)
138
- return;
138
+ return false;
139
139
 
140
140
  // create effects
141
141
  makeDebris(centerPos, layerData.color.mutate());
@@ -144,7 +144,6 @@ function destroyTile(pos, makeSound = 1, cleanNeighbors = 1)
144
144
  // set and clear tile
145
145
  tileLayer.setData(pos, new TileLayerData, 1);
146
146
  setTileCollisionData(pos, tileType_empty);
147
- setTileData(pos, foregroundLayerIndex, 0);
148
147
 
149
148
  // cleanup neighbors
150
149
  if (cleanNeighbors)
@@ -154,7 +153,7 @@ function destroyTile(pos, makeSound = 1, cleanNeighbors = 1)
154
153
  decorateTile(pos.add(vec2(i,j)));
155
154
  }
156
155
 
157
- return 1;
156
+ return true;
158
157
  }
159
158
 
160
159
  ///////////////////////////////////////////////////////////////////////////////