UNPKG

kontra

Version:

Kontra HTML5 game development library

5 lines 41.2 kB
/** * @preserve * Kontra.js v10.0.2 */ function degToRad(t){return t*Math.PI/180}function radToDeg(t){return 180*t/Math.PI}function angleToTarget(t,e){return Math.atan2(e.y-t.y,e.x-t.x)}function rotatePoint(t,e){let i=Math.sin(e),s=Math.cos(e);return{x:t.x*s-t.y*i,y:t.x*i+t.y*s}}function movePoint(t,e,i){return{x:t.x+Math.cos(e)*i,y:t.y+Math.sin(e)*i}}function lerp(t,e,i){return t*(1-i)+e*i}function inverseLerp(t,e,i){return(i-t)/(e-t)}function clamp(t,e,i){return Math.min(Math.max(t,i),e)}function setStoreItem(t,e){null==e?localStorage.removeItem(t):localStorage.setItem(t,JSON.stringify(e))}function getStoreItem(t){let e=localStorage.getItem(t);try{e=JSON.parse(e)}catch(t){}return e}function collides(t,e){let i=getWorldRect(t),s=getWorldRect(e);return!(t.radius&&i.width!=i.height||e.radius&&s.width!=s.height)&&([i,s]=[i,s].map((s=>((s==i?t:e).radius&&(s.radius=s.width/2,s.x+=s.radius,s.y+=s.radius),s))),t.radius&&e.radius?Math.hypot(i.x-s.x,i.y-s.y)<i.radius+s.radius:t.radius||e.radius?circleRectCollision(t.radius?i:s,t.radius?e:t):i.x<s.x+s.width&&i.x+i.width>s.x&&i.y<s.y+s.height&&i.y+i.height>s.y)}function getWorldRect(t){let{x:e=0,y:i=0,width:s,height:a,radius:n}=t.world||t;return t.mapwidth&&(s=t.mapwidth,a=t.mapheight),n&&(s=2*n.x,a=2*n.y),t.anchor&&(e-=s*t.anchor.x,i-=a*t.anchor.y),s<0&&(e+=s,s*=-1),a<0&&(i+=a,a*=-1),{x:e,y:i,width:s,height:a}}function depthSort(t,e,i="y"){return[t,e]=[t,e].map(getWorldRect),t[i]-e[i]}let noop=()=>{},srOnlyStyle="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);",focusParams={preventScroll:!0};function addToDom(t,e){let i=e.parentNode;if(t.setAttribute("data-kontra",""),i){([...i.querySelectorAll(":scope > [data-kontra]")].pop()||e).after(t)}else"CANVAS"==e.nodeName?document.body.append(t):e.append(t)}function removeFromArray(t,e){let i=t.indexOf(e);if(-1!=i)return t.splice(i,1),!0}function circleRectCollision(t,e){let{x:i,y:s,width:a,height:n}=getWorldRect(e);do{i-=e.sx||0,s-=e.sy||0}while(e=e.parent);let r=t.x-Math.max(i,Math.min(t.x,i+a)),o=t.y-Math.max(s,Math.min(t.y,s+n));return r*r+o*o<t.radius*t.radius}let canvasEl,context,callbacks$2={};function on(t,e){callbacks$2[t]=callbacks$2[t]||[],callbacks$2[t].push(e)}function off(t,e){callbacks$2[t]=(callbacks$2[t]||[]).filter((t=>t!=e))}function emit(t,...e){(callbacks$2[t]||[]).map((t=>t(...e)))}let handler$1={get:(t,e)=>"_proxy"==e||noop};function getCanvas(){return canvasEl}function getContext(){return context}function init$1(t,{contextless:e=!1}={}){if(canvasEl=document.getElementById(t)||t||document.querySelector("canvas"),e&&(canvasEl=canvasEl||new Proxy({},handler$1)),!canvasEl)throw Error("You must provide a canvas element for the game");return context=canvasEl.getContext("2d")||new Proxy({},handler$1),context.imageSmoothingEnabled=!1,emit("init"),{canvas:canvasEl,context:context}}class Animation{constructor({spriteSheet:t,frames:e,frameRate:i,loop:s=!0,name:a}){let{width:n,height:r,spacing:o=0,margin:h=0}=t.frame;Object.assign(this,{spriteSheet:t,frames:e,frameRate:i,loop:s,name:a,width:n,height:r,spacing:o,margin:h,isStopped:!1,_f:0,_a:0})}clone(){return new Animation(this)}start(){this.isStopped=!1,this.loop||this.reset()}stop(){this.isStopped=!0}reset(){this._f=0,this._a=0}update(t=1/60){if(!this.isStopped)if(this.loop||this._f!=this.frames.length-1)for(this._a+=t;this._a*this.frameRate>=1;)this._f=++this._f%this.frames.length,this._a-=1/this.frameRate;else this.stop()}render({x:t,y:e,width:i=this.width,height:s=this.height,context:a=getContext()}){let n=this.frames[this._f]/this.spriteSheet._f|0,r=this.frames[this._f]%this.spriteSheet._f|0;a.drawImage(this.spriteSheet.image,this.margin+r*this.width+(2*r+1)*this.spacing,this.margin+n*this.height+(2*n+1)*this.spacing,this.width,this.height,t,e,i,s)}}function factory$b(){return new Animation(...arguments)}let imageRegex=/(jpeg|jpg|gif|png|webp)$/,audioRegex=/(wav|mp3|ogg|aac)$/,leadingSlash=/^\//,trailingSlash=/\/$/,dataMap=new WeakMap,imagePath="",audioPath="",dataPath="";function getUrl(t,e){return new URL(t,e).href}function joinPath(t,e){return[t.replace(trailingSlash,""),t?e.replace(leadingSlash,""):e].filter((t=>t)).join("/")}function getExtension(t){return t.split(".").pop()}function getName(t){let e=t.replace("."+getExtension(t),"");return 2==e.split("/").length?e.replace(leadingSlash,""):e}function getCanPlay(t){return{wav:t.canPlayType('audio/wav; codecs="1"'),mp3:t.canPlayType("audio/mpeg;"),ogg:t.canPlayType('audio/ogg; codecs="vorbis"'),aac:t.canPlayType("audio/aac;")}}let imageAssets={},audioAssets={},dataAssets={};function addGlobal(){window.__k||(window.__k={dm:dataMap,u:getUrl,d:dataAssets,i:imageAssets})}function setImagePath(t){imagePath=t}function setAudioPath(t){audioPath=t}function setDataPath(t){dataPath=t}function loadImage(t){return addGlobal(),new Promise(((e,i)=>{let s,a,n;if(s=joinPath(imagePath,t),imageAssets[s])return e(imageAssets[s]);a=new Image,a.onload=function(){n=getUrl(s,window.location.href),imageAssets[getName(t)]=imageAssets[s]=imageAssets[n]=this,emit("assetLoaded",this,t),e(this)},a.onerror=function(){i("Unable to load image "+s)},a.src=s}))}function loadAudio(t){return new Promise(((e,i)=>{let s,a,n,r,o=t;return s=new Audio,a=getCanPlay(s),(t=[].concat(t).reduce(((t,e)=>t||(a[getExtension(e)]?e:null)),0))?(n=joinPath(audioPath,t),audioAssets[n]?e(audioAssets[n]):(s.addEventListener("canplay",(function(){r=getUrl(n,window.location.href),audioAssets[getName(t)]=audioAssets[n]=audioAssets[r]=this,emit("assetLoaded",this,t),e(this)})),s.onerror=function(){i("Unable to load audio "+n)},s.src=n,void s.load())):i("cannot play any of the audio formats provided "+o)}))}function loadData(t){let e,i;return addGlobal(),e=joinPath(dataPath,t),dataAssets[e]?Promise.resolve(dataAssets[e]):fetch(e).then((t=>{if(!t.ok)throw t;return t.clone().json().catch((()=>t.text()))})).then((s=>(i=getUrl(e,window.location.href),"object"==typeof s&&dataMap.set(s,i),dataAssets[getName(t)]=dataAssets[e]=dataAssets[i]=s,emit("assetLoaded",s,t),s)))}function load(...t){return addGlobal(),Promise.all(t.map((t=>{let e=getExtension([].concat(t)[0]);return e.match(imageRegex)?loadImage(t):e.match(audioRegex)?loadAudio(t):loadData(t)})))}class Vector{constructor(t=0,e=0,i={}){null!=t.x?(this.x=t.x,this.y=t.y):(this.x=t,this.y=e),i._c&&(this.clamp(i._a,i._b,i._d,i._e),this.x=t,this.y=e)}set(t){this.x=t.x,this.y=t.y}add(t){return new Vector(this.x+t.x,this.y+t.y,this)}subtract(t){return new Vector(this.x-t.x,this.y-t.y,this)}scale(t){return new Vector(this.x*t,this.y*t)}normalize(t=this.length()||1){return new Vector(this.x/t,this.y/t)}dot(t){return this.x*t.x+this.y*t.y}length(){return Math.hypot(this.x,this.y)}distance(t){return Math.hypot(this.x-t.x,this.y-t.y)}angle(t){return Math.acos(this.dot(t)/(this.length()*t.length()))}direction(){return Math.atan2(this.y,this.x)}clamp(t,e,i,s){this._c=!0,this._a=t,this._b=e,this._d=i,this._e=s}get x(){return this._x}get y(){return this._y}set x(t){this._x=this._c?clamp(this._a,this._d,t):t}set y(t){this._y=this._c?clamp(this._b,this._e,t):t}}function factory$a(){return new Vector(...arguments)}class Updatable{constructor(t){return this.init(t)}init(t={}){this.position=factory$a(),this.velocity=factory$a(),this.acceleration=factory$a(),this.ttl=1/0,Object.assign(this,t)}update(t){this.advance(t)}advance(t){let e=this.acceleration;t&&(e=e.scale(t)),this.velocity=this.velocity.add(e);let i=this.velocity;t&&(i=i.scale(t)),this.position=this.position.add(i),this._pc(),this.ttl--}get dx(){return this.velocity.x}get dy(){return this.velocity.y}set dx(t){this.velocity.x=t}set dy(t){this.velocity.y=t}get ddx(){return this.acceleration.x}get ddy(){return this.acceleration.y}set ddx(t){this.acceleration.x=t}set ddy(t){this.acceleration.y=t}isAlive(){return this.ttl>0}_pc(){}}class GameObject extends Updatable{init({width:t=0,height:e=0,context:i=getContext(),render:s=this.draw,update:a=this.advance,children:n=[],anchor:r={x:0,y:0},opacity:o=1,rotation:h=0,drotation:d=0,ddrotation:l=0,scaleX:c=1,scaleY:u=1,...p}={}){this._c=[],super.init({width:t,height:e,context:i,anchor:r,opacity:o,rotation:h,drotation:d,ddrotation:l,scaleX:c,scaleY:u,...p}),this._di=!0,this._uw(),this.addChild(n),this._rf=s,this._uf=a,on("init",(()=>{this.context??=getContext()}))}update(t){this._uf(t),this.children.map((e=>e.update&&e.update(t)))}render(){let t=this.context;t.save(),(this.x||this.y)&&t.translate(this.x,this.y),this.rotation&&t.rotate(this.rotation),1==this.scaleX&&1==this.scaleY||t.scale(this.scaleX,this.scaleY);let e=this.width,i=this.height;this.radius&&(e=i=2*this.radius);let s=-e*this.anchor.x,a=-i*this.anchor.y;(s||a)&&t.translate(s,a),this.context.globalAlpha=this.opacity,this._rf(),(s||a)&&t.translate(-s,-a),this.children.map((t=>t.render&&t.render())),t.restore()}draw(){}_pc(){this._uw(),this.children.map((t=>t._pc()))}get x(){return this.position.x}get y(){return this.position.y}set x(t){this.position.x=t,this._pc()}set y(t){this.position.y=t,this._pc()}get width(){return this._w}set width(t){this._w=t,this._pc()}get height(){return this._h}set height(t){this._h=t,this._pc()}_uw(){if(!this._di)return;let{_wx:t=0,_wy:e=0,_wo:i=1,_wrot:s=0,_wsx:a=1,_wsy:n=1}=this.parent||{};this._wx=this.x,this._wy=this.y,this._ww=this.width,this._wh=this.height,this.radius&&(this._wrx=this.radius,this._wry=this.radius),this._wo=i*this.opacity,this._wsx=a*this.scaleX,this._wsy=n*this.scaleY,this._wx=this._wx*a,this._wy=this._wy*n,this._ww=this.width*this._wsx,this._wh=this.height*this._wsy,this.radius&&(this._wrx=this.radius*this._wsx,this._wry=this.radius*this._wsy),this._wrot=s+this.rotation;let{x:r,y:o}=rotatePoint({x:this._wx,y:this._wy},s);this._wx=r,this._wy=o,this._wx+=t,this._wy+=e}get world(){return{x:this._wx,y:this._wy,width:this._ww,height:this._wh,radius:this.radius?{x:this._wrx,y:this._wry}:void 0,opacity:this._wo,rotation:this._wrot,scaleX:this._wsx,scaleY:this._wsy}}set children(t){this.removeChild(this._c),this.addChild(t)}get children(){return this._c}addChild(...t){t.flat().map((t=>{this.children.push(t),t.parent=this,t._pc=t._pc||noop,t._pc()}))}removeChild(...t){t.flat().map((t=>{removeFromArray(this.children,t)&&(t.parent=null,t._pc())}))}get radius(){return this._r}set radius(t){this._r=t,this._pc()}get opacity(){return this._opa}set opacity(t){this._opa=clamp(0,1,t),this._pc()}get rotation(){return this._rot}set rotation(t){this._rot=t,this._pc()}advance(t){super.advance(t),this.drotation+=this.ddrotation,this.rotation+=this.drotation}setScale(t,e=t){this.scaleX=t,this.scaleY=e}get scaleX(){return this._scx}set scaleX(t){this._scx=t,this._pc()}get scaleY(){return this._scy}set scaleY(t){this._scy=t,this._pc()}}function factory$9(){return new GameObject(...arguments)}class Sprite extends GameObject{init({image:t,width:e=(t?t.width:void 0),height:i=(t?t.height:void 0),...s}={}){super.init({image:t,width:e,height:i,...s})}get animations(){return this._a}set animations(t){let e,i;for(e in this._a={},t)this._a[e]=t[e].clone(),i=i||this._a[e];this.currentAnimation=i,this.width=this.width||i.width,this.height=this.height||i.height}playAnimation(t){this.currentAnimation?.stop(),this.currentAnimation=this.animations[t],this.currentAnimation.start()}advance(t){super.advance(t),this.currentAnimation?.update(t)}draw(){if(this.image&&this.context.drawImage(this.image,0,0,this.image.width,this.image.height),this.currentAnimation&&this.currentAnimation.render({x:0,y:0,width:this.width,height:this.height,context:this.context}),this.color){if(this.context.fillStyle=this.color,this.radius)return this.context.beginPath(),this.context.arc(this.radius,this.radius,this.radius,0,2*Math.PI),void this.context.fill();this.context.fillRect(0,0,this.width,this.height)}}}function factory$8(){return new Sprite(...arguments)}let fontSizeRegex=/(\d+)(\w+)/;function parseFont(t){if(!t)return{computed:0};let e=t.match(fontSizeRegex),i=+e[1];return{size:i,unit:e[2],computed:i}}class Text extends GameObject{init({text:t="",textAlign:e="",lineHeight:i=1,font:s=getContext()?.font,...a}={}){t=""+t,super.init({text:t,textAlign:e,lineHeight:i,font:s,...a}),this.context&&this._p(),on("init",(()=>{this.font??=getContext().font,this._p()}))}get width(){return this._w}set width(t){this._d=!0,this._w=t,this._fw=t}get text(){return this._t}set text(t){this._d=!0,this._t=""+t}get font(){return this._f}set font(t){this._d=!0,this._f=t,this._fs=parseFont(t).computed}get lineHeight(){return this._lh}set lineHeight(t){this._d=!0,this._lh=t}render(){this._d&&this._p(),super.render()}_p(){this._s=[],this._d=!1;let t=this.context,e=[this.text];if(t.font=this.font,e=this.text.split("\n"),this._fw&&e.map((e=>{let i=e.split(" "),s=i.shift(),a=s;i.map((e=>{a+=" "+e,t.measureText(a).width>this._fw&&(this._s.push(s),a=e),s=a})),this._s.push(a)})),!this._s.length&&this.text.includes("\n")){let i=0;e.map((e=>{this._s.push(e),i=Math.max(i,t.measureText(e).width)})),this._w=this._fw||i}this._s.length||(this._s.push(this.text),this._w=this._fw||t.measureText(this.text).width),this.height=this._fs+(this._s.length-1)*this._fs*this.lineHeight,this._uw()}draw(){let t=0,e=this.textAlign,i=this.context;e=this.textAlign||("rtl"==i.canvas.dir?"right":"left"),t="right"==e?this.width:"center"==e?this.width/2|0:0,this._s.map(((s,a)=>{i.textBaseline="top",i.textAlign=e,i.fillStyle=this.color,i.font=this.font,this.strokeColor&&(i.strokeStyle=this.strokeColor,i.lineWidth=this.lineWidth??1,i.strokeText(s,t,this._fs*this.lineHeight*a)),i.fillText(s,t,this._fs*this.lineHeight*a)}))}}function factory$7(){return new Text(...arguments)}let pointers=new WeakMap,callbacks$1={},pressedButtons={},pointerMap={0:"left",1:"middle",2:"right"};function getPointer(t=getCanvas()){return pointers.get(t)}function getCurrentObject(t){let e=t._lf.length?t._lf:t._cf;for(let i=e.length-1;i>=0;i--){let s=e[i];if(s.collidesWithPointer?s.collidesWithPointer(t):circleRectCollision(t,s))return s}}function getPropValue(t,e){return parseFloat(t.getPropertyValue(e))||0}function getCanvasOffset(t){let{canvas:e,_s:i}=t,s=e.getBoundingClientRect(),a="none"!=i.transform?i.transform.replace("matrix(","").split(","):[1,1,1,1],n=parseFloat(a[0]),r=parseFloat(a[3]),o=(getPropValue(i,"border-left-width")+getPropValue(i,"border-right-width"))*n,h=(getPropValue(i,"border-top-width")+getPropValue(i,"border-bottom-width"))*r,d=(getPropValue(i,"padding-left")+getPropValue(i,"padding-right"))*n,l=(getPropValue(i,"padding-top")+getPropValue(i,"padding-bottom"))*r;return{scaleX:(s.width-o-d)/e.width,scaleY:(s.height-h-l)/e.height,offsetX:s.left+(getPropValue(i,"border-left-width")+getPropValue(i,"padding-left"))*n,offsetY:s.top+(getPropValue(i,"border-top-width")+getPropValue(i,"padding-top"))*r}}function pointerDownHandler(t){let e=null!=t.button?pointerMap[t.button]:"left";pressedButtons[e]=!0,pointerHandler(t,"onDown")}function pointerUpHandler(t){let e=null!=t.button?pointerMap[t.button]:"left";pressedButtons[e]=!1,pointerHandler(t,"onUp")}function mouseMoveHandler(t){pointerHandler(t,"onOver")}function blurEventHandler$2(t){pointers.get(t.target)._oo=null,pressedButtons={}}function callCallback(t,e,i){let s=getCurrentObject(t);s&&s[e]&&s[e](i),callbacks$1[e]&&callbacks$1[e](i,s),"onOver"==e&&(s!=t._oo&&t._oo&&t._oo.onOut&&t._oo.onOut(i),t._oo=s)}function pointerHandler(t,e){t.preventDefault();let i=t.target,s=pointers.get(i),{scaleX:a,scaleY:n,offsetX:r,offsetY:o}=getCanvasOffset(s);t.type.includes("touch")?(Array.from(t.touches).map((({clientX:t,clientY:e,identifier:i})=>{let h=s.touches[i];h||(h=s.touches[i]={start:{x:(t-r)/a,y:(e-o)/n}},s.touches.length++),h.changed=!1})),Array.from(t.changedTouches).map((({clientX:i,clientY:h,identifier:d})=>{let l=s.touches[d];l.changed=!0,l.x=s.x=(i-r)/a,l.y=s.y=(h-o)/n,callCallback(s,e,t),emit("touchChanged",t,s.touches),"onUp"==e&&(delete s.touches[d],s.touches.length--,s.touches.length||emit("touchEnd"))}))):(s.x=(t.clientX-r)/a,s.y=(t.clientY-o)/n,callCallback(s,e,t))}function initPointer({radius:t=5,canvas:e=getCanvas()}={}){let i=pointers.get(e);if(!i){let s=window.getComputedStyle(e);i={x:0,y:0,radius:t,touches:{length:0},canvas:e,_cf:[],_lf:[],_o:[],_oo:null,_s:s},pointers.set(e,i)}return e.addEventListener("mousedown",pointerDownHandler),e.addEventListener("touchstart",pointerDownHandler),e.addEventListener("mouseup",pointerUpHandler),e.addEventListener("touchend",pointerUpHandler),e.addEventListener("touchcancel",pointerUpHandler),e.addEventListener("blur",blurEventHandler$2),e.addEventListener("mousemove",mouseMoveHandler),e.addEventListener("touchmove",mouseMoveHandler),i._t||(i._t=!0,on("tick",(()=>{i._lf.length=0,i._cf.map((t=>{i._lf.push(t)})),i._cf.length=0}))),i}function track(...t){t.flat().map((t=>{let e=t.context?t.context.canvas:getCanvas(),i=pointers.get(e);if(!i)throw new ReferenceError("Pointer events not initialized for the objects canvas");t.__r||(t.__r=t.render,t.render=function(){i._cf.push(this),this.__r()},i._o.push(t))}))}function untrack(...t){t.flat().map((t=>{let e=t.context?t.context.canvas:getCanvas(),i=pointers.get(e);if(!i)throw new ReferenceError("Pointer events not initialized for the objects canvas");t.render=t.__r,t.__r=0,removeFromArray(i._o,t)}))}function pointerOver(t){let e=t.context?t.context.canvas:getCanvas(),i=pointers.get(e);if(!i)throw new ReferenceError("Pointer events not initialized for the objects canvas");return i._o.includes(t)&&getCurrentObject(i)===t}function onPointer(t,e){let i=t[0].toUpperCase()+t.substr(1);callbacks$1["on"+i]=e}function offPointer(t){let e=t[0].toUpperCase()+t.substr(1);callbacks$1["on"+e]=0}function pointerPressed(t){return!!pressedButtons[t]}class Button extends Sprite{init({padX:t=0,padY:e=0,text:i,disabled:s=!1,container:a,onDown:n,onUp:r,...o}={}){super.init({padX:t,padY:e,...o}),this.textNode=factory$7({...i,context:this.context}),this.width||(this.width=this.textNode.width,this.height=this.textNode.height),track(this),this.addChild(this.textNode),this._od=n||noop,this._ou=r||noop;let h=this._dn=document.createElement("button");h.style=srOnlyStyle,h.textContent=this.text,s&&this.disable(),h.addEventListener("focus",(()=>this.focus())),h.addEventListener("blur",(()=>this.blur())),h.addEventListener("keydown",(t=>this._kd(t))),h.addEventListener("keyup",(t=>this._ku(t))),addToDom(h,a??this.context.canvas),this._uw(),this._p()}get text(){return this.textNode.text}set text(t){this._d=!0,this.textNode.text=t}get node(){return this._dn}destroy(){this._dn.remove()}_p(){this.text!=this._dn.textContent&&(this._dn.textContent=this.text),this.textNode._p();let t=this.textNode.width+2*this.padX,e=this.textNode.height+2*this.padY;this.width=Math.max(t,this.width),this.height=Math.max(e,this.height),this._uw()}render(){this._d&&this._p(),super.render()}enable(){this.disabled=this._dn.disabled=!1,this.onEnable()}disable(){this.disabled=this._dn.disabled=!0,this.onDisable()}focus(){this.disabled||(this.focused=!0,document.activeElement!=this._dn&&this._dn.focus(focusParams),this.onFocus())}blur(){this.focused=!1,document.activeElement==this._dn&&this._dn.blur(),this.onBlur()}onOver(){this.disabled||(this.hovered=!0)}onOut(){this.hovered=!1}onEnable(){}onDisable(){}onFocus(){}onBlur(){}onDown(){this.disabled||(this.pressed=!0,this._od())}onUp(){this.disabled||(this.pressed=!1,this._ou())}_kd(t){"Enter"!=t.code&&"Space"!=t.code||this.onDown()}_ku(t){"Enter"!=t.code&&"Space"!=t.code||this.onUp()}}function factory$6(){return new Button(...arguments)}function clear(t){let e=t.canvas;t.clearRect(0,0,e.width,e.height)}function GameLoop({fps:t=60,clearCanvas:e=!0,update:i=noop,render:s,context:a=getContext(),blur:n=!1}={}){if(!s)throw Error("You must provide a render() function");let r,o,h,d,l,c=0,u=1e3/t,p=1/t,g=e?clear:noop,f=!0;function m(){if(o=requestAnimationFrame(m),f&&(h=performance.now(),d=h-r,r=h,!(d>1e3))){for(c+=d;c>=u;)emit("tick"),l.update(p),c-=u;g(l.context),l.render()}}return n||(window.addEventListener("focus",(()=>{f=!0})),window.addEventListener("blur",(()=>{f=!1}))),on("init",(()=>{l.context??=getContext()})),l={update:i,render:s,isStopped:!0,context:a,start(){this.isStopped&&(r=performance.now(),this.isStopped=!1,requestAnimationFrame(m))},stop(){this.isStopped=!0,cancelAnimationFrame(o)},_frame:m,set _last(t){r=t}},l}let gamepads=[],gamepaddownCallbacks={},gamepadupCallbacks={},gamepadMap={0:"south",1:"east",2:"west",3:"north",4:"leftshoulder",5:"rightshoulder",6:"lefttrigger",7:"righttrigger",8:"select",9:"start",10:"leftstick",11:"rightstick",12:"dpadup",13:"dpaddown",14:"dpadleft",15:"dpadright"};function gamepadConnectedHandler(t){gamepads[t.gamepad.index]={pressedButtons:{},axes:{}}}function gamepadDisconnectedHandler(t){delete gamepads[t.gamepad.index]}function blurEventHandler$1(){gamepads.map((t=>{t.pressedButtons={},t.axes={}}))}function updateGamepad(){let t=navigator.getGamepads?navigator.getGamepads():navigator.webkitGetGamepads?navigator.webkitGetGamepads:[];for(let e=0;e<t.length;e++){let i=t[e];if(!i)continue;i.buttons.map(((t,e)=>{let s=gamepadMap[e],{pressed:a}=t,{pressedButtons:n}=gamepads[i.index],r=n[s];!r&&a?[gamepaddownCallbacks[i.index],gamepaddownCallbacks].map((e=>{e?.[s]?.(i,t,s)})):r&&!a&&[gamepadupCallbacks[i.index],gamepadupCallbacks].map((e=>{e?.[s]?.(i,t,s)})),n[s]=a}));let{axes:s}=gamepads[i.index];s.leftstickx=i.axes[0],s.leftsticky=i.axes[1],s.rightstickx=i.axes[2],s.rightsticky=i.axes[3]}}function initGamepad(){window.addEventListener("gamepadconnected",gamepadConnectedHandler),window.addEventListener("gamepaddisconnected",gamepadDisconnectedHandler),window.addEventListener("blur",blurEventHandler$1),on("tick",updateGamepad)}function onGamepad(t,e,{gamepad:i,handler:s="gamepaddown"}={}){let a="gamepaddown"==s?gamepaddownCallbacks:gamepadupCallbacks;[].concat(t).map((t=>{isNaN(i)?a[t]=e:(a[i]=a[i]||{},a[i][t]=e)}))}function offGamepad(t,{gamepad:e,handler:i="gamepaddown"}={}){let s="gamepaddown"==i?gamepaddownCallbacks:gamepadupCallbacks;[].concat(t).map((t=>{isNaN(e)?delete s[t]:(s[e]=s[e]||{},delete s[e][t])}))}function gamepadPressed(t,{gamepad:e}={}){return isNaN(e)?gamepads.some((e=>e.pressedButtons[t])):!!gamepads[e]&&!!gamepads[e].pressedButtons[t]}function gamepadAxis(t,e){return gamepads[e]?.axes[t]||0}let currGesture,callbacks={},init=!1,gestureMap={swipe:{touches:1,threshold:10,touchend({0:t}){let e=t.x-t.start.x,i=t.y-t.start.y,s=Math.abs(e),a=Math.abs(i);if(!(s<this.threshold&&a<this.threshold))return s>a?e<0?"left":"right":i<0?"up":"down"}},pinch:{touches:2,threshold:2,touchstart({0:t,1:e}){this.prevDist=Math.hypot(t.x-e.x,t.y-e.y)},touchmove({0:t,1:e}){let i=Math.hypot(t.x-e.x,t.y-e.y);if(Math.abs(i-this.prevDist)<this.threshold)return;let s=i>this.prevDist?"out":"in";return this.prevDist=i,s}}};function initGesture(){init||(init=!0,on("touchChanged",((t,e)=>{Object.keys(gestureMap).map((i=>{let s,a=gestureMap[i];(!currGesture||currGesture==i)&&e.length==a.touches&&[...Array(e.length).keys()].every((t=>e[t]))&&(s=a[t.type]?.(e)??"")&&callbacks[i+s]&&(currGesture=i,callbacks[i+s](t,e))}))})),on("touchEnd",(()=>{currGesture=0})))}function onGesture(t,e){[].concat(t).map((t=>{callbacks[t]=e}))}function offGesture(t){[].concat(t).map((t=>{callbacks[t]=0}))}let handler={set:(t,e,i)=>(e.startsWith("_")||(t._d=!0),Reflect.set(t,e,i))},alignment={start:t=>t?1:0,center:()=>.5,end:t=>t?0:1};class Grid extends GameObject{init({flow:t="column",align:e="start",justify:i="start",colGap:s=0,rowGap:a=0,numCols:n=1,dir:r="",breakpoints:o=[],...h}={}){return super.init({flow:t,align:e,justify:i,colGap:s,rowGap:a,numCols:n,dir:r,breakpoints:o,...h}),this._p(),new Proxy(this,handler)}addChild(t){this._d=!0,super.addChild(t)}removeChild(t){this._d=!0,super.removeChild(t)}render(){this._d&&this._p(),super.render()}destroy(){this.children.map((t=>t.destroy&&t.destroy()))}_p(){this._d=!1,this.breakpoints.map((t=>{t.metric.call(this)&&this._b!==t&&(this._b=t,t.callback.call(this))}));let t=this._g=[],e=this._cw=[],i=this._rh=[],s=this.children,a=this._nc="column"==this.flow?1:"row"==this.flow?s.length:this.numCols,n=0,r=0;for(let o,h=0;o=s[h];h++){t[n]=t[n]||[],o._p&&o._p();let{width:s,height:h}=o.world||o;i[n]=Math.max(i[n]||0,h);let d=o.colSpan||1,l=d;do{e[r]=Math.max(e[r]||0,s/l),t[n][r]=o}while(r++<=a&&--d);r>=a&&(r=0,n++)}for(;r>0&&r<a;)t[n][r++]=!1;let o=t.length,h=[].concat(this.colGap),d=[].concat(this.rowGap);this._w=e.reduce(((t,e)=>t+e),0);for(let t=0;t<a-1;t++)this._w+=h[t%h.length];this._h=i.reduce(((t,e)=>t+e),0);for(let t=0;t<o-1;t++)this._h+=d[t%d.length];this._uw();let l="rtl"==this.context.canvas.dir&&!this.dir||"rtl"==this.dir;this._rtl=l,l&&(this._g=t.map((t=>t.reverse())),this._cw=e.reverse(),h=h.reverse());let c=-this.anchor.y*this.height,u=[],p=[].concat(this.justify),g=[].concat(this.align);this._g.map(((t,s)=>{let a=-this.anchor.x*this.width;t.map(((t,n)=>{if(t&&!u.includes(t)){u.push(t);let r=alignment[t.justifySelf||p[n%p.length]](this._rtl),o=alignment[t.alignSelf||g[s%g.length]](),d=t.colSpan||1,l=e[n];if(d>1&&n+d<=this._nc)for(let t=1;t<d;t++)l+=e[n+t]+h[(n+t)%h.length];let f=l*r,m=i[s]*o,_=0,y=0,{width:w,height:x}=t.world||t;if(t.anchor&&(_=t.anchor.x,y=t.anchor.y),0==r)f+=w*_;else if(.5==r){f+=(_<.5?-1:.5==_?0:1)*w*r}else f-=w*(1-_);if(0==o)m+=x*y;else if(.5==o){m+=(y<.5?-1:.5==y?0:1)*x*o}else m-=x*(1-y);t.x=a+f,t.y=c+m}a+=e[n]+h[n%h.length]})),c+=i[s]+d[s%d.length]}))}}function factory$5(){return new Grid(...arguments)}let seed,keydownCallbacks={},keyupCallbacks={},pressedKeys={},keyMap={Enter:"enter",Escape:"esc",Space:"space",ArrowLeft:"arrowleft",ArrowUp:"arrowup",ArrowRight:"arrowright",ArrowDown:"arrowdown"};function call(t=noop,e){t._pd&&e.preventDefault(),t(e)}function keydownEventHandler(t){let e=keyMap[t.code],i=keydownCallbacks[e];pressedKeys[e]=!0,call(i,t)}function keyupEventHandler(t){let e=keyMap[t.code],i=keyupCallbacks[e];pressedKeys[e]=!1,call(i,t)}function blurEventHandler(){pressedKeys={}}function initKeys(){let t;for(t=0;t<26;t++)keyMap["Key"+String.fromCharCode(t+65)]=String.fromCharCode(t+97);for(t=0;t<10;t++)keyMap["Digit"+t]=keyMap["Numpad"+t]=""+t;window.addEventListener("keydown",keydownEventHandler),window.addEventListener("keyup",keyupEventHandler),window.addEventListener("blur",blurEventHandler)}function onKey(t,e,{handler:i="keydown",preventDefault:s=!0}={}){let a="keydown"==i?keydownCallbacks:keyupCallbacks;e._pd=s,[].concat(t).map((t=>a[t]=e))}function offKey(t,{handler:e="keydown"}={}){let i="keydown"==e?keydownCallbacks:keyupCallbacks;[].concat(t).map((t=>delete i[t]))}function keyPressed(t){return!![].concat(t).some((t=>pressedKeys[t]))}function contains(t,e){return Object.values(e).includes(t)}function isGesture(t){return Object.keys(gestureMap).some((e=>t.startsWith(e)))}function initInput(t={}){initKeys();let e=initPointer(t.pointer);return initGesture(),initGamepad(),{pointer:e}}function onInput(t,e,{gamepad:i,key:s}={}){[].concat(t).map((t=>{if(contains(t,gamepadMap))onGamepad(t,e,i);else if(isGesture(t))onGesture(t,e);else if(contains(t,keyMap))onKey(t,e,s);else{if(!["down","up"].includes(t))throw new TypeError(`"${t}" is not a valid input name`);onPointer(t,e)}}))}function offInput(t,{gamepad:e,key:i}={}){[].concat(t).map((t=>{contains(t,gamepadMap)?offGamepad(t,e):isGesture(t)?offGesture(t):contains(t,keyMap)?offKey(t,i):["down","up"].includes(t)&&offPointer(t)}))}function getMethod(t){let e=t.substr(t.search(/[A-Z]/));return e[0].toLowerCase()+e.substr(1)}function registerPlugin(t,e){let i=t.prototype;i&&(i._inc||(i._inc={},i._bInc=function(t,e,...i){return this._inc[e].before.reduce(((e,i)=>{let s=i(t,...e);return s||e}),i)},i._aInc=function(t,e,i,...s){return this._inc[e].after.reduce(((e,i)=>{let a=i(t,e,...s);return a||e}),i)}),Object.getOwnPropertyNames(e).map((t=>{let s=getMethod(t);i[s]&&(i["_o"+s]||(i["_o"+s]=i[s],i[s]=function(...t){let e=this._bInc(this,s,...t),a=i["_o"+s].call(this,...e);return this._aInc(this,s,a,...t)}),i._inc[s]||(i._inc[s]={before:[],after:[]}),t.startsWith("before")?i._inc[s].before.push(e[t]):t.startsWith("after")&&i._inc[s].after.push(e[t]))})))}function unregisterPlugin(t,e){let i=t.prototype;i&&i._inc&&Object.getOwnPropertyNames(e).map((t=>{let s=getMethod(t);t.startsWith("before")?removeFromArray(i._inc[s].before,e[t]):t.startsWith("after")&&removeFromArray(i._inc[s].after,e[t])}))}function extendObject(t,e){let i=t.prototype;i&&Object.getOwnPropertyNames(e).map((t=>{i[t]||(i[t]=e[t])}))}class Pool{constructor({create:t,maxSize:e=1024}={}){let i;if(!t||!(i=t())||!(i.update&&i.init&&i.isAlive&&i.render))throw Error("Must provide create() function which returns an object with init(), update(), render(), and isAlive() functions");this._c=t,this.objects=[t()],this.size=0,this.maxSize=e}get(t={}){if(this.size==this.objects.length){if(this.size==this.maxSize)return;for(let t=0;t<this.size&&this.objects.length<this.maxSize;t++)this.objects.push(this._c())}let e=this.objects[this.size];return this.size++,e.init(t),e}getAliveObjects(){return this.objects.slice(0,this.size)}clear(){this.size=this.objects.length=0,this.objects.push(this._c())}update(t){let e,i=!1;for(let s=this.size;s--;)e=this.objects[s],e.update(t),e.isAlive()||(i=!0,this.size--);i&&this.objects.sort(((t,e)=>e.isAlive()-t.isAlive()))}render(){for(let t=this.size;t--;)this.objects[t].render()}}function factory$4(){return new Pool(...arguments)}function getIndices(t,e){let i=[],s=e.x+e.width/2,a=e.y+e.height/2,n=t.y<a,r=t.y+t.height>=a;return t.x<s&&(n&&i.push(0),r&&i.push(2)),t.x+t.width>=s&&(n&&i.push(1),r&&i.push(3)),i}class Quadtree{constructor({maxDepth:t=3,maxObjects:e=25,bounds:i}={}){this.maxDepth=t,this.maxObjects=e;let s=getCanvas();this.bounds=i||{x:0,y:0,width:s.width,height:s.height},this._b=!1,this._d=0,this._o=[],this._s=[],this._p=null}clear(){this._s.map((t=>{t.clear()})),this._b=!1,this._o.length=0}get(t){let e=new Set;for(;this._s.length&&this._b;)return getIndices(t,this.bounds).map((i=>{this._s[i].get(t).map((t=>e.add(t)))})),Array.from(e);return this._o.filter((e=>e!==t))}add(...t){t.flat().map((t=>{this._b?this._a(t):(this._o.push(t),this._o.length>this.maxObjects&&this._d<this.maxDepth&&(this._sp(),this._o.map((t=>this._a(t))),this._o.length=0))}))}_a(t){getIndices(t,this.bounds).map((e=>{this._s[e].add(t)}))}_sp(t,e,i){if(this._b=!0,!this._s.length)for(t=this.bounds.width/2|0,e=this.bounds.height/2|0,i=0;i<4;i++)this._s[i]=new Quadtree({bounds:{x:this.bounds.x+(i%2==1?t:0),y:this.bounds.y+(i>=2?e:0),width:t,height:e},maxDepth:this.maxDepth,maxObjects:this.maxObjects}),this._s[i]._d=this._d+1}}function factory$3(){return new Quadtree(...arguments)}function rand(){seed??=Date.now(),seed|=0,seed=seed+2654435769|0;let t=seed^seed>>>16;return t=Math.imul(t,569420461),t^=t>>>15,t=Math.imul(t,1935289751),((t^=t>>>15)>>>0)/4294967296}function randInt(t,e,i=rand){return(i()*(e-t+1)|0)+t}function getSeed(){return seed}function seedRand(t=Date.now()){if(seed=t,"string"==typeof t){for(var e=0,i=1779033703^t.length;e<t.length;e++)i=(i=Math.imul(i^t.charCodeAt(e),3432918353))<<13|i>>>19;i=Math.imul(i^i>>>16,2246822507),i=Math.imul(i^i>>>13,3266489909),seed=(i^=i>>>16)>>>0}}function getAllNodes(t){let e=[];return t._dn?e.push(t._dn):t.children&&t.children.map((t=>{e=e.concat(getAllNodes(t))})),e}class Scene{constructor({id:t,name:e=t,objects:i=[],context:s=getContext(),cullObjects:a=!0,cullFunction:n=collides,sortFunction:r,...o}){this._o=[],Object.assign(this,{id:t,name:e,context:s,cullObjects:a,cullFunction:n,sortFunction:r,...o});let h=this._dn=document.createElement("section");h.tabIndex=-1,h.style=srOnlyStyle,h.id=t,h.setAttribute("aria-label",e);let d=this;this.camera=new class extends GameObject{set x(t){d.sx=t-this.centerX,super.x=t}get x(){return super.x}set y(t){d.sy=t-this.centerY,super.y=t}get y(){return super.y}}({context:s,anchor:{x:.5,y:.5},render:this._rf.bind(this)}),this.add(i),this._i=()=>{this.context??=getContext();let t=this.context.canvas,{width:e,height:i}=t,s=e/2,a=i/2;Object.assign(this.camera,{centerX:s,centerY:a,x:s,y:a,width:e,height:i}),h.isConnected||addToDom(h,t)},this.context&&this._i(),on("init",this._i)}set objects(t){this.remove(this._o),this.add(t)}get objects(){return this._o}get node(){return this._dn}add(...t){t.flat().map((t=>{this._o.push(t),t.parent=this,this._dn.append(...getAllNodes(t))}))}remove(...t){t.flat().map((t=>{removeFromArray(this._o,t),t.parent=null,getAllNodes(t).map((t=>{addToDom(t,this.context.canvas)}))}))}show(){this.hidden=this._dn.hidden=!1;let t=this._o.find((t=>t.focus));t?t.focus(focusParams):this._dn.focus(focusParams),this.onShow()}hide(){this.hidden=this._dn.hidden=!0,this.onHide()}destroy(){off("init",this._i),this._dn.remove(),this._o.map((t=>t.destroy&&t.destroy()))}lookAt(t){let{x:e,y:i}=t.world||t;this.camera.x=e,this.camera.y=i}update(t){this.hidden||this._o.map((e=>e.update&&e.update(t)))}_rf(){let{_o:t,context:e,_sx:i,_sy:s,camera:a,sortFunction:n,cullObjects:r,cullFunction:o}=this;e.translate(i,s);let h=t;r&&(h=h.filter((t=>o(a,t)))),n&&h.sort(n),h.map((t=>t.render&&t.render()))}render(){if(!this.hidden){let{context:t,camera:e}=this,{x:i,y:s,centerX:a,centerY:n}=e;t.save(),this._sx=a-i,this._sy=n-s,t.translate(this._sx,this._sy),e.render(),t.restore()}}onShow(){}onHide(){}}function factory$2(){return new Scene(...arguments)}function parseFrames(t){if(+t==t)return t;let e=[],i=t.split(".."),s=+i[0],a=+i[1],n=s;if(s<a)for(;n<=a;n++)e.push(n);else for(;n>=a;n--)e.push(n);return e}class SpriteSheet{constructor({image:t,frameWidth:e,frameHeight:i,spacing:s=0,margin:a=0,animations:n}={}){if(!t)throw Error("You must provide an Image for the SpriteSheet");this.animations={},this.image=t,this.frame={width:e,height:i,spacing:s,margin:a},this._f=(t.width-a)/e|0,this.createAnimations(n)}createAnimations(t){let e,i;for(i in t){let{frames:s,frameRate:a,loop:n}=t[i];if(e=[],null==s)throw Error("Animation "+i+" must provide a frames property");[].concat(s).map((t=>{e=e.concat(parseFrames(t))})),this.animations[i]=factory$b({spriteSheet:this,frames:e,frameRate:a,loop:n,name:i})}}}function factory$1(){return new SpriteSheet(...arguments)}let FLIPPED_HORIZONTALLY=2147483648,FLIPPED_VERTICALLY=1073741824,FLIPPED_DIAGONALLY=536870912;function getRow(t,e){return t/e|0}function getCol(t,e){return t/e|0}class TileEngine{constructor(t={}){let{width:e,height:i,tilewidth:s,tileheight:a,tilesets:n}=t,r=e*s,o=i*a,h=document.createElement("canvas");h.width=r,h.height=o,this._c=h,this._ctx=h.getContext("2d"),n.map((e=>{let{__k:i,location:s}=window,a=(i?i.dm.get(t):"")||s.href,{source:n}=e;if(n){if(!i)throw Error('You must use "load" or "loadData" to resolve tileset.source');let t=i.d[i.u(n,a)];if(!t)throw Error(`You must load the tileset source "${n}" before loading the tileset`);Object.keys(t).map((i=>{e[i]=t[i]}))}let{image:r}=e;if(""+r===r){if(!i)throw Error('You must use "load" or "loadImage" to resolve tileset.image');let t=i.i[i.u(r,a)];if(!t)throw Error(`You must load the image "${r}" before loading the tileset`);e.image=t}})),Object.assign(this,{context:getContext(),layerMap:{},layerCanvases:{},mapwidth:r,mapheight:o,_sx:0,_sy:0,_o:[],...t}),this.context&&this._p(),on("init",(()=>{this.context??=getContext(),this._p()}))}get sx(){return this._sx}get sy(){return this._sy}set sx(t){let e=Math.max(0,this.mapwidth-getCanvas().width);this._sx=clamp(0,e,t)}set sy(t){let e=Math.max(0,this.mapheight-getCanvas().height);this._sy=clamp(0,e,t)}set objects(t){this.remove(this._o),this.add(t)}get objects(){return this._o}add(...t){t.flat().map((t=>{this._o.push(t),t.parent=this}))}remove(...t){t.flat().map((t=>{removeFromArray(this._o,t),t.parent=null}))}getPosition(t){let e=getCanvas().getBoundingClientRect(),i=t.x-e.x,s=t.y-e.y;return i+=this.sx,s+=this.sy,{x:i,y:s,row:getRow(s,this.tileheight),col:getCol(i,this.tilewidth)}}setTileAtLayer(t,e,i){let{layerMap:s,tileheight:a,tilewidth:n,width:r}=this,{row:o,col:h,x:d,y:l}=e,c=o??getRow(l,a),u=h??getCol(d,n);s[t]&&(this._d=!0,s[t]._d=!0,s[t].data[c*r+u]=i)}setLayer(t,e){let{layerMap:i}=this;i[t]&&(this._d=!0,i[t]._d=!0,i[t].data=e)}layerCollidesWith(t,e){let{tilewidth:i,tileheight:s,layerMap:a}=this,{x:n,y:r,width:o,height:h}=getWorldRect(e),d=getRow(r,s),l=getCol(n,i),c=getRow(r+h,s),u=getCol(n+o,i),p=a[t];for(let t=d;t<=c;t++)for(let e=l;e<=u;e++)if(p.data[e+t*this.width])return!0;return!1}tileAtLayer(t,e){let{layerMap:i,tileheight:s,tilewidth:a,width:n}=this,{row:r,col:o,x:h,y:d}=e,l=r??getRow(d,s),c=o??getCol(h,a);return i[t]?i[t].data[l*n+c]:-1}render(t=this._c,e=!0){let{_d:i,context:s,sx:a=0,sy:n=0}=this;i&&this._p();let{width:r,height:o}=getCanvas(),h=Math.min(t.width,r),d=Math.min(t.height,o);s.drawImage(t,a,n,h,d,0,0,h,d),e&&(s.save(),(a||n)&&s.translate(-a,-n),this.objects.map((t=>t.render&&t.render())),s.restore())}renderLayer(t){let{layerCanvases:e,layerMap:i}=this,s=i[t],a=e[t],n=a?.getContext("2d");if(!a){let{mapwidth:i,mapheight:r}=this;a=document.createElement("canvas"),n=a.getContext("2d"),a.width=i,a.height=r,e[t]=a,this._rl(s,n)}s._d&&(s._d=!1,n.clearRect(0,0,a.width,a.height),this._rl(s,n)),this.render(a,!1)}_p(){let{_ctx:t,layers:e=[],layerMap:i}=this;this._d=!1,e.map((e=>{let{name:s,data:a,visible:n}=e;e._d=!1,i[s]=e,a&&0!=n&&this._rl(e,t)}))}_rl(t,e){let{opacity:i,data:s=[]}=t,{tilesets:a,width:n,tilewidth:r,tileheight:o}=this;e.save(),e.globalAlpha=i,s.map(((t,i)=>{if(!t)return;let s,h=0,d=0,l=t&FLIPPED_HORIZONTALLY,c=t&FLIPPED_VERTICALLY,u=0,p=0,g=0,f=0,m=0;h=l||c,m=(t&=~(FLIPPED_HORIZONTALLY|FLIPPED_VERTICALLY))&FLIPPED_DIAGONALLY,m&&(l&&c?g=1:l?u=1:c?p=1:f=1,d=u||p||g||f,t&=~FLIPPED_DIAGONALLY);for(let e=a.length-1;e>=0&&(s=a[e],!(t/s.firstgid>=1));e--);let{image:_,spacing:y=0,margin:w=0,firstgid:x,columns:b}=s,v=t-x,P=b??_.width/(r+y)|0,C=i%n*r,k=(i/n|0)*o,A=w+v%P*(r+y),S=w+(v/P|0)*(o+y);d?(e.save(),e.translate(C+r/2,k+o/2),p||f?e.rotate(-Math.PI/2):(u||g)&&e.rotate(Math.PI/2),(g||f)&&e.scale(-1,1),C=-r/2,k=-o/2):h&&(e.save(),e.translate(C+(l?r:0),k+(c?o:0)),e.scale(l?-1:1,c?-1:1),C=h?0:C,k=h?0:k),e.drawImage(_,A,S,r,o,C,k,r,o),(h||d)&&e.restore()})),e.restore()}}function factory(){return new TileEngine(...arguments)}let kontra={Animation:factory$b,AnimationClass:Animation,imageAssets:imageAssets,audioAssets:audioAssets,dataAssets:dataAssets,setImagePath:setImagePath,setAudioPath:setAudioPath,setDataPath:setDataPath,loadImage:loadImage,loadAudio:loadAudio,loadData:loadData,load:load,Button:factory$6,ButtonClass:Button,init:init$1,getCanvas:getCanvas,getContext:getContext,on:on,off:off,emit:emit,GameLoop:GameLoop,GameObject:factory$9,GameObjectClass:GameObject,gamepadMap:gamepadMap,updateGamepad:updateGamepad,initGamepad:initGamepad,onGamepad:onGamepad,offGamepad:offGamepad,gamepadPressed:gamepadPressed,gamepadAxis:gamepadAxis,gestureMap:gestureMap,initGesture:initGesture,onGesture:onGesture,offGesture:offGesture,Grid:factory$5,GridClass:Grid,degToRad:degToRad,radToDeg:radToDeg,angleToTarget:angleToTarget,rotatePoint:rotatePoint,movePoint:movePoint,lerp:lerp,inverseLerp:inverseLerp,clamp:clamp,setStoreItem:setStoreItem,getStoreItem:getStoreItem,collides:collides,getWorldRect:getWorldRect,depthSort:depthSort,initInput:initInput,onInput:onInput,offInput:offInput,keyMap:keyMap,initKeys:initKeys,onKey:onKey,offKey:offKey,keyPressed:keyPressed,registerPlugin:registerPlugin,unregisterPlugin:unregisterPlugin,extendObject:extendObject,initPointer:initPointer,getPointer:getPointer,track:track,untrack:untrack,pointerOver:pointerOver,onPointer:onPointer,offPointer:offPointer,pointerPressed:pointerPressed,Pool:factory$4,PoolClass:Pool,Quadtree:factory$3,QuadtreeClass:Quadtree,rand:rand,randInt:randInt,getSeed:getSeed,seedRand:seedRand,Scene:factory$2,SceneClass:Scene,Sprite:factory$8,SpriteClass:Sprite,SpriteSheet:factory$1,SpriteSheetClass:SpriteSheet,Text:factory$7,TextClass:Text,TileEngine:factory,TileEngineClass:TileEngine,Vector:factory$a,VectorClass:Vector};export{factory$b as Animation,Animation as AnimationClass,factory$6 as Button,Button as ButtonClass,GameLoop,factory$9 as GameObject,GameObject as GameObjectClass,factory$5 as Grid,Grid as GridClass,factory$4 as Pool,Pool as PoolClass,factory$3 as Quadtree,Quadtree as QuadtreeClass,factory$2 as Scene,Scene as SceneClass,factory$8 as Sprite,Sprite as SpriteClass,factory$1 as SpriteSheet,SpriteSheet as SpriteSheetClass,factory$7 as Text,Text as TextClass,factory as TileEngine,TileEngine as TileEngineClass,factory$a as Vector,Vector as VectorClass,angleToTarget,audioAssets,clamp,collides,dataAssets,kontra as default,degToRad,depthSort,emit,extendObject,gamepadAxis,gamepadMap,gamepadPressed,gestureMap,getCanvas,getContext,getPointer,getSeed,getStoreItem,getWorldRect,imageAssets,init$1 as init,initGamepad,initGesture,initInput,initKeys,initPointer,inverseLerp,keyMap,keyPressed,lerp,load,loadAudio,loadData,loadImage,movePoint,off,offGamepad,offGesture,offInput,offKey,offPointer,on,onGamepad,onGesture,onInput,onKey,onPointer,pointerOver,pointerPressed,radToDeg,rand,randInt,registerPlugin,rotatePoint,seedRand,setAudioPath,setDataPath,setImagePath,setStoreItem,track,unregisterPlugin,untrack,updateGamepad};