p5play
Version:
A JavaScript game engine that uses p5.js for graphics and Box2D for physics.
1 lines • 114 kB
JavaScript
if("object"!=typeof planck){if("object"!=typeof process)throw"planck.js must be loaded before p5play";global.planck=require("./planck.min.js")}p5.prototype.registerMethod("init",(function(){const t=this,e=planck;if("object"!=typeof process&&0!=window._p5play_gtagged){let t=document.createElement("script");t.src="https://www.googletagmanager.com/gtag/js?id=G-EHXNCTSYLK",t.async=!0,document.head.append(t),window._p5play_gtagged=!0,t.onload=()=>{window.dataLayer??=[],window.gtag=function(){dataLayer.push(arguments)},gtag("js",new Date),gtag("config","G-EHXNCTSYLK"),gtag("event","p5play_v3_26")}}const i=t.DEGREES;t.angleMode(i);const s=(i,s,r)=>new e.Vec2(i*r/t.world.meterSize,s*r/t.world.meterSize),r=(i,s,r)=>new e.Vec2(i/r*t.world.meterSize,s/r*t.world.meterSize),o=e.Settings.linearSlop,h=e.Settings.angularSlop/60,a=t=>Math.abs(t)<=o,n=(t,e)=>Math.abs(t-Math.round(t))<=(e||o)?Math.round(t):t,l=(e,s)=>{let r=t._angleMode==i?360:t.TWO_PI,o=(e-s)%r,h=(r-Math.abs(o))*-Math.sign(o);return(Math.abs(o)<Math.abs(h)?o:h)||0},d={_collisions:["_collides","_colliding","_collided"],_overlappers:["_overlaps","_overlapping","_overlapped"]};this.P5Play=class{constructor(){if(this.sprites={},this.groups={},this.groupsCreated=0,this.spritesCreated=0,this.spritesDrawn=0,this.images={},this.disableImages=!1,this.palettes=[],this.emojiScale=1,this.friendlyRounding=!0,this.storeRemovedGroupRefs=!0,this.snapToGrid=!1,this.gridSize=.5,this.os={},this.context="web",window.matchMedia?this.hasMouse=!window.matchMedia("(any-hover: none)").matches:this.hasMouse=!0,this.standardizeKeyboard=!1,"object"==typeof navigator){let t=navigator.userAgent.indexOf("iPhone OS");if(t>-1){let e=navigator.userAgent.substring(t+10,t+12);this.os.platform="iOS",this.os.version=e}else{let t=navigator.userAgentData?.platform;!t&&navigator.platform&&(t=navigator.platform.slice(3),"Mac"==t?t="macOS":"Win"==t?t="Windows":"Lin"==t&&(t="Linux")),this.os.platform=t}}this.renderStats=!1,this._renderStats={x:10,y:20,font:"monospace"},this._fps=60,this._fpsArr=[60],this._collides={},this._colliding={},this._collided={},this._overlaps={},this._overlapping={},this._overlapped={}}onImageLoad(){}},this.p5play=new t.P5Play,delete t.P5Play;let p=!0,u=1,c=t.log=console.log;t.DYN=t.DYNAMIC="dynamic",t.STA=t.STATIC="static",t.KIN=t.KINEMATIC="kinematic",this.Sprite=class{constructor(i,s,r,o,h){this._isSprite=!0,this.idNum;let a,l,d=[...arguments];if(void 0!==d[0]&&d[0]._isGroup&&(a=d[0],d=d.slice(1)),void 0!==d[0]&&("string"==typeof d[0]||d[0]instanceof t.Ani||d[0]instanceof p5.Image)&&(l=d[0],d=d.slice(1)),1==d.length&&"number"==typeof d[0])throw new M("Sprite",0,[d[0]]);if(Array.isArray(d[0])){if(i=void 0,s=void 0,r=d[0],o=void 0,h=d[1],Array.isArray(h))throw new M("Sprite",1,[`[[${r}], [${o}]]`])}else i=d[0],s=d[1],r=d[2],o=d[3],h=d[4];"string"==typeof r&&(h=r,r=void 0),"string"==typeof o&&(!function(t){if("d"==t||"s"==t||"k"==t||"n"==t)return!0;let e=t.slice(0,2);return"dy"==e||"st"==e||"ki"==e||"no"==e}(o)?r=f(r,o):h=o,o=void 0),this.idNum=t.p5play.spritesCreated,this._uid=1e3+this.idNum,t.p5play.sprites[this._uid]=this,t.p5play.spritesCreated++,this.groups=[],this.animations=new t.Anis,this.joints=[],this.joints.removeAll=()=>{for(;this.joints.length;)this.joints.at(-1).remove()},this.watch,this.mod={},this._removed=!1,this._life=2147483647,this._visible=!0,this._pixelPerfect=!1,this._aniChangeCount=0,this._draw=()=>this.__draw(),this._hasOverlap={},this._collisions={},this._overlappers={},a??=t.allSprites,this._tile="",this.tileSize=a.tileSize||1;let u=this;this._position={x:0,y:0},this._pos=t.createVector.call(t),Object.defineProperty(this._pos,"x",{get(){if(!u.body||!p)return u._position.x;let e=u.body.getPosition().x/u.tileSize*t.world.meterSize;return t.p5play.friendlyRounding?n(e):e},set(i){if(u._position.x=i,u.body){let s=new e.Vec2(i*u.tileSize/t.world.meterSize,u.body.getPosition().y);u.body.setPosition(s)}}}),Object.defineProperty(this._pos,"y",{get(){if(!u.body||!p)return u._position.y;let e=u.body.getPosition().y/u.tileSize*t.world.meterSize;return t.p5play.friendlyRounding?n(e):e},set(i){if(u._position.y=i,u.body){let s=new e.Vec2(u.body.getPosition().x,i*u.tileSize/t.world.meterSize);u.body.setPosition(s)}}}),this._canvasPos=t.createVector.call(t),Object.defineProperty(this._canvasPos,"x",{get(){let e=u._pos.x-t.camera.x;return"c2d"==t.canvas.renderer&&(e+=t.canvas.hw/t.camera._zoom),e}}),Object.defineProperty(this._canvasPos,"y",{get(){let e=u._pos.y-t.camera.y;return"c2d"==t.canvas.renderer&&(e+=t.canvas.hh/t.camera._zoom),e}}),this._velocity={x:0,y:0},this._direction=0,this._vel=t.createVector.call(t),Object.defineProperties(this._vel,{x:{get(){let e;return e=u.body?u.body.getLinearVelocity().x:u._velocity.x,e/=u.tileSize,t.p5play.friendlyRounding?n(e):e},set(t){t*=u.tileSize,u.body?u.body.setLinearVelocity(new e.Vec2(t,u.body.getLinearVelocity().y)):u._velocity.x=t,(t||this.y)&&(u._direction=this.heading())}},y:{get(){let e;return e=u.body?u.body.getLinearVelocity().y:u._velocity.y,e/=u.tileSize,t.p5play.friendlyRounding?n(e):e},set(t){t*=u.tileSize,u.body?u.body.setLinearVelocity(new e.Vec2(u.body.getLinearVelocity().x,t)):u._velocity.y=t,(t||this.x)&&(u._direction=this.heading())}}}),this._mirror={_x:1,_y:1,get x(){return this._x<0},set x(t){u.watch&&(u.mod[20]=!0),this._x=t?-1:1},get y(){return this._y<0},set y(t){u.watch&&(u.mod[20]=!0),this._y=t?-1:1}},this._heading="right",this._layer=a._layer,this._layer??=t.allSprites._getTopLayer()+1,a.dynamic&&(h??="dynamic"),a.kinematic&&(h??="kinematic"),a.static&&(h??="static"),h??=a.collider,h&&"string"==typeof h||(h="dynamic"),this.collider=h,i??=a.x,void 0===i&&(i="c2d"!=t.canvas?.renderer||t._webgpuFallback?0:t.canvas.hw/this.tileSize,r&&(this._vertexMode=!0)),s??=a.y,void 0===s&&(s="c2d"!=t.canvas?.renderer||t._webgpuFallback?0:t.canvas.hh/this.tileSize);let c=!1;if(void 0===r&&(r=a.w||a.width||a.d||a.diameter||a.v||a.vertices,o||a.d||a.diameter||(o=a.h||a.height,c=!0)),"function"==typeof i&&(i=i(a.length)),"function"==typeof s&&(s=s(a.length)),"function"==typeof r&&(r=r(a.length)),"function"==typeof o&&(o=o(a.length)),this.x=i,this.y=s,!a._isAllSpritesGroup&&!l){for(let t in a.animations){l=t;break}l||(l=a._img,"function"==typeof l&&(l=l(a.length)),l&&(this._img=!0))}for(let e=a;e;e=t.p5play.groups[e.parent])this.groups.push(e);if(this.groups.reverse(),l){let e=this.tileSize;this._img||l instanceof p5.Image?(this.image="string"!=typeof l?l:new t.EmojiImage(l,r),r||1==this._img.w&&1==this._img.h||(r=(this._img.defaultWidth||this._img.w)/e,o??=(this._img.defaultHeight||this._img.h)/e)):("string"==typeof l?this._changeAni(l):this._ani=l.clone(),r||1==this._ani.w&&1==this._ani.h||(r=(this._ani.defaultWidth||this._ani.w)/e,o??=(this._ani.defaultHeight||this._ani.h)/e))}if(this.groups=[],this.mouse=new t._SpriteMouse,this._rotation=0,this._rotationSpeed=0,this._bearing=0,this._scale=new _,Object.defineProperty(this._scale,"x",{get(){return this._x},set(t){if(t==this._x)return;u.watch&&(u.mod[26]=!0);let e=Math.abs(t/this._x);u._w*=e,u._hw*=e,u._resizeColliders({x:e,y:1}),this._x=t,this._avg=.5*(this._x+this._y)}}),Object.defineProperty(this._scale,"y",{get(){return this._y},set(t){if(t==this._y)return;u.watch&&(u.mod[26]=!0);let e=Math.abs(t/this._y);u._h&&(this._h*=e,this._hh*=e),u._resizeColliders({x:1,y:e}),this._y=t,this._avg=.5*(this._x+this._y)}}),this._offset={_x:0,_y:0,get x(){return this._x},set x(t){t!=this._x&&(u.watch&&(u.mod[21]=!0),u._offsetCenterBy(t-this._x,0))},get y(){return this._y},set y(t){t!=this._y&&(u.watch&&(u.mod[21]=!0),u._offsetCenterBy(0,t-this._y))}},this._massUndef=!0,void 0===r&&(this._dimensionsUndef=!0,this._widthUndef=!0,r=this.tileSize>1?1:50,void 0===o&&(this._heightUndef=!0)),c&&(o??=this.tileSize>1?1:50),this._shape=a.shape,3!=this.__collider)this._vertexMode?this.addCollider(r):this.addCollider(0,0,r,o),this.shape=this._shape;else{if(this.w=r,Array.isArray(r))throw new Error('Cannot set the collider type of a sprite with a polygon or chain shape to "none". To achieve the same effect, use .overlaps(allSprites) to have your sprite overlap with the allSprites group.');void 0!==r&&void 0===o?this.shape="circle":(this.shape="box",this.h=o)}this.prevPos={x:i,y:s},this.prevRotation=0,this._dest={x:i,y:s},this._destIdx=0,this._debug=!1,this.text,a._isAllSpritesGroup||t.allSprites.push(this),a.push(this);let m=a.vel.x||0,y=a.vel.y||0;"function"==typeof m&&(m=m(a.length-1)),"function"==typeof y&&(y=y(a.length-1)),this.vel.x=m,this.vel.y=y;let w=["ani","collider","x","y","w","h","d","diameter","dynamic","height","kinematic","static","vel","width"];for(let e of t.Sprite.propsAll){if(w.includes(e))continue;let i=a[e];void 0!==i&&("function"==typeof i&&g(i)&&(i=i(a.length-1)),"object"==typeof i?i instanceof p5.Color?this[e]=t.color(...i.levels):this[e]=Object.assign({},i):this[e]=i)}w=["add","animation","animations","autoCull","contains","GroupSprite","Group","idNum","length","mod","mouse","p","parent","Sprite","Subgroup","subgroups","velocity"];for(let e=0;e<this.groups.length;e++){let i=this.groups[e],s=Object.keys(i);for(let e of s){if(!isNaN(e)||"_"==e[0]||w.includes(e)||t.Sprite.propsAll.includes(e))continue;let s=i[e];void 0!==s&&("function"==typeof s&&g(s)&&(s=s(i.length-1)),this[e]="object"==typeof s?Object.assign({},s):s)}}{let e=t.random(.12,.96),i=t.random(.12,.96),s=t.random(.12,.96);1!=t._colorFormat&&(e*=255,i*=255,s*=255),this.color??=t.color(e,i,s)}this._textFill??=t.color(0),this._textSize??=1==this.tileSize?t.canvas?t.textSize():12:.8}addCollider(i,r,o,h){if(this._removed)return void console.error("Can't add colliders to a sprite that was removed.");3==this.__collider&&(this._collider="dynamic",this.__collider=0);let a={};a.shape=this._parseShape(...arguments),"chain"==a.shape.m_type&&(a.density=0,a.restitution=0),a.density??=this.density||5,a.friction??=this.friction||.5,a.restitution??=this.bounciness||.2,this.body?this.body.m_gravityScale||=1:(this.body=t.world.createBody({position:s(this.x,this.y,this.tileSize),type:this.collider}),this.body.sprite=this);let n=new e.Vec2(this.body.getLocalCenter());this.body.createFixture(a),this.watch&&(this.mod[19]=!0),this.body.setMassData({mass:this.body.getMass(),center:n,I:this.body.getInertia()})}addSensor(e,i,r,o){if(this._removed)return void console.error("Can't add sensors to a sprite that was removed.");let h=this._parseShape(...arguments);this.body||(this.body=t.world.createBody({position:s(this.x,this.y,this.tileSize),type:"dynamic",gravityScale:0}),this.body.sprite=this,this.mass=0,this._massUndef=!0,this.rotation=this._rotation,this.vel=this._velocity),this.body.createFixture({shape:h,isSensor:!0}),this._sortFixtures(),this._hasSensors=!0}_parseShape(i,r,o,h){let n,l,d,p,u=[...arguments];if(0==u.length?(i=0,r=0,o=this._w,h=this._h):u.length<=2&&(i=0,r=0,o=u[0],h=u[1],this._vertexMode=!0),Array.isArray(o)||"string"==typeof h?(isNaN(o)||(o=Number(o)),"number"!=typeof o&&Array.isArray(o[0])&&(this._originMode??="start"),"string"==typeof h?(n=f(o,h),h=void 0):n=o):(l=void 0!==o&&void 0===h?"circle":"box",o??=this.tileSize>1?1:50,h??=o,d=s(o-.08,h-.08,this.tileSize)),"box"==l)p=e.Box(d.x/2,d.y/2,s(i,r,this.tileSize),0);else if("circle"==l)p=e.Circle(s(i,r,this.tileSize),d.x/2);else if(n){let c,_,g=[{x:0,y:0}],m={x:0,y:0},y={x:0,y:0},w={x:0,y:0},v=Array.isArray(n[0]);function x(){m.x<y.x&&(y.x=m.x),m.y<y.y&&(y.y=m.y),m.x>w.x&&(w.x=m.x),m.y>w.y&&(w.y=m.y)}if(v){this._vertexMode&&(c=n[0][0],_=n[0][1],this.fixture&&this._relativeOrigin?(c=this.x-this._relativeOrigin.x,_=this.y-this._relativeOrigin.y,g.pop()):(this.x=c,this.y=_));for(let S=0;S<n.length;S++){if(this._vertexMode){if(0==S&&!this.fixture)continue;m.x=n[S][0]-c,m.y=n[S][1]-_}else m.x+=n[S][0],m.y+=n[S][1];g.push({x:m.x,y:m.y}),x()}}else{let A=1;n.length%2&&(A=n[n.length-1]);let C=A>0?1:-1;A=Math.abs(A);let k=0;for(let M=0;M<A;M++){for(let z=0;z<n.length-1;z+=2){let T=n[z];k+=n[z+1],m.x+=T*t.cos(k),m.y+=T*t.sin(k),g.push({x:m.x,y:m.y}),x()}k*=C}}let b=!1;if(a(Math.abs(g[0].x)-Math.abs(g[g.length-1].x))&&a(Math.abs(g[0].y)-Math.abs(g[g.length-1].y))?(l="chain"!=this._shape?"polygon":"chain",this._originMode="center",this._isConvexPoly(g.slice(0,-1))&&(b=!0)):l="chain",o=w.x-y.x,h=w.y-y.y,"start"==this._originMode)for(let j=0;j<g.length;j++)g[j]=s(g[j].x,g[j].y,this.tileSize);else{let P=0,O=0,F=0,D=0,I=g.length;("polygon"==l||b)&&I--;for(let L=0;L<I;L++)F+=g[L].x,D+=g[L].y;P=F/I,O=D/I,this.fixture||(this._relativeOrigin={x:P,y:O}),this._vertexMode&&v&&(this.fixture?(P=this._relativeOrigin.x,O=this._relativeOrigin.y):(this.x+=P,this.y+=O));for(let B=0;B<g.length;B++){let W=g[B];g[B]=s(W.x+i-P,W.y+r-O,this.tileSize)}}(!b||g.length-1>e.Settings.maxPolygonVertices||"chain"==this._shape)&&(l="chain"),"polygon"==l?p=e.Polygon(g):"chain"==l&&(p=e.Chain(g,!1))}if(this.shape??=l,this.fixtureList){this._extents??={t:this.hh,b:this.hh,l:this._hw,r:this._hw};let G=this._extents,R=i-.5*o,N=i+.5*o,E=r-.5*h,U=r+.5*h;R<G.l&&(G.l=R),N>G.r&&(G.r=N),E<G.t&&(G.t=E),U>G.b&&(G.b=U),this._totalWidth=G.r-G.l,this._totalHeight=G.b-G.t;let V=Math.abs;this._largestExtent=Math.max(V(G.l),V(G.r),V(G.t),V(G.b))}else this._w=o,this._hw=.5*o,1!=this.__shape&&(this._h=h,this._hh=.5*h);return p}removeColliders(){this.body&&(this._removeContacts(0),this._removeFixtures(0))}removeSensors(){this.body&&(this._removeContacts(1),this._removeFixtures(1),this._hasSensors=!1)}_removeFixtures(e){let i;for(let s=this.fixtureList;s;s=s.getNext())if(void 0===e||s.m_isSensor==e){let e=s.m_next;s.destroyProxies(t.world.m_broadPhase),i?i.m_next=e:this.body.m_fixtureList=e}else i=s}_removeContacts(e){if(!this.body)return;let i=this.body.m_contactList;for(;i;){let s=i.contact;i=i.next,void 0!==e&&s.m_fixtureA.m_isSensor!=e||t.world.destroyContact(s)}}_offsetCenterBy(t,e){if(!t&&!e)return;if(this._offset._x+=t,this._offset._y+=e,!this.body)return;let i=s(t,e,this.tileSize);this.__offsetCenterBy(i.x,i.y)}__offsetCenterBy(t,e){for(let i=this.body.m_fixtureList;i;i=i.m_next){let s=i.m_shape;if("circle"!=s.m_type){let i=s.m_vertices;for(let s of i)s.x+=t,s.y+=e}else s.m_p.x+=t,s.m_p.y+=e}}_cloneBodyProps(){let t={},e=["bounciness","density","drag","friction","heading","isSuperFast","rotation","rotationDrag","rotationLock","rotationSpeed","scale","vel","x","y"];this._massUndef&&this._dimensionsUndef||e.push("mass");for(let i of e)"object"==typeof this[i]?t[i]=Object.assign({},this[i]):t[i]=this[i];return t}get animation(){return this._ani}set animation(t){this.changeAni(t)}get ani(){return this._ani}set ani(t){this.changeAni(t)}get anis(){return this.animations}get autoUpdate(){return this._autoUpdate}set autoUpdate(t){this._autoUpdate=t}get autoDraw(){return this._autoDraw}set autoDraw(t){this._autoDraw=t}get allowSleeping(){return this.body?.isSleepingAllowed()}set allowSleeping(t){this.watch&&(this.mod[5]=!0),this.body&&this.body.setSleepingAllowed(t)}get bounciness(){if(this.fixture)return this.fixture.getRestitution()}set bounciness(t){this.watch&&(this.mod[7]=!0);for(let e=this.fixtureList;e;e=e.getNext())e.setRestitution(t)}get collider(){return this._collider}set collider(e){if(e==this._collider)return;let i=(e=e.toLowerCase())[0];if("d"==i&&(e="dynamic"),"s"==i&&(e="static"),"k"==i&&(e="kinematic"),"n"==i&&(e="none"),e==this._collider)return;if("none"==e&&("chain"==this._shape||"polygon"==this._shape))return void console.error('Cannot set the collider type of a polygon or chain collider to "none". To achieve the same effect, use .overlaps(allSprites) to have your sprite overlap with the allSprites group.');if(this._removed)throw new Error("Cannot change the collider type of a sprite that was removed.");let s=this.__collider;this._collider=e,this.__collider=["d","s","k","n"].indexOf(i),this.watch&&(this.mod[8]=!0),void 0!==s&&(3!=this.__collider?(this.body&&this.body.setType(e),3==s&&(this.addCollider(),this.x=this._position.x,this.y=this._position.y,this.vel.x=this._velocity.x,this.vel.y=this._velocity.y,this.rotation=this._rotation,this.rotationSpeed=this._rotationSpeed)):(this.removeColliders(),this.fixture?.m_isSensor?this.body.m_gravityScale=0:(this._syncWithPhysicsBody(),t.world.destroyBody(this.body),this.body=null)))}_syncWithPhysicsBody(){this._position.x=this.x,this._position.y=this.y,this._velocity.x=this.vel.x,this._velocity.y=this.vel.y,this._rotation=this.rotation,this._rotationSpeed=this.rotationSpeed}_parseColor(e){return e instanceof p5.Color?e:"object"!=typeof e?1==e.length?t.colorPal(e):t.color(e):t.color(...e.levels)}get color(){return this._color}set color(t){this.watch&&(this.mod[9]=!0),this._color=this._parseColor(t)}get colour(){return this._color}set colour(t){this.color=t}get fill(){return this._color}set fill(t){this.color=t}get stroke(){return this._stroke}set stroke(t){this.watch&&(this.mod[29]=!0),this._stroke=this._parseColor(t)}get strokeWeight(){return this._strokeWeight}set strokeWeight(t){this.watch&&(this.mod[30]=!0),this._strokeWeight=t}get textColor(){return this._textFill}set textColor(t){this.watch&&(this.mod[32]=!0),this._textFill=this._parseColor(t)}get textColour(){return this._textFill}set textColour(t){this.textColor=t}get textFill(){return this._textFill}set textFill(t){this.textColor=t}get textSize(){return this._textSize}set textSize(t){this.watch&&(this.mod[33]=!0),this._textSize=t}get textStroke(){return this._textStroke}set textStroke(t){this.watch&&(this.mod[34]=!0),this._textStroke=this._parseColor(t)}get textStrokeWeight(){return this._textStrokeWeight}set textStrokeWeight(t){this.watch&&(this.mod[35]=!0),this._textStrokeWeight=t}get tile(){return this._tile}set tile(t){this.watch&&(this.mod[36]=!0),this._tile=t}get tileSize(){return this._tileSize}set tileSize(t){this.watch&&(this.mod[37]=!0),this._tileSize=t}get bearing(){return this._bearing}set bearing(t){this.watch&&(this.mod[6]=!0),this._bearing=t}get debug(){return this._debug}set debug(t){this.watch&&(this.mod[10]=!0),this._debug=t}get density(){if(this.fixture)return this.fixture.getDensity()}set density(t){this.watch&&(this.mod[11]=!0);for(let e=this.fixtureList;e;e=e.getNext())e.setDensity(t)}_getDirectionAngle(e){e=e.toLowerCase().replaceAll(/[ _-]/g,"");let i={up:-90,down:90,left:180,right:0,upright:-45,rightup:-45,upleft:-135,leftup:-135,downright:45,rightdown:45,downleft:135,leftdown:135,forward:this.rotation,backward:this.rotation+180}[e];return"radians"==t._angleMode&&(i=t.radians(i)),i}get direction(){return 0!==this.vel.x||0!==this.vel.y?t.atan2(this.vel.y,this.vel.x):this._isTurtleSprite?this.rotation:this._direction}set direction(e){this.watch&&(this.mod[12]=!0),"string"==typeof e&&(this._heading=e,e=this._getDirectionAngle(e)),this._direction=e,this._isTurtleSprite&&(this.rotation=e);let i=this.speed;this.vel.x=t.cos(e)*i,this.vel.y=t.sin(e)*i}get drag(){return this.body?.getLinearDamping()}set drag(t){this.watch&&(this.mod[13]=!0),this.body&&this.body.setLinearDamping(t)}get draw(){return this._display}set draw(t){this._userDefinedDraw=!0,this._draw=t}get dynamic(){return this.body?.isDynamic()}set dynamic(t){this.collider=t?"dynamic":"kinematic"}get fixture(){return this.fixtureList}get fixtureList(){return this.body?this.body.m_fixtureList:null}get friction(){if(this.fixture)return this.fixture.getFriction()}set friction(t){this.watch&&(this.mod[14]=!0);for(let e=this.fixtureList;e;e=e.getNext())e.setFriction(t)}get heading(){return this._heading}set heading(t){this.direction=t}get img(){return this._img||this._ani?.frameImage}set img(t){this.image=t}get image(){return this._img||this._ani?.frameImage}set image(e){"string"==typeof e&&(e=e.includes(".")?t.loadImage(e):new t.EmojiImage(e,this.w)),this._img=this._extendImage(e)}_extendImage(t){return t.offset??={x:0,y:0},t._scale??={x:1,y:1},t.scale||Object.defineProperty(t,"scale",{get:()=>t._scale,set:e=>{"number"==typeof e&&(e={x:e,y:e}),t._scale=e}}),t}get isMoving(){return 0!=this.vel.x||0!=this.vel.y}get isSuperFast(){return this.body?.isBullet()}set isSuperFast(t){this.watch&&(this.mod[16]=!0),this.body&&this.body.setBullet(t)}get kinematic(){return this.body?.isKinematic()}set kinematic(t){this.collider=t?"kinematic":"dynamic"}get layer(){return this._layer}set layer(t){this.watch&&(this.mod[17]=!0),this._layer=t}get life(){return this._life}set life(t){this.watch&&(this.mod[18]=!0),this._life=t}get mass(){return this.body?.getMass()}set mass(t){if(!this.body)return;this.watch&&(this.mod[19]=!0);const i={I:0,center:new e.Vec2(this.body.getLocalCenter()),mass:0};this.body.getMassData(i),i.mass=t>0?t:1e-8,this.body.setMassData(i),delete this._massUndef}resetMass(){if(!this.body)return;let t=new e.Vec2(this.body.getLocalCenter());this.watch&&(this.mod[19]=!0),this.body.resetMassData(),this.body.setMassData({mass:this.body.getMass(),center:t,I:this.body.getInertia()})}resetCenterOfMass(){this.watch&&(this.mod[19]=!0),this.body.resetMassData();let{x:t,y:e}=this.body.getLocalCenter();if(0==t&&0==e)return;this.__offsetCenterBy(-t,-e),this.body.resetMassData();let i=this.body.getPosition();this.body.setPosition({x:i.x+t,y:i.y+e})}get mirror(){return this._mirror}set mirror(t){this.watch&&(this.mod[20]=!0),void 0!==t.x&&(this._mirror.x=t.x),void 0!==t.y&&(this._mirror.y=t.y)}get offset(){return this._offset}set offset(t){t.x??=this._offset._x,t.y??=this._offset._y,t.x==this._offset._x&&t.y==this._offset._y||(this.watch&&(this.mod[21]=!0),this._offsetCenterBy(t.x-this._offset._x,t.y-this._offset._y))}get opacity(){return this._opacity??1}set opacity(t){this.watch&&(this.mod[41]=!0),this._opacity=t}get previousPosition(){return this.prevPos}set previousPosition(t){this.prevPos=t}get previousRotation(){return this.prevRotation}set previousRotation(t){this.prevRotation=t}get pixelPerfect(){return this._pixelPerfect}set pixelPerfect(t){this.watch&&(this.mod[22]=!0),this._pixelPerfect=t}get removed(){return this._removed}set removed(t){t&&!this._removed&&(this.watch&&(this.mod[23]=!0),this._removed=!0,this._remove())}get rotation(){if(!this.body||!p)return this._rotation||0;let e=this.body.getAngle();return t.p5play.friendlyRounding&&(e=n(e,h)),t._angleMode==i?t.degrees(e):e}set rotation(e){this._rotation=e,this.body&&(t._angleMode==i&&(e=t.radians(e%360)),this.body.setAngle(e),this.body.synchronizeTransform())}get rotationDrag(){return this.body?.getAngularDamping()}set rotationDrag(t){this.body&&(this.watch&&(this.mod[24]=!0),this.body.setAngularDamping(t))}get rotationLock(){return this.body?.isFixedRotation()}set rotationLock(t){if(!this.body)return;this.watch&&(this.mod[25]=!0);let e=this.mass;this.body.setFixedRotation(t),this.mass=e}get rotationSpeed(){if(this.body){let e=this.body.getAngularVelocity()/60;return t._angleMode==i?t.degrees(e):e}return this._rotationSpeed}set rotationSpeed(e){this.body?(e*=60,t._angleMode==i&&(e=t.radians(e)),this.body.setAngularVelocity(e)):this._rotationSpeed=e}get scale(){return this._scale}set scale(t){if(0==t&&(t=.01),"number"==typeof t?t={x:t,y:t}:(t.x??=this._scale._x,t.y??=this._scale._y),t.x==this._scale._x&&t.y==this._scale._y)return;this.watch&&(this.mod[26]=!0);let e={x:Math.abs(t.x/this._scale._x),y:Math.abs(t.y/this._scale._y)};this._w*=e.x,this._hw*=e.x,this._h&&(this._h*=e.y,this._hh*=e.y),this._resizeColliders(e),this._scale._x=t.x,this._scale._y=t.y,this._scale._avg=t.x}get sleeping(){if(this.body)return!this.body.isAwake()}set sleeping(t){this.body&&(this.watch&&(this.mod[28]=!0),this.body.setAwake(!t))}get speed(){return t.createVector(this.vel.x,this.vel.y).mag()}set speed(e){let i=this.direction;this.vel.x=t.cos(i)*e,this.vel.y=t.sin(i)*e}get static(){return this.body?.isStatic()}set static(t){this.collider=t?"static":"dynamic"}get tint(){return this._tint}set tint(t){this.watch&&(this.mod[38]=!0),this._tint=this._parseColor(t)}get tintColor(){return this._tint}set tintColor(t){this.tint=t}set vertices(t){if(3==this.__collider)throw new Error('Cannot set vertices of a sprite with collider type of "none".');this.watch&&(this.mod[27]=!0),this._removeFixtures(),this._originMode="start",this.addCollider(t),this._hasSensors&&this.addDefaultSensors()}get vertices(){return this._getVertices()}_getVertices(e){let i=this.fixture.getShape(),s=[...i.m_vertices];"polygon"==i.m_type&&s.unshift(s.at(-1));let r=this.x,o=this.y;for(let i=0;i<s.length;i++){let h=[s[i].x/this.tileSize*t.world.meterSize+r,s[i].y/this.tileSize*t.world.meterSize+o];t.p5play.friendlyRounding&&(h[0]=n(h[0]),h[1]=n(h[1])),s[i]=e?h:t.createVector(h[0],h[1])}return s}get visible(){return this._visible}set visible(t){this.watch&&(this.mod[39]=!0),this._visible=t}get x(){return this._pos.x}set x(t){this._pos.x=t}get y(){return this._pos.y}set y(t){this._pos.y=t}get pos(){return this._pos}set pos(i){if(this.body){let s=new e.Vec2(i.x*this.tileSize/t.world.meterSize,i.y*this.tileSize/t.world.meterSize);this.body.setPosition(s)}this._position.x=i.x,this._position.y=i.y}get position(){return this._pos}set position(t){this.pos=t}get canvasPos(){return this._canvasPos}get w(){return this._w}set w(t){if(t<0&&(t=.01),t==this._w)return;this.watch&&(this.mod[40]=!0);let e=t/this._w;this._w=t,this._hw=.5*t,this._resizeColliders({x:e,y:1}),delete this._widthUndef,delete this._dimensionsUndef}get hw(){return this._hw}set hw(t){throw new M("Sprite.hw")}get width(){return this._w}set width(t){this.w=t}get halfWidth(){return this.hw}set halfWidth(t){throw new M("Sprite.hw")}get h(){return this._h||this._w}set h(t){if(t<0&&(t=.01),1==this.__shape)return void(this.w=t);if(t==this._h)return;this.watch&&(this.mod[15]=!0);let e=t/this._h;this._h=t,this._hh=.5*t,this._resizeColliders({x:1,y:e}),delete this._heightUndef,delete this._dimensionsUndef}get hh(){return this._hh||this._hw}set hh(t){throw new M("Sprite.hh")}get height(){return this.h}set height(t){this.h=t}get halfHeight(){return this.hh}set halfHeight(t){throw new M("Sprite.hh")}get d(){return this._w}set d(t){t<0&&(t=.01);let e=1!=this.__shape;if(e||this._w!=t){if(this.watch&&(this.mod[40]=!0),!e){let e=t/this._w;this._resizeColliders({x:e,y:e})}this._w=t,this._hw=.5*t,e&&(this.shape="circle")}}get diameter(){return this._w}set diameter(t){this.d=t}get r(){return this._hw}set r(t){this.d=2*t}get radius(){return this._hw}set radius(t){this.d=2*t}_resizeColliders(t){if(this.body){for(let e=this.fixtureList;e;e=e.getNext()){if(e.m_isSensor)continue;let i=e.m_shape;if("circle"==i.m_type)1!=t.x?i.m_radius*=t.x:i.m_radius*=t.y;else for(let e of i.m_vertices)e.x*=t.x,e.y*=t.y}(this._widthUndef||this._heightUndef)&&this.resetMass(),this.body.synchronizeFixtures()}}_isConvexPoly(t){t:for(let i=0;i<2;i++){1==i&&(t=t.reverse());for(let s=0;s<t.length;++s){const r=s,o=s<t.length-1?r+1:0,h=t[r],a=e.Vec2.sub(t[o],h);for(let s=0;s<t.length;++s){if(s==r||s==o)continue;const n=e.Vec2.sub(t[s],h);if(e.Vec2.cross(a,n)<0){if(0==i)continue t;return!1}}}break}return!0}get shape(){return this._shape}set shape(e){if(e==this._shape)return;let i=t.Sprite.shapeTypes.indexOf(e);if(-1==i)throw new Error('Invalid shape type: "'+e+'"\nThe valid shape types are: "'+t.Sprite.shapeTypes.join('", "')+'"');if(3==this.__collider&&i>=2)return void console.error('Cannot set the collider shape to chain or polygon if the sprite has a collider type of "none". To achieve the same effect, use .overlaps(allSprites) to have your sprite overlap with the allSprites group.');let s,r,o=this.__shape;if(this.__shape=i,this._shape=e,this.watch&&(this.mod[27]=!0),void 0===o)return;if(0==this.__shape?(this._h=this._w,this._hh=this._hw):(this._h=void 0,this._hh=void 0),1!=o&&1!=this.__shape?s=this._getVertices(!0):r=this._w,this._removeFixtures(),3!=this.__collider)if(s)this._originMode??="center",this.addCollider(s);else if(1==o){let t=this._w*Math.sin(Math.PI/12);this.addCollider(0,0,[t,-30,12])}else this.addCollider();this._hasSensors&&this.addDefaultSensors();let h=this._offset._x,a=this._offset._y;(h||a)&&(this._offset._x=0,this._offset._y=0,this._offsetCenterBy(h,a))}get update(){return this._update}set update(t){this._customUpdate=t}get postDraw(){return this._postDraw}set postDraw(t){this._customPostDraw=t}get vel(){return this._vel}set vel(t){this.vel.x=t.x,this.vel.y=t.y}get velocity(){return this._vel}set velocity(t){this.vel=t}get gravityScale(){return this.body?.getGravityScale()}set gravityScale(t){this.body&&(this.watch&&(this.mod[42]=!0),this.body.setGravityScale(t))}_update(){this._customUpdate&&this._customUpdate(),this.autoUpdate&&(this.autoUpdate=null)}_step(){this.life-=u,2147483647!=this._life&&this._life<=0&&this.remove(),this.body&&p||this._removed||(this._position.x+=this.vel.x*u,this._position.y+=this.vel.y*u,this._rotation+=this._rotationSpeed*u),this.watch&&(this.x!=this.prevX&&(this.mod[0]=this.mod[2]=!0),this.y!=this.prevY&&(this.mod[1]=this.mod[2]=!0),this.rotation!=this.prevRotation&&(this.mod[3]=this.mod[4]=!0)),(this.body||this._removed)&&this.__step()}__step(){let e,i=this;for(let s in d)for(let r in this[s]){if(r>=1e3){if(i._isGroup||i._uid>=r)continue;e=t.p5play.sprites[r]}else{if(i._isGroup&&i._uid>=r)continue;e=t.p5play.groups[r]}let o=i[s][r]+1;e&&0!=o&&-2!=o?(this[s][r]=o,e[s][i._uid]=o):(delete i[s][r],e&&delete e[s][i._uid])}}___step(){let e,i,s,r,o=this,h=!0;for(let a in d){for(let n in this[a]){if(n>=1e3){if(o._isGroup||o._uid>=n)continue;e=t.p5play.sprites[n]}else{if(o._isGroup&&o._uid>=n)continue;e=t.p5play.groups[n]}if(o._isGroup||e?._isGroup)continue;if(s=o._hasOverlap[e._uid]??e._hasOverlap[o._uid],h&&!1!==s||!h&&!0!==s)continue;let l=o[a][n];for(let s=0;s<3;s++){if(0==s&&1!=l&&-3!=l)continue;if(1==s&&-1==l)continue;if(2==s&&l>=1)continue;i=d[a][s];let h=t.p5play[i][o._uid];if(h){r=h[e._uid],r&&r.call(o,o,e,l);for(let t of e.groups)r=h[t._uid],r&&r.call(o,o,e,l)}let n=t.p5play[i][e._uid];if(n){r=n[o._uid],r&&r.call(e,e,o,l);for(let t of o.groups)r=n[t._uid],!r||h&&r==h[t._uid]||r.call(e,e,o,l)}}}h=!1}if(this._removed&&0==Object.keys(this._collisions).length&&0==Object.keys(this._overlappers).length){this._isSprite?delete t.p5play.sprites[this._uid]:t.p5play.storeRemovedGroupRefs||delete t.p5play.groups[this._uid];for(let e in d)for(let i of d[e])delete t.p5play[i][this._uid]}}__draw(){if(!t.p5play.disableImages)if(this._ani)this._ani.draw(this._offset._x,this._offset._y,0,this._scale._x,this._scale._y);else if(this._img){let e=this._img,i=1!=this._scale._x||1!=this._scale._y||1!=e.scale.x||1!=e.scale.y;i&&(t.push(),t.scale(this._scale._x*e.scale.x,this._scale._y*e.scale.y)),t.image(e,this._offset._x+e.offset.x,this._offset._y+e.offset.y),i&&t.pop()}if(!this._ani&&!this._img||this.debug||t.p5play.disableImages)if(this.debug&&(t.noFill(),t.stroke(0,255,0),t.line(0,-2,0,2),t.line(-2,0,2,0)),3!=this.__collider){this.debug||0===this._strokeWeight?t.noStroke():2==this.__shape?t.stroke(this.stroke||this.color):this._stroke&&t.stroke(this._stroke);for(let e=this.fixtureList;e;e=e.getNext()){if(this.debug)e.m_isSensor?t.stroke(255,255,0,127):t.stroke(0,255,0,127);else if(e.m_isSensor)continue;this._drawFixture(e)}}else 0!==this._strokeWeight&&t.stroke(this._stroke||120),0==this.__shape?t.rect(this._offset._x,this._offset._y,this.w*this.tileSize,this.h*this.tileSize):1==this.__shape&&t.circle(this._offset._x,this._offset._y,this.d*this.tileSize);void 0!==this.text&&(t.textAlign(t.CENTER,t.CENTER),t.fill(this._textFill),this._textStrokeWeight&&t.strokeWeight(this._textStrokeWeight),this._textStroke?t.stroke(this._textStroke):t.noStroke(),t.textSize(this.textSize*this.tileSize),t.text(this.text,0,0))}_postDraw(){this._ani?.update&&this._ani.update();for(let t in this.mouse)-1==this.mouse[t]&&(this.mouse[t]=0);this._customPostDraw&&this._customPostDraw(),this.autoDraw??=!0,this.autoUpdate??=!0}_display(){let e,i=this.x*this.tileSize+t.world.origin.x,s=this.y*this.tileSize+t.world.origin.y;if(!this._userDefinedDraw){let e;if(e=this._totalWidth?Math.max(this._totalWidth,this._totalHeight):void 0!==this._h?Math.max(this._w,this._h):this._w,this.ani&&!t.p5play.disableImages&&(e=Math.max(e,this.ani.w,this.ani.h)),"chain"!=this.shape&&t.camera.isActive&&(i+e<t.camera.bound.min.x||i-e>t.camera.bound.max.x||s+e<t.camera.bound.min.y||s-e>t.camera.bound.max.y))return void(this._visible=null)}if(this._visible=!0,t.p5play.spritesDrawn++,this._pixelPerfect){let e,r;this.ani&&this.ani.length&&!t.p5play.disableImages?(e=this.ani[this.ani._frame].w,r=this.ani[this.ani._frame].h):(e=this._w,r=this._h),i=e%2==0?Math.round(i):Math.round(i-.5)+.5,s=r%2==0?Math.round(s):Math.round(s-.5)+.5}else i=n(i),s=n(s);for(let t of this.joints)t.visible?this._uid==t.spriteA._uid?(!t.spriteB._visible||this.layer<=t.spriteB.layer)&&t._display():(!t.spriteA._visible||this.layer<t.spriteA.layer)&&t._display():t.visible??=!0;0!=this._opacity&&(t.push(),t.imageMode("center"),t.rectMode("center"),t.ellipseMode("center"),t.translate(i,s),this.rotation&&t.rotate(this.rotation),1==this._mirror._x&&1==this._mirror._y||t.scale(this._mirror._x,this._mirror._y),t.fill(this.color),void 0!==this._strokeWeight&&t.strokeWeight(this._strokeWeight),this._opacity&&(e=t.ctx.globalAlpha,t.ctx.globalAlpha=this._opacity),this._tint&&t.tint(this._tint),this._draw(),t.pop(),this._opacity&&(t.ctx.globalAlpha=e),this._cameraActiveWhenDrawn=t.camera.isActive,t.camera.isActive||(t.camera._wasOff=!0),this.autoDraw&&(this.autoDraw=null))}_drawFixture(e){const i=e.m_shape;if("polygon"==i.m_type||"chain"==i.m_type){if("chain"==i.m_type){if(0==t._strokeWeight)return;t.push(),t.noFill()}let e=i.m_vertices;t.beginShape();for(let i=0;i<e.length;i++)t.vertex(e[i].x*t.world.meterSize,e[i].y*t.world.meterSize);"chain"!=i.m_type?t.endShape("close"):(t.endShape(),t.pop())}else if("circle"==i.m_type){const e=2*i.m_radius*t.world.meterSize;t.ellipse(i.m_p.x*t.world.meterSize,i.m_p.y*t.world.meterSize,e,e)}else"edge"==i.m_type&&t.line(i.m_vertex1.x*t.world.meterSize,i.m_vertex1.y*t.world.meterSize,i.m_vertex2.x*t.world.meterSize,i.m_vertex2.y*t.world.meterSize)}_args2Vec(t,e){return Array.isArray(t)?{x:t[0],y:t[1]}:("object"==typeof t&&(e=t.y,t=t.x),{x:t||0,y:e||0})}_parseForceArgs(){let i=arguments;"number"!=typeof i[0]||1!=i.length&&"number"==typeof i[1]?2==i.length&&"number"!=typeof i[1]&&(i[2]=i[1],i[1]=void 0):(i[3]=i[2],i[2]=i[1],i[1]=t.sin(this._bearing)*i[0],i[0]=t.cos(this._bearing)*i[0]);let r={};return r.forceVector=new e.Vec2(this._args2Vec(i[0],i[1])),void 0!==i[2]&&(r.poa=this._args2Vec(i[2],i[3]),r.poa=s(r.poa.x,r.poa.y,this.tileSize)),r}applyForce(t,e){if(!this.body)return;if("game.thegamebox.ca"==location.host)return this.applyForceScaled(...arguments);let{forceVector:i,poa:s}=this._parseForceArgs(...arguments);s?this.body.applyForce(i,s):this.body.applyForceToCenter(i)}applyForceScaled(t,e){if(!this.body)return;let{forceVector:i,poa:s}=this._parseForceArgs(...arguments);i.mul(this.mass),s?this.body.applyForce(i,s):this.body.applyForceToCenter(i)}attractTo(i,s,r,o,h){if(!this.body||0!=this.__collider)return void console.error("attractTo can only be used on sprites with dynamic colliders");if("number"!=typeof i){let e=i;if(!e||e==t.mouse&&!t.mouse.isActive)return;r=s,s=e.y,i=e.x}if(this.x==i&&this.y==s)return;let a=s-this.y,n=i-this.x,l=r/Math.sqrt(a*a+n*n),d=new e.Vec2(n*l,a*l);this.body.applyForceToCenter(d)}repelFrom(e,i,s,r,o){if(this.body&&0==this.__collider){if("number"!=typeof e){let r=e;if(!r||r==t.mouse&&!t.mouse.isActive)return;s=i,i=r.y,e=r.x}this.attractTo(e,i,-s,r,o)}else console.error("repelFrom can only be used on sprites with dynamic colliders")}applyTorque(t){this.body&&this.body.applyTorque(t)}moveTowards(e,i,s){if(void 0!==e){if("number"!=typeof e&&null!==e){let r=e;if(r==t.mouse&&!t.mouse.isActive)return;if(!r||void 0===r.x||void 0===r.y)throw"sprite.moveTowards/moveAway ERROR: movement destination not defined.";s=i,i=r.y,e=r.x}if(s??=.1,null!=e){let t=e-this.x;a(t)?this.vel.x=0:this.vel.x=t*s*this.tileSize}if(null!=i){let t=i-this.y;a(t)?this.vel.y=0:this.vel.y=t*s*this.tileSize}}}moveAway(t,e,i){this.moveTowards(...arguments),this.vel.x*=-1,this.vel.y*=-1}move(e,i,s){if(!e)return Promise.resolve(!1);let r=isNaN(arguments[0]);r&&(e=1,i=arguments[0],s=arguments[1]),"string"==typeof i&&(r=!0,this._heading=i,i=this._getDirectionAngle(i)),i??=this.direction;let o=t.cos(i)*e,h=t.sin(i)*e;return 1==this.tileSize&&!t.p5play.snapToGrid||!r&&i%90!=0||e%t.p5play.gridSize!=0?(o+=this.x,h+=this.y,i%45==0&&(o=n(o),h=n(h))):(o=Math.round((this.x+Math.round(o))/t.p5play.gridSize)*t.p5play.gridSize,h=Math.round((this.y+Math.round(h))/t.p5play.gridSize)*t.p5play.gridSize),this.moveTo(o,h,s)}moveTo(e,i,s){if("number"!=typeof e&&e){let r=e;if(r==t.mouse&&!t.mouse.isActive)return;if(!r||void 0===r.x||void 0===r.y)throw"sprite.moveTo ERROR: destination not defined.";s=i,i=r.y,e=r.x}if(null!=e&&e!=this.x?(this._dest.x=e,e=!0):(this._dest.x=this.x,e=!1),null!=i&&i!=this.y?(this._dest.y=i,i=!0):(this._dest.y=this.y,i=!1),this._destIdx++,!e&&!i)return Promise.resolve(!0);if(s??=this.speed||(this.tileSize<=1?1:.1),s<=0)return console.warn("sprite.move: speed should be a positive number"),Promise.resolve(!1);let r=this._dest.y-this.y,o=this._dest.x-this.x,h=s/Math.sqrt(r*r+o*o);this.vel.x=o*h,this.vel.y=r*h;let a=this.direction<0?this.direction+360:this.direction,n=a-.1,l=a+.1,d=t.world.velocityThreshold;d=Math.min(d,.1*s);let p=.51*s*(t.world.meterSize/60),u=e&&i,c=this._destIdx;return(async()=>{let s,r;do{if(await t.sleep(),c!=this._destIdx)return!1;let o=this.direction<0?this.direction+360:this.direction;if(u&&(o<=n||o>=l)||Math.abs(this.vel.x)<=d&&Math.abs(this.vel.y)<=d)return!1;e&&(s=this.vel.x>0?this._dest.x-this.x:this.x-this._dest.x),i&&(r=this.vel.y>0?this._dest.y-this.y:this.y-this._dest.y)}while(e&&s>p||i&&r>p);return this.x=this._dest.x,this.y=this._dest.y,this.vel.x=0,this.vel.y=0,!0})()}rotateTowards(t,e){if(1==this.__collider)return void new M(0);let i,s,r,o=arguments;"number"!=typeof o[0]?(i=o[0].x,s=o[0].y,e=o[1],r=o[2]):arguments.length>2&&(i=o[0],s=o[1],e=o[2],r=o[3]),void 0!==i?t=this.angleToFace(i,s,r):t-=this.rotation,e??=.1,this.rotationSpeed=t*e}angleTo(e,i){if("object"==typeof e){let s=e;if(s==t.mouse&&!t.mouse.isActive)return 0;if(void 0===s.x||void 0===s.y)return console.error("sprite.angleTo ERROR: rotation destination not defined, object given with no x or y properties"),0;i=s.y,e=s.x}return t.atan2(i-this.y,e-this.x)}rotationToFace(t,e,i){return"object"==typeof t&&(i=e,e=t.y,t=t.x),Math.abs(t-this.x)<.01&&Math.abs(e-this.y)<.01?0:this.angleTo(t,e)+(i||0)}angleToFace(t,e,i){let s=this.rotationToFace(t,e,i);return l(s,this.rotation)}rotateTo(e,s,r){if(1==this.__collider)return void new M(0);let o=arguments;if("number"!=typeof o[0]?e=this.rotationToFace(o[0].x,o[0].y,r):o.length>2&&(r=o[3],s=o[2],e=this.rotationToFace(o[0],o[1],r)),e==this.rotation)return;let h=t._angleMode==i?360:t.TWO_PI;return(e=(e-this.rotation)%h)<0&&s>0&&(e+=h),e>0&&s<0&&(e-=h),s??=this.rotationSpeed||Math.sign(e),this.rotate(e,s)}rotateMinTo(t,e,i){if(1==this.__collider)return void new M(0);let s=arguments;return"number"!=typeof s[0]?t=this.rotationToFace(s[0].x,s[0].y,i):s.length>2&&(i=s[3],e=s[2],t=this.rotationToFace(s[0],s[1],i)),t!=this.rotation?(t=l(t,this.rotation),e??=this.rotationSpeed>.1?this.rotationSpeed:1,e=Math.abs(e)*Math.sign(t),this.rotate(t,e)):void 0}rotate(e,i){if(1==this.__collider)return void new M(0);if(isNaN(e))return void new M(1,[e]);if(0==e)return;i??=this.rotationSpeed||1;let s=e>0&&i>0;s||(e=-Math.abs(e),i=-Math.abs(i)),this.rotationSpeed=i;let r=Math.abs(i),o=this.rotation+e;this._rotateIdx??=0,this._rotateIdx++;let h=this._rotateIdx;return(async()=>{let e=.01;do{let a=Math.abs(o-this.rotation);if(r>a&&(this.rotationSpeed=a*Math.sign(i)),await t.sleep(),this._rotateIdx!=h)return!1;if(s&&this.rotationSpeed<e||!s&&this.rotationSpeed>-.01)return!1}while((s&&o>this.rotation||!s&&o<this.rotation)&&e<Math.abs(o-this.rotation));return this.rotationSpeed=0,this.rotation=o,!0})()}addAni(){if(t.p5play.disableImages)return void(this._ani=new t.Ani);let e,i,s=[...arguments];return s[0]instanceof t.Ani?(i=s[0],i._addedToSpriteOrGroup&&(i=i.clone()),e=i.name||"default",i.name=e):s[1]instanceof t.Ani?(e=s[0],i=s[1],i._addedToSpriteOrGroup&&(i=i.clone()),i.name=e):(i=new t.Ani(this,...s),e=i.name),this.animations[e]=i,this._ani=i,i._addedToSpriteOrGroup=!0,!this._dimensionsUndef||1==i.w&&1==i.h||(this.w=i.w,this.h=i.h),i}addAnis(){let t,e=arguments;1==e.length?t=e[0]:(this.spriteSheet=e[0],t=e[1]);for(let e in t){let i=t[e];this.addAni(e,i)}}async changeAni(e){if(t.p5play.disableImages)return;if(arguments.length>1)e=[...arguments];else if(e instanceof t.Ani){if(e==this._ani)return;e=[e]}else if(!Array.isArray(e)){if(e==this._ani?.name)return;e=[e]}let i,s;this._aniChangeCount++;for(let r=0;r<e.length;r++){let o=e[r];(o instanceof t.Ani||o instanceof p5.Image||"string"==typeof o&&1!=o.length&&o.includes("."))&&(o=this.addAni(o),e[r]=o),"string"==typeof o&&(o={name:o},e[r]=o),o.name.length>1&&("!"==o.name[0]&&(o.name=o.name.slice(1),o.start=-1,o.end=0),"<"!=o.name[0]&&">"!=o.name[0]||(o.name=o.name.slice(1),o.flipX=!0),"^"==o.name[0]&&(o.name=o.name.slice(1),o.flipY=!0),"**"==o.name&&(i=!0,e=e.slice(0,-1)),";;"==o.name&&(s=!0,e=e.slice(0,-1)))}let r=this._aniChangeCount;do{for(let t=0;t<e.length;t++){let i=e[t];!i.start&&e.length>1&&(i.start=0),await this._playSequencedAni(i)}}while(i&&r==this._aniChangeCount);1!=e.length&&s&&this._ani.stop()}_playSequencedAni(t){return new Promise((e=>{let{name:i,start:s,end:r,flipX:o,flipY:h}=t;this._changeAni(i),o&&(this._ani.scale.x=-this._ani.scale.x),h&&(this._ani.scale.y=-this._ani.scale.y),s<0&&(s=this._ani.length+s),void 0!==s&&(this._ani._frame=s),void 0!==r?this._ani.goToFrame(r):this._ani._frame==this._ani.lastFrame&&e(),this._ani._onComplete=this._ani._onChange=()=>{o&&(this._ani.scale.x=-this._ani.scale.x),h&&(this._ani.scale.y=-this._ani.scale.y),this._ani._onComplete=this._ani._onChange=null,e()}}))}changeAnimation(){return this.changeAni(...arguments)}_changeAni(e){this._ani?._onChange&&this._ani._onChange(),this._ani?.onChange&&this._ani.onChange();let i=this.animations[e];if(!i)for(let t=this.groups.length-1;t>=0;t--){if(i=this.groups[t].animations[e],i){i=i.clone();break}}if(!i)throw t.noLoop(),new M("Sprite.changeAnimation",[e]);this._ani=i,this._ani.name=e,this.resetAnimationsOnChange&&(this._ani._frame=0)}remove(){this.removed=!0}_remove(){this.body&&t.world.destroyBody(this.body),this.body=null;for(let t of this.groups)t.remove(this)}toString(){return"s"+this.idNum}_setContactCB(e,i,s,r){let o;o=0==s?d._collisions[r]:d._overlappers[r];let h=t.p5play[o],a=h[this._uid]??={};a[e._uid]!=i&&(a[e._uid]=i,a=h[e._uid],a&&a[this._uid]&&(delete a[this._uid],0==Object.keys(a).length&&delete h[e._uid]))}_validateCollideParams(t,e){if(!t)throw new M("Sprite.collide",2);if(!t._isSprite&&!t._isGroup)throw new M("Sprite.collide",0,[t]);if(e&&"function"!=typeof e)throw new M("Sprite.collide",1,[e])}_ensureCollide(t,e,i){if(!1!==this._hasOverlap[t._uid]&&(this._hasOverlap[t._uid]=!1),!1!==t._hasOverlap[this._uid]&&(t._hasOverlap[this._uid]=!1,t._isGroup))for(let e of t)e._hasOverlap[this._uid]=!1,this._hasOverlap[e._uid]=!1}collide(t,e){return this.collides(t,e)}collides(t,e){return this._validateCollideParams(t,e),this._ensureCollide(t),e&&this._setContactCB(t,e,0,0),1==this._collisions[t._uid]||this._collisions[t._uid]<=-3}colliding(t,e){this._validateCollideParams(t,e),this._ensureCollide(t),e&&this._setContactCB(t,e,0,1);let i=this._collisions[t._uid];return i<=-3?1:i>0?i:0}collided(t,e){return this._validateCollideParams(t,e),this._ensureCollide(t),e&&this._setContactCB(t,e,0,2),this._collisions[t._uid]<=-1}_validateOverlapParams(t,e){if(!t)throw new M("Sprite.overlap",2);if(!t._isSprite&&!t._isGroup)throw new M("Sprite.overlap",0,[t]);if(e&&"function"!=typeof e)throw new M("Sprite.overlap",1,[e])}_ensureOverlap(t){if(this._hasSensors||this.addDefaultSensors(),!t._hasSensors)if(t._isSprite)t.addDefaultSensors();else{for(let e of t)e._hasSensors||e.addDefaultSensors();t._hasSensors=!0}if(this._hasOverlap[t._uid]||(this._removeContactsWith(t),this._hasOverlap[t._uid]=!0),!t._hasOverlap[this._uid]&&(t._removeContactsWith(this),t._hasOverlap[this._uid]=!0,t._isGroup))for(let e of t)e._hasOverlap[this._uid]=!0,this._hasOverlap[e._uid]=!0}overlap(t,e){return this.overlaps(t,e)}overlaps(t,e){return this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,0),1==this._overlappers[t._uid]||this._overlappers[t._uid]<=-3}overlapping(t,e){this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,1);let i=this._overlappers[t._uid];return i<=-3?1:i>0?i:0}overlapped(t,e){return this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,2),this._overlappers[t._uid]<=-1}_removeContactsWith(t){if(t._isGroup)for(let e of t)this._removeContactsWith(e);else this.__removeContactsWith(t)}__removeContactsWith(e){if(this.body)for(let i=this.body.getContactList();i;i=i.next){let s=i.contact;s.m_fixtureA.m_body.sprite._uid!=e._uid&&s.m_fixtureB.m_body.sprite._uid!=e._uid||t.world.destroyContact(s)}}_sortFixtures(){let t,e,i=null,s=null;for(let r=this.fixtureList;r;r=r.getNext())r.m_isSensor?(s?s.m_next=r:s=r,e=r):(i?i.m_next=r:i=r,t=r);s&&(e.m_next=null),i&&(t.m_next=s),this.body.m_fixtureList=i||s}addDefaultSensors(){let t;if(this.body&&this.fixtureList){for(let e=this.fixtureList;e;e=e.getNext())e.m_isSensor||(t=e.m_shape,this.body.createFixture({shape:t,isSensor:!0}));this._sortFixtures()}else this.addSensor();this._hasSensors=!0}distanceTo(e){return t.dist(this.x,this.y,e.x,e.y)}},t.Sprite.propTypes={x:"Float64",y:"Float64",vel:"Vec2",rotation:"number",rotationSpeed:"number",allowSleeping:"boolean",bearing:"number",bounciness:"number",collider:"Uint8",color:"color",debug:"boolean",density:"number",direction:"number",drag:"number",friction:"number",h:"number",isSuperFast:"boolean",layer:"number",life:"Int32",mass:"number",mirror:"Vec2_boolean",offset:"Vec2",pixelPerfect:"boolean",removed:"boolean",rotationDrag:"number",rotationLock:"boolean",scale:"Vec2",shape:"Uint8",sleeping:"boolean",stroke:"color",strokeWeight:"number",text:"string",textColor:"color",textSize:"number",textStroke:"color",textStrokeWeight:"number",tile:"string",tileSize:"number",tint:"color",visible:"boolean",w:"number",opacity:"number",gravityScale:"number"},t.Sprite.props=Object.keys(t.Sprite.propTypes),t.Sprite.propsAll=t.Sprite.props.concat(["autoDraw","autoUpdate","colour","d","diameter","dynamic","fill","height","heading","kinematic","resetAnimationsOnChange","speed","spriteSheet","static","textColour","textFill","width"]),t.Sprite.colliderTypes=["d","s","k","n"],t.Sprite.shapeTypes=["box","circle","chain","polygon"],t.Turtle=function(e){if(t.allSprites.tileSize>1)throw new Error("Turtle can't be used when allSprites.tileSize is greater than 1.");e??=25;let i=new t.Sprite(e,e,[[e,.4*e],[-e,.4*e],[0,.8*-e]]);i.color="green",i._isTurtleSprite=!0,i._prevPos={x:i.x,y:i.y};let s=i.move;return i.move=function(){return this._prevPos.x=this.x,this._prevPos.y=this.y,s.call(this,...arguments)},i},this.Ani=class extends Array{constructor(){super();let e,i=[...arguments];if(this.name="default","object"==typeof i[0]&&(i[0]._isSprite||i[0]._isGroup)&&(e=i[0],i=i.slice(1),this._addedToSpriteOrGroup=!0),e??=t.allSprites,"string"!=typeof i[0]||1!=i[0].length&&i[0].includes(".")||(this.name=i[0],i=i.slice(1)),this._frame=0,this._cycles=0,this.targetFrame=-1,this.offset={x:e.anis.offset.x??0,y:e.anis.offset.y??0},this._frameDelay=e.anis.frameDelay||4,this.demoMode=e.anis.demoMode??!1,this.playing=!0,this.visible=!0,this.looping=e.anis.looping??!0,this.endOnFirstFrame=e.anis.endOnFirstFrame??!1,this.frameChanged=!1,this.onComplete=this.onChange=null,this._onComplete=this._onChange=null,this.rotation=e.anis.rotation??0,this._scale=new _,0!=i.length&&"number"!=typeof i[0]){if(e.animations[this.name]=this,e._ani=this,Array.isArray(i[0])&&"string"==typeof i[0][0]&&(i=[...i[0]]),2!=i.length||"string"!=typeof i[0]||"string"!=typeof i[1]&&"number"!=typeof i[1])if("string"==typeof i.at(-1)||i.at(-1)instanceof p5.Image)for(let s=0;s<i.length;s++)i[s]instanceof p5.Image?this.push(i[s]):this.push(t.loadImage(i[s]));else{let r,o=e.spriteSheet;if(i[0]instanceof p5.Image||"string"==typeof i[0]){if(i.length>=3)throw new M("Ani",1);o=i[0],r=i[1]}else r=i[0];let h=this;if(o instanceof p5.Image&&1!=o.width&&1!=o.height)this.spriteSheet=o,a();else{let n;n="string"==typeof o?o:o.url,t._incrementPreload(),this.spriteSheet=t.loadImage(n,(()=>{a(),t._decrementPreload()})),"string"==typeof o&&(e.spriteSheet=this.spriteSheet)}function a(){Array.isArray(r)&&(r="object"==typeof r[0]?{frames:r}:4==r.length?{pos:r.slice(0,2),size:r.slice(2)}:{pos:r});let{w:i,h:s,width:o,height:a,size:n,row:l,col:d,line:p,x:u,y:c,pos:_,frames:g,frameCount:f,frameDelay:m,frameSize:y,delay:w,rotation:v}=r;y??=n||e.anis.frameSize,w&&(h.frameDelay=w),m&&(h.frameDelay=m),v&&(h.rotation=v),g&&Array.isArray(g)?f=g.length:f??=g||1,i??=o||e.anis.w,s??=a||e.anis.h,u??=d||0,c??=p||l||0,_&&(u=_[0],c=_[1]),"number"==typeof y?i=s=y:y&&(i=y[0],s=y[1]);let x=e.tileSize;if(i&&s?(i*=x,s*=x):!e._dimensionsUndef&&e.w&&e.h?(i??=e.w*x,s??=e.h*x):1!=x?(i??=x,s??=x):f?(i??=h.spriteSheet.width/f,s??=h.spriteSheet.height):i=s=h.spriteSheet.width<h.spriteSheet.height?h.spriteSheet.width:h.spriteSheet.height,Array.isArray(g)){let e=Math.round(h.spriteSheet.width/i);for(let r of g){let o;"number"==typeof r?(c=Math.floor(r/e)*s,u=r%e*i,o={x:u,y:c,w:i,h:s}):2==r.length?(u=r[0]*i,c=r[1]*s,o={x:u,y:c,w:i,h:s}):o={x:r[0],y:r[1],w:r[2],h:r[3]},t._defaultImageScale&&(o.defaultWidth=o.w*t._defaultImageScale,o.defaultHeight=o.h*t._defaultImageScale),h.push(o)}}else{(1!=x||_||void 0!==p||void 0!==l||void 0!==d)&&(u*=i,c*=s);for(let e=0;e<f;e++){let e={x:u,y:c,w:i,h:s};t._defaultImageScale&&(e.defaultWidth=i*t._defaultImageScale,e.defaultHeight=s*t._defaultImageScale),h.push(e),u+=i,u>=h.spriteSheet.width&&(u=0,c+=