UNPKG

rul2d

Version:

Rul2d is a powerful and flexible TypeScript library for creating games using HTML5 Canvas.

1 lines 73.6 kB
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).rul2d={})}(this,(function(t){"use strict";function __awaiter(t,e,i,s){return new(i||(i=Promise))((function(n,a){function fulfilled(t){try{step(s.next(t))}catch(t){a(t)}}function rejected(t){try{step(s.throw(t))}catch(t){a(t)}}function step(t){t.done?n(t.value):function adopt(t){return t instanceof i?t:new i((function(e){e(t)}))}(t.value).then(fulfilled,rejected)}step((s=s.apply(t,e||[])).next())}))}function __values(t){var e="function"==typeof Symbol&&Symbol.iterator,i=e&&t[e],s=0;if(i)return i.call(t);if(t&&"number"==typeof t.length)return{next:function(){return t&&s>=t.length&&(t=void 0),{value:t&&t[s++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function __asyncValues(t){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var e,i=t[Symbol.asyncIterator];return i?i.call(t):(t=__values(t),e={},verb("next"),verb("throw"),verb("return"),e[Symbol.asyncIterator]=function(){return this},e);function verb(i){e[i]=t[i]&&function(e){return new Promise((function(s,n){(function settle(t,e,i,s){Promise.resolve(s).then((function(e){t({value:e,done:i})}),e)})(s,n,(e=t[i](e)).done,e.value)}))}}}var e;"function"==typeof SuppressedError&&SuppressedError,function(t){t[t.None=0]="None",t[t.Info=1]="Info",t[t.Error=2]="Error",t[t.Warn=3]="Warn",t[t.Debug=4]="Debug",t[t.EngineError=5]="EngineError",t[t.EngineWarn=6]="EngineWarn",t[t.EngineLog=7]="EngineLog",t[t.EngineSpam=8]="EngineSpam",t[t.Full=9]="Full"}(e||(e={}));var i,s=e;class Logging{static message(t,e,...i){Logging.debugLevel>=e&&(t(...i),Logging.isShowTrace&&console.trace(t.name))}static error(...t){Logging.message(console.error,s.Error,...t)}static warn(...t){Logging.message(console.warn,s.Warn,...t)}static debug(...t){Logging.message(console.log,s.Debug,...t)}static info(...t){Logging.message(console.info,s.Info,...t)}static engineError(...t){Logging.message(console.error,s.EngineError,...t)}static engineWarn(...t){Logging.message(console.warn,s.EngineWarn,...t)}static engineLog(...t){Logging.message(console.log,s.EngineLog,...t)}static engineSpam(...t){Logging.message(console.log,s.EngineSpam,...t)}}Logging.debugLevel=s.None,Logging.isShowTrace=!1;class AssetsManager{constructor(){return this._cachedImages=new Map,this._cachedJSON=new Map,this._cachedTexts=new Map,this._cachedAudios=new Map,this._cachedBinaries=new Map,AssetsManager.instance}clear(t,e){return"image"==t?this._cachedImages.delete(e):"json"==t?this._cachedJSON.delete(e):this._cachedTexts.delete(e)}clearDict(t){return"image"==t?this._cachedImages.clear():"json"==t?this._cachedJSON.clear():this._cachedTexts.clear()}clearAll(){[this._cachedImages,this._cachedJSON,this._cachedTexts].forEach((t=>{t.clear()}))}_loadFile(t,e,i){return __awaiter(this,void 0,void 0,(function*(){if(e.has(t))return Logging.engineLog(`used cache value: ${t}`),e.get(t);let s,n=!1;try{if(s=yield fetch(t),Logging.engineLog(`loaded: ${t}`),!s.ok)throw new Error(`(${s.status} ${s.statusText}) Can't load file "${t}"`)}catch(t){Logging.error(t),n=!0}let a=yield i(s,n);return n||e.set(t,a),a}))}loadTextFile(t){return __awaiter(this,void 0,void 0,(function*(){return yield this._loadFile(t,this._cachedTexts,((t,e)=>__awaiter(this,void 0,void 0,(function*(){return e?"":yield t.text()}))))}))}loadBinarytFile(t){return __awaiter(this,void 0,void 0,(function*(){return yield this._loadFile(t,this._cachedBinaries,((t,e)=>__awaiter(this,void 0,void 0,(function*(){return e?new ArrayBuffer:yield t.arrayBuffer()}))))}))}loadJSONFile(t){return __awaiter(this,void 0,void 0,(function*(){return yield this._loadFile(t,this._cachedJSON,((t,e)=>__awaiter(this,void 0,void 0,(function*(){return e?{}:yield t.json()}))))}))}loadImageFile(t){return __awaiter(this,void 0,void 0,(function*(){return yield this._loadFile(t,this._cachedImages,((t,e)=>__awaiter(this,void 0,void 0,(function*(){const i=new Image;if(e)return i;let s=yield t.blob();const n=URL.createObjectURL(s);return i.src=n,i}))))}))}loadAudioFile(t,e){return __awaiter(this,void 0,void 0,(function*(){return yield this._loadFile(t,this._cachedAudios,((t,i)=>__awaiter(this,void 0,void 0,(function*(){if(i)return new AudioBuffer({length:0,numberOfChannels:0,sampleRate:0});const s=yield t.arrayBuffer();return yield e.decodeAudioData(s)}))))}))}}AssetsManager.instance=new AssetsManager;class CustomObject{constructor(){this._id=CustomObject.createdObjectsCount++}loadJSONFromFile(t){return __awaiter(this,void 0,void 0,(function*(){let e=new AssetsManager;try{let i=yield e.loadJSONFile(t);yield this._loadJSONFromFile(i)}catch(t){Logging.engineError("Cant load json from file",t,this)}}))}_loadJSONFromFile(t){return __awaiter(this,void 0,void 0,(function*(){}))}get id(){return this._id}log(){Logging.debug(this)}simplify(){return{}}toString(){let t=`${this.constructor.name} {`,e=Object.entries(this.simplify());return e.forEach((([i,s],n)=>{t+=`${i}: ${s.toString()}`,n+1<e.length&&(t+=", ")})),t+="}",t}toJSONString(){return JSON.stringify(this.simplify())}valueOf(){return NaN}}CustomObject.createdObjectsCount=0;class MathUtils{static lerp(t,e,i){return t+(e-t)*i}static floor(t,e=0){return MathUtils.updateWithAfterDotNumber(t,e,Math.floor)}static ceil(t,e=0){return MathUtils.updateWithAfterDotNumber(t,e,Math.ceil)}static round(t,e=0){return MathUtils.updateWithAfterDotNumber(t,e,Math.round)}static updateWithAfterDotNumber(t,e,i){if(!e)return i(t);let s=Math.pow(10,e);return i(t*s)/s}static percents(t,{min:e,max:i}={min:0,max:100}){return(t-e)/(i-e)}static getArrayValueByCondition(t,e,i=t=>+t){if(0==t.length)return null;if(1==t.length)return t[0];let s=t[0],n=i(s);for(const a of t){let t=i(a);e(t,n)&&(s=a,n=t)}return s}static min(t,e=t=>+t){return MathUtils.getArrayValueByCondition(t,((t,e)=>t<e),e)}static max(t,e=t=>+t){return MathUtils.getArrayValueByCondition(t,((t,e)=>t>e),e)}}class Angle extends CustomObject{static degToRad(t){return t/180*Angle.Pi}static radToDeg(t){return t/Angle.Pi*180}static from(t){return this.fromRadians(t)}static fromRadians(t){let e=new Angle;return e.radians=t,e}static fromDegrees(t){let e=new Angle;return e.degrees=t,e}constructor(){super(),this._radians=0}set radians(t){this._radians=t%Angle.Pi2,this._radians<0&&(this._radians+=Angle.Pi2)}get radians(){return this._radians}set degrees(t){this.radians=Angle.degToRad(t)}get degrees(){return Angle.radToDeg(this.radians)}simplify(){return{radians:this.radians}}setAngle(t){this.radians=+t}addAngle(t){this.setAngle(Angle.from(t.radians+this.radians))}valueOf(){return this.radians}toString(){return`${MathUtils.round(this.degrees,2)}°`}}Angle.Pi=Math.PI,Angle.Pi2=2*Angle.Pi,Angle.Rad_1=Angle.degToRad(1);class CachedValue extends CustomObject{constructor(t){super(),this._cachedValue=t,this._isNeedUpdate=!0,this._updateCallback=()=>this._cachedValue}needUpdate(t=!0){this._isNeedUpdate=null!=t?t:this._isNeedUpdate}setUpdateCallback(t=this._updateCallback){this._updateCallback=t}get(t){return this._isNeedUpdate&&(this._isNeedUpdate=!1,this._cachedValue=this.update(t)),this._cachedValue}update(t){return this._updateCallback(t)}simplify(){return{value:this._cachedValue,isNeedUpdate:this._isNeedUpdate}}}class Bounds extends CustomObject{constructor(t,e){super(),this.min=0,this.max=0,this.set(t,e)}set(t,e){this.min=t,this.max=e}get(t){return t<this.min?this.min:t>this.max?this.max:t}simplify(){return{min:this.min,max:this.max}}}class Random{static number(t,e=0){return MathUtils.floor(Math.random()*t+1,e)}static range(t,e,i=0){return MathUtils.floor(Math.random()*(e-t+1),i)+t}static chance(t,e){return Random.range(0,e)<t}static array(t,{min:e,max:i}={min:0,max:100},s=0){let n=new Array(t);for(let t=0;t<n.length;t++)n[t]=Random.range(e,i,s);return n}}class Color extends CustomObject{constructor(){super(),this._r=0,this._g=0,this._b=0,this._a=1}setRGBA(t,e,i,s=255){return 0==s&&(t=0,e=0,i=0,s=0),this._r=Color.componentBounds.get(t),this._g=Color.componentBounds.get(e),this._b=Color.componentBounds.get(i),this._a=Color.componentBounds.get(s)/255,this}toString(){return`rgba(${this._r}, ${this._g}, ${this._b}, ${this._a})`}simplify(){return{r:this._r,g:this._g,b:this._b,a:255*this._a}}static interpolate(t,e,i){const{r:s,g:n,b:a,a:r}=t.simplify(),{r:o,g:h,b:l,a:c}=e.simplify();return Color.from(MathUtils.lerp(s,o,i),MathUtils.lerp(n,h,i),MathUtils.lerp(a,l,i),MathUtils.lerp(r,c,i))}static from(t,e,i,s=255){return(new Color).setRGBA(t,e,i,s)}static fromSimple({r:t,g:e,b:i,a:s}){return Color.from(t,e,i,s)}static random(t=255){return Color.from(Random.number(255),Random.number(255),Random.number(255),Color.componentBounds.get(t)||Random.number(255))}static get Transparent(){return Color.from(0,0,0,0)}static get Black(){return new Color}static get White(){return Color.from(255,255,255,255)}static get Red(){return Color.from(255,0,0,255)}static get Blue(){return Color.from(0,0,255,255)}static get Green(){return Color.from(0,255,0,255)}}Color.componentBounds=new Bounds(0,255);class SimpleRect extends CustomObject{constructor(t,e,i,s){super(),this.x=null!=t?t:0,this.y=null!=e?e:this.x,this.width=i||1,this.height=s||this.width}simplify(){return{x:this.x,y:this.y,width:this.width,height:this.height}}}!function(t){t[t.Fill=0]="Fill",t[t.Stroke=1]="Stroke",t[t.All=2]="All"}(i||(i={}));var n,a=i;class EventEmitter extends CustomObject{constructor(){super(),this._events=new Map}on(t,e,{isOnce:i}={}){this._events.has(t)||this._events.set(t,new Set);let s=e;i&&(s=i=>{e(i),this.off(t,s)});let n=this._events.get(t);n.has(s)||n.add(s)}once(t,e){this.on(t,e,{isOnce:!0})}off(t,e){let i=this._events.get(t);return!!i&&i.delete(e)}emit(t,e){let i=this._events.get(t);i&&i.forEach((t=>{t(e)}))}}class DrawableObject extends CustomObject{constructor(){super(),this.eventEmitter=new EventEmitter,this.root=null,this.managers=new Set,this.isVisible=!0,this.isInViewport=!0,this._isInitialized=!1,this._lineWidth=1,this._color=Color.Black,this.outlineColor=Color.Red,this._currentRootId=0,this._opacity=1,this._zIndex=this.id,this._offset={x:0,y:0},this._drawMode=a.Fill}setDrawMode(t){this._drawMode=t}get canBeSubObject(){return!0}get zIndex(){let t=0;return this.root&&(t=this.root.zIndex),this._zIndex+t}set zIndex(t){this._zIndex=t;for(const t of this.managers)t.updateZIndex();Logging.engineLog("updated z-index",this)}get inheritOpacity(){let{root:t}=this;return t?this._opacity*t.inheritOpacity:this._opacity}setVisibility(t){this.isVisible=t,Logging.engineLog(`update visibility: ${t}`,this)}toggleVisibility(){return this.setVisibility(!this.isVisible),this.isVisible}setColor(t){this._color=t,Logging.engineLog(`update color: ${t}`,this)}setOffset(t,e){this._offset.x=t,this._offset.y=e,Logging.engineLog(`update offset: (${t} ${e})`,this)}set offset({x:t,y:e}){this.setOffset(t,e)}get offset(){return this._offset}set color(t){this.setColor(t)}get color(){return this._color}set opacity(t){this._opacity=DrawableObject.normalizedBounds.get(t),Logging.engineLog(`update opacity: (${this._opacity})`,this)}get opacity(){return this._opacity}set lineWidth(t){this._lineWidth=DrawableObject.positiveNumberBounds.get(t),Logging.engineLog(`update opacity: (${this._lineWidth})`,this)}get lineWidth(){return this._lineWidth}simplify(){return{color:this._color.simplify(),lineWidth:this._lineWidth,opacity:this._opacity,zIndex:this.zIndex}}updateColor(t){t.fillStyle=this.color.toString(),t.strokeStyle=this.outlineColor.toString(),Logging.engineSpam(`update color for context: (${t.fillStyle})`,this)}updateContextParameters(t){this.updateColor(t),t.lineWidth=this._lineWidth,t.globalAlpha=this.inheritOpacity,Logging.engineSpam("update context parameters",this)}_init(t){}init(t){this._isInitialized||(this._isInitialized=!0,this._init(t),Logging.engineSpam("initialized",this))}isNeedDraw(){return this.isInViewport&&this.isVisible}update(t){Logging.engineSpam(`updated(${t})`,this)}_fill(t){}_stroke(t){}_drawDefault(t){this.executeCallbackByDrawMode((()=>this._fill(t)),(()=>this._stroke(t)))}_draw(t){this._drawDefault(t)}executeCallbackByDrawMode(t,e){switch(this._drawMode){case a.Fill:t();break;case a.Stroke:e();break;case a.All:t(),e()}}draw(t){this.isNeedDraw()&&(t.save(),this.updateContextParameters(t),this._draw(t),t.restore(),Logging.engineSpam("drawed",this))}}DrawableObject.positiveNumberBounds=new Bounds(Number.EPSILON,Number.MAX_SAFE_INTEGER),DrawableObject.normalizedBounds=new Bounds(0,1);class Point extends DrawableObject{static get NaN(){return new Point(NaN)}static fromSimplePoint({x:t,y:e}){return new Point(t,e)}constructor(t,e){super(),this._x=0,this._y=0,this.setPosition(t,e)}get factRect(){let t=Point.drawRadius/2;return new SimpleRect(this._x-t,this._y-t,2*Point.drawRadius)}set x(t){this.setPosition(t,this._y)}get x(){return this._x}set y(t){this.setPosition(this._x,t)}get y(){return this._y}set point({x:t,y:e}){this.setPosition(t,e)}get point(){return new Point(this._x,this._y)}updatePositionByOffset({x:t,y:e}){this.setPosition(t+this.offset.x,e+this.offset.y),Logging.engineSpam("new position by offset",this.point,this,this.offset)}setPosition(t,e){this._x=null!=t?t:0,this._y=null!=e?e:this._x,this.eventEmitter.emit("update-position")}addPosition(t,e){this.setPosition(this._x+t,this._y+e)}move({x:t,y:e},i){this.addPosition(t*i,e*i)}simplify(){return Object.assign(Object.assign({},super.simplify()),{x:this._x,y:this._y})}drawPoint(t){this._fill(t)}drawOutline(t){this._stroke(t)}_drawArc(t,e){t.beginPath(),this.updateColor(t),t.arc(this._x,this._y,e,0,Angle.Pi2),t.closePath()}_fill(t){this._drawArc(t,Point.drawRadius),t.fill(),this._drawArc(t,2),t.fill(),this._drawArc(t,1),t.fill()}_stroke(t){this._drawArc(t,Point.drawRadius),t.stroke()}isObjectInViewport(t){const{viewport:e}=t;return e.isPointInShape(this)}}Point.drawRadius=3;class PointerPoint extends Point{constructor(t,e,i=0){super(t,e),this.pointerId=i}}class Size extends CustomObject{constructor(t=0,e=0){super(),this.width=0,this.height=0,this.setSize(t,e)}setSize(t,e){this.width=t||1,this.height=e||this.width}set center({x:t,y:e}){Logging.engineWarn("you cant set center for Size")}get center(){return new Point(this.width/2,this.height/2)}set size({width:t,height:e}){this.setSize(t,e)}get size(){return new Size(this.width,this.height)}simplify(){return{width:this.width,height:this.height}}}class Timer extends CustomObject{constructor(){super(),this.paused=!1}simplify(){return{paused:this.paused}}}class PeriodicTimer extends Timer{constructor(t=0,e=()=>{}){super(),this._currentTime=0,this._callback=e,this.targetTime=t}start(){this.paused=!1}reset(){this._currentTime=0}stop(){this.paused=!0}setCallback(t){this._callback=t}get currentTime(){return this._currentTime}update(t){this.paused||(this._currentTime+=t,this._currentTime>=this.targetTime&&(this._callback(),this.reset()))}simplify(){return Object.assign(Object.assign({},super.simplify()),{targetTime:this.targetTime,currentTime:this.currentTime})}}class VectorUtils{static getAngle({x:t,y:e},{x:i,y:s}){return Angle.from(Math.atan2(s-e,i-t))}static getPerpendicular({x:t,y:e}){return{x:-e,y:t}}static getDoubleDistance({x:t,y:e},{x:i,y:s}){return Math.pow(t-i,2)+Math.pow(e-s,2)}static getDistance(t,e){return Math.sqrt(this.getDoubleDistance(t,e))}static isInDistance(t,e,i){return VectorUtils.getDoubleDistance(t,e)<i*i}static magnitude(t){return this.getDistance(t,{x:0,y:0})}static cross(t,e){return t.x*e.y-t.y*e.x}static dot(t,e){return t.x*e.x+t.y*e.y}static normalize(t){let{x:e,y:i}=t,s=VectorUtils.magnitude(t);return s?{x:e/s,y:i/s}:{x:0,y:0}}static createPointByCallback(t,e,i){return{x:i(t.x,e.x),y:i(t.y,e.y)}}static plus(t,e){return this.createPointByCallback(t,e,((t,e)=>t+e))}static minus(t,e){return this.createPointByCallback(t,e,((t,e)=>t-e))}static multiply(t,e){return this.createPointByCallback(t,e,((t,e)=>t*e))}static div(t,e){return this.createPointByCallback(t,e,((t,e)=>t/e))}static negative({x:t,y:e}){return{x:-t,y:-e}}static multiplyOnNumber({x:t,y:e},i){return{x:t*i,y:e*i}}}class SAT{static projectPolygon(t,e){const i=e.getCorners();let s=1/0,n=-1/0;for(const e of i){const i=VectorUtils.dot(e,t);s=Math.min(s,i),n=Math.max(n,i)}return{min:s,max:n}}static projectionsOverlap(t,e){return t.max>=e.min&&e.max>=t.min}static checkIntersections(t,e){const i=[t,e];for(const s of i){const i=s.getCorners();for(let s=0;s<i.length;s++){const n=i[s],a=i[(s+1)%i.length],r=VectorUtils.minus(a,n),o=VectorUtils.normalize(VectorUtils.getPerpendicular(r));if(0==o.x&&o.y==o.x)continue;const h=SAT.projectPolygon(o,t),l=SAT.projectPolygon(o,e);if(!this.projectionsOverlap(h,l))return!1}}return!0}}class Search{static binary(t,e,i=t=>+t){let s=0,n=t.length-1;for(;s<=n;){let a=Math.floor((s+n)/2),r=i(t[a]);if(r==e)return a;r<e?s=a+1:n=a-1}return-1}static findInsertPosition(t,e,i=t=>+t){let s=0,n=t.length;for(;s<n;){let a=Math.floor((s+n)/2);i(t[a])<=i(e)?s=a+1:n=a}return s}static linear(t,e,i=t=>+t){for(let s=0;s<t.length;s++)if(i(t[s])===e)return s;return-1}}class Sorting{static addToArray(t,e,i=t=>+t){if(!t.length)return t.push(e),0;let s=Search.findInsertPosition(t,e,i);return t.splice(s,0,e),Logging.engineLog(s,e),s}static merge(t,e=t=>+t){if(t.length<=1)return t;const i=Math.floor(t.length/2),s=t.slice(0,i),n=t.slice(i),a=Sorting.merge(s,e),r=Sorting.merge(n,e),o=[];let h=0,l=0;for(;h<a.length&&l<r.length;)e(a[h])<=e(r[l])?(o.push(a[h]),h++):(o.push(r[l]),l++);for(;h<a.length;)o.push(a[h]),h++;for(;l<r.length;)o.push(r[l]),l++;return o}static quick(t,e=t=>+t){if(t.length<=1)return t;const i=e(t[Math.floor(t.length/2)]),s=[],n=[],a=[];for(const r of t){const t=e(r);t<i?s.push(r):t>i?n.push(r):a.push(r)}return[...Sorting.quick(s,e),...a,...Sorting.quick(n,e)]}}class HotKey extends CustomObject{constructor(t,e={}){super(),this.key=t,this.options=e}simplify(){return{key:this.key,options:this.options}}}!function(t){t.Any="Any",t.All="All",t.A="KeyA",t.B="KeyB",t.C="KeyC",t.D="KeyD",t.E="KeyE",t.F="KeyF",t.G="KeyG",t.H="KeyH",t.I="KeyI",t.J="KeyJ",t.K="KeyK",t.L="KeyL",t.M="KeyM",t.N="KeyN",t.O="KeyO",t.P="KeyP",t.Q="KeyQ",t.R="KeyR",t.S="KeyS",t.T="KeyT",t.U="KeyU",t.V="KeyV",t.W="KeyW",t.X="KeyX",t.Y="KeyY",t.Z="KeyZ",t.D0="Digit0",t.D1="Digit1",t.D2="Digit2",t.D3="Digit3",t.D4="Digit4",t.D5="Digit5",t.D6="Digit6",t.D7="Digit7",t.D8="Digit8",t.D9="Digit9",t.Num0="Numpad0",t.Num1="Numpad1",t.Num2="Numpad2",t.Num3="Numpad3",t.Num4="Numpad4",t.Num5="Numpad5",t.Num6="Numpad6",t.Num7="Numpad7",t.Num8="Numpad8",t.Num9="Numpad9",t.F1="F1",t.F2="F2",t.F3="F3",t.F4="F4",t.F5="F5",t.F6="F6",t.F7="F7",t.F8="F8",t.F9="F9",t.F10="F10",t.F11="F11",t.F12="F12",t.ArrowUp="ArrowUp",t.ArrowDown="ArrowDown",t.ArrowLeft="ArrowLeft",t.ArrowRight="ArrowRight",t.Enter="Enter",t.Space="Space",t.Esc="Escape",t.Tab="Tab",t.BackSpace="Backspace",t.Delete="Delete",t.ShiftLeft="ShiftLeft",t.ShiftRight="ShiftRight",t.CtrlLeft="ControlLeft",t.CtrlRight="ControlRight",t.AltLeft="AltLeft",t.AltRight="AltRight",t.MetaLeft="MetaLeft",t.MetaRight="MetaRight",t.CapsLock="CapsLock",t.NumLock="NumLock",t.Comma="Comma",t.Period="Period",t.Slash="Slash",t.BackSlash="Backslash",t.Semicolon="Semicolon",t.Quote="Quote",t.BracketLeft="BracketLeft",t.BracketRight="BracketRight",t.Minus="Minus",t.Equal="Equal"}(n||(n={}));const r=[n.AltLeft,n.AltRight,n.ShiftLeft,n.ShiftRight,n.CtrlLeft,n.CtrlRight,n.MetaLeft,n.MetaRight];var o=n;class StorageEvent extends Event{}class SpriteAnimation extends CustomObject{constructor(){super(),this._keyframes=[],this._totalDuration=0}get totalDuration(){return this._totalDuration}deleteKeyFrames(){this._keyframes=[],this._totalDuration=0}add(...t){t.forEach((t=>{this._totalDuration+=t.duration,t.currentTime=this._totalDuration,this._keyframes.push(t)}))}remove(...t){t.forEach((t=>{let e=this._keyframes.indexOf(t);if(-1==e)return Logging.engineWarn(this,"didnt remove",t);this._keyframes.splice(e,1),this._totalDuration-=t.duration})),this.updateFramesCurrentTime()}updateFramesCurrentTime(){this._totalDuration=0,this._keyframes.forEach((t=>{this._totalDuration+=t.duration,t.currentTime=this._totalDuration}))}getFrameByTime(t){if(!this._keyframes.length)return Logging.engineWarn(this,"no keyframes"),null;let e=0,i=this._keyframes[0];for(const s of this._keyframes){if(t<=e)return i;e=s.currentTime,i=s}return this._keyframes[this._keyframes.length-1]}simplify(){return{keyframes:this._keyframes.map((t=>t.simplify())),totalDuration:this._totalDuration}}}class SpriteKeyFrame extends CustomObject{constructor(t,e,i){super(),this.x=t,this.y=e,this.duration=i,this.currentTime=-1}static createFrames(t,e,i,s){let n=[];const a=SpriteKeyFrame.createGenerator(s);let r=t.x,o=i;for(let i=t.y;i<=e.y;i++){i==e.y&&(o=e.x);for(let t=r;t<=o;t++)n.push(a(t,i));r=0}return n}static createGenerator(t){return(e,i)=>new SpriteKeyFrame(e,i,t)}simplify(){return{x:this.x,y:this.y,duration:this.duration}}}class Shape extends Point{static rotatePoints(t,e,i){if(0==+e)return t;const s=+e,n=Math.cos(s),a=Math.sin(s);return t.map((t=>{const e=VectorUtils.minus(t,i),s=new Point(e.x*n-e.y*a,e.x*a+e.y*n);return Point.fromSimplePoint(VectorUtils.plus(s,i))}))}constructor(t,e,i,s){super(t,e),this._isCachedValueExist=!1,this._size=new Size,this._cachedPath=new CachedValue(new Path2D),this._cachedPath.setUpdateCallback((()=>this._updatePath())),this._cachedBoundingBox=new CachedValue({x:0,y:0,width:0,height:0}),this._cachedBoundingBox.setUpdateCallback((()=>this._updateBox())),this._cachedCorners=new CachedValue([]),this._cachedCorners.setUpdateCallback((()=>this._updateCorners())),this._angle=new Angle,this._isCachedValueExist=!0,this._flipDirection=new Point(1),this.setSize(i,s)}get bottom(){let{y:t,height:e}=this.getBox();return t+e}get right(){let{x:t,width:e}=this.getBox();return t+e}flip(t,e){this.flipHorisontally(t),this.flipVertically(e)}flipHorisontally(t){this._flipDirection.x=t?1:-1}flipVertically(t){this._flipDirection.y=t?1:-1}_updateCorners(){return[new Point(this.x,this.y)]}getCorners(){return this._cachedCorners.get()}_updateBox(){let t=new Point(1/0),e=new Point(-1/0);for(const{x:i,y:s}of this.getCorners())i>e.x&&(e.x=i),s>e.y&&(e.y=s),i<t.x&&(t.x=i),s<t.y&&(t.y=s);return new SimpleRect(t.x,t.y,e.x-t.x,e.y-t.y)}getBox(){return this._cachedBoundingBox.get()}_updatePath(){let t=new Path2D,e=this.getCorners();if(!e.length)return Logging.engineWarn("no corners",this),t;let[i,...s]=e;t.moveTo(i.x,i.y);for(const{x:e,y:i}of s)t.lineTo(e,i);return t.lineTo(i.x,i.y),t}getPath(){return this._cachedPath.get()}set size(t){this._size.size=t}get size(){let{width:t,height:e}=this._size;return new Size(t,e)}set center({x:t,y:e}){let{x:i,y:s}=this._size.center;this.setPosition(t-i,e-s)}get center(){let{x:t,y:e}=this._size.center;return new Point(this.x+t,this.y+e)}needUpdate(t=!0){this._isCachedValueExist&&(this._cachedBoundingBox.needUpdate(t),this._cachedCorners.needUpdate(t),this._cachedPath.needUpdate(t))}isObjectInViewport(t){let{viewport:e}=t,i=e.getBox();return this.isBoxesIntersects(i)}setPosition(t,e){super.setPosition(t,e),this.needUpdate()}setSize(t,e){this._size.setSize(t,e),this.needUpdate()}setAngle(t){this._angle.setAngle(t),this.needUpdate()}addAngle(t){this._angle.addAngle(t),this.needUpdate()}set angle(t){this.setAngle(t)}get angle(){return this._angle}get factRect(){return this.getBox()}simplify(){return Object.assign(Object.assign({},super.simplify()),{size:this._size.simplify(),angle:this._angle.simplify()})}_stroke(t){t.stroke(this.getPath())}_fill(t){t.fill(this.getPath())}clip(t,e){t.save(),t.clip(this.getPath()),e(this.getPath()),t.restore()}isShapesIntersects(t){if(!this.isBoxesIntersects(t.getBox()))return!1;for(const e of t.getCorners())if(this.isPointInShape(e))return!0;return SAT.checkIntersections(this,t)}isPointInBoundingBox(t){let e=this.getBox();return t.x>=e.x&&t.x<=e.x+e.width&&t.y>=e.y&&t.y<=e.y+e.height}isBoxesIntersects(t){let e=this.getBox();return e.x<=t.x+t.width&&e.x+e.width>=t.x&&e.y<=t.y+t.height&&e.y+e.height>=t.y}isPointInShape(t){if(!this.isPointInBoundingBox(t))return!1;let e=this.getCorners();if(0==e.length)return!1;if(1==e.length)return this.x==t.x&&this.y==t.y;const{x:i,y:s}=t;let n=!1;for(let t=0,a=e.length-1;t<e.length;a=t++){const{x:r,y:o}=e[t],{x:h,y:l}=e[a];o>s!=l>s&&i<(h-r)*(s-o)/(l-o)+r&&(n=!n)}return n}drawTransformed(t,e){const{width:i,height:s}=this.size,{x:n,y:a}=this.center;t.save(),t.translate(n,a),t.rotate(+this.angle),t.scale(this._flipDirection.x,this._flipDirection.y),e(-i/2,-s/2,i,s),t.restore()}}Shape.cosBounds=new Bounds(-1,1);class Rectangle extends Shape{constructor(t,e,i,s){super(t,e),this.setSize(i,s)}get bottom(){return this.y+this.size.height}get right(){return this.x+this.size.width}set rect({x:t,y:e,width:i,height:s}){this.setPosition(t,e),this.setSize(i,s)}get rect(){return Rectangle.from(this,this.size)}set rotatedRectangle(t){this.rect=t,this.angle.radians=t.radians}get rotatedRectangle(){let t=this.rect;return t.setAngle(this.angle),t}_updateCorners(){let{width:t,height:e}=this.size,{x:i,y:s,center:n}=this;return Shape.rotatePoints([new Point(i,s),new Point(i+t,s),new Point(i+t,s+e),new Point(i,s+e)],this.angle,n)}static from(t,e){let i=new Rectangle;return i.point=t,i.size=e,i}static fromSimpleRectangle(t){let e=new Rectangle;return e.rect=t,e}static fromPoints(t,e){const i=Math.min(t.x,e.x),s=Math.max(t.x,e.x),n=Math.min(t.y,e.y),a=Math.max(t.y,e.y);return new Rectangle(i,n,s-i,a-n)}}class ShapeableObject extends DrawableObject{constructor(t,e,i,s){super(),this._shape=new Rectangle,this.setPosition(t,e),this.setSize(i,s)}get bottom(){return this.shape.bottom}get right(){return this.shape.right}set point(t){this.shape.point=t}get point(){return this.shape.point}set x(t){this.shape.x=t}get x(){return this.shape.x}set y(t){this.shape.y=t}get y(){return this.shape.y}updatePositionByOffset(t){this.shape.updatePositionByOffset(t)}addPosition(t,e){this.shape.addPosition(t,e)}move(t,e){this.shape.move(t,e)}setPosition(t,e){this.shape.setPosition(t,e)}set center(t){this.shape.center=t}get center(){return this.shape.center}set size(t){this.shape.size=t}get size(){return this.shape.size}setSize(t,e){this.shape.setSize(t,e)}isPointInShape(t){return this.shape.isPointInShape(t)}setShape(t){this._shape=t}setAngle(t){this.shape.setAngle(t)}addAngle(t){this.setAngle(Angle.fromRadians(+this.shape.angle+ +t))}set shape(t){this.setShape(t)}get shape(){return this._shape}get factRect(){return this.shape.factRect}setOffset(t,e){this.shape.setOffset(t,e)}set offset({x:t,y:e}){this.setOffset(t,e)}get offset(){return this.shape.offset}_fill(t){this.shape.draw(t)}_stroke(t){this.shape.drawOutline(t)}_draw(t){this.shape.clip(t,(()=>{this._drawDefault(t)}))}update(t){this.shape.update(t)}isObjectInViewport(t){return this.shape.isObjectInViewport(t)}}class DefaultTextRendering{strokeDrawText(t,e){t.strokeText(...e)}fillDrawText(t,e){t.fillText(...e)}updateText(t,e,i){return i}}class DynamicText extends ShapeableObject{static _transformColorFromSimpleColor(t,e){t[e]&&(t[e]instanceof Color||(t[e]=Color.fromSimple(t[e])))}static getTextHeight(t,e){let{fontBoundingBoxAscent:i,fontBoundingBoxDescent:s}=t.measureText(e);return i+s}constructor(t,e,i,s){super(t,e,i,s),this._text="",this._customRenderingText=new DefaultTextRendering,this._fittedText=new CachedValue([]),this._maxSymbols=-1,this.replaceableSymbols=new Map,this._font={family:"Arial",size:30,kerning:"auto",variant:"normal",color:Color.Green,outlineColor:Color.Green,letterSpacing:0,stretch:"normal",tabSize:1,horisontalAlign:"left",verticalAlign:"top"},this._updateTabSize(),this._fittedText.setUpdateCallback((t=>this._updateFittedText(t)))}_loadJSONFromFile(t){return __awaiter(this,arguments,void 0,(function*({text:t,font:e}){t&&("src"==t.type?this.text=yield AssetsManager.instance.loadTextFile(t.value):this.text=t.value),e&&(DynamicText._transformColorFromSimpleColor(e,"color"),DynamicText._transformColorFromSimpleColor(e,"outlineColor"),this.font=e)}))}setAlign(t,e){this._font.horisontalAlign=t,this._font.verticalAlign=e}_updateTabSize(){this.replaceableSymbols.set("\t"," ".repeat(this._font.tabSize))}_drawText(t,e=new Point){this._updateFont(t);let i=this._fittedText.get(t),s=0;const n=i.map((e=>DynamicText.getTextHeight(t,e)));"top"!=this._font.verticalAlign&&(s=i.reduce(((t,e,i)=>t+n[i]),0));let{width:a,height:r}=this._getTextOffsetByAlign(s),o=e.y+r;i.forEach(((i,s)=>{let r=[i,e.x+a,o];this.executeCallbackByDrawMode((()=>{this._customRenderingText.fillDrawText(t,r)}),(()=>{this._customRenderingText.strokeDrawText(t,r)})),o+=n[s]}))}setCustomTextRendering(t){this._customRenderingText=t}_updateFittedText(t){let e=[""];if(!t)return e;let i=0,s=0,{width:n,height:a}=this.shape.size,r=this._text;for(const o of r){let h=e.length-1,{width:l}=t.measureText(e[h]+o),c=DynamicText.getTextHeight(t,r);if(l<=n&&"\n"!=o)e[h]+=o;else{if(i+c>a){r=r.substring(0,s);break}i+=c,"\n"==o?e.push(""):e.push(o),s++}}return this._customRenderingText.updateText(t,{x:0,y:0},e)}_needUpdateText(t=!0){this._fittedText&&this._fittedText.needUpdate(t)}setSize(t,e){super.setSize(t,e),this._needUpdateText()}set font(t){const e=Object.fromEntries(Object.entries(t).filter((([t,e])=>void 0!==e)));this._font=Object.assign(Object.assign({},this._font),e),t.tabSize&&this._updateTabSize()}set text(t){let e=t.split("");for(let i=0;i<t.length;i++){const s=t[i];this.replaceableSymbols.forEach(((t,n)=>{s==n&&e.splice(i,1,t)}))}this._text=e.join(""),-1!=this._maxSymbols&&(this._text=this._text.substring(0,this._maxSymbols)),this._needUpdateText()}get text(){return this._text}_updateFont(t){t.textAlign=this._font.horisontalAlign,t.textBaseline="top",t.fillStyle=this._font.color.toString(),t.strokeStyle=this._font.outlineColor.toString(),t.letterSpacing=`${this._font.letterSpacing}px`,t.font=`${this._font.size}px ${this._font.family}`,t.fontStretch=this._font.stretch,t.fontKerning=this._font.kerning,t.fontVariantCaps=this._font.variant}_getTextOffsetByAlign(t){let e=new Size;switch(this._font.horisontalAlign){case"center":e.width=this.size.width/2;break;case"right":e.width=this.size.width}let i=Math.max(this.size.height-t,0);switch(this._font.verticalAlign){case"middle":e.height=i/2;break;case"bottom":e.height=i}return e}_fill(t){this.shape.drawTransformed(t,((e,i)=>{this._drawText(t,{x:e,y:i})}))}}class CanvasManager extends CustomObject{static createImageURLFromTempCanvas({size:t,quality:e=.9,mimeImageType:i="image/jpeg",callback:s=t=>{}}){CanvasManager.tempCanvasManager?CanvasManager.tempCanvasManager.resize(t):CanvasManager.tempCanvasManager=CanvasManager.createTempCanvasManager(document.body,t),CanvasManager.tempCanvasManager.clear();const n=CanvasManager.tempCanvasManager.canvas,a=CanvasManager.tempCanvasManager.getContext();let r="";return a?(s(a),r=n.toDataURL(i,e)):(Logging.engineWarn("no temp canvas's context"),r=""),r}static createTempCanvasManager(t,e){const i=new CanvasManager,s=i.create({root:t,size:e});return i.getContext(),s.style.position="fixed",s.style.top="-9999%",i}constructor(){super(),this._canvas=null,this._ctx=null,this._isContextNeedUpdate=!0}get canvas(){return this._canvas}get ctx(){return this._ctx}get isCanvasExist(){return Boolean(this._canvas)}setCanvas(t){this._canvas=t,this._isContextNeedUpdate=!0}getContext(){return this.isCanvasExist?(this._ctx&&!this._isContextNeedUpdate||(this._ctx=this._canvas.getContext("2d"),this._isContextNeedUpdate=!1),this._ctx):null}resize({width:t,height:e}){this.isCanvasExist&&(this._canvas.width!=t&&(this._canvas.width=t),this._canvas.height!=e&&(this._canvas.height=e))}resizeToClientRect(){this.isCanvasExist&&this.resize(this._canvas.getBoundingClientRect())}create({root:t=document.body,size:e=null}={}){let i=document.createElement("canvas");return t.appendChild(i),this.setCanvas(i),e?this.resize(e):this.addStandardResizeHandler(),i}clear({x:t,y:e}={x:0,y:0}){if(!this.isCanvasExist)return;const{width:i,height:s}=this.canvas;this.ctx.clearRect(t,e,i,s)}addStandardResizeHandler(){this.resizeToClientRect(),addEventListener("resize",(t=>this.resizeToClientRect()))}simplify(){return{isContextNeedUpdate:this._isContextNeedUpdate}}}CanvasManager.tempCanvasManager=null;class FormattedTextRendering{_drawText(t,e){return"stroke"==e?t.strokeText:t.fillText}static _drawFormattedText(t,e,i,s,n){const a=this._parseText(e),r=new SimpleRect(i,s,1);for(const{type:e,value:i}of a){(0,FormattedTextRendering._parsedSymbols[e])(t,i,r,n)}}static _parseText(t){let e=[],i=t.split("#$");for(const t of i){if(t.length<1)continue;const i=t[0],s=t.substring(1);if(FormattedTextRendering._parsedSymbols[i]){if(s.length<1)continue;e.push({type:i,value:s})}else e.push({type:"#",value:t})}return e}strokeDrawText(t,[e,i,s]){FormattedTextRendering._drawFormattedText(t,e,i,s,"stroke")}fillDrawText(t,[e,i,s]){FormattedTextRendering._drawFormattedText(t,e,i,s,"fill")}updateText(t,e,i){return i}}FormattedTextRendering._parsedSymbols={"*":(t,e,i,s)=>{const{width:n}=t.measureText(e);t.font=t.font+" bold",t[`${s}Text`](e,i.x,i.y)},"/":(t,e,i,s)=>{const{width:n}=t.measureText(e);t.font=t.font+" italic",t[`${s}Text`](e,i.x,i.y)},_:(t,e,i,s)=>{const{width:n}=t.measureText(e)},"#":(t,e,i,s)=>{const{width:n}=t.measureText(e);t[`${s}Text`](e,i.x,i.y),i.x+=n}};class Circle extends Shape{constructor(t,e,i){super(t,e),this._radius=1,this.setRadius(i)}_updateCorners(){let t=[],{x:e,y:i}=this.center;for(let s=0;s<=Angle.Pi2;s+=Angle.Rad_1){let n=Math.sin(s),a=Math.cos(s),r=new Point(e+this.radius*a,i+this.radius*n);t.push(r)}return t}_updateBox(){return new SimpleRect(this.x,this.y,2*this.radius)}_updatePath(){let{x:t,y:e}=this.center,i=new Path2D;return i.arc(t,e,this.radius,0,Angle.Pi2),i}isPointInShape(t){return VectorUtils.isInDistance(this,t,this.radius)}setRadius(t){this._radius=DrawableObject.positiveNumberBounds.get(null!=t?t:1),super.setSize(2*this._radius),this.needUpdate()}set radius(t){this.setRadius(t)}get radius(){return this._radius}setSize(t,e){let i=t||1,s=e||i;this.setRadius(Math.min(i,s)/2)}simplify(){return Object.assign(Object.assign({},super.simplify()),{radius:this.radius})}}class DrawablePath extends Shape{constructor(t,e){super(t,e),this._relativePoints=[]}get relativePoints(){return Array.from(this._relativePoints)}clearPoints(){this._relativePoints=[],this.needUpdate()}addPoints(...t){this._relativePoints.push(...t),this.needUpdate()}removePoints(...t){this._relativePoints.length&&(t.forEach((t=>{let e=this._relativePoints.indexOf(t);-1!=e&&this._relativePoints.splice(e,1)})),this.needUpdate())}_loadJSONFromFile(t){return __awaiter(this,void 0,void 0,(function*(){this.clearPoints(),t.forEach((t=>{this.addPoints(Point.fromSimplePoint(t))}))}))}_updateCorners(){const t=this._relativePoints.map((({x:t,y:e})=>new Point(t+this.x,e+this.y)));return Shape.rotatePoints(t,this.angle,this.center)}_draw(t){this._relativePoints.length>2?super._draw(t):this.drawOutline(t)}}class RoundedRectangle extends Shape{static createArc(t,e,i,s,n=8){let a=[];const r=(+s-+i)/n;for(let s=1;s<=n;s++){const n=+i+s*r,o=t.x+e*Math.cos(n),h=t.y+e*Math.sin(n);a.push(new Point(o,h))}return a}constructor(t,e,i,s){super(t,e,i,s),this._rawRadii={leftTop:0,leftBottom:0,rightTop:0,rightBottom:0},this._boxRectangle=new Rectangle,this._arcSegmentsCount=8,this._radii=new CachedValue(this._rawRadii),this._radii.setUpdateCallback((()=>this._normalizeRadii()))}set arcSegmentsCount(t){this._arcSegmentsCount=Math.floor(DrawableObject.positiveNumberBounds.get(t)),this._radii.needUpdate(),this.needUpdate()}get arcSegmentsCount(){return this._arcSegmentsCount}setRadii(t,e,i,s){this._rawRadii={leftTop:t,leftBottom:e,rightTop:i,rightBottom:s},this._radii.needUpdate()}setSize(t,e){super.setSize(t,e),this._radii&&this._radii.needUpdate()}get maxRadius(){const{x:t,y:e}=this.size.center;return Math.min(t,e)}_normalizeRadii(){return this._rawRadii={leftTop:Math.min(this._rawRadii.leftTop,this.maxRadius),leftBottom:Math.min(this._rawRadii.leftBottom,this.maxRadius),rightTop:Math.min(this._rawRadii.rightTop,this.maxRadius),rightBottom:Math.min(this._rawRadii.rightBottom,this.maxRadius)}}_updateBox(){return this._boxRectangle.point=this,this._boxRectangle.size=this.size,this._boxRectangle.angle=this.angle,this._boxRectangle.getBox()}_updateCorners(){let t=[],{width:e,height:i}=this.size;const{leftTop:s,leftBottom:n,rightTop:a,rightBottom:r}=this._radii.get();return t.push(new Point(this.x+s,this.y),new Point(this.x+e-a,this.y)),a>0&&t.push(...RoundedRectangle.createArc(new Point(this.x+e-a,this.y+a),a,Angle.fromDegrees(270),Angle.fromDegrees(359.99),this._arcSegmentsCount)),t.push(new Point(this.x+e,this.y+i-r)),r>0&&t.push(...RoundedRectangle.createArc(new Point(this.x+e-r,this.y+i-r),r,Angle.fromDegrees(0),Angle.fromDegrees(90),this._arcSegmentsCount)),t.push(new Point(this.x+n,this.y+i)),n>0&&t.push(...RoundedRectangle.createArc(new Point(this.x+n,this.y+i-n),n,Angle.fromDegrees(90),Angle.fromDegrees(180),this._arcSegmentsCount)),t.push(new Point(this.x,this.y+s)),s>0&&t.push(...RoundedRectangle.createArc(new Point(this.x+s,this.y+ +s),s,Angle.fromDegrees(180),Angle.fromDegrees(270),this._arcSegmentsCount)),RoundedRectangle.rotatePoints(t,this.angle,this.center)}}class PointerableObject extends ShapeableObject{_nonDownCallbackFactory(t){return e=>{this._isPressed&&!this.isPressedInFrame&&(this._isPressed=!1,this._upCallback(e)),t(e)}}constructor(t,e,i,s){super(t,e,i,s),this.isPressedInFrame=!1,this._isPressed=!1,this._downCallback=t=>{},this._upCallback=t=>{},this._hoverCallback=t=>{},this._pressedCallback=t=>{},this._nonInteractiveCallback=t=>{},this.doWhenPressed((t=>{})),this.doWhenHover((t=>{})),this.doWhenNotInteracted((t=>{}))}get isPressed(){return this._isPressed}get hoverCallback(){return this._hoverCallback}get pressedCallback(){return this._pressedCallback}get nonInteractiveCallback(){return this._nonInteractiveCallback}doWhenDown(t){this._downCallback=t}doWhenUp(t){this._upCallback=t}doWhenPressed(t){this._pressedCallback=e=>{!this._isPressed&&this.isPressedInFrame&&(this._isPressed=!0,this._downCallback(e)),t(e)}}doWhenHover(t){this._hoverCallback=this._nonDownCallbackFactory(t)}doWhenNotInteracted(t){this._nonInteractiveCallback=this._nonDownCallbackFactory(t)}}class KeyboardManager extends EventEmitter{static stringify(t,e={}){for(const e of r)if(t==e)return e;let i="";const{ctrlKey:s,shiftKey:n,metaKey:a,altKey:o,ignoreModifiers:h}=e;return h?i+="Any-":(s&&(i+="Ctrl-"),n&&(i+="Shift-"),a&&(i+="Meta-"),o&&(i+="Alt-")),i+=t,Logging.engineSpam(`stringified key is ${i}`),i}static from(t){return KeyboardManager.stringify(t.code,t)}constructor(){super(),this._events.set(o.All,new Set)}hasStringifiedKey(t,e){let i=KeyboardManager.stringify(t,e);return[i,this._events.has(i)]}addKey({key:t,options:e},i){this.on(KeyboardManager.stringify(t,e),i)}addKeys(t,e,i={}){t.forEach((t=>this.addKey(new HotKey(t,i),e)))}removeKey({key:t,options:e},i){return this.off(KeyboardManager.stringify(t,e),i)}onceKey(t,e){const onceCallback=i=>{e(i),this.removeKey(t,onceCallback)};this.addKey(t,onceCallback)}_handleIgnoreModifiersKey(t){const[e,i]=this.hasStringifiedKey(t.code,{ignoreModifiers:!0});if(!i)return;this._events.get(e).forEach((e=>e(t)))}_handleAnyKey(t){const[e,i]=this.hasStringifiedKey(o.Any,t);if(!i)return;this._events.get(e).forEach((e=>e(t)))}_handleAllKey(t){this._events.get(o.All).forEach((e=>e(t)))}anyKey(t,e={}){this.addKey(new HotKey(o.Any,e),t)}allKey(t){this._events.get(o.All).add(t)}addControls(t){addEventListener(t,(t=>{const e=KeyboardManager.from(t),i=this._events.get(e);this._handleIgnoreModifiersKey(t),this._handleAnyKey(t),this._handleAllKey(t),i&&i.forEach((e=>{e(t)}))}))}}class KeyStateManager extends CustomObject{constructor(){super(),this.downKeyboardManager=null,this.upKeyboardManager=null,this._hotKey=null,this._downCallback=t=>{},this._upCallback=t=>{}}trackKeyState({options:t,key:e},i){this.setKey(e,t),this.bindKeyHandlers((t=>i(!0)),(t=>i(!1)))}trackAxis({negative:t,positive:e,callback:i}){let s={negative:!1,positive:!1};const updatePoint=()=>{const{negative:t,positive:e}=s;let n=0;t&&n--,e&&n++,i(n)};{const{options:e,key:i}=t;this.setKey(i,e),this.trackKeyState(t,(t=>{s.negative=t,updatePoint()}))}{const{options:t,key:i}=e;this.setKey(i,t),this.trackKeyState(e,(t=>{s.positive=t,updatePoint()}))}}trackVector({negativeX:t,negativeY:e,positiveX:i,positiveY:s,callback:n}){let a=0,r=0;const updatePosition=()=>{n(new Point(a,r))};this.trackAxis({negative:t,positive:i,callback:t=>{a=t,updatePosition()}}),this.trackAxis({negative:e,positive:s,callback:t=>{r=t,updatePosition()}})}setKey(t,e){this._hotKey=new HotKey(t,e)}setKeyboardManagers(t,e){this.downKeyboardManager=t,this.upKeyboardManager=e}bindKeyHandlers(t,e){this._downCallback=t,this._upCallback=e,this._registerCallbacks()}unbindKeyHandlers(t=this._downCallback,e=this._upCallback){(this.downKeyboardManager||this.upKeyboardManager)&&this._hotKey&&(this.downKeyboardManager.removeKey(this._hotKey,t),this.upKeyboardManager.removeKey(this._hotKey,e))}_registerCallbacks(){(this.downKeyboardManager||this.upKeyboardManager)&&this._hotKey&&(this.downKeyboardManager.addKey(this._hotKey,this._downCallback),this.upKeyboardManager.addKey(this._hotKey,this._upCallback))}}class LocalStorageManager extends EventEmitter{constructor(t){super(),this._name=t,this._value={},this._isLoaded=!1}_load(){if(this._isLoaded)return;this._isLoaded=!0;let t=localStorage.getItem(this._name);if(!t)return Logging.warn(`LocalStorage "${this._name}" doesn't exist. Created new one`),localStorage.setItem(this._name,"{}"),void this.emit("init");this._value=JSON.parse(t),this.emit("load")}set(t,e){this._load(),this._value[t]=e;let i=new StorageEvent("set");i.key=t,i.value=e,this.emit("set",i),localStorage.setItem(this._name,JSON.stringify(this._value))}setAll(t){this._load();for(const[e,i]of Object.entries(t))this.set(e,i)}get(t,e){var i;return this._load(),null!==(i=this._value[t])&&void 0!==i?i:e}getAll(){return this._load(),this._value}}class PointerInputManager extends CustomObject{constructor(){super(),this._isPressed=!1,this._cursorPosition=Point.NaN,this._pointersLocation=[],this._pointerables=[],this._camera=null}_setCursorPoint(t){this._cursorPosition.point=this._createPoint(t)}_getPointerIndex(t){let e=0,{pointerId:i}=t;for(let t=0;t<this._pointersLocation.length;t++){if(i==this._pointersLocation[t].pointerId){e=t;break}}return e}_createPoint(t){var e;let i=new PointerPoint(t.offsetX,t.offsetY,null!==(e=t.pointerId)&&void 0!==e?e:0);return this._updatePointWithCamera(i)}_editPoint(t,e){this._pointersLocation[t]&&(this._pointersLocation[t].point=this._createPoint(e))}_downEventCallback(t){this._isPressed=!0,this._pointersLocation.push(this._createPoint(t))}_moveEventCallback(t){let e=this._getPointerIndex(t);-1!=e&&this._editPoint(e,t)}_upEventCallback(t){let e=this._getPointerIndex(t);-1!=e&&(this._pointersLocation.splice(e,1),this._isPressed=this._pointersLocation.length>0)}_allControlsEventCallback(t){this._setCursorPoint(t)}setCamera(t){this._camera=t}getCursorPosition(){return this._cursorPosition}_updatePointWithCamera(t){if(!this._camera)return t;const{x:e,y:i}=t,getUpdatedCoordinate=(t,e)=>t/this._camera.zoom-e;return new PointerPoint(getUpdatedCoordinate(e,this._camera.x),getUpdatedCoordinate(i,this._camera.y),t.pointerId)}addPointerable(t){t.managers.add(this),this._pointerables.push(t),this.updateZIndex()}removePointerable(t){t.managers.delete(this);let e=Search.binary(this._pointerables,t,PointerInputManager._pointerableSortCallback);this._pointerables.splice(e,1)}addControls(t){t.addEventListener("pointerdown",(t=>{this._downEventCallback(t),this._allControlsEventCallback(t)})),t.addEventListener("pointermove",(t=>{this._moveEventCallback(t),this._allControlsEventCallback(t)})),t.addEventListener("pointerup",(t=>{this._upEventCallback(t),this._allControlsEventCallback(t)})),t.addEventListener("pointercancel",(t=>{this._upEventCallback(t),this._allControlsEventCallback(t)})),t.addEventListener("pointerout",(t=>{this._upEventCallback(t),this._allControlsEventCallback(t)})),t.addEventListener("wheel",(t=>{this._allControlsEventCallback(t)}))}updateZIndex(){this._pointerables=Sorting.merge(this._pointerables,PointerInputManager._pointerableSortCallback)}get isPressed(){return this._isPressed}update(){if(this._pointerables.length){for(const t of this._pointerables)t.isPressedInFrame=!1;for(const t of[...this._pointersLocation,this._cursorPosition]){let e=t===this._cursorPosition,i=e;for(const s of this._pointerables){let n=s.isPointInShape(t);!e&&n?(s.isPressedInFrame=!0,s.pressedCallback(t),i=!1,e=n||e):s.isPressedInFrame||(n?s.hoverCallback(t):i&&s.nonInteractiveCallback(t))}}}}}PointerInputManager._pointerableSortCallback=t=>-t.zIndex;class CanvasImage extends ShapeableObject{constructor(t,e,i,s){super(t,e),this.setSize(i,s),this._isLoaded=!1,this._image=new Image,this.eventEmitter.on("image-load",(t=>{this._isLoaded=!0})),this._cuttedImageBox=null}_loadJSONFromFile(t){return __awaiter(this,void 0,void 0,(function*(){yield this.loadImage(t.src)}))}doWhenLoaded(t){this.isLoaded()?t():this.eventEmitter.once("image-load",(e=>{t()}))}setShape(t){t.setPosition(this.x,this.y),t.setSize(this.size.width,this.size.height),super.setShape(t)}setAngle(t){super.setAngle(t),this._cuttedImageBox&&this._cuttedImageBox.setAngle(t)}cutImage({x:t,y:e,width:i,height:s}){this._cuttedImageBox||(this._cuttedImageBox=new Rectangle),this._cuttedImageBox.setPosition(t,e),this._cuttedImageBox.setSize(i,s)}setImage(t){this._image=t}setSizeByImage(){this.doWhenLoaded((()=>{const{naturalHeight:t,naturalWidth:e}=this._image;this.setSize(e,t)}))}loadImage(t){return __awaiter(this,void 0,void 0,(function*(){let e=new AssetsManager,i=yield e.loadImageFile(t);this.setImage(i),i.addEventListener("load",(t=>this.eventEmitter.emit("image-load")))}))}isLoaded(){return this._isLoaded}_fill(t){if(!this.isLoaded())return;let e;e=this._cuttedImageBox?this._cuttedImageBox:new Rectangle(0,0,this._image.naturalWidth,this._image.naturalHeight);let{x:i,y:s,size:{width:n,height:a}}=e;this.shape.clip(t,(()=>{this.shape.drawTransformed(t,((e,r,o,h)=>{t.drawImage(this._image,i,s,n,a,e,r,o,h)}))}))}}class SpriteSheet extends CanvasImage{constructor(t,e,i,s){super(t,e,i,s),this._currentFrame=new SimpleRect,this._rows=1,this._columns=1,this.doWhenLoaded((()=>{this.setCurrentFrame(new Point),this.setGrid(this._columns,this._rows)}))}loadImage(t){const e=Object.create(null,{loadImage:{get:()=>super.loadImage}});return __awaiter(this,void 0,void 0,(function*(){yield e.loadImage.call(this,t),this.setGrid(this._columns,this._rows)}))}_loadJSONFromFile(t){const e=Object.create(null,{_loadJSONFromFile:{get:()=>super._loadJSONFromFile}});return __awaiter(this,void 0,void 0,(function*(){yield e._loadJSONFromFile.call(this,t);const{type:i,width:s,height:n}=t.size;"dimensions"==i?this.setGridBySize(s,n):"grid"==i?this.setGrid(s,n):Logging.engineWarn(`There is not supported type: ${i}`,this)}))}setGrid(t=1,e=1){this.doWhenLoaded((()=>{const{naturalWidth:i,naturalHeight:s}=this._image;this.setGridBySize(i/t,s/e)}))}setGridBySize(t,e){this.doWhenLoaded((()=>{const{naturalWidth:i,naturalHeight:s}=this._image;Logging.engineLog(i,s),Logging.engineLog(t,e),this._currentFrame.width=t,this._currentFrame.height=e,this._columns=MathUtils.ceil(i/t),this._rows=MathUtils.ceil(s/e),this.setCurrentFrame(this._currentFrame)}))}getGridSize(){return new Point(this._columns,this._rows)}setCurrentFrameByIndex(t){let e=new Point(t%this._columns,MathUtils.floor(t/this._columns));this.setCurrentFrame(e)}setCurrentFrame({x:t,y:e}){(t<0||t>=this._columns)&&Logging.engineWarn("x not in range",this),(e<0||e>=this._rows)&&Logging.engineWarn("y not in range",this),this._currentFrame.x=new Bounds(0,this._columns).get(t),this._currentFrame.y=new Bounds(0,this._rows).get(e),this._cuttedImageBox=Rectangle.fromSimpleRectangle(this.getCurrentFrame())}getCurrentFrame(){const{x:t,y:e,width:i,height:s}=this._currentFrame;return new SimpleRect(t*i,e*s,i,s)}}class GameObject extends DrawableObject{constructor(){super(),this._objects=[]}_addObjectToArray(t,e){if(!t.canBeSubObject)return Logging.engineWarn("Cant be sub object",t),!1;e.push(t);let i=Sorting.quick(e,(t=>t.zIndex));return e.splice(0,e.length,...i),t.root=this,t.managers.add(this),!0}_removeObjectFromArray(t,e){if(!Boolean(t.root))return!1;t.managers.delete(this);let i=Search.binary(e,t,(t=>t.zIndex));return this._objects.splice(i,1),!0}setPointerManager(t){this.forAll((e=>{e instanceof PointerableObject&&t.addPointerable(e)}))}forUI(t){}forAll(t){this.forEach(t),this.forUI(t)}addObjects(...t){t.forEach((t=>this.addObject(t)))}addObject(t){return this._addObjectToArray(t,this._objects)}removeObject(t){return this._removeObjectFromArray(t,this._objects)}forEach(t=(t,e)=>{}){for(let e=0;e<this._objects.length;e++){t(this._objects[e],e)}}_preload(t){return __awaiter(this,void 0,void 0,(function*(){}))}preload(t){return __awaiter(this,void 0,void 0,(function*(){yield this._preload(t)}))}_create(t){return[]}init(t){this._isInitialized||(this.addObjects(...this._create(t)),Logging.engineLog("create",this),super.init(t))}_draw(t){this.forEach((e=>{e.draw(t)}))}updateObjects(t){this.forEach((e=>{e.update(t)}))}updatePositionByOffset(t){}_update(t){this.updateObjects(t)}update(t){this._update(t)}updateZIndex(){this._objects=Sorting.merge(this._objects,(t=>t.zIndex))}isObjectInViewport(t){return!0}get factRect(){return new SimpleRect(0,0,1,1)}}class GameEntity extends GameObject{constructor(t,e){super(),this._position=new Point(t,e),this._factRect=new CachedValue(new SimpleRect),this._factRect.setUpdateCallback((()=>this._updateFactRect()))}addObject(t){let e=super.addObject(t);return e&&(t.offset=t.point),e}removeObject(t){return!!super.removeObject(t)&&(t.setOff