diff --git a/engine/engine.all.js b/engine/engine.all.js index 6d87eb95..491c15dd 100644 --- a/engine/engine.all.js +++ b/engine/engine.all.js @@ -3878,7 +3878,7 @@ gl_VERTEX_BYTE_STRIDE = 4 + (4 * 2) * 3 + (4) * 2; // float + vec2 * 3 + (char * const engineName = 'LittleJS'; /** Version of engine */ -const engineVersion = '1.1.8'; +const engineVersion = '1.1.9'; /** Frames per second to update objects * @default */ diff --git a/engine/engine.all.min.js b/engine/engine.all.min.js index 5d82dc6d..502a71c1 100644 --- a/engine/engine.all.min.js +++ b/engine/engine.all.min.js @@ -1 +1 @@ -"use strict";const debug=0,showWatermark=0,godMode=0,debugOverlay=0,debugPhysics=0,debugParticles=0,debugRaycast=0,debugGamepads=0,debugMedals=0,ASSERT=()=>{},debugInit=()=>{},debugUpdate=()=>{},debugRender=()=>{},debugRect=()=>{},debugCircle=()=>{},debugPoint=()=>{},debugLine=()=>{},debugAABB=()=>{},debugClear=()=>{},debugSaveCanvas=()=>{};"use strict";const PI=Math.PI,isChrome=window.chrome,abs=a=>0>a?-a:a,sign=a=>0>a?-1:1,min=(a,b)=>aa>b?a:b,mod=(a,b)=>(a%b+b)%b,clamp=(a,b=1,c=0)=>(ASSERT(b>c),ab?b:a),percent=(a,b=1,c=0)=>b-c?clamp((a-c)/(b-c)):0,lerp=(a,b=1,c=0)=>c+clamp(a)*(b-c),formatTime=a=>(a/60|0)+":"+(10>a%60?"0":"")+(a%60|0),nearestPowerOfTwo=a=>2**Math.ceil(Math.log2(a)),smoothStep=a=>a*a*(3-2*a),isOverlapping=(a,b,c,d)=>2*abs(a.x-c.x)b/2*(1-Math.cos(c*a*2*PI)),rand=(a=1,b=0)=>b+(a-b)*Math.random(),randInt=(a=1,b=0)=>rand(a,b)|0,randSign=()=>2*(rand(2)|0)-1,randInCircle=(a=1,b=0)=>0(new Vector2).setAngle(rand(2*PI),a),randColor=(a=new Color,b=new Color(0,0,0,1),c)=>c?a.lerp(b,rand()):new Color(rand(a.r,b.r),rand(a.g,b.g),rand(a.b,b.b),rand(a.a,b.a));let randSeed=1;const randSeeded=(a=1,b=0)=>{randSeed^=randSeed<<13;randSeed^=randSeed>>>17;randSeed^=randSeed<<5;return b+(a-b)*abs(randSeed%1e9)/1e9},vec2=(a=0,b)=>void 0==a.x?new Vector2(a,void 0==b?a:b):new Vector2(a.x,a.y);class Vector2{constructor(a=0,b=0){this.x=a;this.y=b}copy(){return new Vector2(this.x,this.y)}add(a){ASSERT(void 0!=a.x);return new Vector2(this.x+a.x,this.y+a.y)}subtract(a){ASSERT(void 0!=a.x);return new Vector2(this.x-a.x,this.y-a.y)}multiply(a){ASSERT(void 0!=a.x);return new Vector2(this.x*a.x,this.y*a.y)}divide(a){ASSERT(void 0!=a.x);return new Vector2(this.x/a.x,this.y/a.y)}scale(a){ASSERT(void 0==a.x);return new Vector2(this.x*a,this.y*a)}length(){return this.lengthSquared()**.5}lengthSquared(){return this.x**2+this.y**2}distance(a){return this.distanceSquared(a)**.5}distanceSquared(a){return(this.x-a.x)**2+(this.y-a.y)**2}normalize(a=1){const b=this.length();return b?this.scale(a/b):new Vector2(a)}clampLength(a=1){const b=this.length();return b>a?this.scale(a/b):this}dot(a){ASSERT(void 0!=a.x);return this.x*a.x+this.y*a.y}cross(a){ASSERT(void 0!=a.x);return this.x*a.y-this.y*a.x}angle(){return Math.atan2(this.x,this.y)}setAngle(a=0,b=1){this.x=b*Math.sin(a);this.y=b*Math.cos(a);return this}rotate(a){const b=Math.cos(a);a=Math.sin(a);return new Vector2(this.x*b-this.y*a,this.x*a+this.y*b)}direction(){return abs(this.x)>abs(this.y)?0>this.x?3:1:0>this.y?2:0}invert(){return new Vector2(this.y,-this.x)}flip(){return new Vector2(this.y,this.x)}floor(){return new Vector2(Math.floor(this.x),Math.floor(this.y))}area(){return this.x*this.y}lerp(a,b){ASSERT(void 0!=a.x);return this.add(a.subtract(this).scale(clamp(b)))}arrayCheck(a){return 0<=this.x&&0<=this.y&&this.xc?c*(1+b):c+b-c*b;c=2*c-b;const e=(f,k,h)=>(h=(h%1+1)%1)<1/6?f+6*(k-f)*h:.5>h?k:h<2/3?f+(k-f)*(2/3-h)*6:f;this.r=e(c,b,a+1/3);this.g=e(c,b,a);this.b=e(c,b,a-1/3);this.a=d;return this}mutate(a=.05,b=0){return new Color(this.r+rand(a,-a),this.g+rand(a,-a),this.b+rand(a,-a),this.a+rand(b,-b)).clamp()}rgba(){ASSERT(0<=this.r&&1>=this.r&&0<=this.g&&1>=this.g&&0<=this.b&&1>=this.b&&0<=this.a&&1>=this.a);return`rgb(${255*this.r|0},${255*this.g|0},${255*this.b|0},${this.a})`}rgbaInt(){ASSERT(0<=this.r&&1>=this.r&&0<=this.g&&1>=this.g&&0<=this.b&&1>=this.b&&0<=this.a&&1>=this.a);return(255*this.r|0)+(255*this.g<<8)+(255*this.b<<16)+(255*this.a<<24)}}class Timer{constructor(a){this.time=void 0==a?void 0:time+a;this.setTime=a}set(a=0){this.time=time+a;this.setTime=a}unset(){this.time=void 0}isSet(){return void 0!=this.time}active(){return time<=this.time}elapsed(){return time>this.time}get(){return this.isSet()?time-this.time:0}getPercent(){return this.isSet()?percent(this.time-time,0,this.setTime):0}}"use strict";const maxSize=vec2(1920,1200);let fixedSize=vec2(),fontDefault="arial",pixelated=1;const tileSizeDefault=vec2(16),tileBleedShrinkFix=.3,objectDefaultSize=vec2(1),objectDefaultMass=1,objectDefaultDamping=.99,objectDefaultAngleDamping=.99,objectDefaultElasticity=0,objectDefaultFriction=.8,objectMaxSpeed=1;let gravity=0,cameraPos=vec2(),cameraScale=max(tileSizeDefault.x,tileSizeDefault.y);const glEnable=1;let glOverlay=1;const gamepadsEnable=1,gamepadDirectionEmulateStick=1,inputTouchEnable=1,inputWASDEmulateDirection=1;let soundVolume=.5;const soundEnable=1,soundDefaultRange=30,soundDefaultTaper=.7,medalDisplayTime=5,medalDisplaySlideTime=.5,medalDisplayWidth=640,medalDisplayHeight=99,medalDisplayIconSize=80;"use strict";const engineName="LittleJS",engineVersion="1.1.8",FPS=60,timeDelta=1/FPS;let engineObjects=[],engineCollideObjects=[],frame=0,time=0,timeReal=0,paused=0,frameTimeLastMS=0,frameTimeBufferMS=0,debugFPS=0,shrinkTilesX,shrinkTilesY,drawCount,tileImageSize,tileImageSizeInverse;function engineInit(a,b,c,d,e,f){tileImage.onerror=tileImage.onload=()=>{tileImageSizeInverse=vec2(1).divide(tileImageSize=vec2(tileImage.width,tileImage.height));debug&&(tileImage.onload=()=>ASSERT(1));shrinkTilesX=tileBleedShrinkFix/tileImageSize.x;shrinkTilesY=tileBleedShrinkFix/tileImageSize.y;document.body.appendChild(mainCanvas=document.createElement("canvas"));document.body.style="margin:0;overflow:hidden;background:#000";mainCanvas.style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)"+(pixelated?";image-rendering:crisp-edges;image-rendering:pixelated":"");mainContext=mainCanvas.getContext("2d");debugInit();glInit();document.body.appendChild(overlayCanvas=document.createElement("canvas"));overlayCanvas.style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)";overlayContext=overlayCanvas.getContext("2d");a();k()};const k=(h=0)=>{requestAnimationFrame(k);var l=h-frameTimeLastMS;frameTimeLastMS=h;if(debug||showWatermark)debugFPS=lerp(.05,1e3/(l||1),debugFPS);debug&&(l*=keyIsDown(107)?5:keyIsDown(109)?.2:1);timeReal+=l/1e3;frameTimeBufferMS=min(frameTimeBufferMS+!paused*l,50);if(paused)inputUpdate(),debugUpdate(),c(),inputUpdatePost();else{h=0;0>frameTimeBufferMS&&-9m.renderOrder-g.renderOrder);for(var n of engineObjects)n.destroyed||n.render();e();medalsRender();debugRender();glCopyToContext(mainContext);showWatermark&&(overlayContext.textAlign="right",overlayContext.textBaseline="top",overlayContext.font="1em monospace",overlayContext.fillStyle="#000",n=engineName+" v"+engineVersion+" / "+drawCount+" / "+engineObjects.length+" / "+debugFPS.toFixed(1),overlayContext.fillText(n,mainCanvas.width-3,3),overlayContext.fillStyle="#fff",overlayContext.fillText(n,mainCanvas.width-2,2),drawCount=0)};f?tileImage.src=f:tileImage.onload()}function engineObjectsUpdate(){const a=b=>{if(!b.destroyed){b.update();for(const c of b.children)a(c)}};for(const b of engineObjects)b.parent||a(b);engineObjects=engineObjects.filter(b=>!b.destroyed);engineCollideObjects=engineCollideObjects.filter(b=>!b.destroyed);time=++frame/FPS}function engineObjectsDestroy(){for(const a of engineObjects)a.persistent||a.parent||a.destroy();engineObjects=engineObjects.filter(a=>!a.destroyed)}function engineObjectsCallback(a,b,c,d=engineObjects){if(a)if(void 0!=b.x)for(const e of d)isOverlapping(a,b,e.pos,e.size)&&c(e);else{b*=b;for(const e of d)a.distanceSquared(e.pos)=this.angleDamping),ASSERT(0<=this.damping&&1>=this.damping),this.mass){var b=0>this.velocity.y;if(this.groundObject){var c=this.groundObject.velocity?this.groundObject.velocity.x:0;this.velocity.x=c+(this.velocity.x-c)*this.friction;this.groundObject=0}if(this.collideSolidObjects)for(var d of engineCollideObjects)if(!(!this.isSolid&!d.isSolid||d.destroyed||d.parent||!isOverlapping(this.pos,this.size,d.pos,d.size)||d==this||!this.collideWithObject(d)|!d.collideWithObject(this)))if(isOverlapping(a,this.size,d.pos,d.size)){c=a.subtract(d.pos);var e=c.length();c=.01>e?randVector(.001):c.scale(.001/e);this.velocity=this.velocity.add(c);d.mass&&(d.velocity=d.velocity.subtract(c));debugPhysics&&debugAABB(this.pos,this.size,d.pos,d.size,"#f00")}else{c=this.size.x+d.size.x;var f=this.size.y+d.size.y;e=2*(a.y-d.pos.y)>f+gravity;var k=2*abs(a.y-d.pos.y)c&&console.log("stepUp",a.y-d.pos.y)}e||!k&&h||(this.pos.x=d.pos.x+(c/2+.001)*sign(a.x-d.pos.x),d.mass?(c=(this.mass*this.velocity.x+d.mass*d.velocity.x)/(this.mass+d.mass),e=this.velocity.x*(this.mass-d.mass)/(this.mass+d.mass)+2*d.velocity.x*d.mass/(this.mass+d.mass),k=d.velocity.x*(d.mass-this.mass)/(this.mass+d.mass)+2*this.velocity.x*this.mass/(this.mass+d.mass),h=max(this.elasticity,d.elasticity),this.velocity.x=lerp(h,e,c),d.velocity.x=lerp(h,k,c)):this.velocity.x*=-this.elasticity);debugPhysics&&debugAABB(this.pos,this.size,d.pos,d.size,"#f0f")}if(this.collideTiles&&tileCollisionTest(this.pos,this.size,this)&&!tileCollisionTest(a,this.size,this)){c=tileCollisionTest(new Vector2(a.x,this.pos.y),this.size,this);d=tileCollisionTest(new Vector2(this.pos.x,a.y),this.size,this);if(c||!d)this.groundObject=b,this.velocity.y*=-this.elasticity,b=(a.y-this.size.y/2|0)-(a.y-this.size.y/2),0>b&&-1this.damping*this.velocity.y+gravity*this.gravityScale&&(this.velocity.y=this.damping?(b-gravity*this.gravityScale)/this.damping:0),this.pos.y=a.y;d&&(this.pos.x=a.x,this.velocity.x*=-this.elasticity)}}}render(){drawTile(this.pos,this.drawSize||this.size,this.tileIndex,this.tileSize,this.color,this.angle,this.mirror,this.additiveColor)}destroy(){if(!this.destroyed){this.destroyed=1;this.parent&&this.parent.removeChild(this);for(const a of this.children)a.destroy(a.parent=0)}}collideWithTile(a,b){return 0a.add(vec2(.5)).subtract(mainCanvasSize.scale(.5)).multiply(vec2(1/cameraScale,-1/cameraScale)).add(cameraPos),worldToScreen=a=>a.subtract(cameraPos).multiply(vec2(cameraScale,-cameraScale)).add(mainCanvasSize.scale(.5)).subtract(vec2(.5));function drawTile(a,b=vec2(1),c=-1,d=tileSizeDefault,e=new Color,f=0,k,h=new Color(0,0,0,0),l=glEnable){showWatermark&&++drawCount;if(glEnable&&l)if(0>c||!tileImage.width)glDraw(a.x,a.y,b.x,b.y,f,0,0,0,0,0,e.rgbaInt());else{var n=tileImage.width/d.x|0;l=d.x*tileImageSizeInverse.x;const m=d.y*tileImageSizeInverse.y,g=c%n*l;n=(c/n|0)*m;const q=tileBleedShrinkFix*tileImageSizeInverse.x;glDraw(a.x,a.y,k?-b.x:b.x,b.y,f,g+q,n+tileBleedShrinkFix*tileImageSizeInverse.y,g-q+l,n-q+m,e.rgbaInt(),h.rgbaInt())}else drawCanvas2D(a,b,f,k,m=>{if(0>c)m.fillStyle=e.rgba(),m.fillRect(-.5,-.5,1,1);else{var g=tileImage.width/d.x|0;const q=c%g*d.x+tileBleedShrinkFix;g=(c/g|0)*d.y+tileBleedShrinkFix;const w=d.x-2*tileBleedShrinkFix,v=d.y-2*tileBleedShrinkFix;m.globalAlpha=e.a;m.drawImage(tileImage,q,g,w,v,-.5,-.5,1,1)}})}function drawRect(a,b,c,d,e){drawTile(a,b,-1,tileSizeDefault,c,d,0,0,e)}function drawTileScreenSpace(a,b=vec2(1),c,d,e,f,k,h,l){drawTile(screenToWorld(a),b.scale(1/cameraScale),c,d,e,f,k,h,l)}function drawRectScreenSpace(a,b,c,d,e){drawTileSrceenSpace(a,b,-1,tileSizeDefault,c,d,0,0,e)}function drawLine(a,b,c=.1,d,e){b=vec2((b.x-a.x)/2,(b.y-a.y)/2);c=vec2(c,2*b.length());drawRect(a.add(b),c,d,b.angle(),0,0,e)}function drawCanvas2D(a,b,c,d,e,f=mainContext){a=worldToScreen(a);b=b.scale(cameraScale);f.save();f.translate(a.x+.5|0,a.y-.5|0);f.rotate(c);f.scale(d?-b.x:b.x,b.y);e(f);f.restore()}function drawText(a,b,c=1,d=new Color,e=0,f=new Color(0,0,0),k="center",h=fontDefault){b=worldToScreen(b);overlayContext.font=c*cameraScale+"px "+h;overlayContext.textAlign=k;overlayContext.textBaseline="middle";e&&(overlayContext.lineWidth=e*cameraScale,overlayContext.strokeStyle=f.rgba(),overlayContext.strokeText(a,b.x,b.y));overlayContext.fillStyle=d.rgba();overlayContext.fillText(a,b.x,b.y)}function setBlendMode(a,b=glEnable){glEnable&&b?glSetBlendMode(a):mainContext.globalCompositeOperation=a?"lighter":"source-over"}const isFullscreen=()=>document.fullscreenElement;function toggleFullscreen(){isFullscreen()?document.exitFullscreen?document.exitFullscreen():document.mozCancelFullScreen&&document.mozCancelFullScreen():document.body.webkitRequestFullScreen?document.body.webkitRequestFullScreen():document.body.mozRequestFullScreen&&document.body.mozRequestFullScreen()}"use strict";const keyIsDown=(a,b=0)=>inputData[b]&&inputData[b][a]&1?1:0,keyWasPressed=(a,b=0)=>inputData[b]&&inputData[b][a]&2?1:0,keyWasReleased=(a,b=0)=>inputData[b]&&inputData[b][a]&4?1:0,clearInput=()=>inputData[0]=[],mouseIsDown=keyIsDown,mouseWasPressed=keyWasPressed,mouseWasReleased=keyWasReleased;let mousePos=vec2(),mousePosScreen=vec2(),mouseWheel=0,isUsingGamepad=0;const gamepadIsDown=(a,b=0)=>keyIsDown(a,b+1),gamepadWasPressed=(a,b=0)=>keyWasPressed(a,b+1),gamepadWasReleased=(a,b=0)=>keyWasReleased(a,b+1),gamepadStick=(a,b=0)=>stickData[b]?stickData[b][a]||vec2():vec2(),inputData=[[]];function inputUpdate(){document.hasFocus()||clearInput();mousePos=screenToWorld(mousePosScreen);gamepadsUpdate()}function inputUpdatePost(){for(const a of inputData)for(const b in a)a[b]&=1;mouseWheel=0}onkeydown=a=>{debug&&a.target!=document.body||(a.repeat||(inputData[isUsingGamepad=0][remapKeyCode(a.keyCode)]=3),debug||a.preventDefault())};onkeyup=a=>{debug&&a.target!=document.body||(inputData[0][remapKeyCode(a.keyCode)]=4)};const remapKeyCode=a=>inputWASDEmulateDirection?87==a?38:83==a?40:65==a?37:68==a?39:a:a;onmousedown=a=>{inputData[isUsingGamepad=0][a.button]=3;onmousemove(a);a.button&&a.preventDefault()};onmouseup=a=>inputData[0][a.button]=inputData[0][a.button]&2|4;onmousemove=a=>{if(mainCanvas){var b=mainCanvas.getBoundingClientRect();mousePosScreen.x=mainCanvasSize.x*percent(a.x,b.right,b.left);mousePosScreen.y=mainCanvasSize.y*percent(a.y,b.bottom,b.top)}};onwheel=a=>a.ctrlKey||(mouseWheel=sign(a.deltaY));oncontextmenu=a=>!1;const stickData=[];function gamepadsUpdate(){if(gamepadsEnable&&navigator.getGamepads&&(document.hasFocus()||debug)){var a=navigator.getGamepads();for(let e=a.length;e--;){var b=a[e];const f=inputData[e+1]||(inputData[e+1]=[]),k=stickData[e]||(stickData[e]=[]);if(b){var c=h=>.3h?-percent(-h,.8,.3):0;for(var d=0;d>1]=vec2(c(b.axes[d]),c(-b.axes[d+1])).clampLength();for(c=b.buttons.length;c--;)d=b.buttons[c],f[c]=d.pressed?1+2*!gamepadIsDown(c,e):4*gamepadIsDown(c,e),isUsingGamepad|=!e&&d.pressed;gamepadDirectionEmulateStick&&(b=vec2(gamepadIsDown(15,e)-gamepadIsDown(14,e),gamepadIsDown(12,e)-gamepadIsDown(13,e)),b.lengthSquared()&&(k[0]=b.clampLength()))}}}}const isTouchDevice=inputTouchEnable&&void 0!==window.ontouchstart;if(isTouchDevice){let a,b;ontouchstart=ontouchmove=ontouchend=c=>{c.button=0;const d=c.touches.length;d?(b||zzfx(0,b=1),c.x=c.touches[0].clientX,c.y=c.touches[0].clientY,a?onmousemove(c):onmousedown(c)):a&&onmouseup(c);a=d;return!c.cancelable}}"use strict";class Sound{constructor(a,b=soundDefaultRange,c=soundDefaultTaper){soundEnable&&(this.range=b,this.taper=c,this.randomness=a[1]||0,a[1]=0,this.cachedSamples=zzfxG(...a))}play(a,b=1,c=1,d=1){if(soundEnable){var e=0;if(a){if(e=this.range){const f=cameraPos.distanceSquared(a);if(f>e*e)return;b*=percent(f**.5,e*this.taper,e)}e=2*worldToScreen(a).x/mainCanvas.width-1}a=c+c*this.randomness*d*rand(-1,1);return playSamples([this.cachedSamples],b,a,e)}}playNote(a,b,c=1){if(soundEnable)return this.play(b,c,2**(a/12),0)}}class Music{constructor(a){soundEnable&&(this.cachedSamples=zzfxM(...a))}play(a=1,b=1){if(soundEnable)return playSamples(this.cachedSamples,a,1,0,b)}}function playAudioFile(a,b=1,c=1){if(soundEnable)return a=new Audio(a),a.volume=soundVolume*b,a.loop=c,a.play(),a}function speak(a,b="",c=1,d=1,e=1){if(soundEnable&&speechSynthesis)return a=new SpeechSynthesisUtterance(a),a.lang=b,a.volume=2*c*soundVolume,a.rate=d,a.pitch=e,speechSynthesis.speak(a),a}const stopSpeech=()=>speechSynthesis&&speechSynthesis.cancel(),getNoteFrequency=(a,b=220)=>b*2**(a/12);let audioContext;function playSamples(a,b=1,c=1,d=0,e=0){if(soundEnable){audioContext||(audioContext=new(window.AudioContext||webkitAudioContext));var f=audioContext.createBuffer(a.length,a[0].length,zzfxR),k=audioContext.createBufferSource();a.forEach((h,l)=>f.getChannelData(l).set(h));k.buffer=f;k.playbackRate.value=c;k.loop=e;k.connect(new StereoPannerNode(audioContext,{pan:clamp(d,1,-1)})).connect(new GainNode(audioContext,{gain:soundVolume*b})).connect(audioContext.destination);k.start();return k}}const zzfx=(...a)=>playSamples([zzfxG(...a)]),zzfxR=44100;function zzfxG(a=1,b=.05,c=220,d=0,e=0,f=.1,k=0,h=1,l=0,n=0,m=0,g=0,q=0,w=0,v=0,A=0,r=0,B=1,x=0,C=0){let t=2*PI,E=l*=500*t/zzfxR/zzfxR,y=[];b=c*=(1+b*rand(-1,1))*t/zzfxR;let u=0,F=0,p=0,z=1,H=0,I=0,D=0,J,G;d=d*zzfxR+9;x*=zzfxR;e*=zzfxR;f*=zzfxR;r*=zzfxR;n*=500*t/zzfxR**3;v*=t/zzfxR;m*=t/zzfxR;g*=zzfxR;q=q*zzfxR|0;for(G=d+x+e+f+r|0;pp?0:(pg&&(c+=m,b+=m,z=0),!q||++H%q||(c=b,l=E,z=z||1);return y}function zzfxM(a,b,c,d=125){let e,f,k,h,l,n,m,g,q,w,v,A,r,B=0,x,C=[],t=[],E=[],y=0,u=0,F=1,p={},z=zzfxR/d*60>>2;for(;F;y++)C=[F=g=A=0],c.forEach((H,I)=>{m=b[H][y]||[0,0,0];F|=!!b[H][y];x=A+(b[H][0].length-2-!g)*z;r=I==c.length-1;f=2;for(h=A;fz-99&&q?v+=(1>v)/99:0)n=(1-v)*C[B++]/2||0,t[h]=(t[h]||0)-n*u+n,E[h]=(E[h++]||0)+n*u+n;l&&(v=l%1,u=m[1]||0,l|=0)&&(C=p[[w=m[B=0]||0,l]]=p[[w,l]]||(e=[...a[w]],e[2]*=2**((l-12)/12),0a.arrayCheck(tileCollisionSize)&&(tileCollision[(a.y|0)*tileCollisionSize.x+a.x|0]=b),getTileCollisionData=a=>a.arrayCheck(tileCollisionSize)?tileCollision[(a.y|0)*tileCollisionSize.x+a.x|0]:0;function tileCollisionTest(a,b=vec2(),c){const d=max(Math.floor(a.x-b.x/2),0);var e=max(Math.floor(a.y-b.y/2),0);const f=min(a.x+b.x/2,tileCollisionSize.x-1);for(a=min(a.y+b.y/2,tileCollisionSize.y-1);e=f&&(h+=f,n+=k);l<=e&&(h+=e,m+=d)}debugRaycast&&debugLine(a,b,"#00f",.02,1)}const tileLayerCanvasCache=[];class TileLayerData{constructor(a,b=0,c=0,d=new Color){this.tile=a;this.direction=b;this.mirror=c;this.color=d}clear(){this.tile=this.direction=this.mirror=0;color=new Color}}class TileLayer extends EngineObject{constructor(a,b=tileCollisionSize,c=tileSizeDefault,d=vec2(1),e=0){super(a,b,-1,c,0,void 0,e);this.canvas=tileLayerCanvasCache.length?tileLayerCanvasCache.pop():document.createElement("canvas");this.context=this.canvas.getContext("2d");this.scale=d;this.isOverlay;this.data=[];for(a=this.size.area();a--;)this.data.push(new TileLayerData)}destroy(){tileLayerCanvasCache.push(this.canvas);super.destroy()}setData(a,b,c){a.arrayCheck(this.size)&&(this.data[(a.y|0)*this.size.x+a.x|0]=b,c&&this.drawTileData(a))}getData(a){return a.arrayCheck(this.size)&&this.data[(a.y|0)*this.size.x+a.x|0]}update(){}render(){ASSERT(mainContext!=this.context);glEnable&&!glOverlay&&!this.isOverlay&&glCopyToContext(mainContext);const a=worldToScreen(this.pos.add(vec2(0,this.size.y*this.scale.y)));(this.isOverlay?overlayContext:mainContext).drawImage(this.canvas,a.x,a.y,cameraScale*this.size.x*this.scale.x,cameraScale*this.size.y*this.scale.y)}redraw(){this.redrawStart();this.drawAllTileData();this.redrawEnd()}redrawStart(a=1){const b=this.size.x*this.tileSize.x,c=this.size.y*this.tileSize.y;a&&(this.canvas.width=b,this.canvas.height=c);this.savedRenderSettings=[mainCanvasSize,mainCanvas,mainContext,cameraScale,cameraPos];cameraScale=this.tileSize.x;cameraPos=this.size.scale(.5);mainCanvas=this.canvas;mainContext=this.context;mainContext.imageSmoothingEnabled=!pixelated;mainCanvasSize=vec2(b,c);glPreRender(b,c)}redrawEnd(){ASSERT(mainContext==this.context);glCopyToContext(mainContext,1);[mainCanvasSize,mainCanvas,mainContext,cameraScale,cameraPos]=this.savedRenderSettings}drawTileData(a){const b=a.floor().add(this.pos).add(vec2(.5));this.drawCanvas2D(b,vec2(1),0,0,c=>c.clearRect(-.5,-.5,1,1));a=this.getData(a);void 0!=a.tile&&(ASSERT(mainContext==this.context),drawTile(b,vec2(1),a.tile,this.tileSize,a.color,a.direction*PI/2,a.mirror))}drawAllTileData(){for(let a=this.size.x;a--;)for(let b=this.size.y;b--;)this.drawTileData(vec2(a,b))}drawCanvas2D(a,b,c,d,e){const f=this.context;f.save();a=a.subtract(this.pos).multiply(this.tileSize);b=b.multiply(this.tileSize);f.translate(a.x,this.canvas.height-a.y);f.rotate(c);f.scale(d?-b.x:b.x,b.y);e(f);f.restore()}drawTile(a,b=vec2(1),c=-1,d=tileSizeDefault,e=new Color,f=0,k){this.drawCanvas2D(a,b,f,k,h=>{if(0>c)h.fillStyle=e.rgba(),h.fillRect(-.5,-.5,1,1);else{const l=tileImage.width/d.x;h.globalAlpha=e.a;h.drawImage(tileImage,c%l*d.x,(c/l|0)*d.x,d.x,d.y,-.5,-.5,1,1)}})}drawRect(a,b,c,d){this.drawTile(a,b,-1,0,c,d,0)}}"use strict";class ParticleEmitter extends EngineObject{constructor(a,b=0,c=0,d=100,e=PI,f=-1,k=tileSizeDefault,h=new Color,l=new Color,n=new Color(1,1,1,0),m=new Color(1,1,1,0),g=.5,q=.1,w=1,v=.1,A=.05,r=1,B=1,x=0,C=PI,t=.1,E=.2,y,u,F=1,p=u?1e9:0){super(a,new Vector2,f,k,0,void 0,p);this.emitSize=b;this.emitTime=c;this.emitRate=d;this.emitConeAngle=e;this.colorStartA=h;this.colorStartB=l;this.colorEndA=n;this.colorEndB=m;this.randomColorLinear=F;this.particleTime=g;this.sizeStart=q;this.sizeEnd=w;this.speed=v;this.angleSpeed=A;this.damping=r;this.angleDamping=B;this.gravityScale=x;this.particleConeAngle=C;this.fadeRate=t;this.randomness=E;this.collideTiles=y;this.additive=u;this.emitTimeBuffer=this.trailScale=0}update(){this.parent&&super.update();if(!this.emitTime||this.getAliveTime()<=this.emitTime){if(this.emitRate){const a=1/this.emitRate;for(this.emitTimeBuffer+=timeDelta;0m+m*rand(b,-b);const d=c(this.particleTime),e=c(this.sizeStart),f=c(this.sizeEnd),k=c(this.speed);c=c(this.angleSpeed)*randSign();const h=rand(this.emitConeAngle,-this.emitConeAngle),l=randColor(this.colorStartA,this.colorStartB,this.randomColorLinear),n=randColor(this.colorEndA,this.colorEndB,this.randomColorLinear);a.colorStart=l;a.colorEndDelta=n.subtract(l);a.velocity=(new Vector2).setAngle(this.angle+h,k);a.angleVelocity=c;a.lifeTime=d;a.sizeStart=e;a.sizeEndDelta=f-e;a.fadeRate=this.fadeRate;a.damping=this.damping;a.angleDamping=this.angleDamping;a.elasticity=this.elasticity;a.friction=this.friction;a.gravityScale=this.gravityScale;a.collideTiles=this.collideTiles;a.additive=this.additive;a.renderOrder=this.renderOrder;a.trailScale=this.trailScale;a.mirror=.5>rand();a.destroyCallback=this.particleDestroyCallback;this.particleCreateCallback&&this.particleCreateCallback(a);return a}render(){}}class Particle extends EngineObject{constructor(a,b,c,d){super(a,new Vector2,b,c,d)}render(){const a=min((time-this.spawnTime)/this.lifeTime,1);var b=this.sizeStart+a*this.sizeEndDelta;b=new Vector2(b,b);var c=this.fadeRate/2;c=new Color(this.colorStart.r+a*this.colorEndDelta.r,this.colorStart.g+a*this.colorEndDelta.g,this.colorStart.b+a*this.colorEndDelta.b,(this.colorStart.a+a*this.colorEndDelta.a)*(a1-c?(1-a)/c:1));this.additive&&setBlendMode(1);if(this.trailScale){var d=this.velocity.length();const e=this.velocity.scale(1/d);d*=this.trailScale;b.y=max(b.x,d);this.angle=e.angle();drawTile(this.pos.add(e.multiply(vec2(0,-d/2))),b,this.tileIndex,this.tileSize,c,this.angle,this.mirror)}else drawTile(this.pos,b,this.tileIndex,this.tileSize,c,this.angle,this.mirror);this.additive&&setBlendMode();debugParticles&&debugRect(this.pos,b,"#f005",0,this.angle);1==a&&(this.color=c,this.size=b,this.destroyCallback&&this.destroyCallback(this),this.destroyed=1)}}"use strict";const medals=[];let medalsPreventUnlock,newgrounds,medalsDisplayQueue=[],medalsSaveName,medalsDisplayTimer;function medalsInit(a){medalsSaveName=a;debugMedals||medals.forEach(b=>b.unlocked=localStorage[b.storageKey()])}class Medal{constructor(a,b,c="",d="🏆",e){ASSERT(0<=a&&!medals[a]);medals[this.id=a]=this;this.name=b;this.description=c;this.icon=d;e&&(this.image=new Image,this.image.src=e)}unlock(){medalsPreventUnlock||this.unlocked||(ASSERT(medalsSaveName),localStorage[this.storageKey()]=this.unlocked=1,medalsDisplayQueue.push(this),newgrounds&&newgrounds.unlockMedal(this.id),localStorage["OS13kTrophy,"+this.icon+","+medalsSaveName+","+this.name]=this.description)}render(a=0){const b=overlayContext,c=overlayCanvas.width-medalDisplayWidth;a*=-medalDisplayHeight;b.save();b.beginPath();b.fillStyle="#ddd";b.fill(b.rect(c,a,medalDisplayWidth,medalDisplayHeight));b.strokeStyle=b.fillStyle="#000";b.lineWidth=2;b.stroke();b.clip();this.renderIcon(c+15+medalDisplayIconSize/2,a+medalDisplayHeight/2);b.textAlign="left";b.font="3em "+fontDefault;b.fillText(this.name,c+medalDisplayIconSize+25,a+35);b.font="1.5em "+fontDefault;b.restore(b.fillText(this.description,c+medalDisplayIconSize+25,a+70))}renderIcon(a,b,c=medalDisplayIconSize){const d=overlayContext;d.textAlign="center";d.textBaseline="middle";d.font=.6*c+"px "+fontDefault;d.fillStyle="#000";this.image?d.drawImage(this.image,a-c/2,b-c/2,c,c):d.fillText(this.icon,a,b)}storageKey(){return medalsSaveName+"_medal_"+this.id}}function medalsRender(){if(medalsDisplayQueue.length){var a=medalsDisplayQueue[0],b=timeReal-medalsDisplayTimer;if(medalsDisplayTimer)if(b>medalDisplayTime)medalsDisplayQueue.shift(medalsDisplayTimer=0);else{const c=medalDisplayTime-medalDisplaySlideTime;a.render(bc?(b-c)/medalDisplaySlideTime:0)}else medalsDisplayTimer=timeReal}}class Newgrounds{constructor(a,b){ASSERT(!newgrounds&&a);this.app_id=a;this.cipher=b;this.host=location?location.hostname:"";b&&(this.cryptoJS=CryptoJS());this.session_id=new URL(window.location.href).searchParams.get("ngio_session_id")||0;if(0!=this.session_id){this.medals=(a=this.call("Medal.getList"))?a.result.data.medals:[];debugMedals&&console.log(this.medals);for(var c of this.medals)if(a=medals[c.id])a.image=new Image,a.image.src=c.icon,a.name=c.name,a.description=c.description,a.unlocked=c.unlocked,a.difficulty=c.difficulty,a.value=c.value,a.value&&(a.description=a.description+" ("+a.value+")");this.scoreboards=(c=this.call("ScoreBoard.getBoards"))?c.result.data.scoreboards:[];debugMedals&&console.log(this.scoreboards)}}unlockMedal(a){return this.call("Medal.unlock",{id:a},1)}postScore(a,b){return this.call("ScoreBoard.postScore",{id:a,value:b},1)}logView(){return this.call("App.logView",{host:this.host},1)}getScores(a,b=0,c=0,d=0,e=10){return this.call("ScoreBoard.getScores",{id:a,user:b,social:c,skip:d,limit:e})}call(a,b=0,c=0){a={component:a,parameters:b};if(this.cipher){b=this.cryptoJS;var d=b.enc.Base64.parse(this.cipher);const e=b.lib.WordArray.random(16);d=b.AES.encrypt(JSON.stringify(a),d,{iv:e});a.secure=b.enc.Base64.stringify(e.concat(d.ciphertext));a.parameters=0}b={app_id:this.app_id,session_id:this.session_id,call:a};a=new FormData;a.append("input",JSON.stringify(b));b=new XMLHttpRequest;b.open("POST","https://newgrounds.io/gateway_v3.php",!debugMedals&&c);b.send(a);debugMedals&&console.log(b.responseText);return b.responseText&&JSON.parse(b.responseText)}}const CryptoJS=()=>eval(Function("[M='GBMGXz^oVYPPKKbB`agTXU|LxPc_ZBcMrZvCr~wyGfWrwk@ATqlqeTp^N?p{we}jIpEnB_sEr`l?YDkDhWhprc|Er|XETG?pTl`e}dIc[_N~}fzRycIfpW{HTolvoPB_FMe_eH~BTMx]yyOhv?biWPCGc]kABencBhgERHGf{OL`Dj`c^sh@canhy[secghiyotcdOWgO{tJIE^JtdGQRNSCrwKYciZOa]Y@tcRATYKzv|sXpboHcbCBf`}SKeXPFM|RiJsSNaIb]QPc[D]Jy_O^XkOVTZep`ONmntLL`Qz~UupHBX_Ia~WX]yTRJIxG`ioZ{fefLJFhdyYoyLPvqgH?b`[TMnTwwfzDXhfM?rKs^aFr|nyBdPmVHTtAjXoYUloEziWDCw_suyYT~lSMksI~ZNCS[Bex~j]Vz?kx`gdYSEMCsHpjbyxQvw|XxX_^nQYue{sBzVWQKYndtYQMWRef{bOHSfQhiNdtR{o?cUAHQAABThwHPT}F{VvFmgN`E@FiFYS`UJmpQNM`X|tPKHlccT}z}k{sACHL?Rt@MkWplxO`ASgh?hBsuuP|xD~LSH~KBlRs]t|l|_tQAroDRqWS^SEr[sYdPB}TAROtW{mIkE|dWOuLgLmJrucGLpebrAFKWjikTUzS|j}M}szasKOmrjy[?hpwnEfX[jGpLt@^v_eNwSQHNwtOtDgWD{rk|UgASs@mziIXrsHN_|hZuxXlPJOsA^^?QY^yGoCBx{ekLuZzRqQZdsNSx@ezDAn{XNj@fRXIwrDX?{ZQHwTEfu@GhxDOykqts|n{jOeZ@c`dvTY?e^]ATvWpb?SVyg]GC?SlzteilZJAL]mlhLjYZazY__qcVFYvt@|bIQnSno@OXyt]OulzkWqH`rYFWrwGs`v|~XeTsIssLrbmHZCYHiJrX}eEzSssH}]l]IhPQhPoQ}rCXLyhFIT[clhzYOvyHqigxmjz`phKUU^TPf[GRAIhNqSOdayFP@FmKmuIzMOeoqdpxyCOwCthcLq?n`L`tLIBboNn~uXeFcPE{C~mC`h]jUUUQe^`UqvzCutYCgct|SBrAeiYQW?X~KzCz}guXbsUw?pLsg@hDArw?KeJD[BN?GD@wgFWCiHq@Ypp_QKFixEKWqRp]oJFuVIEvjDcTFu~Zz]a{IcXhWuIdMQjJ]lwmGQ|]g~c]Hl]pl`Pd^?loIcsoNir_kikBYyg?NarXZEGYspt_vLBIoj}LI[uBFvm}tbqvC|xyR~a{kob|HlctZslTGtPDhBKsNsoZPuH`U`Fqg{gKnGSHVLJ^O`zmNgMn~{rsQuoymw^JY?iUBvw_~mMr|GrPHTERS[MiNpY[Mm{ggHpzRaJaoFomtdaQ_?xuTRm}@KjU~RtPsAdxa|uHmy}n^i||FVL[eQAPrWfLm^ndczgF~Nk~aplQvTUpHvnTya]kOenZlLAQIm{lPl@CCTchvCF[fI{^zPkeYZTiamoEcKmBMfZhk_j_~Fjp|wPVZlkh_nHu]@tP|hS@^G^PdsQ~f[RqgTDqezxNFcaO}HZhb|MMiNSYSAnQWCDJukT~e|OTgc}sf[cnr?fyzTa|EwEtRG|I~|IO}O]S|rp]CQ}}DWhSjC_|z|oY|FYl@WkCOoPuWuqr{fJu?Brs^_EBI[@_OCKs}?]O`jnDiXBvaIWhhMAQDNb{U`bqVR}oqVAvR@AZHEBY@depD]OLh`kf^UsHhzKT}CS}HQKy}Q~AeMydXPQztWSSzDnghULQgMAmbWIZ|lWWeEXrE^EeNoZApooEmrXe{NAnoDf`m}UNlRdqQ@jOc~HLOMWs]IDqJHYoMziEedGBPOxOb?[X`KxkFRg@`mgFYnP{hSaxwZfBQqTm}_?RSEaQga]w[vxc]hMne}VfSlqUeMo_iqmd`ilnJXnhdj^EEFifvZyxYFRf^VaqBhLyrGlk~qowqzHOBlOwtx?i{m~`n^G?Yxzxux}b{LSlx]dS~thO^lYE}bzKmUEzwW^{rPGhbEov[Plv??xtyKJshbG`KuO?hjBdS@Ru}iGpvFXJRrvOlrKN?`I_n_tplk}kgwSXuKylXbRQ]]?a|{xiT[li?k]CJpwy^o@ebyGQrPfF`aszGKp]baIx~H?ElETtFh]dz[OjGl@C?]VDhr}OE@V]wLTc[WErXacM{We`F|utKKjgllAxvsVYBZ@HcuMgLboFHVZmi}eIXAIFhS@A@FGRbjeoJWZ_NKd^oEH`qgy`q[Tq{x?LRP|GfBFFJV|fgZs`MLbpPYUdIV^]mD@FG]pYAT^A^RNCcXVrPsgk{jTrAIQPs_`mD}rOqAZA[}RETFz]WkXFTz_m{N@{W@_fPKZLT`@aIqf|L^Mb|crNqZ{BVsijzpGPEKQQZGlApDn`ruH}cvF|iXcNqK}cxe_U~HRnKV}sCYb`D~oGvwG[Ca|UaybXea~DdD~LiIbGRxJ_VGheI{ika}KC[OZJLn^IBkPrQj_EuoFwZ}DpoBRcK]Q}?EmTv~i_Tul{bky?Iit~tgS|o}JL_VYcCQdjeJ_MfaA`FgCgc[Ii|CBHwq~nbJeYTK{e`CNstKfTKPzw{jdhp|qsZyP_FcugxCFNpKitlR~vUrx^NrSVsSTaEgnxZTmKc`R|lGJeX}ccKLsQZQhsFkeFd|ckHIVTlGMg`~uPwuHRJS_CPuN_ogXe{Ba}dO_UBhuNXby|h?JlgBIqMKx^_u{molgL[W_iavNQuOq?ap]PGB`clAicnl@k~pA?MWHEZ{HuTLsCpOxxrKlBh]FyMjLdFl|nMIvTHyGAlPogqfZ?PlvlFJvYnDQd}R@uAhtJmDfe|iJqdkYr}r@mEjjIetDl_I`TELfoR|qTBu@Tic[BaXjP?dCS~MUK[HPRI}OUOwAaf|_}HZzrwXvbnNgltjTwkBE~MztTQhtRSWoQHajMoVyBBA`kdgK~h`o[J`dm~pm]tk@i`[F~F]DBlJKklrkR]SNw@{aG~Vhl`KINsQkOy?WhcqUMTGDOM_]bUjVd|Yh_KUCCgIJ|LDIGZCPls{RzbVWVLEhHvWBzKq|^N?DyJB|__aCUjoEgsARki}j@DQXS`RNU|DJ^a~d{sh_Iu{ONcUtSrGWW@cvUjefHHi}eSSGrNtO?cTPBShLqzwMVjWQQCCFB^culBjZHEK_{dO~Q`YhJYFn]jq~XSnG@[lQr]eKrjXpG~L^h~tDgEma^AUFThlaR{xyuP@[^VFwXSeUbVetufa@dX]CLyAnDV@Bs[DnpeghJw^?UIana}r_CKGDySoRudklbgio}kIDpA@McDoPK?iYcG?_zOmnWfJp}a[JLR[stXMo?_^Ng[whQlrDbrawZeSZ~SJstIObdDSfAA{MV}?gNunLOnbMv_~KFQUAjIMj^GkoGxuYtYbGDImEYiwEMyTpMxN_LSnSMdl{bg@dtAnAMvhDTBR_FxoQgANniRqxd`pWv@rFJ|mWNWmh[GMJz_Nq`BIN@KsjMPASXORcdHjf~rJfgZYe_uulzqM_KdPlMsuvU^YJuLtofPhGonVOQxCMuXliNvJIaoC?hSxcxKVVxWlNs^ENDvCtSmO~WxI[itnjs^RDvI@KqG}YekaSbTaB]ki]XM@[ZnDAP~@|BzLRgOzmjmPkRE@_sobkT|SszXK[rZN?F]Z_u}Yue^[BZgLtR}FHzWyxWEX^wXC]MJmiVbQuBzkgRcKGUhOvUc_bga|Tx`KEM`JWEgTpFYVeXLCm|mctZR@uKTDeUONPozBeIkrY`cz]]~WPGMUf`MNUGHDbxZuO{gmsKYkAGRPqjc|_FtblEOwy}dnwCHo]PJhN~JoteaJ?dmYZeB^Xd?X^pOKDbOMF@Ugg^hETLdhwlA}PL@_ur|o{VZosP?ntJ_kG][g{Zq`Tu]dzQlSWiKfnxDnk}KOzp~tdFstMobmy[oPYjyOtUzMWdjcNSUAjRuqhLS@AwB^{BFnqjCmmlk?jpn}TksS{KcKkDboXiwK]qMVjm~V`LgWhjS^nLGwfhAYrjDSBL_{cRus~{?xar_xqPlArrYFd?pHKdMEZzzjJpfC?Hv}mAuIDkyBxFpxhstTx`IO{rp}XGuQ]VtbHerlRc_LFGWK[XluFcNGUtDYMZny[M^nVKVeMllQI[xtvwQnXFlWYqxZZFp_|]^oWX[{pOMpxXxvkbyJA[DrPzwD|LW|QcV{Nw~U^dgguSpG]ClmO@j_TENIGjPWwgdVbHganhM?ema|dBaqla|WBd`poj~klxaasKxGG^xbWquAl~_lKWxUkDFagMnE{zHug{b`A~IYcQYBF_E}wiA}K@yxWHrZ{[d~|ARsYsjeNWzkMs~IOqqp[yzDE|WFrivsidTcnbHFRoW@XpAV`lv_zj?B~tPCppRjgbbDTALeFaOf?VcjnKTQMLyp{NwdylHCqmo?oelhjWuXj~}{fpuX`fra?GNkDiChYgVSh{R[BgF~eQa^WVz}ATI_CpY?g_diae]|ijH`TyNIF}|D_xpmBq_JpKih{Ba|sWzhnAoyraiDvk`h{qbBfsylBGmRH}DRPdryEsSaKS~tIaeF[s]I~xxHVrcNe@Jjxa@jlhZueLQqHh_]twVMqG_EGuwyab{nxOF?`HCle}nBZzlTQjkLmoXbXhOtBglFoMz?eqre`HiE@vNwBulglmQjj]DB@pPkPUgA^sjOAUNdSu_`oAzar?n?eMnw{{hYmslYi[TnlJD'",..."]charCodeAtUinyxpf","for(;e<10359;c[e++]=p-=128,A=A?p-A&&A:p==34&&p)for(p=1;p<128;y=f.map((n,x)=>(U=r[n]*2+1,U=Math.log(U/(h-U)),t-=a[x]*U,U/500)),t=~-h/(1+Math.exp(t))|1,i=o%h>17)-!i*t,f.map((n,x)=>(U=r[n]+=(i*h/2-r[n]<<13)/((C[n]+=C[n]<5)+1/20)>>13,a[x]+=y[x]*(i-t/h))),p=p*2+i)for(f='010202103203210431053105410642065206541'.split(t=0).map((n,x)=>(U=0,[...n].map((n,x)=>(U=U*997+(c[e-n]|0)|0)),h*32-1&U*997+p+!!A*129)*12+x);o{c=glContext.getAttribLocation(glShader,c);glContext.enableVertexAttribArray(c);glContext.vertexAttribPointer(c,f,d,k,gl_VERTEX_BYTE_STRIDE,b);b+=f*e};var b=glDirty=glBatchCount=0;a("a",gl_FLOAT,4,1);a("p",gl_FLOAT,4,2);a("s",gl_FLOAT,4,2);a("t",gl_FLOAT,4,2);a("c",gl_UNSIGNED_BYTE,1,4,1);a("b",gl_UNSIGNED_BYTE,1,4,1)}}function glSetBlendMode(a){glEnable&&(glAdditive=a)}function glSetTexture(a=glTileTexture){glEnable&&(a!=glActiveTexture&&glFlush(),glContext.bindTexture(gl_TEXTURE_2D,glActiveTexture=a))}function glCompileShader(a,b){if(glEnable){b=glContext.createShader(b);glContext.shaderSource(b,a);glContext.compileShader(b);if(debug&&!glContext.getShaderParameter(b,gl_COMPILE_STATUS))throw glContext.getShaderInfoLog(b);return b}}function glCreateProgram(a,b){if(glEnable){var c=glContext.createProgram();glContext.attachShader(c,glCompileShader(a,gl_VERTEX_SHADER));glContext.attachShader(c,glCompileShader(b,gl_FRAGMENT_SHADER));glContext.linkProgram(c);if(debug&&!glContext.getProgramParameter(c,gl_LINK_STATUS))throw glContext.getProgramInfoLog(c);return c}}function glCreateBuffer(a,b,c){if(glEnable){var d=glContext.createBuffer();glContext.bindBuffer(a,d);glContext.bufferData(a,b,c);return d}}function glCreateTexture(a){if(glEnable&&a&&a.width){var b=glContext.createTexture();glContext.bindTexture(gl_TEXTURE_2D,b);glContext.texImage2D(gl_TEXTURE_2D,0,gl_RGBA,gl_RGBA,gl_UNSIGNED_BYTE,a);glContext.texParameteri(gl_TEXTURE_2D,gl_TEXTURE_MIN_FILTER,pixelated?gl_NEAREST:gl_LINEAR);glContext.texParameteri(gl_TEXTURE_2D,gl_TEXTURE_MAG_FILTER,pixelated?gl_NEAREST:gl_LINEAR);glContext.texParameteri(gl_TEXTURE_2D,gl_TEXTURE_WRAP_S,gl_CLAMP_TO_EDGE);glContext.texParameteri(gl_TEXTURE_2D,gl_TEXTURE_WRAP_T,gl_CLAMP_TO_EDGE);return b}}function glPreRender(a,b){glEnable&&(glCanvas.width=a,glCanvas.height=b,glContext.viewport(0,0,a,b),glContext.bindTexture(gl_TEXTURE_2D,glActiveTexture=glTileTexture),glContext.useProgram(glShader),glSetBlendMode(),a=2*cameraScale/a,b=2*cameraScale/b,glContext.uniformMatrix4fv(glContext.getUniformLocation(glShader,"m"),0,new Float32Array([a,0,0,0,0,b,0,0,1,1,-1,1,-1-a*cameraPos.x,-1-b*cameraPos.y,0,0])))}function glFlush(){if(glEnable&&glBatchCount){var a=glBatchAdditive?gl_ONE:gl_ONE_MINUS_SRC_ALPHA;glContext.blendFuncSeparate(gl_SRC_ALPHA,a,gl_ONE,a);glContext.enable(gl_BLEND);glContext.bufferSubData(gl_ARRAY_BUFFER,0,glPositionData.subarray(0,glBatchCount*gl_VERTICES_PER_QUAD*gl_INDICIES_PER_VERT));glContext.drawArrays(gl_TRIANGLES,0,glBatchCount*gl_VERTICES_PER_QUAD);glBatchCount=0;glBatchAdditive=glAdditive}}function glCopyToContext(a,b){glEnable&&glDirty&&(glFlush(),!glOverlay||b)&&(a.drawImage(glCanvas,0,glAdditive=glDirty=0),glContext.clear(gl_COLOR_BUFFER_BIT))}function glDraw(a,b,c,d,e=0,f=0,k=0,h=1,l=1,n=4294967295,m=0){if(glEnable){glBatchCount!=gl_MAX_BATCH&&glBatchAdditive==glAdditive||glFlush();var g=glBatchCount++*gl_VERTICES_PER_QUAD*gl_INDICIES_PER_VERT;glDirty=1;glPositionData[g++]=e;glPositionData[g++]=a;glPositionData[g++]=b;glPositionData[g++]=-c;glPositionData[g++]=-d;glPositionData[g++]=f;glPositionData[g++]=l;glColorData[g++]=n;glColorData[g++]=m;glPositionData[g++]=e;glPositionData[g++]=a;glPositionData[g++]=b;glPositionData[g++]=c;glPositionData[g++]=d;glPositionData[g++]=h;glPositionData[g++]=k;glColorData[g++]=n;glColorData[g++]=m;glPositionData[g++]=e;glPositionData[g++]=a;glPositionData[g++]=b;glPositionData[g++]=-c;glPositionData[g++]=d;glPositionData[g++]=f;glPositionData[g++]=k;glColorData[g++]=n;glColorData[g++]=m;glPositionData[g++]=e;glPositionData[g++]=a;glPositionData[g++]=b;glPositionData[g++]=-c;glPositionData[g++]=-d;glPositionData[g++]=f;glPositionData[g++]=l;glColorData[g++]=n;glColorData[g++]=m;glPositionData[g++]=e;glPositionData[g++]=a;glPositionData[g++]=b;glPositionData[g++]=c;glPositionData[g++]=-d;glPositionData[g++]=h;glPositionData[g++]=l;glColorData[g++]=n;glColorData[g++]=m;glPositionData[g++]=e;glPositionData[g++]=a;glPositionData[g++]=b;glPositionData[g++]=c;glPositionData[g++]=d;glPositionData[g++]=h;glPositionData[g++]=k;glColorData[g++]=n;glColorData[g++]=m}}const gl_ONE=1,gl_TRIANGLES=4,gl_SRC_ALPHA=770,gl_ONE_MINUS_SRC_ALPHA=771,gl_BLEND=3042,gl_TEXTURE_2D=3553,gl_UNSIGNED_BYTE=5121,gl_FLOAT=5126,gl_RGBA=6408,gl_NEAREST=9728,gl_LINEAR=9729,gl_TEXTURE_MAG_FILTER=10240,gl_TEXTURE_MIN_FILTER=10241,gl_TEXTURE_WRAP_S=10242,gl_TEXTURE_WRAP_T=10243,gl_COLOR_BUFFER_BIT=16384,gl_CLAMP_TO_EDGE=33071,gl_ARRAY_BUFFER=34962,gl_DYNAMIC_DRAW=35048,gl_FRAGMENT_SHADER=35632,gl_VERTEX_SHADER=35633,gl_COMPILE_STATUS=35713,gl_LINK_STATUS=35714,gl_VERTICES_PER_QUAD=6,gl_INDICIES_PER_VERT=9,gl_MAX_BATCH=65536,gl_VERTEX_BYTE_STRIDE=36; \ No newline at end of file +"use strict";const debug=0,showWatermark=0,godMode=0,debugOverlay=0,debugPhysics=0,debugParticles=0,debugRaycast=0,debugGamepads=0,debugMedals=0,ASSERT=()=>{},debugInit=()=>{},debugUpdate=()=>{},debugRender=()=>{},debugRect=()=>{},debugCircle=()=>{},debugPoint=()=>{},debugLine=()=>{},debugAABB=()=>{},debugClear=()=>{},debugSaveCanvas=()=>{};"use strict";const PI=Math.PI,isChrome=window.chrome,abs=a=>0>a?-a:a,sign=a=>0>a?-1:1,min=(a,b)=>aa>b?a:b,mod=(a,b)=>(a%b+b)%b,clamp=(a,b=1,c=0)=>(ASSERT(b>c),ab?b:a),percent=(a,b=1,c=0)=>b-c?clamp((a-c)/(b-c)):0,lerp=(a,b=1,c=0)=>c+clamp(a)*(b-c),formatTime=a=>(a/60|0)+":"+(10>a%60?"0":"")+(a%60|0),nearestPowerOfTwo=a=>2**Math.ceil(Math.log2(a)),smoothStep=a=>a*a*(3-2*a),isOverlapping=(a,b,c,d)=>2*abs(a.x-c.x)b/2*(1-Math.cos(c*a*2*PI)),rand=(a=1,b=0)=>b+(a-b)*Math.random(),randInt=(a=1,b=0)=>rand(a,b)|0,randSign=()=>2*(rand(2)|0)-1,randInCircle=(a=1,b=0)=>0(new Vector2).setAngle(rand(2*PI),a),randColor=(a=new Color,b=new Color(0,0,0,1),c)=>c?a.lerp(b,rand()):new Color(rand(a.r,b.r),rand(a.g,b.g),rand(a.b,b.b),rand(a.a,b.a));let randSeed=1;const randSeeded=(a=1,b=0)=>{randSeed^=randSeed<<13;randSeed^=randSeed>>>17;randSeed^=randSeed<<5;return b+(a-b)*abs(randSeed%1e9)/1e9},vec2=(a=0,b)=>void 0==a.x?new Vector2(a,void 0==b?a:b):new Vector2(a.x,a.y);class Vector2{constructor(a=0,b=0){this.x=a;this.y=b}copy(){return new Vector2(this.x,this.y)}add(a){ASSERT(void 0!=a.x);return new Vector2(this.x+a.x,this.y+a.y)}subtract(a){ASSERT(void 0!=a.x);return new Vector2(this.x-a.x,this.y-a.y)}multiply(a){ASSERT(void 0!=a.x);return new Vector2(this.x*a.x,this.y*a.y)}divide(a){ASSERT(void 0!=a.x);return new Vector2(this.x/a.x,this.y/a.y)}scale(a){ASSERT(void 0==a.x);return new Vector2(this.x*a,this.y*a)}length(){return this.lengthSquared()**.5}lengthSquared(){return this.x**2+this.y**2}distance(a){return this.distanceSquared(a)**.5}distanceSquared(a){return(this.x-a.x)**2+(this.y-a.y)**2}normalize(a=1){const b=this.length();return b?this.scale(a/b):new Vector2(a)}clampLength(a=1){const b=this.length();return b>a?this.scale(a/b):this}dot(a){ASSERT(void 0!=a.x);return this.x*a.x+this.y*a.y}cross(a){ASSERT(void 0!=a.x);return this.x*a.y-this.y*a.x}angle(){return Math.atan2(this.x,this.y)}setAngle(a=0,b=1){this.x=b*Math.sin(a);this.y=b*Math.cos(a);return this}rotate(a){const b=Math.cos(a);a=Math.sin(a);return new Vector2(this.x*b-this.y*a,this.x*a+this.y*b)}direction(){return abs(this.x)>abs(this.y)?0>this.x?3:1:0>this.y?2:0}invert(){return new Vector2(this.y,-this.x)}flip(){return new Vector2(this.y,this.x)}floor(){return new Vector2(Math.floor(this.x),Math.floor(this.y))}area(){return this.x*this.y}lerp(a,b){ASSERT(void 0!=a.x);return this.add(a.subtract(this).scale(clamp(b)))}arrayCheck(a){return 0<=this.x&&0<=this.y&&this.xc?c*(1+b):c+b-c*b;c=2*c-b;const e=(f,k,h)=>(h=(h%1+1)%1)<1/6?f+6*(k-f)*h:.5>h?k:h<2/3?f+(k-f)*(2/3-h)*6:f;this.r=e(c,b,a+1/3);this.g=e(c,b,a);this.b=e(c,b,a-1/3);this.a=d;return this}mutate(a=.05,b=0){return new Color(this.r+rand(a,-a),this.g+rand(a,-a),this.b+rand(a,-a),this.a+rand(b,-b)).clamp()}rgba(){ASSERT(0<=this.r&&1>=this.r&&0<=this.g&&1>=this.g&&0<=this.b&&1>=this.b&&0<=this.a&&1>=this.a);return`rgb(${255*this.r|0},${255*this.g|0},${255*this.b|0},${this.a})`}rgbaInt(){ASSERT(0<=this.r&&1>=this.r&&0<=this.g&&1>=this.g&&0<=this.b&&1>=this.b&&0<=this.a&&1>=this.a);return(255*this.r|0)+(255*this.g<<8)+(255*this.b<<16)+(255*this.a<<24)}}class Timer{constructor(a){this.time=void 0==a?void 0:time+a;this.setTime=a}set(a=0){this.time=time+a;this.setTime=a}unset(){this.time=void 0}isSet(){return void 0!=this.time}active(){return time<=this.time}elapsed(){return time>this.time}get(){return this.isSet()?time-this.time:0}getPercent(){return this.isSet()?percent(this.time-time,0,this.setTime):0}}"use strict";const maxSize=vec2(1920,1200);let fixedSize=vec2(),fontDefault="arial",pixelated=1;const tileSizeDefault=vec2(16),tileBleedShrinkFix=.3,objectDefaultSize=vec2(1),objectDefaultMass=1,objectDefaultDamping=.99,objectDefaultAngleDamping=.99,objectDefaultElasticity=0,objectDefaultFriction=.8,objectMaxSpeed=1;let gravity=0,cameraPos=vec2(),cameraScale=max(tileSizeDefault.x,tileSizeDefault.y);const glEnable=1;let glOverlay=1;const gamepadsEnable=1,gamepadDirectionEmulateStick=1,inputTouchEnable=1,inputWASDEmulateDirection=1;let soundVolume=.5;const soundEnable=1,soundDefaultRange=30,soundDefaultTaper=.7,medalDisplayTime=5,medalDisplaySlideTime=.5,medalDisplayWidth=640,medalDisplayHeight=99,medalDisplayIconSize=80;"use strict";const engineName="LittleJS",engineVersion="1.1.9",FPS=60,timeDelta=1/FPS;let engineObjects=[],engineCollideObjects=[],frame=0,time=0,timeReal=0,paused=0,frameTimeLastMS=0,frameTimeBufferMS=0,debugFPS=0,shrinkTilesX,shrinkTilesY,drawCount,tileImageSize,tileImageSizeInverse;function engineInit(a,b,c,d,e,f){tileImage.onerror=tileImage.onload=()=>{tileImageSizeInverse=vec2(1).divide(tileImageSize=vec2(tileImage.width,tileImage.height));debug&&(tileImage.onload=()=>ASSERT(1));shrinkTilesX=tileBleedShrinkFix/tileImageSize.x;shrinkTilesY=tileBleedShrinkFix/tileImageSize.y;document.body.appendChild(mainCanvas=document.createElement("canvas"));document.body.style="margin:0;overflow:hidden;background:#000";mainCanvas.style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)"+(pixelated?";image-rendering:crisp-edges;image-rendering:pixelated":"");mainContext=mainCanvas.getContext("2d");debugInit();glInit();document.body.appendChild(overlayCanvas=document.createElement("canvas"));overlayCanvas.style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)";overlayContext=overlayCanvas.getContext("2d");a();k()};const k=(h=0)=>{requestAnimationFrame(k);var l=h-frameTimeLastMS;frameTimeLastMS=h;if(debug||showWatermark)debugFPS=lerp(.05,1e3/(l||1),debugFPS);debug&&(l*=keyIsDown(107)?5:keyIsDown(109)?.2:1);timeReal+=l/1e3;frameTimeBufferMS=min(frameTimeBufferMS+!paused*l,50);if(paused)inputUpdate(),debugUpdate(),c(),inputUpdatePost();else{h=0;0>frameTimeBufferMS&&-9m.renderOrder-g.renderOrder);for(var n of engineObjects)n.destroyed||n.render();e();medalsRender();debugRender();glCopyToContext(mainContext);showWatermark&&(overlayContext.textAlign="right",overlayContext.textBaseline="top",overlayContext.font="1em monospace",overlayContext.fillStyle="#000",n=engineName+" v"+engineVersion+" / "+drawCount+" / "+engineObjects.length+" / "+debugFPS.toFixed(1),overlayContext.fillText(n,mainCanvas.width-3,3),overlayContext.fillStyle="#fff",overlayContext.fillText(n,mainCanvas.width-2,2),drawCount=0)};f?tileImage.src=f:tileImage.onload()}function engineObjectsUpdate(){const a=b=>{if(!b.destroyed){b.update();for(const c of b.children)a(c)}};for(const b of engineObjects)b.parent||a(b);engineObjects=engineObjects.filter(b=>!b.destroyed);engineCollideObjects=engineCollideObjects.filter(b=>!b.destroyed);time=++frame/FPS}function engineObjectsDestroy(){for(const a of engineObjects)a.persistent||a.parent||a.destroy();engineObjects=engineObjects.filter(a=>!a.destroyed)}function engineObjectsCallback(a,b,c,d=engineObjects){if(a)if(void 0!=b.x)for(const e of d)isOverlapping(a,b,e.pos,e.size)&&c(e);else{b*=b;for(const e of d)a.distanceSquared(e.pos)=this.angleDamping),ASSERT(0<=this.damping&&1>=this.damping),this.mass){var b=0>this.velocity.y;if(this.groundObject){var c=this.groundObject.velocity?this.groundObject.velocity.x:0;this.velocity.x=c+(this.velocity.x-c)*this.friction;this.groundObject=0}if(this.collideSolidObjects)for(var d of engineCollideObjects)if(!(!this.isSolid&!d.isSolid||d.destroyed||d.parent||!isOverlapping(this.pos,this.size,d.pos,d.size)||d==this||!this.collideWithObject(d)|!d.collideWithObject(this)))if(isOverlapping(a,this.size,d.pos,d.size)){c=a.subtract(d.pos);var e=c.length();c=.01>e?randVector(.001):c.scale(.001/e);this.velocity=this.velocity.add(c);d.mass&&(d.velocity=d.velocity.subtract(c));debugPhysics&&debugAABB(this.pos,this.size,d.pos,d.size,"#f00")}else{c=this.size.x+d.size.x;var f=this.size.y+d.size.y;e=2*(a.y-d.pos.y)>f+gravity;var k=2*abs(a.y-d.pos.y)c&&console.log("stepUp",a.y-d.pos.y)}e||!k&&h||(this.pos.x=d.pos.x+(c/2+.001)*sign(a.x-d.pos.x),d.mass?(c=(this.mass*this.velocity.x+d.mass*d.velocity.x)/(this.mass+d.mass),e=this.velocity.x*(this.mass-d.mass)/(this.mass+d.mass)+2*d.velocity.x*d.mass/(this.mass+d.mass),k=d.velocity.x*(d.mass-this.mass)/(this.mass+d.mass)+2*this.velocity.x*this.mass/(this.mass+d.mass),h=max(this.elasticity,d.elasticity),this.velocity.x=lerp(h,e,c),d.velocity.x=lerp(h,k,c)):this.velocity.x*=-this.elasticity);debugPhysics&&debugAABB(this.pos,this.size,d.pos,d.size,"#f0f")}if(this.collideTiles&&tileCollisionTest(this.pos,this.size,this)&&!tileCollisionTest(a,this.size,this)){c=tileCollisionTest(new Vector2(a.x,this.pos.y),this.size,this);d=tileCollisionTest(new Vector2(this.pos.x,a.y),this.size,this);if(c||!d)this.groundObject=b,this.velocity.y*=-this.elasticity,b=(a.y-this.size.y/2|0)-(a.y-this.size.y/2),0>b&&-1this.damping*this.velocity.y+gravity*this.gravityScale&&(this.velocity.y=this.damping?(b-gravity*this.gravityScale)/this.damping:0),this.pos.y=a.y;d&&(this.pos.x=a.x,this.velocity.x*=-this.elasticity)}}}render(){drawTile(this.pos,this.drawSize||this.size,this.tileIndex,this.tileSize,this.color,this.angle,this.mirror,this.additiveColor)}destroy(){if(!this.destroyed){this.destroyed=1;this.parent&&this.parent.removeChild(this);for(const a of this.children)a.destroy(a.parent=0)}}collideWithTile(a,b){return 0a.add(vec2(.5)).subtract(mainCanvasSize.scale(.5)).multiply(vec2(1/cameraScale,-1/cameraScale)).add(cameraPos),worldToScreen=a=>a.subtract(cameraPos).multiply(vec2(cameraScale,-cameraScale)).add(mainCanvasSize.scale(.5)).subtract(vec2(.5));function drawTile(a,b=vec2(1),c=-1,d=tileSizeDefault,e=new Color,f=0,k,h=new Color(0,0,0,0),l=glEnable){showWatermark&&++drawCount;if(glEnable&&l)if(0>c||!tileImage.width)glDraw(a.x,a.y,b.x,b.y,f,0,0,0,0,0,e.rgbaInt());else{var n=tileImage.width/d.x|0;l=d.x*tileImageSizeInverse.x;const m=d.y*tileImageSizeInverse.y,g=c%n*l;n=(c/n|0)*m;const q=tileBleedShrinkFix*tileImageSizeInverse.x;glDraw(a.x,a.y,k?-b.x:b.x,b.y,f,g+q,n+tileBleedShrinkFix*tileImageSizeInverse.y,g-q+l,n-q+m,e.rgbaInt(),h.rgbaInt())}else drawCanvas2D(a,b,f,k,m=>{if(0>c)m.fillStyle=e.rgba(),m.fillRect(-.5,-.5,1,1);else{var g=tileImage.width/d.x|0;const q=c%g*d.x+tileBleedShrinkFix;g=(c/g|0)*d.y+tileBleedShrinkFix;const w=d.x-2*tileBleedShrinkFix,v=d.y-2*tileBleedShrinkFix;m.globalAlpha=e.a;m.drawImage(tileImage,q,g,w,v,-.5,-.5,1,1)}})}function drawRect(a,b,c,d,e){drawTile(a,b,-1,tileSizeDefault,c,d,0,0,e)}function drawTileScreenSpace(a,b=vec2(1),c,d,e,f,k,h,l){drawTile(screenToWorld(a),b.scale(1/cameraScale),c,d,e,f,k,h,l)}function drawRectScreenSpace(a,b,c,d,e){drawTileSrceenSpace(a,b,-1,tileSizeDefault,c,d,0,0,e)}function drawLine(a,b,c=.1,d,e){b=vec2((b.x-a.x)/2,(b.y-a.y)/2);c=vec2(c,2*b.length());drawRect(a.add(b),c,d,b.angle(),0,0,e)}function drawCanvas2D(a,b,c,d,e,f=mainContext){a=worldToScreen(a);b=b.scale(cameraScale);f.save();f.translate(a.x+.5|0,a.y-.5|0);f.rotate(c);f.scale(d?-b.x:b.x,b.y);e(f);f.restore()}function drawText(a,b,c=1,d=new Color,e=0,f=new Color(0,0,0),k="center",h=fontDefault){b=worldToScreen(b);overlayContext.font=c*cameraScale+"px "+h;overlayContext.textAlign=k;overlayContext.textBaseline="middle";e&&(overlayContext.lineWidth=e*cameraScale,overlayContext.strokeStyle=f.rgba(),overlayContext.strokeText(a,b.x,b.y));overlayContext.fillStyle=d.rgba();overlayContext.fillText(a,b.x,b.y)}function setBlendMode(a,b=glEnable){glEnable&&b?glSetBlendMode(a):mainContext.globalCompositeOperation=a?"lighter":"source-over"}const isFullscreen=()=>document.fullscreenElement;function toggleFullscreen(){isFullscreen()?document.exitFullscreen?document.exitFullscreen():document.mozCancelFullScreen&&document.mozCancelFullScreen():document.body.webkitRequestFullScreen?document.body.webkitRequestFullScreen():document.body.mozRequestFullScreen&&document.body.mozRequestFullScreen()}"use strict";const keyIsDown=(a,b=0)=>inputData[b]&&inputData[b][a]&1?1:0,keyWasPressed=(a,b=0)=>inputData[b]&&inputData[b][a]&2?1:0,keyWasReleased=(a,b=0)=>inputData[b]&&inputData[b][a]&4?1:0,clearInput=()=>inputData[0]=[],mouseIsDown=keyIsDown,mouseWasPressed=keyWasPressed,mouseWasReleased=keyWasReleased;let mousePos=vec2(),mousePosScreen=vec2(),mouseWheel=0,isUsingGamepad=0;const gamepadIsDown=(a,b=0)=>keyIsDown(a,b+1),gamepadWasPressed=(a,b=0)=>keyWasPressed(a,b+1),gamepadWasReleased=(a,b=0)=>keyWasReleased(a,b+1),gamepadStick=(a,b=0)=>stickData[b]?stickData[b][a]||vec2():vec2(),inputData=[[]];function inputUpdate(){document.hasFocus()||clearInput();mousePos=screenToWorld(mousePosScreen);gamepadsUpdate()}function inputUpdatePost(){for(const a of inputData)for(const b in a)a[b]&=1;mouseWheel=0}onkeydown=a=>{debug&&a.target!=document.body||(a.repeat||(inputData[isUsingGamepad=0][remapKeyCode(a.keyCode)]=3),debug||a.preventDefault())};onkeyup=a=>{debug&&a.target!=document.body||(inputData[0][remapKeyCode(a.keyCode)]=4)};const remapKeyCode=a=>inputWASDEmulateDirection?87==a?38:83==a?40:65==a?37:68==a?39:a:a;onmousedown=a=>{inputData[isUsingGamepad=0][a.button]=3;onmousemove(a);a.button&&a.preventDefault()};onmouseup=a=>inputData[0][a.button]=inputData[0][a.button]&2|4;onmousemove=a=>{if(mainCanvas){var b=mainCanvas.getBoundingClientRect();mousePosScreen.x=mainCanvasSize.x*percent(a.x,b.right,b.left);mousePosScreen.y=mainCanvasSize.y*percent(a.y,b.bottom,b.top)}};onwheel=a=>a.ctrlKey||(mouseWheel=sign(a.deltaY));oncontextmenu=a=>!1;const stickData=[];function gamepadsUpdate(){if(gamepadsEnable&&navigator.getGamepads&&(document.hasFocus()||debug)){var a=navigator.getGamepads();for(let e=a.length;e--;){var b=a[e];const f=inputData[e+1]||(inputData[e+1]=[]),k=stickData[e]||(stickData[e]=[]);if(b){var c=h=>.3h?-percent(-h,.8,.3):0;for(var d=0;d>1]=vec2(c(b.axes[d]),c(-b.axes[d+1])).clampLength();for(c=b.buttons.length;c--;)d=b.buttons[c],f[c]=d.pressed?1+2*!gamepadIsDown(c,e):4*gamepadIsDown(c,e),isUsingGamepad|=!e&&d.pressed;gamepadDirectionEmulateStick&&(b=vec2(gamepadIsDown(15,e)-gamepadIsDown(14,e),gamepadIsDown(12,e)-gamepadIsDown(13,e)),b.lengthSquared()&&(k[0]=b.clampLength()))}}}}const isTouchDevice=inputTouchEnable&&void 0!==window.ontouchstart;if(isTouchDevice){let a,b;ontouchstart=ontouchmove=ontouchend=c=>{c.button=0;const d=c.touches.length;d?(b||zzfx(0,b=1),c.x=c.touches[0].clientX,c.y=c.touches[0].clientY,a?onmousemove(c):onmousedown(c)):a&&onmouseup(c);a=d;return!c.cancelable}}"use strict";class Sound{constructor(a,b=soundDefaultRange,c=soundDefaultTaper){soundEnable&&(this.range=b,this.taper=c,this.randomness=a[1]||0,a[1]=0,this.cachedSamples=zzfxG(...a))}play(a,b=1,c=1,d=1){if(soundEnable){var e=0;if(a){if(e=this.range){const f=cameraPos.distanceSquared(a);if(f>e*e)return;b*=percent(f**.5,e*this.taper,e)}e=2*worldToScreen(a).x/mainCanvas.width-1}a=c+c*this.randomness*d*rand(-1,1);return playSamples([this.cachedSamples],b,a,e)}}playNote(a,b,c=1){if(soundEnable)return this.play(b,c,2**(a/12),0)}}class Music{constructor(a){soundEnable&&(this.cachedSamples=zzfxM(...a))}play(a=1,b=1){if(soundEnable)return playSamples(this.cachedSamples,a,1,0,b)}}function playAudioFile(a,b=1,c=1){if(soundEnable)return a=new Audio(a),a.volume=soundVolume*b,a.loop=c,a.play(),a}function speak(a,b="",c=1,d=1,e=1){if(soundEnable&&speechSynthesis)return a=new SpeechSynthesisUtterance(a),a.lang=b,a.volume=2*c*soundVolume,a.rate=d,a.pitch=e,speechSynthesis.speak(a),a}const stopSpeech=()=>speechSynthesis&&speechSynthesis.cancel(),getNoteFrequency=(a,b=220)=>b*2**(a/12);let audioContext;function playSamples(a,b=1,c=1,d=0,e=0){if(soundEnable){audioContext||(audioContext=new(window.AudioContext||webkitAudioContext));var f=audioContext.createBuffer(a.length,a[0].length,zzfxR),k=audioContext.createBufferSource();a.forEach((h,l)=>f.getChannelData(l).set(h));k.buffer=f;k.playbackRate.value=c;k.loop=e;k.connect(new StereoPannerNode(audioContext,{pan:clamp(d,1,-1)})).connect(new GainNode(audioContext,{gain:soundVolume*b})).connect(audioContext.destination);k.start();return k}}const zzfx=(...a)=>playSamples([zzfxG(...a)]),zzfxR=44100;function zzfxG(a=1,b=.05,c=220,d=0,e=0,f=.1,k=0,h=1,l=0,n=0,m=0,g=0,q=0,w=0,v=0,A=0,r=0,B=1,x=0,C=0){let t=2*PI,E=l*=500*t/zzfxR/zzfxR,y=[];b=c*=(1+b*rand(-1,1))*t/zzfxR;let u=0,F=0,p=0,z=1,H=0,I=0,D=0,J,G;d=d*zzfxR+9;x*=zzfxR;e*=zzfxR;f*=zzfxR;r*=zzfxR;n*=500*t/zzfxR**3;v*=t/zzfxR;m*=t/zzfxR;g*=zzfxR;q=q*zzfxR|0;for(G=d+x+e+f+r|0;pp?0:(pg&&(c+=m,b+=m,z=0),!q||++H%q||(c=b,l=E,z=z||1);return y}function zzfxM(a,b,c,d=125){let e,f,k,h,l,n,m,g,q,w,v,A,r,B=0,x,C=[],t=[],E=[],y=0,u=0,F=1,p={},z=zzfxR/d*60>>2;for(;F;y++)C=[F=g=A=0],c.forEach((H,I)=>{m=b[H][y]||[0,0,0];F|=!!b[H][y];x=A+(b[H][0].length-2-!g)*z;r=I==c.length-1;f=2;for(h=A;fz-99&&q?v+=(1>v)/99:0)n=(1-v)*C[B++]/2||0,t[h]=(t[h]||0)-n*u+n,E[h]=(E[h++]||0)+n*u+n;l&&(v=l%1,u=m[1]||0,l|=0)&&(C=p[[w=m[B=0]||0,l]]=p[[w,l]]||(e=[...a[w]],e[2]*=2**((l-12)/12),0a.arrayCheck(tileCollisionSize)&&(tileCollision[(a.y|0)*tileCollisionSize.x+a.x|0]=b),getTileCollisionData=a=>a.arrayCheck(tileCollisionSize)?tileCollision[(a.y|0)*tileCollisionSize.x+a.x|0]:0;function tileCollisionTest(a,b=vec2(),c){const d=max(Math.floor(a.x-b.x/2),0);var e=max(Math.floor(a.y-b.y/2),0);const f=min(a.x+b.x/2,tileCollisionSize.x-1);for(a=min(a.y+b.y/2,tileCollisionSize.y-1);e=f&&(h+=f,n+=k);l<=e&&(h+=e,m+=d)}debugRaycast&&debugLine(a,b,"#00f",.02,1)}const tileLayerCanvasCache=[];class TileLayerData{constructor(a,b=0,c=0,d=new Color){this.tile=a;this.direction=b;this.mirror=c;this.color=d}clear(){this.tile=this.direction=this.mirror=0;color=new Color}}class TileLayer extends EngineObject{constructor(a,b=tileCollisionSize,c=tileSizeDefault,d=vec2(1),e=0){super(a,b,-1,c,0,void 0,e);this.canvas=tileLayerCanvasCache.length?tileLayerCanvasCache.pop():document.createElement("canvas");this.context=this.canvas.getContext("2d");this.scale=d;this.isOverlay;this.data=[];for(a=this.size.area();a--;)this.data.push(new TileLayerData)}destroy(){tileLayerCanvasCache.push(this.canvas);super.destroy()}setData(a,b,c){a.arrayCheck(this.size)&&(this.data[(a.y|0)*this.size.x+a.x|0]=b,c&&this.drawTileData(a))}getData(a){return a.arrayCheck(this.size)&&this.data[(a.y|0)*this.size.x+a.x|0]}update(){}render(){ASSERT(mainContext!=this.context);glEnable&&!glOverlay&&!this.isOverlay&&glCopyToContext(mainContext);const a=worldToScreen(this.pos.add(vec2(0,this.size.y*this.scale.y)));(this.isOverlay?overlayContext:mainContext).drawImage(this.canvas,a.x,a.y,cameraScale*this.size.x*this.scale.x,cameraScale*this.size.y*this.scale.y)}redraw(){this.redrawStart();this.drawAllTileData();this.redrawEnd()}redrawStart(a=1){const b=this.size.x*this.tileSize.x,c=this.size.y*this.tileSize.y;a&&(this.canvas.width=b,this.canvas.height=c);this.savedRenderSettings=[mainCanvasSize,mainCanvas,mainContext,cameraScale,cameraPos];cameraScale=this.tileSize.x;cameraPos=this.size.scale(.5);mainCanvas=this.canvas;mainContext=this.context;mainContext.imageSmoothingEnabled=!pixelated;mainCanvasSize=vec2(b,c);glPreRender(b,c)}redrawEnd(){ASSERT(mainContext==this.context);glCopyToContext(mainContext,1);[mainCanvasSize,mainCanvas,mainContext,cameraScale,cameraPos]=this.savedRenderSettings}drawTileData(a){const b=a.floor().add(this.pos).add(vec2(.5));this.drawCanvas2D(b,vec2(1),0,0,c=>c.clearRect(-.5,-.5,1,1));a=this.getData(a);void 0!=a.tile&&(ASSERT(mainContext==this.context),drawTile(b,vec2(1),a.tile,this.tileSize,a.color,a.direction*PI/2,a.mirror))}drawAllTileData(){for(let a=this.size.x;a--;)for(let b=this.size.y;b--;)this.drawTileData(vec2(a,b))}drawCanvas2D(a,b,c,d,e){const f=this.context;f.save();a=a.subtract(this.pos).multiply(this.tileSize);b=b.multiply(this.tileSize);f.translate(a.x,this.canvas.height-a.y);f.rotate(c);f.scale(d?-b.x:b.x,b.y);e(f);f.restore()}drawTile(a,b=vec2(1),c=-1,d=tileSizeDefault,e=new Color,f=0,k){this.drawCanvas2D(a,b,f,k,h=>{if(0>c)h.fillStyle=e.rgba(),h.fillRect(-.5,-.5,1,1);else{const l=tileImage.width/d.x;h.globalAlpha=e.a;h.drawImage(tileImage,c%l*d.x,(c/l|0)*d.x,d.x,d.y,-.5,-.5,1,1)}})}drawRect(a,b,c,d){this.drawTile(a,b,-1,0,c,d,0)}}"use strict";class ParticleEmitter extends EngineObject{constructor(a,b=0,c=0,d=100,e=PI,f=-1,k=tileSizeDefault,h=new Color,l=new Color,n=new Color(1,1,1,0),m=new Color(1,1,1,0),g=.5,q=.1,w=1,v=.1,A=.05,r=1,B=1,x=0,C=PI,t=.1,E=.2,y,u,F=1,p=u?1e9:0){super(a,new Vector2,f,k,0,void 0,p);this.emitSize=b;this.emitTime=c;this.emitRate=d;this.emitConeAngle=e;this.colorStartA=h;this.colorStartB=l;this.colorEndA=n;this.colorEndB=m;this.randomColorLinear=F;this.particleTime=g;this.sizeStart=q;this.sizeEnd=w;this.speed=v;this.angleSpeed=A;this.damping=r;this.angleDamping=B;this.gravityScale=x;this.particleConeAngle=C;this.fadeRate=t;this.randomness=E;this.collideTiles=y;this.additive=u;this.emitTimeBuffer=this.trailScale=0}update(){this.parent&&super.update();if(!this.emitTime||this.getAliveTime()<=this.emitTime){if(this.emitRate){const a=1/this.emitRate;for(this.emitTimeBuffer+=timeDelta;0m+m*rand(b,-b);const d=c(this.particleTime),e=c(this.sizeStart),f=c(this.sizeEnd),k=c(this.speed);c=c(this.angleSpeed)*randSign();const h=rand(this.emitConeAngle,-this.emitConeAngle),l=randColor(this.colorStartA,this.colorStartB,this.randomColorLinear),n=randColor(this.colorEndA,this.colorEndB,this.randomColorLinear);a.colorStart=l;a.colorEndDelta=n.subtract(l);a.velocity=(new Vector2).setAngle(this.angle+h,k);a.angleVelocity=c;a.lifeTime=d;a.sizeStart=e;a.sizeEndDelta=f-e;a.fadeRate=this.fadeRate;a.damping=this.damping;a.angleDamping=this.angleDamping;a.elasticity=this.elasticity;a.friction=this.friction;a.gravityScale=this.gravityScale;a.collideTiles=this.collideTiles;a.additive=this.additive;a.renderOrder=this.renderOrder;a.trailScale=this.trailScale;a.mirror=.5>rand();a.destroyCallback=this.particleDestroyCallback;this.particleCreateCallback&&this.particleCreateCallback(a);return a}render(){}}class Particle extends EngineObject{constructor(a,b,c,d){super(a,new Vector2,b,c,d)}render(){const a=min((time-this.spawnTime)/this.lifeTime,1);var b=this.sizeStart+a*this.sizeEndDelta;b=new Vector2(b,b);var c=this.fadeRate/2;c=new Color(this.colorStart.r+a*this.colorEndDelta.r,this.colorStart.g+a*this.colorEndDelta.g,this.colorStart.b+a*this.colorEndDelta.b,(this.colorStart.a+a*this.colorEndDelta.a)*(a1-c?(1-a)/c:1));this.additive&&setBlendMode(1);if(this.trailScale){var d=this.velocity.length();const e=this.velocity.scale(1/d);d*=this.trailScale;b.y=max(b.x,d);this.angle=e.angle();drawTile(this.pos.add(e.multiply(vec2(0,-d/2))),b,this.tileIndex,this.tileSize,c,this.angle,this.mirror)}else drawTile(this.pos,b,this.tileIndex,this.tileSize,c,this.angle,this.mirror);this.additive&&setBlendMode();debugParticles&&debugRect(this.pos,b,"#f005",0,this.angle);1==a&&(this.color=c,this.size=b,this.destroyCallback&&this.destroyCallback(this),this.destroyed=1)}}"use strict";const medals=[];let medalsPreventUnlock,newgrounds,medalsDisplayQueue=[],medalsSaveName,medalsDisplayTimer;function medalsInit(a){medalsSaveName=a;debugMedals||medals.forEach(b=>b.unlocked=localStorage[b.storageKey()])}class Medal{constructor(a,b,c="",d="🏆",e){ASSERT(0<=a&&!medals[a]);medals[this.id=a]=this;this.name=b;this.description=c;this.icon=d;e&&(this.image=new Image,this.image.src=e)}unlock(){medalsPreventUnlock||this.unlocked||(ASSERT(medalsSaveName),localStorage[this.storageKey()]=this.unlocked=1,medalsDisplayQueue.push(this),newgrounds&&newgrounds.unlockMedal(this.id),localStorage["OS13kTrophy,"+this.icon+","+medalsSaveName+","+this.name]=this.description)}render(a=0){const b=overlayContext,c=overlayCanvas.width-medalDisplayWidth;a*=-medalDisplayHeight;b.save();b.beginPath();b.fillStyle="#ddd";b.fill(b.rect(c,a,medalDisplayWidth,medalDisplayHeight));b.strokeStyle=b.fillStyle="#000";b.lineWidth=2;b.stroke();b.clip();this.renderIcon(c+15+medalDisplayIconSize/2,a+medalDisplayHeight/2);b.textAlign="left";b.font="3em "+fontDefault;b.fillText(this.name,c+medalDisplayIconSize+25,a+35);b.font="1.5em "+fontDefault;b.restore(b.fillText(this.description,c+medalDisplayIconSize+25,a+70))}renderIcon(a,b,c=medalDisplayIconSize){const d=overlayContext;d.textAlign="center";d.textBaseline="middle";d.font=.6*c+"px "+fontDefault;d.fillStyle="#000";this.image?d.drawImage(this.image,a-c/2,b-c/2,c,c):d.fillText(this.icon,a,b)}storageKey(){return medalsSaveName+"_medal_"+this.id}}function medalsRender(){if(medalsDisplayQueue.length){var a=medalsDisplayQueue[0],b=timeReal-medalsDisplayTimer;if(medalsDisplayTimer)if(b>medalDisplayTime)medalsDisplayQueue.shift(medalsDisplayTimer=0);else{const c=medalDisplayTime-medalDisplaySlideTime;a.render(bc?(b-c)/medalDisplaySlideTime:0)}else medalsDisplayTimer=timeReal}}class Newgrounds{constructor(a,b){ASSERT(!newgrounds&&a);this.app_id=a;this.cipher=b;this.host=location?location.hostname:"";b&&(this.cryptoJS=CryptoJS());this.session_id=new URL(window.location.href).searchParams.get("ngio_session_id")||0;if(0!=this.session_id){this.medals=(a=this.call("Medal.getList"))?a.result.data.medals:[];debugMedals&&console.log(this.medals);for(var c of this.medals)if(a=medals[c.id])a.image=new Image,a.image.src=c.icon,a.name=c.name,a.description=c.description,a.unlocked=c.unlocked,a.difficulty=c.difficulty,a.value=c.value,a.value&&(a.description=a.description+" ("+a.value+")");this.scoreboards=(c=this.call("ScoreBoard.getBoards"))?c.result.data.scoreboards:[];debugMedals&&console.log(this.scoreboards)}}unlockMedal(a){return this.call("Medal.unlock",{id:a},1)}postScore(a,b){return this.call("ScoreBoard.postScore",{id:a,value:b},1)}logView(){return this.call("App.logView",{host:this.host},1)}getScores(a,b=0,c=0,d=0,e=10){return this.call("ScoreBoard.getScores",{id:a,user:b,social:c,skip:d,limit:e})}call(a,b=0,c=0){a={component:a,parameters:b};if(this.cipher){b=this.cryptoJS;var d=b.enc.Base64.parse(this.cipher);const e=b.lib.WordArray.random(16);d=b.AES.encrypt(JSON.stringify(a),d,{iv:e});a.secure=b.enc.Base64.stringify(e.concat(d.ciphertext));a.parameters=0}b={app_id:this.app_id,session_id:this.session_id,call:a};a=new FormData;a.append("input",JSON.stringify(b));b=new XMLHttpRequest;b.open("POST","https://newgrounds.io/gateway_v3.php",!debugMedals&&c);b.send(a);debugMedals&&console.log(b.responseText);return b.responseText&&JSON.parse(b.responseText)}}const CryptoJS=()=>eval(Function("[M='GBMGXz^oVYPPKKbB`agTXU|LxPc_ZBcMrZvCr~wyGfWrwk@ATqlqeTp^N?p{we}jIpEnB_sEr`l?YDkDhWhprc|Er|XETG?pTl`e}dIc[_N~}fzRycIfpW{HTolvoPB_FMe_eH~BTMx]yyOhv?biWPCGc]kABencBhgERHGf{OL`Dj`c^sh@canhy[secghiyotcdOWgO{tJIE^JtdGQRNSCrwKYciZOa]Y@tcRATYKzv|sXpboHcbCBf`}SKeXPFM|RiJsSNaIb]QPc[D]Jy_O^XkOVTZep`ONmntLL`Qz~UupHBX_Ia~WX]yTRJIxG`ioZ{fefLJFhdyYoyLPvqgH?b`[TMnTwwfzDXhfM?rKs^aFr|nyBdPmVHTtAjXoYUloEziWDCw_suyYT~lSMksI~ZNCS[Bex~j]Vz?kx`gdYSEMCsHpjbyxQvw|XxX_^nQYue{sBzVWQKYndtYQMWRef{bOHSfQhiNdtR{o?cUAHQAABThwHPT}F{VvFmgN`E@FiFYS`UJmpQNM`X|tPKHlccT}z}k{sACHL?Rt@MkWplxO`ASgh?hBsuuP|xD~LSH~KBlRs]t|l|_tQAroDRqWS^SEr[sYdPB}TAROtW{mIkE|dWOuLgLmJrucGLpebrAFKWjikTUzS|j}M}szasKOmrjy[?hpwnEfX[jGpLt@^v_eNwSQHNwtOtDgWD{rk|UgASs@mziIXrsHN_|hZuxXlPJOsA^^?QY^yGoCBx{ekLuZzRqQZdsNSx@ezDAn{XNj@fRXIwrDX?{ZQHwTEfu@GhxDOykqts|n{jOeZ@c`dvTY?e^]ATvWpb?SVyg]GC?SlzteilZJAL]mlhLjYZazY__qcVFYvt@|bIQnSno@OXyt]OulzkWqH`rYFWrwGs`v|~XeTsIssLrbmHZCYHiJrX}eEzSssH}]l]IhPQhPoQ}rCXLyhFIT[clhzYOvyHqigxmjz`phKUU^TPf[GRAIhNqSOdayFP@FmKmuIzMOeoqdpxyCOwCthcLq?n`L`tLIBboNn~uXeFcPE{C~mC`h]jUUUQe^`UqvzCutYCgct|SBrAeiYQW?X~KzCz}guXbsUw?pLsg@hDArw?KeJD[BN?GD@wgFWCiHq@Ypp_QKFixEKWqRp]oJFuVIEvjDcTFu~Zz]a{IcXhWuIdMQjJ]lwmGQ|]g~c]Hl]pl`Pd^?loIcsoNir_kikBYyg?NarXZEGYspt_vLBIoj}LI[uBFvm}tbqvC|xyR~a{kob|HlctZslTGtPDhBKsNsoZPuH`U`Fqg{gKnGSHVLJ^O`zmNgMn~{rsQuoymw^JY?iUBvw_~mMr|GrPHTERS[MiNpY[Mm{ggHpzRaJaoFomtdaQ_?xuTRm}@KjU~RtPsAdxa|uHmy}n^i||FVL[eQAPrWfLm^ndczgF~Nk~aplQvTUpHvnTya]kOenZlLAQIm{lPl@CCTchvCF[fI{^zPkeYZTiamoEcKmBMfZhk_j_~Fjp|wPVZlkh_nHu]@tP|hS@^G^PdsQ~f[RqgTDqezxNFcaO}HZhb|MMiNSYSAnQWCDJukT~e|OTgc}sf[cnr?fyzTa|EwEtRG|I~|IO}O]S|rp]CQ}}DWhSjC_|z|oY|FYl@WkCOoPuWuqr{fJu?Brs^_EBI[@_OCKs}?]O`jnDiXBvaIWhhMAQDNb{U`bqVR}oqVAvR@AZHEBY@depD]OLh`kf^UsHhzKT}CS}HQKy}Q~AeMydXPQztWSSzDnghULQgMAmbWIZ|lWWeEXrE^EeNoZApooEmrXe{NAnoDf`m}UNlRdqQ@jOc~HLOMWs]IDqJHYoMziEedGBPOxOb?[X`KxkFRg@`mgFYnP{hSaxwZfBQqTm}_?RSEaQga]w[vxc]hMne}VfSlqUeMo_iqmd`ilnJXnhdj^EEFifvZyxYFRf^VaqBhLyrGlk~qowqzHOBlOwtx?i{m~`n^G?Yxzxux}b{LSlx]dS~thO^lYE}bzKmUEzwW^{rPGhbEov[Plv??xtyKJshbG`KuO?hjBdS@Ru}iGpvFXJRrvOlrKN?`I_n_tplk}kgwSXuKylXbRQ]]?a|{xiT[li?k]CJpwy^o@ebyGQrPfF`aszGKp]baIx~H?ElETtFh]dz[OjGl@C?]VDhr}OE@V]wLTc[WErXacM{We`F|utKKjgllAxvsVYBZ@HcuMgLboFHVZmi}eIXAIFhS@A@FGRbjeoJWZ_NKd^oEH`qgy`q[Tq{x?LRP|GfBFFJV|fgZs`MLbpPYUdIV^]mD@FG]pYAT^A^RNCcXVrPsgk{jTrAIQPs_`mD}rOqAZA[}RETFz]WkXFTz_m{N@{W@_fPKZLT`@aIqf|L^Mb|crNqZ{BVsijzpGPEKQQZGlApDn`ruH}cvF|iXcNqK}cxe_U~HRnKV}sCYb`D~oGvwG[Ca|UaybXea~DdD~LiIbGRxJ_VGheI{ika}KC[OZJLn^IBkPrQj_EuoFwZ}DpoBRcK]Q}?EmTv~i_Tul{bky?Iit~tgS|o}JL_VYcCQdjeJ_MfaA`FgCgc[Ii|CBHwq~nbJeYTK{e`CNstKfTKPzw{jdhp|qsZyP_FcugxCFNpKitlR~vUrx^NrSVsSTaEgnxZTmKc`R|lGJeX}ccKLsQZQhsFkeFd|ckHIVTlGMg`~uPwuHRJS_CPuN_ogXe{Ba}dO_UBhuNXby|h?JlgBIqMKx^_u{molgL[W_iavNQuOq?ap]PGB`clAicnl@k~pA?MWHEZ{HuTLsCpOxxrKlBh]FyMjLdFl|nMIvTHyGAlPogqfZ?PlvlFJvYnDQd}R@uAhtJmDfe|iJqdkYr}r@mEjjIetDl_I`TELfoR|qTBu@Tic[BaXjP?dCS~MUK[HPRI}OUOwAaf|_}HZzrwXvbnNgltjTwkBE~MztTQhtRSWoQHajMoVyBBA`kdgK~h`o[J`dm~pm]tk@i`[F~F]DBlJKklrkR]SNw@{aG~Vhl`KINsQkOy?WhcqUMTGDOM_]bUjVd|Yh_KUCCgIJ|LDIGZCPls{RzbVWVLEhHvWBzKq|^N?DyJB|__aCUjoEgsARki}j@DQXS`RNU|DJ^a~d{sh_Iu{ONcUtSrGWW@cvUjefHHi}eSSGrNtO?cTPBShLqzwMVjWQQCCFB^culBjZHEK_{dO~Q`YhJYFn]jq~XSnG@[lQr]eKrjXpG~L^h~tDgEma^AUFThlaR{xyuP@[^VFwXSeUbVetufa@dX]CLyAnDV@Bs[DnpeghJw^?UIana}r_CKGDySoRudklbgio}kIDpA@McDoPK?iYcG?_zOmnWfJp}a[JLR[stXMo?_^Ng[whQlrDbrawZeSZ~SJstIObdDSfAA{MV}?gNunLOnbMv_~KFQUAjIMj^GkoGxuYtYbGDImEYiwEMyTpMxN_LSnSMdl{bg@dtAnAMvhDTBR_FxoQgANniRqxd`pWv@rFJ|mWNWmh[GMJz_Nq`BIN@KsjMPASXORcdHjf~rJfgZYe_uulzqM_KdPlMsuvU^YJuLtofPhGonVOQxCMuXliNvJIaoC?hSxcxKVVxWlNs^ENDvCtSmO~WxI[itnjs^RDvI@KqG}YekaSbTaB]ki]XM@[ZnDAP~@|BzLRgOzmjmPkRE@_sobkT|SszXK[rZN?F]Z_u}Yue^[BZgLtR}FHzWyxWEX^wXC]MJmiVbQuBzkgRcKGUhOvUc_bga|Tx`KEM`JWEgTpFYVeXLCm|mctZR@uKTDeUONPozBeIkrY`cz]]~WPGMUf`MNUGHDbxZuO{gmsKYkAGRPqjc|_FtblEOwy}dnwCHo]PJhN~JoteaJ?dmYZeB^Xd?X^pOKDbOMF@Ugg^hETLdhwlA}PL@_ur|o{VZosP?ntJ_kG][g{Zq`Tu]dzQlSWiKfnxDnk}KOzp~tdFstMobmy[oPYjyOtUzMWdjcNSUAjRuqhLS@AwB^{BFnqjCmmlk?jpn}TksS{KcKkDboXiwK]qMVjm~V`LgWhjS^nLGwfhAYrjDSBL_{cRus~{?xar_xqPlArrYFd?pHKdMEZzzjJpfC?Hv}mAuIDkyBxFpxhstTx`IO{rp}XGuQ]VtbHerlRc_LFGWK[XluFcNGUtDYMZny[M^nVKVeMllQI[xtvwQnXFlWYqxZZFp_|]^oWX[{pOMpxXxvkbyJA[DrPzwD|LW|QcV{Nw~U^dgguSpG]ClmO@j_TENIGjPWwgdVbHganhM?ema|dBaqla|WBd`poj~klxaasKxGG^xbWquAl~_lKWxUkDFagMnE{zHug{b`A~IYcQYBF_E}wiA}K@yxWHrZ{[d~|ARsYsjeNWzkMs~IOqqp[yzDE|WFrivsidTcnbHFRoW@XpAV`lv_zj?B~tPCppRjgbbDTALeFaOf?VcjnKTQMLyp{NwdylHCqmo?oelhjWuXj~}{fpuX`fra?GNkDiChYgVSh{R[BgF~eQa^WVz}ATI_CpY?g_diae]|ijH`TyNIF}|D_xpmBq_JpKih{Ba|sWzhnAoyraiDvk`h{qbBfsylBGmRH}DRPdryEsSaKS~tIaeF[s]I~xxHVrcNe@Jjxa@jlhZueLQqHh_]twVMqG_EGuwyab{nxOF?`HCle}nBZzlTQjkLmoXbXhOtBglFoMz?eqre`HiE@vNwBulglmQjj]DB@pPkPUgA^sjOAUNdSu_`oAzar?n?eMnw{{hYmslYi[TnlJD'",..."]charCodeAtUinyxpf","for(;e<10359;c[e++]=p-=128,A=A?p-A&&A:p==34&&p)for(p=1;p<128;y=f.map((n,x)=>(U=r[n]*2+1,U=Math.log(U/(h-U)),t-=a[x]*U,U/500)),t=~-h/(1+Math.exp(t))|1,i=o%h>17)-!i*t,f.map((n,x)=>(U=r[n]+=(i*h/2-r[n]<<13)/((C[n]+=C[n]<5)+1/20)>>13,a[x]+=y[x]*(i-t/h))),p=p*2+i)for(f='010202103203210431053105410642065206541'.split(t=0).map((n,x)=>(U=0,[...n].map((n,x)=>(U=U*997+(c[e-n]|0)|0)),h*32-1&U*997+p+!!A*129)*12+x);o{c=glContext.getAttribLocation(glShader,c);glContext.enableVertexAttribArray(c);glContext.vertexAttribPointer(c,f,d,k,gl_VERTEX_BYTE_STRIDE,b);b+=f*e};var b=glDirty=glBatchCount=0;a("a",gl_FLOAT,4,1);a("p",gl_FLOAT,4,2);a("s",gl_FLOAT,4,2);a("t",gl_FLOAT,4,2);a("c",gl_UNSIGNED_BYTE,1,4,1);a("b",gl_UNSIGNED_BYTE,1,4,1)}}function glSetBlendMode(a){glEnable&&(glAdditive=a)}function glSetTexture(a=glTileTexture){glEnable&&(a!=glActiveTexture&&glFlush(),glContext.bindTexture(gl_TEXTURE_2D,glActiveTexture=a))}function glCompileShader(a,b){if(glEnable){b=glContext.createShader(b);glContext.shaderSource(b,a);glContext.compileShader(b);if(debug&&!glContext.getShaderParameter(b,gl_COMPILE_STATUS))throw glContext.getShaderInfoLog(b);return b}}function glCreateProgram(a,b){if(glEnable){var c=glContext.createProgram();glContext.attachShader(c,glCompileShader(a,gl_VERTEX_SHADER));glContext.attachShader(c,glCompileShader(b,gl_FRAGMENT_SHADER));glContext.linkProgram(c);if(debug&&!glContext.getProgramParameter(c,gl_LINK_STATUS))throw glContext.getProgramInfoLog(c);return c}}function glCreateBuffer(a,b,c){if(glEnable){var d=glContext.createBuffer();glContext.bindBuffer(a,d);glContext.bufferData(a,b,c);return d}}function glCreateTexture(a){if(glEnable&&a&&a.width){var b=glContext.createTexture();glContext.bindTexture(gl_TEXTURE_2D,b);glContext.texImage2D(gl_TEXTURE_2D,0,gl_RGBA,gl_RGBA,gl_UNSIGNED_BYTE,a);glContext.texParameteri(gl_TEXTURE_2D,gl_TEXTURE_MIN_FILTER,pixelated?gl_NEAREST:gl_LINEAR);glContext.texParameteri(gl_TEXTURE_2D,gl_TEXTURE_MAG_FILTER,pixelated?gl_NEAREST:gl_LINEAR);glContext.texParameteri(gl_TEXTURE_2D,gl_TEXTURE_WRAP_S,gl_CLAMP_TO_EDGE);glContext.texParameteri(gl_TEXTURE_2D,gl_TEXTURE_WRAP_T,gl_CLAMP_TO_EDGE);return b}}function glPreRender(a,b){glEnable&&(glCanvas.width=a,glCanvas.height=b,glContext.viewport(0,0,a,b),glContext.bindTexture(gl_TEXTURE_2D,glActiveTexture=glTileTexture),glContext.useProgram(glShader),glSetBlendMode(),a=2*cameraScale/a,b=2*cameraScale/b,glContext.uniformMatrix4fv(glContext.getUniformLocation(glShader,"m"),0,new Float32Array([a,0,0,0,0,b,0,0,1,1,-1,1,-1-a*cameraPos.x,-1-b*cameraPos.y,0,0])))}function glFlush(){if(glEnable&&glBatchCount){var a=glBatchAdditive?gl_ONE:gl_ONE_MINUS_SRC_ALPHA;glContext.blendFuncSeparate(gl_SRC_ALPHA,a,gl_ONE,a);glContext.enable(gl_BLEND);glContext.bufferSubData(gl_ARRAY_BUFFER,0,glPositionData.subarray(0,glBatchCount*gl_VERTICES_PER_QUAD*gl_INDICIES_PER_VERT));glContext.drawArrays(gl_TRIANGLES,0,glBatchCount*gl_VERTICES_PER_QUAD);glBatchCount=0;glBatchAdditive=glAdditive}}function glCopyToContext(a,b){glEnable&&glDirty&&(glFlush(),!glOverlay||b)&&(a.drawImage(glCanvas,0,glAdditive=glDirty=0),glContext.clear(gl_COLOR_BUFFER_BIT))}function glDraw(a,b,c,d,e=0,f=0,k=0,h=1,l=1,n=4294967295,m=0){if(glEnable){glBatchCount!=gl_MAX_BATCH&&glBatchAdditive==glAdditive||glFlush();var g=glBatchCount++*gl_VERTICES_PER_QUAD*gl_INDICIES_PER_VERT;glDirty=1;glPositionData[g++]=e;glPositionData[g++]=a;glPositionData[g++]=b;glPositionData[g++]=-c;glPositionData[g++]=-d;glPositionData[g++]=f;glPositionData[g++]=l;glColorData[g++]=n;glColorData[g++]=m;glPositionData[g++]=e;glPositionData[g++]=a;glPositionData[g++]=b;glPositionData[g++]=c;glPositionData[g++]=d;glPositionData[g++]=h;glPositionData[g++]=k;glColorData[g++]=n;glColorData[g++]=m;glPositionData[g++]=e;glPositionData[g++]=a;glPositionData[g++]=b;glPositionData[g++]=-c;glPositionData[g++]=d;glPositionData[g++]=f;glPositionData[g++]=k;glColorData[g++]=n;glColorData[g++]=m;glPositionData[g++]=e;glPositionData[g++]=a;glPositionData[g++]=b;glPositionData[g++]=-c;glPositionData[g++]=-d;glPositionData[g++]=f;glPositionData[g++]=l;glColorData[g++]=n;glColorData[g++]=m;glPositionData[g++]=e;glPositionData[g++]=a;glPositionData[g++]=b;glPositionData[g++]=c;glPositionData[g++]=-d;glPositionData[g++]=h;glPositionData[g++]=l;glColorData[g++]=n;glColorData[g++]=m;glPositionData[g++]=e;glPositionData[g++]=a;glPositionData[g++]=b;glPositionData[g++]=c;glPositionData[g++]=d;glPositionData[g++]=h;glPositionData[g++]=k;glColorData[g++]=n;glColorData[g++]=m}}const gl_ONE=1,gl_TRIANGLES=4,gl_SRC_ALPHA=770,gl_ONE_MINUS_SRC_ALPHA=771,gl_BLEND=3042,gl_TEXTURE_2D=3553,gl_UNSIGNED_BYTE=5121,gl_FLOAT=5126,gl_RGBA=6408,gl_NEAREST=9728,gl_LINEAR=9729,gl_TEXTURE_MAG_FILTER=10240,gl_TEXTURE_MIN_FILTER=10241,gl_TEXTURE_WRAP_S=10242,gl_TEXTURE_WRAP_T=10243,gl_COLOR_BUFFER_BIT=16384,gl_CLAMP_TO_EDGE=33071,gl_ARRAY_BUFFER=34962,gl_DYNAMIC_DRAW=35048,gl_FRAGMENT_SHADER=35632,gl_VERTEX_SHADER=35633,gl_COMPILE_STATUS=35713,gl_LINK_STATUS=35714,gl_VERTICES_PER_QUAD=6,gl_INDICIES_PER_VERT=9,gl_MAX_BATCH=65536,gl_VERTEX_BYTE_STRIDE=36; \ No newline at end of file diff --git a/engine/engine.all.release.js b/engine/engine.all.release.js index aa4ff066..97729dc7 100644 --- a/engine/engine.all.release.js +++ b/engine/engine.all.release.js @@ -730,7 +730,7 @@ const medalDisplayIconSize = 80; const engineName = 'LittleJS'; /** Version of engine */ -const engineVersion = '1.1.8'; +const engineVersion = '1.1.9'; /** Frames per second to update objects * @default */ diff --git a/engine/engine.js b/engine/engine.js index a1f16fed..19717d7e 100644 --- a/engine/engine.js +++ b/engine/engine.js @@ -22,7 +22,7 @@ const engineName = 'LittleJS'; /** Version of engine */ -const engineVersion = '1.1.8'; +const engineVersion = '1.1.9'; /** Frames per second to update objects * @default */ diff --git a/package.json b/package.json index 787a618e..83ea948a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "littlejsengine", - "version": "1.1.8", + "version": "1.1.9", "description": "LittleJS - Tiny and Fast HTML5 Game Engine", "main": "engine/engine.all.js", "repository": {