tscratch 0.5.8 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,5 +18,6 @@ at `sebastianrucabado0@gmail.com`, or open a pull request here on Github.
18
18
  - [Collisions](https://github.com/Sebastian-GOAT/tscratch/blob/main/docs/collisions.md)
19
19
  - [Scenes](https://github.com/Sebastian-GOAT/tscratch/blob/main/docs/scenes.md)
20
20
  - [Sounds](https://github.com/Sebastian-GOAT/tscratch/blob/main/docs/sounds.md)
21
+ - [Multiplayer](https://github.com/Sebastian-GOAT/tscratch/blob/main/docs/multiplayer.md)
21
22
  - [Showcases](https://github.com/Sebastian-GOAT/tscratch/blob/main/docs/showcases.md)
22
23
  - [License](https://github.com/Sebastian-GOAT/tscratch/blob/main/docs/license.md)
@@ -0,0 +1,2 @@
1
+ "use strict";var I=Object.defineProperty;var U=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var N=(n,t)=>{for(var i in t)I(n,i,{get:t[i],enumerable:!0})},Q=(n,t,i,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of J(t))!K.call(n,r)&&r!==i&&I(n,r,{get:()=>t[r],enumerable:!(e=U(t,r))||e.enumerable});return n};var Z=n=>Q(I({},"__esModule",{value:!0}),n);var it={};N(it,{Arc:()=>B,Circle:()=>P,CustomPolygon:()=>M,Engine:()=>d,ImageSprite:()=>W,Multiplayer:()=>w,Oval:()=>C,Pen:()=>R,Rectangle:()=>v,RegularPolygon:()=>O,Sprite:()=>l,Square:()=>S,Text:()=>k,aspectRatio:()=>y,canvas:()=>s,ctx:()=>h,default:()=>tt,scale:()=>b,setAspectRatio:()=>A,setScale:()=>L});module.exports=Z(it);var s=document.getElementById("game-window")||document.createElement("canvas"),h=s.getContext("2d"),u=document.createElement("canvas"),a=u.getContext("2d");u.id="pen-canvas";var y=16/9,b;function z(){s.width=y*b,s.height=b,u.width=y*b,u.height=b}function L(n){b=n,z()}function A(n){y=n,z()}s.parentElement?.insertBefore(u,s);L(500);var l=class n{x;y;dir;scene;hidden;layer;cachedPath=null;pathDirty=!0;static collisionCanvas=null;static collisionCtx=null;refresh(){d.init().refresh()}invalidatePath(){this.pathDirty=!0,this.cachedPath=null}getCachedPath(){return(this.pathDirty||!this.cachedPath)&&(this.cachedPath=this.getPath(),this.pathDirty=!1),this.cachedPath}constructor(t){Object.assign(this,t),d.init().addSprite(this)}clone(t){return this.create({x:this.x,y:this.y,dir:this.dir,scene:this.scene,layer:this.layer,hidden:this.hidden,...t})}touching(t){if(this.hidden||t.hidden)return!1;let i=this.getBoundingBox(),e=t.getBoundingBox();if(!(Math.abs(i.x-e.x)<(i.width+e.width)/2&&Math.abs(i.y-e.y)<(i.height+e.height)/2))return!1;let o=i.x-i.width/2,g=i.y+i.height/2,f=i.x+i.width/2,x=i.y-i.height/2,D=e.x-e.width/2,F=e.y+e.height/2,q=e.x+e.width/2,H=e.y-e.height/2,X=Math.max(o,D),Y=Math.min(x,H),$=Math.min(f,q),G=Math.max(g,F),m=$-X,p=G-Y;if(m<=1||p<=1)return!1;n.collisionCanvas||(n.collisionCanvas=document.createElement("canvas"),n.collisionCtx=n.collisionCanvas.getContext("2d",{willReadFrequently:!0})),(n.collisionCanvas.width<m||n.collisionCanvas.height<p)&&(n.collisionCanvas.width=Math.max(m,n.collisionCanvas.width),n.collisionCanvas.height=Math.max(p,n.collisionCanvas.height));let c=n.collisionCtx;c.clearRect(0,0,m,p),c.save(),c.translate(this.x-X,p-this.y+Y),c.rotate(this.toRadians(this.dir)),c.fillStyle="red",c.fill(this.getCachedPath()),c.restore();let V=c.getImageData(0,0,m,p).data;c.clearRect(0,0,m,p),c.save(),c.translate(t.x-X,p-t.y+Y),c.rotate(this.toRadians(t.dir)),c.fillStyle="blue",c.fill(t.getCachedPath()),c.restore();let j=c.getImageData(0,0,m,p).data;for(let T=3;T<V.length;T+=4)if(V[T]>0&&j[T]>0)return!0;return!1}toRadians(t){return t*Math.PI/180}toDegrees(t){return t*180/Math.PI}move(t){this.x+=t*Math.sin(this.toRadians(this.dir)),this.y+=t*Math.cos(this.toRadians(this.dir)),this.refresh()}turn(t){this.dir+=t,this.refresh()}point(t){this.dir=t,this.refresh()}pointTowards(t,i){this.dir=90-this.toDegrees(Math.atan2(i,t)),this.refresh()}setX(t){this.x=t,this.refresh()}setY(t){this.y=t,this.refresh()}goTo(t,i){this.x=t,this.y=i,this.refresh()}changeX(t){this.x+=t,this.refresh()}changeY(t){this.y+=t,this.refresh()}show(){this.hidden=!1,this.refresh()}hide(){this.hidden=!0,this.refresh()}goToLayer(t){this.layer=t,this.refresh()}changeLayer(t){this.layer+=t,this.refresh()}};var d=class n{static instance;loopRunning=!1;gameLoop=null;maxFPS=24;deltaTime=1/this.maxFPS;lastFrame=performance.now();refreshScheduled=!1;animationFrameId=null;sounds=[];mouseX=0;mouseY=0;mouseDown=!1;mouseClicked=!1;keysPressed=new Set;currentScene="main";sceneMap=new Map;static init(){return this.instance||(this.instance=new n),this.instance}changeScene(t){this.sceneMap.get(t)||this.sceneMap.set(t,{sprites:[],loop:null}),this.loopRunning=!1,this.currentScene=t,this.gameLoop=this.sceneMap.get(t).loop,this.setMaxFramesPerSecond(this.maxFPS)}setLoop(t,i){if(!this.sceneMap.get(t)){this.sceneMap.set(t,{sprites:[],loop:i}),t===this.currentScene&&this.changeScene(t);return}this.sceneMap.get(t).loop=i,t===this.currentScene&&this.changeScene(t)}pauseLoop(){this.loopRunning=!1,this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}resumeLoop(){this.loopRunning=!0,this.setMaxFramesPerSecond(this.maxFPS)}addSprite(t){let{scene:i,layer:e}=t;if(!this.sceneMap.get(i)){this.sceneMap.set(i,{sprites:[t],loop:null});return}let r=this.sceneMap.get(i).sprites.findIndex(o=>o.layer>e);if(r===-1){this.sceneMap.get(i).sprites.push(t);return}this.sceneMap.get(i).sprites.splice(r,0,t),this.refresh()}removeSprite(t){let{scene:i}=t;this.sceneMap.get(i)&&(this.sceneMap.get(i).sprites=this.sceneMap.get(i).sprites.filter(e=>e!==t),this.refresh())}async setMaxFramesPerSecond(t){this.maxFPS=t;let i=this.gameLoop;if(!i)return;this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.loopRunning=!0;let e=1e3/t,r=0,o=async g=>{if(!this.loopRunning)return;let f=g-this.lastFrame;this.lastFrame=g,r+=f,r>=e&&(this.deltaTime=r/1e3,r=r%e,i&&await i()),this.animationFrameId=requestAnimationFrame(o)};this.lastFrame=performance.now(),this.animationFrameId=requestAnimationFrame(o)}refresh(){this.refreshScheduled||(this.refreshScheduled=!0,requestAnimationFrame(()=>{this.refreshScheduled=!1,h.clearRect(0,0,s.width,s.height),[...this.sceneMap.get(this.currentScene).sprites,...this.sceneMap.get("*").sprites].forEach(i=>{i.hidden||i.draw()})}))}async wait(t){return new Promise(i=>setTimeout(i,t))}async waitUntil(t){return new Promise(i=>{let e=()=>{t()?i():setTimeout(e,1e3/this.maxFPS)};e()})}hovering(t){let{mouseX:i,mouseY:e}=this,r=i+s.width/2,o=s.height/2-e,g=r-(t.x+s.width/2),f=o-(s.height/2-t.y),x=-this.toRadians(t.dir),D=g*Math.cos(x)-f*Math.sin(x),F=g*Math.sin(x)+f*Math.cos(x);return h.isPointInPath(t.getPath(),D,F)}keyPressed(t){return this.keysPressed.has(t)}playSound(t){let i=new Audio(t);return this.sounds.push(i),i.play(),i}stopSound(t){t.pause(),t.currentTime=0,this.sounds=this.sounds.filter(i=>i!==t)}stopAllSounds(){this.sounds.forEach(t=>{t.pause(),t.currentTime=0}),this.sounds=[]}pickRandom(t,i){return t>i&&([t,i]=[i,t]),Math.floor(Math.random()*(i-t+1)+t)}dotProduct(t){let[i,e]=t;switch(i.length){case 2:return i[0]*e[0]+i[1]*e[1];case 3:return i[0]*e[0]+i[1]*e[1]+i[2]*e[2];case 4:return i[0]*e[0]+i[1]*e[1]+i[2]*e[2]+i[3]*e[3]}}sin(t){return Math.sin(this.toRadians(t))}cos(t){return Math.cos(this.toRadians(t))}tan(t){return Math.tan(this.toRadians(t))}csc(t){return 1/Math.sin(this.toRadians(t))}sec(t){return 1/Math.cos(this.toRadians(t))}cot(t){return 1/Math.tan(this.toRadians(t))}asin(t){return this.toDegrees(Math.asin(t))}acos(t){return this.toDegrees(Math.acos(t))}acsc(t){return this.toDegrees(Math.asin(1/t))}asec(t){return this.toDegrees(Math.acos(1/t))}toRadians(t){return t*Math.PI/180}toDegrees(t){return t*180/Math.PI}constructor(){this.setMaxFramesPerSecond(24),u.addEventListener("mousemove",t=>{this.mouseX=t.clientX-u.offsetLeft-u.width/2,this.mouseY=-(t.clientY-u.offsetTop-u.height/2)}),u.addEventListener("mousedown",t=>{this.mouseDown=!0}),u.addEventListener("mouseup",t=>{this.mouseDown=!1}),u.addEventListener("click",t=>{this.mouseClicked=!0,setTimeout(()=>this.mouseClicked=!1,0)}),addEventListener("keydown",t=>{t.repeat||this.keysPressed.add(t.key)}),addEventListener("keyup",t=>{this.keysPressed.delete(t.key)})}};var E=require("socket.io-client"),w=class n{static instance;socket;static connect(t="http://localhost:3000"){return this.instance||(this.instance=new n(t)),this.instance}disconnect(){this.socket.disconnect()}constructor(t){this.socket=(0,E.io)(t)}broadcast(t,i){this.socket.emit(t,i)}on(t,i){this.socket.on(t,i)}};var v=class n extends l{discriminant="rectangle";width;height;color;outlineColor;outlineWidth;getBoundingBox(){return{x:this.x,y:this.y,width:Math.hypot(this.width,this.height),height:Math.hypot(this.width,this.height)}}getPath(){let t=new Path2D;return t.rect(-this.width/2,-this.height/2,this.width,this.height),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setWidth(t){this.width=t,this.invalidatePath(),this.refresh()}setHeight(t){this.height=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.width=t?.width??50,this.height=t?.height??50,this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var S=class n extends l{discriminant="square";sideLength;color;outlineColor;outlineWidth;getBoundingBox(){return{x:this.x,y:this.y,width:Math.hypot(this.sideLength,this.sideLength),height:Math.hypot(this.sideLength,this.sideLength)}}getPath(){let t=new Path2D;return t.rect(-this.sideLength/2,-this.sideLength/2,this.sideLength,this.sideLength),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setSideLength(t){this.sideLength=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.sideLength=t?.sideLength??50,this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var C=class n extends l{discriminant="oval";radX;radY;color;outlineColor;outlineWidth;getBoundingBox(){return{x:this.x,y:this.y,width:Math.hypot(this.radX*2,this.radY*2),height:Math.hypot(this.radX*2,this.radY*2)}}getPath(){let t=new Path2D;return t.ellipse(0,0,this.radX,this.radY,0,0,Math.PI*2),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setRadX(t){this.radX=t,this.invalidatePath(),this.refresh()}setRadY(t){this.radY=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.radX=t?.radX??25,this.radY=t?.radY??25,this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var P=class n extends l{discriminant="circle";radius;color;outlineColor;outlineWidth;getBoundingBox(){return{x:this.x,y:this.y,width:this.radius*2,height:this.radius*2}}getPath(){let t=new Path2D;return t.ellipse(0,0,this.radius,this.radius,0,0,Math.PI*2),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setRadius(t){this.radius=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.radius=t?.radius??25,this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var B=class n extends l{discriminant="arc";radius;angle;color;outlineColor;outlineWidth;getBoundingBox(){return{x:this.x,y:this.y,width:this.radius*2,height:this.radius*2}}getPath(){let t=new Path2D;return t.arc(0,0,this.radius,this.toRadians(this.angle/2-90),this.toRadians(-this.angle/2-90)),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setRadius(t){this.radius=t,this.invalidatePath(),this.refresh()}setAngle(t){this.angle=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.radius=t?.radius??25,this.angle=t?.angle??270,this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var O=class n extends l{discriminant="regularpolygon";sides;radius;color;outlineColor;outlineWidth;getBoundingBox(){return{x:this.x,y:this.y,width:this.radius*2,height:this.radius*2}}getPath(){let t=new Path2D,i=2*Math.PI/this.sides;t.moveTo(this.radius,0);for(let e=1;e<this.sides;e++)t.lineTo(this.radius*Math.cos(i*e),this.radius*Math.sin(i*e));return t.closePath(),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setSides(t){this.sides=t,this.invalidatePath(),this.refresh()}setRadius(t){this.radius=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.sides=t?.sides??5,this.radius=t?.radius??50,this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var M=class n extends l{discriminant="custompolygon";vertices;color;outlineColor;outlineWidth;getBoundingBox(){let t=0;for(let i of this.vertices){let e=Math.hypot(i[0],i[1]);e>t&&(t=e)}return{x:this.x,y:this.y,width:t,height:t}}getPath(){let t=new Path2D,i=this.vertices;if(i.length<2)return t;t.moveTo(i[0][0],i[0][1]);for(let e=1;e<i.length;e++)t.lineTo(i[e][0],i[e][1]);return t.closePath(),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setVertices(t){this.vertices=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.vertices=t?.vertices??[],this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var R=class n extends l{discriminant="pen";drawing;size;color;getBoundingBox(){return{x:this.x,y:this.y,width:this.size,height:this.size}}getPath(){return new Path2D}draw(){}create(t){return new n(t)}up(){this.drawing=!1}down(){this.drawing=!0}stamp(t){t.draw(!0)}eraseAll(){a.clearRect(0,0,s.width,s.height)}dot(){a.fillStyle=this.color,a.fillRect(this.x-this.size/2+s.width/2,-this.y-this.size/2+s.height/2,this.size,this.size)}drawLine(t,i){a.beginPath(),a.moveTo(t+s.width/2,-i+s.height/2),a.lineTo(this.x+s.width/2,-this.y+s.height/2),a.lineWidth=this.size,a.strokeStyle=this.color,a.stroke()}move(t){let i=this.x,e=this.y;this.x+=t*Math.sin(this.toRadians(this.dir)),this.y+=t*Math.cos(this.toRadians(this.dir)),this.drawing&&this.drawLine(i,e),this.refresh()}setX(t){let i=this.x,e=this.y;this.x=t,this.drawing&&this.drawLine(i,e),this.refresh()}setY(t){let i=this.x,e=this.y;this.y=t,this.drawing&&this.drawLine(i,e),this.refresh()}goTo(t,i){let e=this.x,r=this.y;this.x=t,this.y=i,this.drawing&&this.drawLine(e,r),this.refresh()}changeX(t){let i=this.x,e=this.y;this.x+=t,this.drawing&&this.drawLine(i,e),this.refresh()}changeY(t){let i=this.x,e=this.y;this.y+=t,this.drawing&&this.drawLine(i,e),this.refresh()}constructor(t){super(t),this.drawing=t?.drawing??!1,this.size=t?.size??5,this.color=t?.color??"black"}};var k=class n extends l{discriminant="text";content;color;fontFamily;fontSize;align;baseline;font;getBoundingBox(){let t=h.measureText(this.content),i=t.width,e=t.actualBoundingBoxAscent+t.actualBoundingBoxDescent;return{x:this.x,y:this.y,width:i,height:e}}getPath(){let t=new Path2D;h.save(),h.font=this.font;let i=h.measureText(this.content),e=i.width,r=i.actualBoundingBoxAscent+i.actualBoundingBoxDescent;return h.restore(),t.rect(-e/2,-r/2,e,r),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir)),i.font=this.font,i.fillStyle=this.color,i.textAlign=this.align,i.textBaseline=this.baseline,i.fillText(this.content,0,0),i.restore()}create(t){return new n(t)}setContent(t){this.content=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}setFontSize(t){this.fontSize=t,this.font=`${this.fontSize}px ${this.fontFamily}`,this.invalidatePath(),this.refresh()}setFontFamily(t){this.fontFamily=t,this.font=`${this.fontSize}px ${this.fontFamily}`,this.invalidatePath(),this.refresh()}setAlign(t){this.align=t,this.invalidatePath(),this.refresh()}setBaseline(t){this.baseline=t,this.invalidatePath(),this.refresh()}constructor(t){super(t),this.content=t?.content??"",this.color=t?.color??"black",this.fontFamily=t?.fontFamily??"Arial",this.fontSize=t?.fontSize??16,this.align=t?.align??"center",this.baseline=t?.baseline??"middle",this.font=`${this.fontSize}px ${this.fontFamily}`,this.draw()}};var W=class n extends l{discriminant="imagesprite";src;width;height;outlineColor;outlineWidth;img;getBoundingBox(){return{x:this.x,y:this.y,width:this.width,height:this.height}}getPath(){let t=new Path2D;return t.rect(-this.width/2,-this.height/2,this.width,this.height),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir)),i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.drawImage(this.img,0,0,this.img.width,this.img.height,-this.width/2,-this.height/2,this.width,this.height),this.outlineWidth&&i.stroke(this.getCachedPath()),i.restore()}create(t){return new n(t)}setSrc(t){this.src=t,this.refresh()}setWidth(t){this.width=t,this.invalidatePath(),this.refresh()}setHeight(t){this.height=t,this.invalidatePath(),this.refresh()}constructor(t){super(t),this.src=t?.src??"",this.img=new Image,this.img.src=this.src,this.width=t?.width??this.img.width,this.height=t?.height??this.img.height,this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var _={Engine:d,Sprite:l,Multiplayer:w,Rectangle:v,Square:S,Oval:C,Circle:P,Arc:B,RegularPolygon:O,CustomPolygon:M,Pen:R,Text:k,ImageSprite:W,scale:b,aspectRatio:y,setScale:L,setAspectRatio:A,canvas:s,ctx:h},tt=_;0&&(module.exports={Arc,Circle,CustomPolygon,Engine,ImageSprite,Multiplayer,Oval,Pen,Rectangle,RegularPolygon,Sprite,Square,Text,aspectRatio,canvas,ctx,scale,setAspectRatio,setScale});
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/index.ts","../../src/client/canvas.ts","../../src/client/Sprite.ts","../../src/client/Engine.ts","../../src/client/Multiplayer.ts","../../src/client/sprites/Rectangle.ts","../../src/client/sprites/Square.ts","../../src/client/sprites/Oval.ts","../../src/client/sprites/Circle.ts","../../src/client/sprites/Arc.ts","../../src/client/sprites/RegularPolygon.ts","../../src/client/sprites/CustomPolygon.ts","../../src/client/sprites/Pen.ts","../../src/client/sprites/Text.ts","../../src/client/sprites/ImageSprite.ts"],"sourcesContent":["// Main\r\nimport Engine from './Engine.ts';\r\nimport Sprite, { type SpriteOptions } from './Sprite.ts';\r\nimport { scale, aspectRatio, setScale, setAspectRatio, canvas, ctx } from './canvas.ts';\r\n\r\n// Multiplayer\r\nimport Multiplayer from './Multiplayer.ts';\r\n\r\n// Sprites\r\nimport Rectangle, { type RectangleOptions } from './sprites/Rectangle.ts';\r\nimport Square, { type SquareOptions } from './sprites/Square.ts';\r\nimport Oval, { type OvalOptions } from './sprites/Oval.ts';\r\nimport Circle, { type CircleOptions } from './sprites/Circle.ts';\r\nimport Arc, { type ArcOptions } from './sprites/Arc.ts';\r\nimport RegularPolygon, { type RegularPolygonOptions } from './sprites/RegularPolygon.ts';\r\nimport CustomPolygon, { type CustomPolygonOptions } from './sprites/CustomPolygon.ts';\r\nimport Pen, { type PenOptions } from './sprites/Pen.ts';\r\nimport Text, { type TextOptions, type CanvasTextAlign, type CanvasTextBaseline } from './sprites/Text.ts';\r\nimport ImageSprite, { type ImageSpriteOptions } from './sprites/ImageSprite.ts';\r\n\r\n// Types\r\nimport type { Vec2, Vec3, Vec4 } from './types/Vectors.ts';\r\n\r\nconst TScratch = {\r\n // Main\r\n Engine,\r\n Sprite,\r\n\r\n // Multiplayer\r\n Multiplayer,\r\n\r\n // Sprites\r\n Rectangle,\r\n Square,\r\n Oval,\r\n Circle,\r\n Arc,\r\n RegularPolygon,\r\n CustomPolygon,\r\n Pen,\r\n Text,\r\n ImageSprite,\r\n\r\n // Canvas\r\n scale,\r\n aspectRatio,\r\n setScale,\r\n setAspectRatio,\r\n canvas,\r\n ctx\r\n};\r\n\r\nexport default TScratch;\r\nexport {\r\n // Main\r\n Engine,\r\n Sprite,\r\n\r\n // Multiplayer\r\n Multiplayer,\r\n\r\n // Sprites\r\n Rectangle,\r\n Square,\r\n Oval,\r\n Circle,\r\n Arc,\r\n RegularPolygon,\r\n CustomPolygon,\r\n Pen,\r\n Text,\r\n ImageSprite,\r\n\r\n // Options\r\n type SpriteOptions,\r\n type RectangleOptions,\r\n type SquareOptions,\r\n type OvalOptions,\r\n type CircleOptions,\r\n type ArcOptions,\r\n type RegularPolygonOptions,\r\n type CustomPolygonOptions,\r\n type PenOptions,\r\n type TextOptions,\r\n type ImageSpriteOptions,\r\n\r\n // Other types\r\n type CanvasTextAlign,\r\n type CanvasTextBaseline,\r\n type Vec2,\r\n type Vec3,\r\n type Vec4,\r\n \r\n // Canvas\r\n scale,\r\n aspectRatio,\r\n setScale,\r\n setAspectRatio,\r\n canvas,\r\n ctx\r\n};","export const canvas = document.getElementById('game-window') as HTMLCanvasElement || document.createElement('canvas'); // For testing\r\nexport const ctx = canvas.getContext('2d')!;\r\n\r\nexport const penCanvas = document.createElement('canvas');\r\nexport const penCtx = penCanvas.getContext('2d')!;\r\npenCanvas.id = 'pen-canvas';\r\n\r\nexport let aspectRatio: number = 16 / 9;\r\nexport let scale: number;\r\n\r\nfunction updateSize() {\r\n canvas.width = aspectRatio * scale;\r\n canvas.height = scale;\r\n\r\n penCanvas.width = aspectRatio * scale;\r\n penCanvas.height = scale;\r\n}\r\n\r\nexport function setScale(newScale: number) {\r\n scale = newScale;\r\n updateSize();\r\n}\r\n\r\nexport function setAspectRatio(newAspectRatio: number) {\r\n aspectRatio = newAspectRatio;\r\n updateSize();\r\n}\r\n\r\ncanvas.parentElement?.insertBefore(penCanvas, canvas);\r\n\r\nsetScale(500);","import Engine from './Engine.ts';\r\n\r\nexport interface BoundingBox {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n}\r\n\r\nexport interface SpriteOptions {\r\n x: number;\r\n y: number;\r\n dir: number;\r\n scene: string;\r\n hidden: boolean;\r\n layer: number;\r\n}\r\n\r\nexport default abstract class Sprite {\r\n\r\n public x!: number;\r\n public y!: number;\r\n public dir!: number;\r\n public scene!: string;\r\n public hidden!: boolean;\r\n public layer!: number;\r\n\r\n private cachedPath: Path2D | null = null;\r\n private pathDirty: boolean = true;\r\n\r\n // Reusable collision detection canvas\r\n private static collisionCanvas: HTMLCanvasElement | null = null;\r\n private static collisionCtx: CanvasRenderingContext2D | null = null;\r\n\r\n // Rendering\r\n\r\n public abstract getBoundingBox(): BoundingBox;\r\n public abstract getPath(): Path2D;\r\n public abstract draw(stamping?: boolean): void;\r\n protected abstract create(options?: SpriteOptions): this;\r\n\r\n protected refresh() {\r\n Engine.init().refresh();\r\n }\r\n\r\n protected invalidatePath() {\r\n this.pathDirty = true;\r\n this.cachedPath = null;\r\n }\r\n\r\n protected getCachedPath(): Path2D {\r\n if (this.pathDirty || !this.cachedPath) {\r\n this.cachedPath = this.getPath();\r\n this.pathDirty = false;\r\n }\r\n return this.cachedPath;\r\n }\r\n\r\n constructor(options?: SpriteOptions) {\r\n Object.assign(this, options);\r\n Engine.init().addSprite(this);\r\n }\r\n\r\n public clone(options?: SpriteOptions): this {\r\n return this.create({\r\n x: this.x,\r\n y: this.y,\r\n dir: this.dir,\r\n scene: this.scene,\r\n layer: this.layer,\r\n hidden: this.hidden,\r\n ...options\r\n });\r\n }\r\n\r\n // Sensing\r\n\r\n public touching(sprite: Sprite): boolean {\r\n\r\n // Return if hidden\r\n if (this.hidden || sprite.hidden) return false;\r\n\r\n // AABB (bounding boxes)\r\n const bBox1 = this.getBoundingBox();\r\n const bBox2 = sprite.getBoundingBox();\r\n\r\n const aabbOverlap =\r\n Math.abs(bBox1.x - bBox2.x) < (bBox1.width + bBox2.width) / 2 &&\r\n Math.abs(bBox1.y - bBox2.y) < (bBox1.height + bBox2.height) / 2;\r\n\r\n if (!aabbOverlap) return false;\r\n\r\n // Image data (pixel perfect)\r\n\r\n // Compute intersection bounding box\r\n const b1Left = bBox1.x - bBox1.width / 2;\r\n const b1Top = bBox1.y + bBox1.height / 2;\r\n const b1Right = bBox1.x + bBox1.width / 2;\r\n const b1Bottom = bBox1.y - bBox1.height / 2;\r\n\r\n const b2Left = bBox2.x - bBox2.width / 2;\r\n const b2Top = bBox2.y + bBox2.height / 2;\r\n const b2Right = bBox2.x + bBox2.width / 2;\r\n const b2Bottom = bBox2.y - bBox2.height / 2;\r\n\r\n const xMin = Math.max(b1Left, b2Left);\r\n const yMin = Math.min(b1Bottom, b2Bottom);\r\n const xMax = Math.min(b1Right, b2Right);\r\n const yMax = Math.max(b1Top, b2Top);\r\n\r\n const width = xMax - xMin;\r\n const height = yMax - yMin;\r\n\r\n if (width <= 1 || height <= 1) return false;\r\n\r\n // Reuse or create offscreen canvas for collision detection\r\n if (!Sprite.collisionCanvas) {\r\n Sprite.collisionCanvas = document.createElement('canvas');\r\n Sprite.collisionCtx = Sprite.collisionCanvas.getContext('2d', { willReadFrequently: true })!;\r\n }\r\n\r\n // Resize if needed\r\n if (Sprite.collisionCanvas.width < width || Sprite.collisionCanvas.height < height) {\r\n Sprite.collisionCanvas.width = Math.max(width, Sprite.collisionCanvas.width);\r\n Sprite.collisionCanvas.height = Math.max(height, Sprite.collisionCanvas.height);\r\n }\r\n\r\n const ctx = Sprite.collisionCtx!;\r\n ctx.clearRect(0, 0, width, height);\r\n\r\n // Draw first sprite\r\n ctx.save();\r\n ctx.translate(this.x - xMin, height - this.y + yMin);\r\n ctx.rotate(this.toRadians(this.dir));\r\n ctx.fillStyle = 'red';\r\n ctx.fill(this.getCachedPath());\r\n ctx.restore();\r\n const img1 = ctx.getImageData(0, 0, width, height).data;\r\n\r\n // Draw second sprite\r\n ctx.clearRect(0, 0, width, height);\r\n ctx.save();\r\n ctx.translate(sprite.x - xMin, height - sprite.y + yMin);\r\n ctx.rotate(this.toRadians(sprite.dir));\r\n ctx.fillStyle = 'blue';\r\n ctx.fill(sprite.getCachedPath());\r\n ctx.restore();\r\n const img2 = ctx.getImageData(0, 0, width, height).data;\r\n\r\n // Check for overlapping non-transparent pixels\r\n for (let i = 3; i < img1.length; i += 4) // alpha channel\r\n if (img1[i]! > 0 && img2[i]! > 0) return true;\r\n\r\n return false;\r\n }\r\n\r\n // Helpers\r\n\r\n protected toRadians(deg: number) {\r\n return deg * Math.PI / 180;\r\n }\r\n\r\n protected toDegrees(rad: number) {\r\n return rad * 180 / Math.PI;\r\n }\r\n\r\n // Methods\r\n\r\n // Motion\r\n public move(steps: number) {\r\n this.x += steps * Math.sin(this.toRadians(this.dir));\r\n this.y += steps * Math.cos(this.toRadians(this.dir));\r\n this.refresh();\r\n }\r\n\r\n public turn(deg: number) {\r\n this.dir += deg;\r\n this.refresh();\r\n }\r\n\r\n public point(dir: number) {\r\n this.dir = dir;\r\n this.refresh();\r\n }\r\n\r\n public pointTowards(x: number, y: number) {\r\n this.dir = 90 - this.toDegrees(Math.atan2(y, x));\r\n this.refresh();\r\n }\r\n\r\n public setX(x: number) {\r\n this.x = x;\r\n this.refresh();\r\n }\r\n\r\n public setY(y: number) {\r\n this.y = y;\r\n this.refresh();\r\n }\r\n\r\n public goTo(x: number, y: number) {\r\n this.x = x;\r\n this.y = y;\r\n this.refresh();\r\n }\r\n\r\n public changeX(dX: number) {\r\n this.x += dX;\r\n this.refresh();\r\n }\r\n\r\n public changeY(dY: number) {\r\n this.y += dY;\r\n this.refresh();\r\n }\r\n\r\n // Looks\r\n\r\n public show() {\r\n this.hidden = false;\r\n this.refresh();\r\n }\r\n\r\n public hide() {\r\n this.hidden = true;\r\n this.refresh();\r\n }\r\n\r\n public goToLayer(layer: number) {\r\n this.layer = layer;\r\n this.refresh();\r\n }\r\n\r\n public changeLayer(dL: number) {\r\n this.layer += dL;\r\n this.refresh();\r\n }\r\n}","import { canvas, ctx, penCanvas } from './canvas.ts';\r\nimport Sprite from './Sprite.ts';\r\nimport type { Vec2, Vec3, Vec4 } from './types/Vectors.ts';\r\n\r\ntype GameLoop = (() => void) | (() => Promise<void>);\r\n\r\ntype SceneMap = Map<string, {\r\n sprites: Sprite[];\r\n loop: GameLoop | null;\r\n}>\r\n\r\nexport default class Engine {\r\n\r\n private static instance: Engine;\r\n\r\n private loopRunning: boolean = false;\r\n public gameLoop: GameLoop | null = null;\r\n\r\n public maxFPS: number = 24;\r\n public deltaTime: number = 1 / this.maxFPS;\r\n private lastFrame: number = performance.now();\r\n private refreshScheduled: boolean = false;\r\n private animationFrameId: number | null = null;\r\n\r\n public sounds: HTMLAudioElement[] = [];\r\n\r\n public mouseX: number = 0;\r\n public mouseY: number = 0;\r\n\r\n public mouseDown: boolean = false;\r\n public mouseClicked: boolean = false;\r\n\r\n private keysPressed: Set<string> = new Set<string>();\r\n\r\n public currentScene: string = 'main';\r\n public sceneMap: SceneMap = new Map();\r\n\r\n // Singleton initialization\r\n\r\n public static init() {\r\n if (!this.instance)\r\n this.instance = new Engine();\r\n\r\n return this.instance;\r\n }\r\n\r\n // Change the scene\r\n\r\n public changeScene(scene: string) {\r\n if (!this.sceneMap.get(scene))\r\n this.sceneMap.set(scene, { sprites: [], loop: null });\r\n\r\n this.loopRunning = false;\r\n this.currentScene = scene;\r\n this.gameLoop = this.sceneMap.get(scene)!.loop;\r\n this.setMaxFramesPerSecond(this.maxFPS); // Update the interval function\r\n }\r\n\r\n // Loops\r\n\r\n public setLoop(scene: string, loop: GameLoop) {\r\n if (!this.sceneMap.get(scene)) {\r\n this.sceneMap.set(scene, { sprites: [], loop });\r\n if (scene === this.currentScene)\r\n this.changeScene(scene);\r\n return;\r\n }\r\n\r\n this.sceneMap.get(scene)!.loop = loop;\r\n if (scene === this.currentScene)\r\n this.changeScene(scene);\r\n }\r\n\r\n public pauseLoop() {\r\n this.loopRunning = false;\r\n if (this.animationFrameId !== null) {\r\n cancelAnimationFrame(this.animationFrameId);\r\n this.animationFrameId = null;\r\n }\r\n }\r\n\r\n public resumeLoop() {\r\n this.loopRunning = true;\r\n void this.setMaxFramesPerSecond(this.maxFPS);\r\n }\r\n\r\n // Internal\r\n\r\n public addSprite(sprite: Sprite) {\r\n const { scene, layer } = sprite;\r\n\r\n if (!this.sceneMap.get(scene)) {\r\n this.sceneMap.set(scene, { sprites: [sprite], loop: null });\r\n return;\r\n }\r\n\r\n let targetIndex = this.sceneMap.get(scene)!.sprites.findIndex(s => s.layer > layer);\r\n if (targetIndex === -1) {\r\n this.sceneMap.get(scene)!.sprites.push(sprite);\r\n return;\r\n }\r\n\r\n this.sceneMap.get(scene)!.sprites.splice(targetIndex, 0, sprite);\r\n this.refresh();\r\n }\r\n\r\n public removeSprite(sprite: Sprite) {\r\n const { scene } = sprite;\r\n\r\n if (!this.sceneMap.get(scene)) return;\r\n\r\n this.sceneMap.get(scene)!.sprites = this.sceneMap.get(scene)!.sprites.filter(s => s !== sprite);\r\n this.refresh();\r\n }\r\n\r\n public async setMaxFramesPerSecond(maxFPS: number) {\r\n this.maxFPS = maxFPS;\r\n\r\n let loop = this.gameLoop;\r\n if (!loop) return;\r\n\r\n // Cancel existing animation frame if any\r\n if (this.animationFrameId !== null) {\r\n cancelAnimationFrame(this.animationFrameId);\r\n this.animationFrameId = null;\r\n }\r\n\r\n this.loopRunning = true;\r\n const frameInterval = 1000 / maxFPS;\r\n let accumulator = 0;\r\n\r\n const tick = async (currentTime: number) => {\r\n if (!this.loopRunning) return;\r\n\r\n const deltaTime = currentTime - this.lastFrame;\r\n this.lastFrame = currentTime;\r\n accumulator += deltaTime;\r\n\r\n // Fixed timestep: only run loop when enough time has passed\r\n if (accumulator >= frameInterval) {\r\n this.deltaTime = accumulator / 1000;\r\n accumulator = accumulator % frameInterval;\r\n\r\n if (loop) await loop();\r\n }\r\n\r\n this.animationFrameId = requestAnimationFrame(tick);\r\n };\r\n\r\n this.lastFrame = performance.now();\r\n this.animationFrameId = requestAnimationFrame(tick);\r\n }\r\n\r\n public refresh() {\r\n if (this.refreshScheduled) return;\r\n this.refreshScheduled = true;\r\n\r\n requestAnimationFrame(() => {\r\n this.refreshScheduled = false;\r\n ctx.clearRect(0, 0, canvas.width, canvas.height);\r\n const sprites = [\r\n ...this.sceneMap.get(this.currentScene)!.sprites,\r\n ...this.sceneMap.get('*')!.sprites\r\n ];\r\n sprites.forEach(sprite => {\r\n if (!sprite.hidden)\r\n sprite.draw();\r\n });\r\n });\r\n }\r\n\r\n // Wait functions\r\n\r\n public async wait(ms: number): Promise<void> {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n }\r\n\r\n public async waitUntil(conditionGetter: () => boolean): Promise<void> {\r\n return new Promise(resolve => {\r\n const check = () => {\r\n if (conditionGetter()) resolve();\r\n else setTimeout(check, 1000 / this.maxFPS);\r\n }\r\n check();\r\n });\r\n }\r\n\r\n // Events\r\n\r\n public hovering(sprite: Sprite) {\r\n const { mouseX, mouseY } = this;\r\n\r\n const canvasMouseX = mouseX + canvas.width / 2;\r\n const canvasMouseY = canvas.height / 2 - mouseY;\r\n\r\n // Mouse relative to sprite center\r\n const localX = canvasMouseX - (sprite.x + canvas.width / 2);\r\n const localY = canvasMouseY - (canvas.height / 2 - sprite.y);\r\n\r\n // Rotate mouse point by -dir to align with the path's local coordinates\r\n const angle = -this.toRadians(sprite.dir);\r\n const rotatedX = localX * Math.cos(angle) - localY * Math.sin(angle);\r\n const rotatedY = localX * Math.sin(angle) + localY * Math.cos(angle);\r\n\r\n return ctx.isPointInPath(sprite.getPath(), rotatedX, rotatedY);\r\n }\r\n\r\n public keyPressed(key: string) {\r\n return this.keysPressed.has(key);\r\n }\r\n\r\n // Sound\r\n\r\n public playSound(src: string) {\r\n const audio = new Audio(src);\r\n this.sounds.push(audio);\r\n\r\n audio.play();\r\n\r\n return audio;\r\n }\r\n\r\n public stopSound(sound: HTMLAudioElement) {\r\n sound.pause();\r\n sound.currentTime = 0;\r\n this.sounds = this.sounds.filter(s => s !== sound);\r\n }\r\n\r\n public stopAllSounds() {\r\n this.sounds.forEach(sound => {\r\n sound.pause();\r\n sound.currentTime = 0;\r\n });\r\n this.sounds = [];\r\n }\r\n\r\n // Math\r\n\r\n public pickRandom(min: number, max: number) {\r\n if (min > max)\r\n [min, max] = [max, min];\r\n return Math.floor(Math.random() * (max - min + 1) + min);\r\n }\r\n\r\n public dotProduct(vectors: [Vec2, Vec2] | [Vec3, Vec3] | [Vec4, Vec4]) {\r\n const [a, b] = vectors;\r\n\r\n switch (a.length) {\r\n case 2: return a[0] * b[0] + a[1] * b[1];\r\n case 3: return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]!;\r\n case 4: return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]! + a[3] * b[3]!; // TypeScript doesn't narrow down the types on b\r\n }\r\n }\r\n\r\n // Trigonometric functions\r\n public sin(deg: number) {\r\n return Math.sin(this.toRadians(deg));\r\n }\r\n\r\n public cos(deg: number) {\r\n return Math.cos(this.toRadians(deg));\r\n }\r\n\r\n public tan(deg: number) {\r\n return Math.tan(this.toRadians(deg));\r\n }\r\n\r\n public csc(deg: number) {\r\n return 1 / Math.sin(this.toRadians(deg));\r\n }\r\n\r\n public sec(deg: number) {\r\n return 1 / Math.cos(this.toRadians(deg));\r\n }\r\n\r\n public cot(deg: number) {\r\n return 1 / Math.tan(this.toRadians(deg));\r\n }\r\n\r\n // Inverse Trigonometric functions\r\n public asin(val: number) {\r\n return this.toDegrees(Math.asin(val));\r\n }\r\n\r\n public acos(val: number) {\r\n return this.toDegrees(Math.acos(val));\r\n }\r\n\r\n public acsc(val: number) {\r\n return this.toDegrees(Math.asin(1 / val));\r\n }\r\n\r\n public asec(val: number) {\r\n return this.toDegrees(Math.acos(1 / val));\r\n }\r\n\r\n // Helpers\r\n\r\n public toRadians(deg: number) {\r\n return deg * Math.PI / 180;\r\n }\r\n\r\n public toDegrees(rad: number) {\r\n return rad * 180 / Math.PI;\r\n }\r\n\r\n // Private constructor\r\n\r\n private constructor() {\r\n void this.setMaxFramesPerSecond(24);\r\n\r\n // Events\r\n\r\n // Mouse\r\n penCanvas.addEventListener('mousemove', e => {\r\n this.mouseX = e.clientX - penCanvas.offsetLeft - penCanvas.width / 2;\r\n this.mouseY = -(e.clientY - penCanvas.offsetTop - penCanvas.height / 2);\r\n });\r\n penCanvas.addEventListener('mousedown', e => {\r\n this.mouseDown = true;\r\n });\r\n penCanvas.addEventListener('mouseup', e => {\r\n this.mouseDown = false;\r\n });\r\n penCanvas.addEventListener('click', e => {\r\n this.mouseClicked = true;\r\n setTimeout(() => this.mouseClicked = false, 0);\r\n });\r\n\r\n // Keys\r\n addEventListener('keydown', e => {\r\n if (e.repeat) return;\r\n this.keysPressed.add(e.key);\r\n });\r\n\r\n addEventListener('keyup', e => {\r\n this.keysPressed.delete(e.key);\r\n });\r\n }\r\n}","import { io, Socket } from 'socket.io-client';\r\n\r\nexport default class Multiplayer {\r\n\r\n private static instance: Multiplayer;\r\n private socket: Socket;\r\n\r\n public static connect(serverURL: string = 'http://localhost:3000') {\r\n if (!this.instance)\r\n this.instance = new Multiplayer(serverURL);\r\n\r\n return this.instance;\r\n }\r\n\r\n public disconnect() {\r\n this.socket.disconnect();\r\n }\r\n\r\n private constructor(serverURL: string) {\r\n this.socket = io(serverURL);\r\n }\r\n\r\n // Methods\r\n\r\n public broadcast<T = unknown>(eventName: string, data: T) {\r\n this.socket.emit(eventName, data);\r\n }\r\n\r\n public on<T = unknown>(eventName: string, callback: (data: T) => void) {\r\n this.socket.on(eventName, callback);\r\n }\r\n}","import Sprite, { type BoundingBox, type SpriteOptions } from '../Sprite.ts';\r\nimport { ctx, canvas, penCtx } from '../canvas.ts';\r\n\r\nexport interface RectangleOptions extends SpriteOptions {\r\n width?: number;\r\n height?: number;\r\n color?: string;\r\n outlineColor?: string;\r\n outlineWidth?: number;\r\n};\r\n\r\nexport default class Rectangle extends Sprite {\r\n\r\n public discriminant = 'rectangle';\r\n\r\n public width: number;\r\n public height: number;\r\n public color: string;\r\n public outlineColor: string;\r\n public outlineWidth: number;\r\n\r\n public getBoundingBox(): BoundingBox {\r\n return {\r\n x: this.x,\r\n y: this.y,\r\n width: Math.hypot(this.width, this.height),\r\n height: Math.hypot(this.width, this.height)\r\n };\r\n }\r\n\r\n public getPath(): Path2D {\r\n const path = new Path2D();\r\n\r\n path.rect(\r\n -this.width / 2,\r\n -this.height / 2,\r\n this.width,\r\n this.height\r\n );\r\n\r\n return path;\r\n }\r\n\r\n public draw(stamping?: boolean): void {\r\n const c = stamping ? penCtx : ctx;\r\n\r\n c.save();\r\n\r\n const cX = this.x + canvas.width / 2;\r\n const cY = -this.y + canvas.height / 2;\r\n c.translate(cX, cY);\r\n\r\n c.rotate(this.toRadians(this.dir));\r\n\r\n const path = this.getCachedPath();\r\n\r\n c.fillStyle = this.color;\r\n c.strokeStyle = this.outlineColor;\r\n c.lineWidth = this.outlineWidth;\r\n c.fill(path)\r\n if (this.outlineWidth)\r\n c.stroke(path);\r\n\r\n c.restore();\r\n }\r\n\r\n public create(options?: RectangleOptions): this {\r\n return new Rectangle(options) as this;\r\n }\r\n\r\n public setWidth(width: number) {\r\n this.width = width;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setHeight(height: number) {\r\n this.height = height;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setColor(color: string) {\r\n this.color = color;\r\n this.refresh();\r\n }\r\n\r\n constructor(options?: RectangleOptions) {\r\n super(options);\r\n this.width = options?.width ?? 50;\r\n this.height = options?.height ?? 50;\r\n this.color = options?.color ?? 'black';\r\n this.outlineColor = options?.outlineColor ?? 'black';\r\n this.outlineWidth = options?.outlineWidth ?? 0;\r\n this.draw();\r\n }\r\n\r\n}","import Sprite, { type BoundingBox, type SpriteOptions } from '../Sprite.ts';\r\nimport { ctx, canvas, penCtx } from '../canvas.ts';\r\n\r\nexport interface SquareOptions extends SpriteOptions {\r\n sideLength?: number;\r\n color?: string;\r\n outlineColor?: string;\r\n outlineWidth?: number;\r\n};\r\n\r\nexport default class Square extends Sprite {\r\n\r\n public discriminant = 'square';\r\n\r\n public sideLength: number;\r\n public color: string;\r\n public outlineColor: string;\r\n public outlineWidth: number;\r\n\r\n public getBoundingBox(): BoundingBox {\r\n return {\r\n x: this.x,\r\n y: this.y,\r\n width: Math.hypot(this.sideLength, this.sideLength),\r\n height: Math.hypot(this.sideLength, this.sideLength)\r\n };\r\n }\r\n\r\n public getPath(): Path2D {\r\n const path = new Path2D();\r\n\r\n path.rect(\r\n -this.sideLength / 2,\r\n -this.sideLength / 2,\r\n this.sideLength,\r\n this.sideLength\r\n );\r\n\r\n return path;\r\n }\r\n\r\n public draw(stamping?: boolean): void {\r\n const c = stamping ? penCtx : ctx;\r\n\r\n c.save();\r\n\r\n const cX = this.x + canvas.width / 2;\r\n const cY = -this.y + canvas.height / 2;\r\n c.translate(cX, cY);\r\n\r\n c.rotate(this.toRadians(this.dir));\r\n\r\n const path = this.getCachedPath();\r\n\r\n c.fillStyle = this.color;\r\n c.strokeStyle = this.outlineColor;\r\n c.lineWidth = this.outlineWidth;\r\n c.fill(path)\r\n if (this.outlineWidth)\r\n c.stroke(path);\r\n\r\n c.restore();\r\n }\r\n\r\n public create(options?: SquareOptions): this {\r\n return new Square(options) as this;\r\n }\r\n\r\n public setSideLength(sideLength: number) {\r\n this.sideLength = sideLength;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setColor(color: string) {\r\n this.color = color;\r\n this.refresh();\r\n }\r\n\r\n constructor(options?: SquareOptions) {\r\n super(options);\r\n this.sideLength = options?.sideLength ?? 50;\r\n this.color = options?.color ?? 'black';\r\n this.outlineColor = options?.outlineColor ?? 'black';\r\n this.outlineWidth = options?.outlineWidth ?? 0;\r\n this.draw();\r\n }\r\n\r\n}","import Sprite, { type BoundingBox, type SpriteOptions } from '../Sprite.ts';\r\nimport { canvas, ctx, penCtx } from '../canvas.ts';\r\n\r\nexport interface OvalOptions extends SpriteOptions {\r\n radX?: number;\r\n radY?: number;\r\n color?: string;\r\n outlineColor?: string;\r\n outlineWidth?: number;\r\n};\r\n\r\nexport default class Oval extends Sprite {\r\n\r\n public discriminant = 'oval';\r\n\r\n public radX: number;\r\n public radY: number;\r\n public color: string;\r\n public outlineColor: string;\r\n public outlineWidth: number;\r\n\r\n public getBoundingBox(): BoundingBox {\r\n return {\r\n x: this.x,\r\n y: this.y,\r\n width: Math.hypot(this.radX * 2, this.radY * 2),\r\n height: Math.hypot(this.radX * 2, this.radY * 2)\r\n };\r\n }\r\n\r\n public getPath(): Path2D {\r\n const path = new Path2D();\r\n\r\n path.ellipse(\r\n 0, 0,\r\n this.radX,\r\n this.radY,\r\n 0, 0,\r\n Math.PI * 2\r\n );\r\n\r\n return path;\r\n }\r\n\r\n public draw(stamping?: boolean): void {\r\n const c = stamping ? penCtx : ctx;\r\n\r\n c.save();\r\n\r\n const cX = this.x + canvas.width / 2;\r\n const cY = -this.y + canvas.height / 2;\r\n c.translate(cX, cY);\r\n\r\n c.rotate(this.toRadians(this.dir));\r\n\r\n const path = this.getCachedPath();\r\n\r\n c.fillStyle = this.color;\r\n c.strokeStyle = this.outlineColor;\r\n c.lineWidth = this.outlineWidth;\r\n c.fill(path)\r\n if (this.outlineWidth)\r\n c.stroke(path);\r\n\r\n c.restore();\r\n }\r\n\r\n public create(options?: OvalOptions): this {\r\n return new Oval(options) as this;\r\n }\r\n\r\n public setRadX(radX: number) {\r\n this.radX = radX;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setRadY(radY: number) {\r\n this.radY = radY;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setColor(color: string) {\r\n this.color = color;\r\n this.refresh();\r\n }\r\n\r\n constructor(options?: OvalOptions) {\r\n super(options);\r\n this.radX = options?.radX ?? 25;\r\n this.radY = options?.radY ?? 25;\r\n this.color = options?.color ?? 'black';\r\n this.outlineColor = options?.outlineColor ?? 'black';\r\n this.outlineWidth = options?.outlineWidth ?? 0;\r\n this.draw();\r\n }\r\n\r\n}","import Sprite, { type BoundingBox, type SpriteOptions } from '../Sprite.ts';\r\nimport { canvas, ctx, penCtx } from '../canvas.ts';\r\n\r\nexport interface CircleOptions extends SpriteOptions {\r\n radius?: number;\r\n color?: string;\r\n outlineColor?: string;\r\n outlineWidth?: number;\r\n};\r\n\r\nexport default class Circle extends Sprite {\r\n\r\n public discriminant = 'circle';\r\n\r\n public radius: number;\r\n public color: string;\r\n public outlineColor: string;\r\n public outlineWidth: number;\r\n\r\n public getBoundingBox(): BoundingBox {\r\n return {\r\n x: this.x,\r\n y: this.y,\r\n width: this.radius * 2,\r\n height: this.radius * 2\r\n };\r\n }\r\n\r\n public getPath(): Path2D {\r\n const path = new Path2D();\r\n\r\n path.ellipse(\r\n 0, 0,\r\n this.radius,\r\n this.radius,\r\n 0, 0,\r\n Math.PI * 2\r\n );\r\n\r\n return path;\r\n }\r\n\r\n public draw(stamping?: boolean): void {\r\n const c = stamping ? penCtx : ctx;\r\n\r\n c.save();\r\n\r\n const cX = this.x + canvas.width / 2;\r\n const cY = -this.y + canvas.height / 2;\r\n c.translate(cX, cY);\r\n\r\n c.rotate(this.toRadians(this.dir));\r\n\r\n const path = this.getCachedPath();\r\n\r\n c.fillStyle = this.color;\r\n c.strokeStyle = this.outlineColor;\r\n c.lineWidth = this.outlineWidth;\r\n c.fill(path)\r\n if (this.outlineWidth)\r\n c.stroke(path);\r\n\r\n c.restore();\r\n }\r\n\r\n public create(options?: CircleOptions): this {\r\n return new Circle(options) as this;\r\n }\r\n\r\n public setRadius(radius: number) {\r\n this.radius = radius;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setColor(color: string) {\r\n this.color = color;\r\n this.refresh();\r\n }\r\n\r\n constructor(options?: CircleOptions) {\r\n super(options);\r\n this.radius = options?.radius ?? 25;\r\n this.color = options?.color ?? 'black';\r\n this.outlineColor = options?.outlineColor ?? 'black';\r\n this.outlineWidth = options?.outlineWidth ?? 0;\r\n this.draw();\r\n }\r\n\r\n}","import Sprite, { type BoundingBox, type SpriteOptions } from '../Sprite.ts';\r\nimport { canvas, ctx, penCtx } from '../canvas.ts';\r\n\r\nexport interface ArcOptions extends SpriteOptions {\r\n radius?: number;\r\n angle?: number;\r\n color?: string;\r\n outlineColor?: string;\r\n outlineWidth?: number;\r\n};\r\n\r\nexport default class Arc extends Sprite {\r\n\r\n public discriminant = 'arc';\r\n\r\n public radius: number;\r\n public angle: number;\r\n public color: string;\r\n public outlineColor: string;\r\n public outlineWidth: number;\r\n\r\n public getBoundingBox(): BoundingBox {\r\n return {\r\n x: this.x,\r\n y: this.y,\r\n width: this.radius * 2,\r\n height: this.radius * 2\r\n };\r\n }\r\n\r\n public getPath(): Path2D {\r\n const path = new Path2D();\r\n\r\n path.arc(\r\n 0, 0,\r\n this.radius,\r\n this.toRadians(this.angle / 2 - 90),\r\n this.toRadians(-this.angle / 2 - 90)\r\n );\r\n\r\n return path;\r\n }\r\n\r\n public draw(stamping?: boolean): void {\r\n const c = stamping ? penCtx : ctx;\r\n\r\n c.save();\r\n\r\n const cX = this.x + canvas.width / 2;\r\n const cY = -this.y + canvas.height / 2;\r\n c.translate(cX, cY);\r\n\r\n c.rotate(this.toRadians(this.dir));\r\n\r\n const path = this.getCachedPath();\r\n\r\n c.fillStyle = this.color;\r\n c.strokeStyle = this.outlineColor;\r\n c.lineWidth = this.outlineWidth;\r\n c.fill(path)\r\n if (this.outlineWidth)\r\n c.stroke(path);\r\n\r\n c.restore();\r\n }\r\n\r\n public create(options?: ArcOptions): this {\r\n return new Arc(options) as this;\r\n }\r\n\r\n public setRadius(radius: number) {\r\n this.radius = radius;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setAngle(angle: number) {\r\n this.angle = angle;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setColor(color: string) {\r\n this.color = color;\r\n this.refresh();\r\n }\r\n\r\n constructor(options?: ArcOptions) {\r\n super(options);\r\n\r\n this.radius = options?.radius ?? 25;\r\n this.angle = options?.angle ?? 270;\r\n this.color = options?.color ?? 'black';\r\n this.outlineColor = options?.outlineColor ?? 'black';\r\n this.outlineWidth = options?.outlineWidth ?? 0;\r\n\r\n this.draw();\r\n }\r\n\r\n}","import { canvas, ctx, penCtx } from '../canvas.ts';\r\nimport Sprite, { type BoundingBox, type SpriteOptions } from '../Sprite.ts';\r\n\r\nexport interface RegularPolygonOptions extends SpriteOptions {\r\n sides?: number;\r\n radius?: number;\r\n color?: string;\r\n outlineColor?: string;\r\n outlineWidth?: number;\r\n}\r\n\r\nexport default class RegularPolygon extends Sprite {\r\n\r\n public discriminant = 'regularpolygon';\r\n\r\n public sides: number;\r\n public radius: number;\r\n public color: string;\r\n public outlineColor: string;\r\n public outlineWidth: number;\r\n\r\n public getBoundingBox(): BoundingBox {\r\n return {\r\n x: this.x,\r\n y: this.y,\r\n width: this.radius * 2,\r\n height: this.radius * 2\r\n };\r\n }\r\n\r\n public getPath(): Path2D {\r\n const path = new Path2D();\r\n const step = (2 * Math.PI) / this.sides;\r\n path.moveTo(this.radius, 0);\r\n for (let i = 1; i < this.sides; i++) {\r\n path.lineTo(this.radius * Math.cos(step * i), this.radius * Math.sin(step * i));\r\n }\r\n path.closePath();\r\n return path;\r\n }\r\n\r\n public draw(stamping?: boolean) {\r\n const c = stamping ? penCtx : ctx;\r\n\r\n c.save();\r\n\r\n const cX = this.x + canvas.width / 2;\r\n const cY = -this.y + canvas.height / 2;\r\n\r\n c.translate(cX, cY);\r\n c.rotate(this.toRadians(this.dir));\r\n\r\n const path = this.getCachedPath();\r\n\r\n c.fillStyle = this.color;\r\n c.strokeStyle = this.outlineColor;\r\n c.lineWidth = this.outlineWidth;\r\n c.fill(path)\r\n if (this.outlineWidth)\r\n c.stroke(path);\r\n\r\n c.restore();\r\n }\r\n\r\n public create(options?: RegularPolygonOptions): this {\r\n return new RegularPolygon(options) as this;\r\n }\r\n\r\n public setSides(sides: number) {\r\n this.sides = sides;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setRadius(radius: number) {\r\n this.radius = radius;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setColor(color: string) {\r\n this.color = color;\r\n this.refresh();\r\n }\r\n\r\n constructor(options?: RegularPolygonOptions) {\r\n super(options);\r\n this.sides = options?.sides ?? 5;\r\n this.radius = options?.radius ?? 50;\r\n this.color = options?.color ?? 'black';\r\n this.outlineColor = options?.outlineColor ?? 'black';\r\n this.outlineWidth = options?.outlineWidth ?? 0;\r\n this.draw();\r\n }\r\n\r\n}","import Sprite, { type BoundingBox, type SpriteOptions } from '../Sprite.ts';\r\nimport { canvas, ctx, penCtx } from '../canvas.ts';\r\nimport type { Vec2 } from '../types/Vectors.ts';\r\n\r\nexport interface CustomPolygonOptions extends SpriteOptions {\r\n vertices?: Vec2[];\r\n color?: string;\r\n outlineColor?: string;\r\n outlineWidth?: number;\r\n};\r\n\r\nexport default class CustomPolygon extends Sprite {\r\n\r\n public discriminant = 'custompolygon';\r\n\r\n public vertices: Vec2[];\r\n public color: string;\r\n public outlineColor: string;\r\n public outlineWidth: number;\r\n\r\n public getBoundingBox(): BoundingBox {\r\n\r\n let furthestVertexSize = 0;\r\n\r\n for (const v of this.vertices) {\r\n\r\n const size = Math.hypot(v[0], v[1]);\r\n\r\n if (size > furthestVertexSize)\r\n furthestVertexSize = size;\r\n }\r\n\r\n return {\r\n x: this.x,\r\n y: this.y,\r\n width: furthestVertexSize,\r\n height: furthestVertexSize\r\n };\r\n }\r\n\r\n public getPath(): Path2D {\r\n const path = new Path2D();\r\n const vertices = this.vertices;\r\n\r\n if (vertices.length < 2) return path;\r\n\r\n path.moveTo(vertices[0]![0], vertices[0]![1]);\r\n\r\n for (let i = 1; i < vertices.length; i++)\r\n path.lineTo(vertices[i]![0], vertices[i]![1]);\r\n\r\n path.closePath();\r\n\r\n return path;\r\n }\r\n\r\n public draw(stamping?: boolean): void {\r\n const c = stamping ? penCtx : ctx;\r\n\r\n c.save();\r\n\r\n const cX = this.x + canvas.width / 2;\r\n const cY = -this.y + canvas.height / 2;\r\n c.translate(cX, cY);\r\n\r\n c.rotate(this.toRadians(this.dir));\r\n\r\n const path = this.getCachedPath();\r\n\r\n c.fillStyle = this.color;\r\n c.strokeStyle = this.outlineColor;\r\n c.lineWidth = this.outlineWidth;\r\n c.fill(path)\r\n if (this.outlineWidth)\r\n c.stroke(path);\r\n\r\n c.restore();\r\n }\r\n\r\n public create(options?: CustomPolygonOptions): this {\r\n return new CustomPolygon(options) as this;\r\n }\r\n\r\n public setVertices(vertices: Vec2[]) {\r\n this.vertices = vertices;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setColor(color: string) {\r\n this.color = color;\r\n this.refresh();\r\n }\r\n\r\n constructor(options?: CustomPolygonOptions) {\r\n super(options);\r\n\r\n this.vertices = options?.vertices ?? [];\r\n this.color = options?.color ?? 'black';\r\n this.outlineColor = options?.outlineColor ?? 'black';\r\n this.outlineWidth = options?.outlineWidth ?? 0;\r\n\r\n this.draw();\r\n }\r\n\r\n}","import { canvas, penCtx } from '../canvas.ts';\r\nimport Sprite, { type BoundingBox, type SpriteOptions } from '../Sprite.ts';\r\n\r\nexport interface PenOptions extends SpriteOptions {\r\n drawing?: boolean;\r\n size?: number;\r\n color?: string;\r\n}\r\n\r\nexport default class Pen extends Sprite {\r\n\r\n public discriminant = 'pen';\r\n\r\n public drawing: boolean;\r\n public size: number;\r\n public color: string;\r\n\r\n public getBoundingBox(): BoundingBox {\r\n return {\r\n x: this.x,\r\n y: this.y,\r\n width: this.size,\r\n height: this.size\r\n };\r\n }\r\n\r\n public getPath(): Path2D {\r\n return new Path2D();\r\n }\r\n public draw() {}\r\n\r\n public create(options?: PenOptions): this {\r\n return new Pen(options) as this;\r\n }\r\n\r\n public up() {\r\n this.drawing = false;\r\n }\r\n\r\n public down() {\r\n this.drawing = true;\r\n }\r\n\r\n public stamp(sprite: Sprite) {\r\n sprite.draw(true);\r\n }\r\n\r\n public eraseAll() {\r\n penCtx.clearRect(0, 0, canvas.width, canvas.height);\r\n }\r\n\r\n public dot() {\r\n penCtx.fillStyle = this.color;\r\n penCtx.fillRect(\r\n this.x - this.size / 2 + canvas.width / 2,\r\n -this.y - this.size / 2 + canvas.height / 2,\r\n this.size,\r\n this.size\r\n );\r\n }\r\n\r\n private drawLine(lastX: number, lastY: number) {\r\n penCtx.beginPath();\r\n\r\n penCtx.moveTo(lastX + canvas.width / 2, -lastY + canvas.height / 2);\r\n penCtx.lineTo(this.x + canvas.width / 2, -this.y + canvas.height / 2);\r\n\r\n penCtx.lineWidth = this.size;\r\n penCtx.strokeStyle = this.color;\r\n penCtx.stroke();\r\n }\r\n\r\n // Overriding methods to include drawing\r\n\r\n public override move(steps: number) {\r\n const lastX = this.x;\r\n const lastY = this.y;\r\n\r\n this.x += steps * Math.sin(this.toRadians(this.dir));\r\n this.y += steps * Math.cos(this.toRadians(this.dir));\r\n if (this.drawing)\r\n this.drawLine(lastX, lastY);\r\n this.refresh();\r\n }\r\n\r\n public override setX(x: number) {\r\n const lastX = this.x;\r\n const lastY = this.y;\r\n\r\n this.x = x;\r\n if (this.drawing)\r\n this.drawLine(lastX, lastY);\r\n this.refresh();\r\n }\r\n\r\n public override setY(y: number) {\r\n const lastX = this.x;\r\n const lastY = this.y;\r\n\r\n this.y = y;\r\n if (this.drawing)\r\n this.drawLine(lastX, lastY);\r\n this.refresh();\r\n }\r\n\r\n public override goTo(x: number, y: number) {\r\n const lastX = this.x;\r\n const lastY = this.y;\r\n\r\n this.x = x;\r\n this.y = y;\r\n if (this.drawing)\r\n this.drawLine(lastX, lastY);\r\n this.refresh();\r\n }\r\n\r\n public override changeX(dX: number) {\r\n const lastX = this.x;\r\n const lastY = this.y;\r\n\r\n this.x += dX;\r\n if (this.drawing)\r\n this.drawLine(lastX, lastY);\r\n this.refresh();\r\n }\r\n\r\n public override changeY(dY: number) {\r\n const lastX = this.x;\r\n const lastY = this.y;\r\n\r\n this.y += dY;\r\n if (this.drawing)\r\n this.drawLine(lastX, lastY);\r\n this.refresh();\r\n }\r\n\r\n // Constructor\r\n\r\n constructor(options?: PenOptions) {\r\n super(options);\r\n this.drawing = options?.drawing ?? false;\r\n this.size = options?.size ?? 5;\r\n this.color = options?.color ?? 'black';\r\n }\r\n\r\n}","import { canvas, ctx, penCtx } from '../canvas.ts';\r\nimport Sprite, { type BoundingBox, type SpriteOptions } from '../Sprite.ts';\r\n\r\nexport type CanvasTextAlign =\r\n | 'left'\r\n | 'right'\r\n | 'center'\r\n | 'start'\r\n | 'end';\r\n\r\nexport type CanvasTextBaseline =\r\n | 'top'\r\n | 'hanging'\r\n | 'middle'\r\n | 'alphabetic'\r\n | 'ideographic'\r\n | 'bottom';\r\n\r\nexport interface TextOptions extends SpriteOptions {\r\n content?: string;\r\n color?: string;\r\n fontFamily?: string;\r\n fontSize?: number;\r\n align?: CanvasTextAlign;\r\n baseline?: CanvasTextBaseline;\r\n}\r\n\r\nexport default class Text extends Sprite {\r\n\r\n public discriminant = 'text';\r\n\r\n public content: string;\r\n public color: string;\r\n public fontFamily: string;\r\n public fontSize: number;\r\n public align: CanvasTextAlign;\r\n public baseline: CanvasTextBaseline;\r\n\r\n private font: string;\r\n\r\n public getBoundingBox(): BoundingBox {\r\n const metrics = ctx.measureText(this.content);\r\n const width = metrics.width;\r\n const height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;\r\n\r\n return {\r\n x: this.x,\r\n y: this.y,\r\n width, height\r\n };\r\n }\r\n\r\n public getPath(): Path2D {\r\n const path = new Path2D();\r\n\r\n ctx.save();\r\n \r\n ctx.font = this.font;\r\n\r\n const metrics = ctx.measureText(this.content);\r\n const width = metrics.width;\r\n const height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;\r\n\r\n ctx.restore();\r\n\r\n path.rect(-width / 2, -height / 2, width, height);\r\n\r\n return path\r\n }\r\n\r\n public override draw(stamping?: boolean) {\r\n const c = stamping ? penCtx : ctx;\r\n\r\n c.save();\r\n\r\n const cX = this.x + canvas.width / 2;\r\n const cY = -this.y + canvas.height / 2;\r\n c.translate(cX, cY);\r\n\r\n c.rotate(this.toRadians(this.dir));\r\n\r\n c.font = this.font;\r\n c.fillStyle = this.color;\r\n c.textAlign = this.align;\r\n c.textBaseline = this.baseline;\r\n\r\n c.fillText(this.content, 0, 0);\r\n\r\n c.restore();\r\n }\r\n\r\n public create(options?: TextOptions): this {\r\n return new Text(options) as this;\r\n }\r\n\r\n // Methods\r\n\r\n public setContent(content: string) {\r\n this.content = content;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setColor(color: string) {\r\n this.color = color;\r\n this.refresh();\r\n }\r\n\r\n public setFontSize(fontSize: number) {\r\n this.fontSize = fontSize;\r\n this.font = `${this.fontSize}px ${this.fontFamily}`;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setFontFamily(fontFamily: string) {\r\n this.fontFamily = fontFamily;\r\n this.font = `${this.fontSize}px ${this.fontFamily}`;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setAlign(align: CanvasTextAlign) {\r\n this.align = align;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setBaseline(baseline: CanvasTextBaseline) {\r\n this.baseline = baseline;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n // Constructor\r\n\r\n constructor(options?: TextOptions) {\r\n super(options);\r\n\r\n this.content = options?.content ?? '';\r\n this.color = options?.color ?? 'black';\r\n this.fontFamily = options?.fontFamily ?? 'Arial';\r\n this.fontSize = options?.fontSize ?? 16;\r\n this.align = options?.align ?? 'center';\r\n this.baseline = options?.baseline ?? 'middle';\r\n\r\n this.font = `${this.fontSize}px ${this.fontFamily}`;\r\n\r\n this.draw();\r\n }\r\n}","import { canvas, ctx, penCtx } from '../canvas.ts';\r\nimport Sprite, { type BoundingBox, type SpriteOptions } from '../Sprite.ts';\r\n\r\nexport interface ImageSpriteOptions extends SpriteOptions {\r\n src?: string;\r\n width: number;\r\n height: number;\r\n outlineColor?: string;\r\n outlineWidth?: number;\r\n};\r\n\r\nexport default class ImageSprite extends Sprite {\r\n\r\n public discriminant = 'imagesprite';\r\n\r\n public src: string;\r\n public width: number;\r\n public height: number;\r\n public outlineColor: string;\r\n public outlineWidth: number;\r\n\r\n protected img: HTMLImageElement;\r\n\r\n public getBoundingBox(): BoundingBox {\r\n return {\r\n x: this.x,\r\n y: this.y,\r\n width: this.width,\r\n height: this.height\r\n };\r\n }\r\n\r\n public getPath(): Path2D {\r\n const path = new Path2D();\r\n\r\n path.rect(\r\n -this.width / 2,\r\n -this.height / 2,\r\n this.width,\r\n this.height\r\n );\r\n\r\n return path;\r\n }\r\n\r\n public override draw(stamping?: boolean) {\r\n const c = stamping ? penCtx : ctx;\r\n\r\n c.save();\r\n\r\n const cX = this.x + canvas.width / 2;\r\n const cY = -this.y + canvas.height / 2;\r\n c.translate(cX, cY);\r\n\r\n c.rotate(this.toRadians(this.dir));\r\n\r\n c.strokeStyle = this.outlineColor;\r\n c.lineWidth = this.outlineWidth;\r\n c.drawImage(\r\n this.img,\r\n 0, 0,\r\n this.img.width,\r\n this.img.height,\r\n -this.width / 2,\r\n -this.height / 2,\r\n this.width, this.height\r\n );\r\n if (this.outlineWidth)\r\n c.stroke(this.getCachedPath());\r\n\r\n c.restore();\r\n }\r\n\r\n public create(options?: ImageSpriteOptions): this {\r\n return new ImageSprite(options) as this;\r\n }\r\n\r\n // Methods\r\n\r\n public setSrc(src: string) {\r\n this.src = src;\r\n this.refresh();\r\n }\r\n\r\n public setWidth(width: number) {\r\n this.width = width;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n public setHeight(height: number) {\r\n this.height = height;\r\n this.invalidatePath();\r\n this.refresh();\r\n }\r\n\r\n // Constructor\r\n\r\n constructor(options?: ImageSpriteOptions) {\r\n super(options);\r\n\r\n this.src = options?.src ?? '';\r\n this.img = new Image();\r\n this.img.src = this.src;\r\n\r\n this.width = options?.width ?? this.img.width;\r\n this.height = options?.height ?? this.img.height;\r\n\r\n this.outlineColor = options?.outlineColor ?? 'black';\r\n this.outlineWidth = options?.outlineWidth ?? 0;\r\n \r\n this.draw();\r\n }\r\n}"],"mappings":"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","names":["client_exports","__export","Arc","Circle","CustomPolygon","Engine","ImageSprite","Multiplayer","Oval","Pen","Rectangle","RegularPolygon","Sprite","Square","Text","aspectRatio","canvas","ctx","client_default","scale","setAspectRatio","setScale","__toCommonJS","canvas","ctx","penCanvas","penCtx","aspectRatio","scale","updateSize","setScale","newScale","setAspectRatio","newAspectRatio","Sprite","_Sprite","Engine","options","sprite","bBox1","bBox2","b1Left","b1Top","b1Right","b1Bottom","b2Left","b2Top","b2Right","b2Bottom","xMin","yMin","xMax","yMax","width","height","ctx","img1","img2","i","deg","rad","steps","dir","x","y","dX","dY","layer","dL","Engine","_Engine","scene","loop","sprite","layer","targetIndex","s","maxFPS","frameInterval","accumulator","tick","currentTime","deltaTime","ctx","canvas","ms","resolve","conditionGetter","check","mouseX","mouseY","canvasMouseX","canvasMouseY","localX","localY","angle","rotatedX","rotatedY","key","src","audio","sound","min","max","vectors","a","b","deg","val","rad","penCanvas","e","import_socket","Multiplayer","_Multiplayer","serverURL","eventName","data","callback","Rectangle","_Rectangle","Sprite","path","stamping","c","penCtx","ctx","cX","canvas","cY","options","width","height","color","Square","_Square","Sprite","path","stamping","c","penCtx","ctx","cX","canvas","cY","options","sideLength","color","Oval","_Oval","Sprite","path","stamping","c","penCtx","ctx","cX","canvas","cY","options","radX","radY","color","Circle","_Circle","Sprite","path","stamping","c","penCtx","ctx","cX","canvas","cY","options","radius","color","Arc","_Arc","Sprite","path","stamping","c","penCtx","ctx","cX","canvas","cY","options","radius","angle","color","RegularPolygon","_RegularPolygon","Sprite","path","step","i","stamping","c","penCtx","ctx","cX","canvas","cY","options","sides","radius","color","CustomPolygon","_CustomPolygon","Sprite","furthestVertexSize","v","size","path","vertices","i","stamping","c","penCtx","ctx","cX","canvas","cY","options","color","Pen","_Pen","Sprite","options","sprite","penCtx","canvas","lastX","lastY","steps","x","y","dX","dY","Text","_Text","Sprite","metrics","ctx","width","height","path","stamping","c","penCtx","cX","canvas","cY","options","content","color","fontSize","fontFamily","align","baseline","ImageSprite","_ImageSprite","Sprite","path","stamping","c","penCtx","ctx","cX","canvas","cY","options","src","width","height","TScratch","Engine","Sprite","Multiplayer","Rectangle","Square","Oval","Circle","Arc","RegularPolygon","CustomPolygon","Pen","Text","ImageSprite","scale","aspectRatio","setScale","setAspectRatio","canvas","ctx","client_default"]}
@@ -5,12 +5,12 @@ interface BoundingBox {
5
5
  height: number;
6
6
  }
7
7
  interface SpriteOptions {
8
- x?: number;
9
- y?: number;
10
- dir?: number;
11
- scene?: string;
12
- hidden?: boolean;
13
- layer?: number;
8
+ x: number;
9
+ y: number;
10
+ dir: number;
11
+ scene: string;
12
+ hidden: boolean;
13
+ layer: number;
14
14
  }
15
15
  declare abstract class Sprite {
16
16
  x: number;
@@ -26,10 +26,12 @@ declare abstract class Sprite {
26
26
  abstract getBoundingBox(): BoundingBox;
27
27
  abstract getPath(): Path2D;
28
28
  abstract draw(stamping?: boolean): void;
29
+ protected abstract create(options?: SpriteOptions): this;
29
30
  protected refresh(): void;
30
31
  protected invalidatePath(): void;
31
32
  protected getCachedPath(): Path2D;
32
33
  constructor(options?: SpriteOptions);
34
+ clone(options?: SpriteOptions): this;
33
35
  touching(sprite: Sprite): boolean;
34
36
  protected toRadians(deg: number): number;
35
37
  protected toDegrees(rad: number): number;
@@ -52,13 +54,11 @@ type Vec2 = [number, number];
52
54
  type Vec3 = [number, number, number];
53
55
  type Vec4 = [number, number, number, number];
54
56
 
55
- type GameLoop = (() => any) | (() => Promise<any>);
56
- type SceneMap = {
57
- [scene: string]: {
58
- sprites: Sprite[];
59
- loop: GameLoop | null;
60
- };
61
- };
57
+ type GameLoop = (() => void) | (() => Promise<void>);
58
+ type SceneMap = Map<string, {
59
+ sprites: Sprite[];
60
+ loop: GameLoop | null;
61
+ }>;
62
62
  declare class Engine {
63
63
  private static instance;
64
64
  private loopRunning;
@@ -111,9 +111,21 @@ declare class Engine {
111
111
 
112
112
  declare const canvas: HTMLCanvasElement;
113
113
  declare const ctx: CanvasRenderingContext2D;
114
+ declare let aspectRatio: number;
115
+ declare let scale: number;
114
116
  declare function setScale(newScale: number): void;
115
117
  declare function setAspectRatio(newAspectRatio: number): void;
116
118
 
119
+ declare class Multiplayer {
120
+ private static instance;
121
+ private socket;
122
+ static connect(serverURL?: string): Multiplayer;
123
+ disconnect(): void;
124
+ private constructor();
125
+ broadcast<T = unknown>(eventName: string, data: T): void;
126
+ on<T = unknown>(eventName: string, callback: (data: T) => void): void;
127
+ }
128
+
117
129
  interface RectangleOptions extends SpriteOptions {
118
130
  width?: number;
119
131
  height?: number;
@@ -131,6 +143,7 @@ declare class Rectangle extends Sprite {
131
143
  getBoundingBox(): BoundingBox;
132
144
  getPath(): Path2D;
133
145
  draw(stamping?: boolean): void;
146
+ create(options?: RectangleOptions): this;
134
147
  setWidth(width: number): void;
135
148
  setHeight(height: number): void;
136
149
  setColor(color: string): void;
@@ -152,6 +165,7 @@ declare class Square extends Sprite {
152
165
  getBoundingBox(): BoundingBox;
153
166
  getPath(): Path2D;
154
167
  draw(stamping?: boolean): void;
168
+ create(options?: SquareOptions): this;
155
169
  setSideLength(sideLength: number): void;
156
170
  setColor(color: string): void;
157
171
  constructor(options?: SquareOptions);
@@ -174,6 +188,7 @@ declare class Oval extends Sprite {
174
188
  getBoundingBox(): BoundingBox;
175
189
  getPath(): Path2D;
176
190
  draw(stamping?: boolean): void;
191
+ create(options?: OvalOptions): this;
177
192
  setRadX(radX: number): void;
178
193
  setRadY(radY: number): void;
179
194
  setColor(color: string): void;
@@ -195,6 +210,7 @@ declare class Circle extends Sprite {
195
210
  getBoundingBox(): BoundingBox;
196
211
  getPath(): Path2D;
197
212
  draw(stamping?: boolean): void;
213
+ create(options?: CircleOptions): this;
198
214
  setRadius(radius: number): void;
199
215
  setColor(color: string): void;
200
216
  constructor(options?: CircleOptions);
@@ -217,6 +233,7 @@ declare class Arc extends Sprite {
217
233
  getBoundingBox(): BoundingBox;
218
234
  getPath(): Path2D;
219
235
  draw(stamping?: boolean): void;
236
+ create(options?: ArcOptions): this;
220
237
  setRadius(radius: number): void;
221
238
  setAngle(angle: number): void;
222
239
  setColor(color: string): void;
@@ -240,6 +257,7 @@ declare class RegularPolygon extends Sprite {
240
257
  getBoundingBox(): BoundingBox;
241
258
  getPath(): Path2D;
242
259
  draw(stamping?: boolean): void;
260
+ create(options?: RegularPolygonOptions): this;
243
261
  setSides(sides: number): void;
244
262
  setRadius(radius: number): void;
245
263
  setColor(color: string): void;
@@ -261,6 +279,7 @@ declare class CustomPolygon extends Sprite {
261
279
  getBoundingBox(): BoundingBox;
262
280
  getPath(): Path2D;
263
281
  draw(stamping?: boolean): void;
282
+ create(options?: CustomPolygonOptions): this;
264
283
  setVertices(vertices: Vec2[]): void;
265
284
  setColor(color: string): void;
266
285
  constructor(options?: CustomPolygonOptions);
@@ -279,6 +298,7 @@ declare class Pen extends Sprite {
279
298
  getBoundingBox(): BoundingBox;
280
299
  getPath(): Path2D;
281
300
  draw(): void;
301
+ create(options?: PenOptions): this;
282
302
  up(): void;
283
303
  down(): void;
284
304
  stamp(sprite: Sprite): void;
@@ -316,6 +336,7 @@ declare class Text extends Sprite {
316
336
  getBoundingBox(): BoundingBox;
317
337
  getPath(): Path2D;
318
338
  draw(stamping?: boolean): void;
339
+ create(options?: TextOptions): this;
319
340
  setContent(content: string): void;
320
341
  setColor(color: string): void;
321
342
  setFontSize(fontSize: number): void;
@@ -343,6 +364,7 @@ declare class ImageSprite extends Sprite {
343
364
  getBoundingBox(): BoundingBox;
344
365
  getPath(): Path2D;
345
366
  draw(stamping?: boolean): void;
367
+ create(options?: ImageSpriteOptions): this;
346
368
  setSrc(src: string): void;
347
369
  setWidth(width: number): void;
348
370
  setHeight(height: number): void;
@@ -352,6 +374,7 @@ declare class ImageSprite extends Sprite {
352
374
  declare const TScratch: {
353
375
  Engine: typeof Engine;
354
376
  Sprite: typeof Sprite;
377
+ Multiplayer: typeof Multiplayer;
355
378
  Rectangle: typeof Rectangle;
356
379
  Square: typeof Square;
357
380
  Oval: typeof Oval;
@@ -362,10 +385,12 @@ declare const TScratch: {
362
385
  Pen: typeof Pen;
363
386
  Text: typeof Text;
364
387
  ImageSprite: typeof ImageSprite;
388
+ scale: number;
389
+ aspectRatio: number;
365
390
  setScale: typeof setScale;
366
391
  setAspectRatio: typeof setAspectRatio;
367
392
  canvas: HTMLCanvasElement;
368
393
  ctx: CanvasRenderingContext2D;
369
394
  };
370
395
 
371
- export { Arc, type ArcOptions, type CanvasTextAlign, type CanvasTextBaseline, Circle, type CircleOptions, CustomPolygon, type CustomPolygonOptions, Engine, ImageSprite, type ImageSpriteOptions, Oval, type OvalOptions, Pen, type PenOptions, Rectangle, type RectangleOptions, RegularPolygon, type RegularPolygonOptions, Sprite, type SpriteOptions, Square, type SquareOptions, Text, type TextOptions, type Vec2, type Vec3, type Vec4, canvas, ctx, TScratch as default, setAspectRatio, setScale };
396
+ export { Arc, type ArcOptions, type CanvasTextAlign, type CanvasTextBaseline, Circle, type CircleOptions, CustomPolygon, type CustomPolygonOptions, Engine, ImageSprite, type ImageSpriteOptions, Multiplayer, Oval, type OvalOptions, Pen, type PenOptions, Rectangle, type RectangleOptions, RegularPolygon, type RegularPolygonOptions, Sprite, type SpriteOptions, Square, type SquareOptions, Text, type TextOptions, type Vec2, type Vec3, type Vec4, aspectRatio, canvas, ctx, TScratch as default, scale, setAspectRatio, setScale };
@@ -5,12 +5,12 @@ interface BoundingBox {
5
5
  height: number;
6
6
  }
7
7
  interface SpriteOptions {
8
- x?: number;
9
- y?: number;
10
- dir?: number;
11
- scene?: string;
12
- hidden?: boolean;
13
- layer?: number;
8
+ x: number;
9
+ y: number;
10
+ dir: number;
11
+ scene: string;
12
+ hidden: boolean;
13
+ layer: number;
14
14
  }
15
15
  declare abstract class Sprite {
16
16
  x: number;
@@ -26,10 +26,12 @@ declare abstract class Sprite {
26
26
  abstract getBoundingBox(): BoundingBox;
27
27
  abstract getPath(): Path2D;
28
28
  abstract draw(stamping?: boolean): void;
29
+ protected abstract create(options?: SpriteOptions): this;
29
30
  protected refresh(): void;
30
31
  protected invalidatePath(): void;
31
32
  protected getCachedPath(): Path2D;
32
33
  constructor(options?: SpriteOptions);
34
+ clone(options?: SpriteOptions): this;
33
35
  touching(sprite: Sprite): boolean;
34
36
  protected toRadians(deg: number): number;
35
37
  protected toDegrees(rad: number): number;
@@ -52,13 +54,11 @@ type Vec2 = [number, number];
52
54
  type Vec3 = [number, number, number];
53
55
  type Vec4 = [number, number, number, number];
54
56
 
55
- type GameLoop = (() => any) | (() => Promise<any>);
56
- type SceneMap = {
57
- [scene: string]: {
58
- sprites: Sprite[];
59
- loop: GameLoop | null;
60
- };
61
- };
57
+ type GameLoop = (() => void) | (() => Promise<void>);
58
+ type SceneMap = Map<string, {
59
+ sprites: Sprite[];
60
+ loop: GameLoop | null;
61
+ }>;
62
62
  declare class Engine {
63
63
  private static instance;
64
64
  private loopRunning;
@@ -111,9 +111,21 @@ declare class Engine {
111
111
 
112
112
  declare const canvas: HTMLCanvasElement;
113
113
  declare const ctx: CanvasRenderingContext2D;
114
+ declare let aspectRatio: number;
115
+ declare let scale: number;
114
116
  declare function setScale(newScale: number): void;
115
117
  declare function setAspectRatio(newAspectRatio: number): void;
116
118
 
119
+ declare class Multiplayer {
120
+ private static instance;
121
+ private socket;
122
+ static connect(serverURL?: string): Multiplayer;
123
+ disconnect(): void;
124
+ private constructor();
125
+ broadcast<T = unknown>(eventName: string, data: T): void;
126
+ on<T = unknown>(eventName: string, callback: (data: T) => void): void;
127
+ }
128
+
117
129
  interface RectangleOptions extends SpriteOptions {
118
130
  width?: number;
119
131
  height?: number;
@@ -131,6 +143,7 @@ declare class Rectangle extends Sprite {
131
143
  getBoundingBox(): BoundingBox;
132
144
  getPath(): Path2D;
133
145
  draw(stamping?: boolean): void;
146
+ create(options?: RectangleOptions): this;
134
147
  setWidth(width: number): void;
135
148
  setHeight(height: number): void;
136
149
  setColor(color: string): void;
@@ -152,6 +165,7 @@ declare class Square extends Sprite {
152
165
  getBoundingBox(): BoundingBox;
153
166
  getPath(): Path2D;
154
167
  draw(stamping?: boolean): void;
168
+ create(options?: SquareOptions): this;
155
169
  setSideLength(sideLength: number): void;
156
170
  setColor(color: string): void;
157
171
  constructor(options?: SquareOptions);
@@ -174,6 +188,7 @@ declare class Oval extends Sprite {
174
188
  getBoundingBox(): BoundingBox;
175
189
  getPath(): Path2D;
176
190
  draw(stamping?: boolean): void;
191
+ create(options?: OvalOptions): this;
177
192
  setRadX(radX: number): void;
178
193
  setRadY(radY: number): void;
179
194
  setColor(color: string): void;
@@ -195,6 +210,7 @@ declare class Circle extends Sprite {
195
210
  getBoundingBox(): BoundingBox;
196
211
  getPath(): Path2D;
197
212
  draw(stamping?: boolean): void;
213
+ create(options?: CircleOptions): this;
198
214
  setRadius(radius: number): void;
199
215
  setColor(color: string): void;
200
216
  constructor(options?: CircleOptions);
@@ -217,6 +233,7 @@ declare class Arc extends Sprite {
217
233
  getBoundingBox(): BoundingBox;
218
234
  getPath(): Path2D;
219
235
  draw(stamping?: boolean): void;
236
+ create(options?: ArcOptions): this;
220
237
  setRadius(radius: number): void;
221
238
  setAngle(angle: number): void;
222
239
  setColor(color: string): void;
@@ -240,6 +257,7 @@ declare class RegularPolygon extends Sprite {
240
257
  getBoundingBox(): BoundingBox;
241
258
  getPath(): Path2D;
242
259
  draw(stamping?: boolean): void;
260
+ create(options?: RegularPolygonOptions): this;
243
261
  setSides(sides: number): void;
244
262
  setRadius(radius: number): void;
245
263
  setColor(color: string): void;
@@ -261,6 +279,7 @@ declare class CustomPolygon extends Sprite {
261
279
  getBoundingBox(): BoundingBox;
262
280
  getPath(): Path2D;
263
281
  draw(stamping?: boolean): void;
282
+ create(options?: CustomPolygonOptions): this;
264
283
  setVertices(vertices: Vec2[]): void;
265
284
  setColor(color: string): void;
266
285
  constructor(options?: CustomPolygonOptions);
@@ -279,6 +298,7 @@ declare class Pen extends Sprite {
279
298
  getBoundingBox(): BoundingBox;
280
299
  getPath(): Path2D;
281
300
  draw(): void;
301
+ create(options?: PenOptions): this;
282
302
  up(): void;
283
303
  down(): void;
284
304
  stamp(sprite: Sprite): void;
@@ -316,6 +336,7 @@ declare class Text extends Sprite {
316
336
  getBoundingBox(): BoundingBox;
317
337
  getPath(): Path2D;
318
338
  draw(stamping?: boolean): void;
339
+ create(options?: TextOptions): this;
319
340
  setContent(content: string): void;
320
341
  setColor(color: string): void;
321
342
  setFontSize(fontSize: number): void;
@@ -343,6 +364,7 @@ declare class ImageSprite extends Sprite {
343
364
  getBoundingBox(): BoundingBox;
344
365
  getPath(): Path2D;
345
366
  draw(stamping?: boolean): void;
367
+ create(options?: ImageSpriteOptions): this;
346
368
  setSrc(src: string): void;
347
369
  setWidth(width: number): void;
348
370
  setHeight(height: number): void;
@@ -352,6 +374,7 @@ declare class ImageSprite extends Sprite {
352
374
  declare const TScratch: {
353
375
  Engine: typeof Engine;
354
376
  Sprite: typeof Sprite;
377
+ Multiplayer: typeof Multiplayer;
355
378
  Rectangle: typeof Rectangle;
356
379
  Square: typeof Square;
357
380
  Oval: typeof Oval;
@@ -362,10 +385,12 @@ declare const TScratch: {
362
385
  Pen: typeof Pen;
363
386
  Text: typeof Text;
364
387
  ImageSprite: typeof ImageSprite;
388
+ scale: number;
389
+ aspectRatio: number;
365
390
  setScale: typeof setScale;
366
391
  setAspectRatio: typeof setAspectRatio;
367
392
  canvas: HTMLCanvasElement;
368
393
  ctx: CanvasRenderingContext2D;
369
394
  };
370
395
 
371
- export { Arc, type ArcOptions, type CanvasTextAlign, type CanvasTextBaseline, Circle, type CircleOptions, CustomPolygon, type CustomPolygonOptions, Engine, ImageSprite, type ImageSpriteOptions, Oval, type OvalOptions, Pen, type PenOptions, Rectangle, type RectangleOptions, RegularPolygon, type RegularPolygonOptions, Sprite, type SpriteOptions, Square, type SquareOptions, Text, type TextOptions, type Vec2, type Vec3, type Vec4, canvas, ctx, TScratch as default, setAspectRatio, setScale };
396
+ export { Arc, type ArcOptions, type CanvasTextAlign, type CanvasTextBaseline, Circle, type CircleOptions, CustomPolygon, type CustomPolygonOptions, Engine, ImageSprite, type ImageSpriteOptions, Multiplayer, Oval, type OvalOptions, Pen, type PenOptions, Rectangle, type RectangleOptions, RegularPolygon, type RegularPolygonOptions, Sprite, type SpriteOptions, Square, type SquareOptions, Text, type TextOptions, type Vec2, type Vec3, type Vec4, aspectRatio, canvas, ctx, TScratch as default, scale, setAspectRatio, setScale };
@@ -0,0 +1,2 @@
1
+ var s=document.getElementById("game-window")||document.createElement("canvas"),h=s.getContext("2d"),u=document.createElement("canvas"),a=u.getContext("2d");u.id="pen-canvas";var y=16/9,m;function A(){s.width=y*m,s.height=m,u.width=y*m,u.height=m}function Y(n){m=n,A()}function V(n){y=n,A()}s.parentElement?.insertBefore(u,s);Y(500);var l=class n{x;y;dir;scene;hidden;layer;cachedPath=null;pathDirty=!0;static collisionCanvas=null;static collisionCtx=null;refresh(){d.init().refresh()}invalidatePath(){this.pathDirty=!0,this.cachedPath=null}getCachedPath(){return(this.pathDirty||!this.cachedPath)&&(this.cachedPath=this.getPath(),this.pathDirty=!1),this.cachedPath}constructor(t){Object.assign(this,t),d.init().addSprite(this)}clone(t){return this.create({x:this.x,y:this.y,dir:this.dir,scene:this.scene,layer:this.layer,hidden:this.hidden,...t})}touching(t){if(this.hidden||t.hidden)return!1;let i=this.getBoundingBox(),e=t.getBoundingBox();if(!(Math.abs(i.x-e.x)<(i.width+e.width)/2&&Math.abs(i.y-e.y)<(i.height+e.height)/2))return!1;let o=i.x-i.width/2,b=i.y+i.height/2,f=i.x+i.width/2,x=i.y-i.height/2,L=e.x-e.width/2,D=e.y+e.height/2,z=e.x+e.width/2,E=e.y-e.height/2,F=Math.max(o,L),X=Math.min(x,E),q=Math.min(f,z),H=Math.max(b,D),g=q-F,p=H-X;if(g<=1||p<=1)return!1;n.collisionCanvas||(n.collisionCanvas=document.createElement("canvas"),n.collisionCtx=n.collisionCanvas.getContext("2d",{willReadFrequently:!0})),(n.collisionCanvas.width<g||n.collisionCanvas.height<p)&&(n.collisionCanvas.width=Math.max(g,n.collisionCanvas.width),n.collisionCanvas.height=Math.max(p,n.collisionCanvas.height));let c=n.collisionCtx;c.clearRect(0,0,g,p),c.save(),c.translate(this.x-F,p-this.y+X),c.rotate(this.toRadians(this.dir)),c.fillStyle="red",c.fill(this.getCachedPath()),c.restore();let I=c.getImageData(0,0,g,p).data;c.clearRect(0,0,g,p),c.save(),c.translate(t.x-F,p-t.y+X),c.rotate(this.toRadians(t.dir)),c.fillStyle="blue",c.fill(t.getCachedPath()),c.restore();let $=c.getImageData(0,0,g,p).data;for(let T=3;T<I.length;T+=4)if(I[T]>0&&$[T]>0)return!0;return!1}toRadians(t){return t*Math.PI/180}toDegrees(t){return t*180/Math.PI}move(t){this.x+=t*Math.sin(this.toRadians(this.dir)),this.y+=t*Math.cos(this.toRadians(this.dir)),this.refresh()}turn(t){this.dir+=t,this.refresh()}point(t){this.dir=t,this.refresh()}pointTowards(t,i){this.dir=90-this.toDegrees(Math.atan2(i,t)),this.refresh()}setX(t){this.x=t,this.refresh()}setY(t){this.y=t,this.refresh()}goTo(t,i){this.x=t,this.y=i,this.refresh()}changeX(t){this.x+=t,this.refresh()}changeY(t){this.y+=t,this.refresh()}show(){this.hidden=!1,this.refresh()}hide(){this.hidden=!0,this.refresh()}goToLayer(t){this.layer=t,this.refresh()}changeLayer(t){this.layer+=t,this.refresh()}};var d=class n{static instance;loopRunning=!1;gameLoop=null;maxFPS=24;deltaTime=1/this.maxFPS;lastFrame=performance.now();refreshScheduled=!1;animationFrameId=null;sounds=[];mouseX=0;mouseY=0;mouseDown=!1;mouseClicked=!1;keysPressed=new Set;currentScene="main";sceneMap=new Map;static init(){return this.instance||(this.instance=new n),this.instance}changeScene(t){this.sceneMap.get(t)||this.sceneMap.set(t,{sprites:[],loop:null}),this.loopRunning=!1,this.currentScene=t,this.gameLoop=this.sceneMap.get(t).loop,this.setMaxFramesPerSecond(this.maxFPS)}setLoop(t,i){if(!this.sceneMap.get(t)){this.sceneMap.set(t,{sprites:[],loop:i}),t===this.currentScene&&this.changeScene(t);return}this.sceneMap.get(t).loop=i,t===this.currentScene&&this.changeScene(t)}pauseLoop(){this.loopRunning=!1,this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}resumeLoop(){this.loopRunning=!0,this.setMaxFramesPerSecond(this.maxFPS)}addSprite(t){let{scene:i,layer:e}=t;if(!this.sceneMap.get(i)){this.sceneMap.set(i,{sprites:[t],loop:null});return}let r=this.sceneMap.get(i).sprites.findIndex(o=>o.layer>e);if(r===-1){this.sceneMap.get(i).sprites.push(t);return}this.sceneMap.get(i).sprites.splice(r,0,t),this.refresh()}removeSprite(t){let{scene:i}=t;this.sceneMap.get(i)&&(this.sceneMap.get(i).sprites=this.sceneMap.get(i).sprites.filter(e=>e!==t),this.refresh())}async setMaxFramesPerSecond(t){this.maxFPS=t;let i=this.gameLoop;if(!i)return;this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.loopRunning=!0;let e=1e3/t,r=0,o=async b=>{if(!this.loopRunning)return;let f=b-this.lastFrame;this.lastFrame=b,r+=f,r>=e&&(this.deltaTime=r/1e3,r=r%e,i&&await i()),this.animationFrameId=requestAnimationFrame(o)};this.lastFrame=performance.now(),this.animationFrameId=requestAnimationFrame(o)}refresh(){this.refreshScheduled||(this.refreshScheduled=!0,requestAnimationFrame(()=>{this.refreshScheduled=!1,h.clearRect(0,0,s.width,s.height),[...this.sceneMap.get(this.currentScene).sprites,...this.sceneMap.get("*").sprites].forEach(i=>{i.hidden||i.draw()})}))}async wait(t){return new Promise(i=>setTimeout(i,t))}async waitUntil(t){return new Promise(i=>{let e=()=>{t()?i():setTimeout(e,1e3/this.maxFPS)};e()})}hovering(t){let{mouseX:i,mouseY:e}=this,r=i+s.width/2,o=s.height/2-e,b=r-(t.x+s.width/2),f=o-(s.height/2-t.y),x=-this.toRadians(t.dir),L=b*Math.cos(x)-f*Math.sin(x),D=b*Math.sin(x)+f*Math.cos(x);return h.isPointInPath(t.getPath(),L,D)}keyPressed(t){return this.keysPressed.has(t)}playSound(t){let i=new Audio(t);return this.sounds.push(i),i.play(),i}stopSound(t){t.pause(),t.currentTime=0,this.sounds=this.sounds.filter(i=>i!==t)}stopAllSounds(){this.sounds.forEach(t=>{t.pause(),t.currentTime=0}),this.sounds=[]}pickRandom(t,i){return t>i&&([t,i]=[i,t]),Math.floor(Math.random()*(i-t+1)+t)}dotProduct(t){let[i,e]=t;switch(i.length){case 2:return i[0]*e[0]+i[1]*e[1];case 3:return i[0]*e[0]+i[1]*e[1]+i[2]*e[2];case 4:return i[0]*e[0]+i[1]*e[1]+i[2]*e[2]+i[3]*e[3]}}sin(t){return Math.sin(this.toRadians(t))}cos(t){return Math.cos(this.toRadians(t))}tan(t){return Math.tan(this.toRadians(t))}csc(t){return 1/Math.sin(this.toRadians(t))}sec(t){return 1/Math.cos(this.toRadians(t))}cot(t){return 1/Math.tan(this.toRadians(t))}asin(t){return this.toDegrees(Math.asin(t))}acos(t){return this.toDegrees(Math.acos(t))}acsc(t){return this.toDegrees(Math.asin(1/t))}asec(t){return this.toDegrees(Math.acos(1/t))}toRadians(t){return t*Math.PI/180}toDegrees(t){return t*180/Math.PI}constructor(){this.setMaxFramesPerSecond(24),u.addEventListener("mousemove",t=>{this.mouseX=t.clientX-u.offsetLeft-u.width/2,this.mouseY=-(t.clientY-u.offsetTop-u.height/2)}),u.addEventListener("mousedown",t=>{this.mouseDown=!0}),u.addEventListener("mouseup",t=>{this.mouseDown=!1}),u.addEventListener("click",t=>{this.mouseClicked=!0,setTimeout(()=>this.mouseClicked=!1,0)}),addEventListener("keydown",t=>{t.repeat||this.keysPressed.add(t.key)}),addEventListener("keyup",t=>{this.keysPressed.delete(t.key)})}};import{io as G}from"socket.io-client";var w=class n{static instance;socket;static connect(t="http://localhost:3000"){return this.instance||(this.instance=new n(t)),this.instance}disconnect(){this.socket.disconnect()}constructor(t){this.socket=G(t)}broadcast(t,i){this.socket.emit(t,i)}on(t,i){this.socket.on(t,i)}};var v=class n extends l{discriminant="rectangle";width;height;color;outlineColor;outlineWidth;getBoundingBox(){return{x:this.x,y:this.y,width:Math.hypot(this.width,this.height),height:Math.hypot(this.width,this.height)}}getPath(){let t=new Path2D;return t.rect(-this.width/2,-this.height/2,this.width,this.height),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setWidth(t){this.width=t,this.invalidatePath(),this.refresh()}setHeight(t){this.height=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.width=t?.width??50,this.height=t?.height??50,this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var S=class n extends l{discriminant="square";sideLength;color;outlineColor;outlineWidth;getBoundingBox(){return{x:this.x,y:this.y,width:Math.hypot(this.sideLength,this.sideLength),height:Math.hypot(this.sideLength,this.sideLength)}}getPath(){let t=new Path2D;return t.rect(-this.sideLength/2,-this.sideLength/2,this.sideLength,this.sideLength),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setSideLength(t){this.sideLength=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.sideLength=t?.sideLength??50,this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var C=class n extends l{discriminant="oval";radX;radY;color;outlineColor;outlineWidth;getBoundingBox(){return{x:this.x,y:this.y,width:Math.hypot(this.radX*2,this.radY*2),height:Math.hypot(this.radX*2,this.radY*2)}}getPath(){let t=new Path2D;return t.ellipse(0,0,this.radX,this.radY,0,0,Math.PI*2),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setRadX(t){this.radX=t,this.invalidatePath(),this.refresh()}setRadY(t){this.radY=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.radX=t?.radX??25,this.radY=t?.radY??25,this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var P=class n extends l{discriminant="circle";radius;color;outlineColor;outlineWidth;getBoundingBox(){return{x:this.x,y:this.y,width:this.radius*2,height:this.radius*2}}getPath(){let t=new Path2D;return t.ellipse(0,0,this.radius,this.radius,0,0,Math.PI*2),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setRadius(t){this.radius=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.radius=t?.radius??25,this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var B=class n extends l{discriminant="arc";radius;angle;color;outlineColor;outlineWidth;getBoundingBox(){return{x:this.x,y:this.y,width:this.radius*2,height:this.radius*2}}getPath(){let t=new Path2D;return t.arc(0,0,this.radius,this.toRadians(this.angle/2-90),this.toRadians(-this.angle/2-90)),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setRadius(t){this.radius=t,this.invalidatePath(),this.refresh()}setAngle(t){this.angle=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.radius=t?.radius??25,this.angle=t?.angle??270,this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var O=class n extends l{discriminant="regularpolygon";sides;radius;color;outlineColor;outlineWidth;getBoundingBox(){return{x:this.x,y:this.y,width:this.radius*2,height:this.radius*2}}getPath(){let t=new Path2D,i=2*Math.PI/this.sides;t.moveTo(this.radius,0);for(let e=1;e<this.sides;e++)t.lineTo(this.radius*Math.cos(i*e),this.radius*Math.sin(i*e));return t.closePath(),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setSides(t){this.sides=t,this.invalidatePath(),this.refresh()}setRadius(t){this.radius=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.sides=t?.sides??5,this.radius=t?.radius??50,this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var M=class n extends l{discriminant="custompolygon";vertices;color;outlineColor;outlineWidth;getBoundingBox(){let t=0;for(let i of this.vertices){let e=Math.hypot(i[0],i[1]);e>t&&(t=e)}return{x:this.x,y:this.y,width:t,height:t}}getPath(){let t=new Path2D,i=this.vertices;if(i.length<2)return t;t.moveTo(i[0][0],i[0][1]);for(let e=1;e<i.length;e++)t.lineTo(i[e][0],i[e][1]);return t.closePath(),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir));let o=this.getCachedPath();i.fillStyle=this.color,i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.fill(o),this.outlineWidth&&i.stroke(o),i.restore()}create(t){return new n(t)}setVertices(t){this.vertices=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}constructor(t){super(t),this.vertices=t?.vertices??[],this.color=t?.color??"black",this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var R=class n extends l{discriminant="pen";drawing;size;color;getBoundingBox(){return{x:this.x,y:this.y,width:this.size,height:this.size}}getPath(){return new Path2D}draw(){}create(t){return new n(t)}up(){this.drawing=!1}down(){this.drawing=!0}stamp(t){t.draw(!0)}eraseAll(){a.clearRect(0,0,s.width,s.height)}dot(){a.fillStyle=this.color,a.fillRect(this.x-this.size/2+s.width/2,-this.y-this.size/2+s.height/2,this.size,this.size)}drawLine(t,i){a.beginPath(),a.moveTo(t+s.width/2,-i+s.height/2),a.lineTo(this.x+s.width/2,-this.y+s.height/2),a.lineWidth=this.size,a.strokeStyle=this.color,a.stroke()}move(t){let i=this.x,e=this.y;this.x+=t*Math.sin(this.toRadians(this.dir)),this.y+=t*Math.cos(this.toRadians(this.dir)),this.drawing&&this.drawLine(i,e),this.refresh()}setX(t){let i=this.x,e=this.y;this.x=t,this.drawing&&this.drawLine(i,e),this.refresh()}setY(t){let i=this.x,e=this.y;this.y=t,this.drawing&&this.drawLine(i,e),this.refresh()}goTo(t,i){let e=this.x,r=this.y;this.x=t,this.y=i,this.drawing&&this.drawLine(e,r),this.refresh()}changeX(t){let i=this.x,e=this.y;this.x+=t,this.drawing&&this.drawLine(i,e),this.refresh()}changeY(t){let i=this.x,e=this.y;this.y+=t,this.drawing&&this.drawLine(i,e),this.refresh()}constructor(t){super(t),this.drawing=t?.drawing??!1,this.size=t?.size??5,this.color=t?.color??"black"}};var k=class n extends l{discriminant="text";content;color;fontFamily;fontSize;align;baseline;font;getBoundingBox(){let t=h.measureText(this.content),i=t.width,e=t.actualBoundingBoxAscent+t.actualBoundingBoxDescent;return{x:this.x,y:this.y,width:i,height:e}}getPath(){let t=new Path2D;h.save(),h.font=this.font;let i=h.measureText(this.content),e=i.width,r=i.actualBoundingBoxAscent+i.actualBoundingBoxDescent;return h.restore(),t.rect(-e/2,-r/2,e,r),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir)),i.font=this.font,i.fillStyle=this.color,i.textAlign=this.align,i.textBaseline=this.baseline,i.fillText(this.content,0,0),i.restore()}create(t){return new n(t)}setContent(t){this.content=t,this.invalidatePath(),this.refresh()}setColor(t){this.color=t,this.refresh()}setFontSize(t){this.fontSize=t,this.font=`${this.fontSize}px ${this.fontFamily}`,this.invalidatePath(),this.refresh()}setFontFamily(t){this.fontFamily=t,this.font=`${this.fontSize}px ${this.fontFamily}`,this.invalidatePath(),this.refresh()}setAlign(t){this.align=t,this.invalidatePath(),this.refresh()}setBaseline(t){this.baseline=t,this.invalidatePath(),this.refresh()}constructor(t){super(t),this.content=t?.content??"",this.color=t?.color??"black",this.fontFamily=t?.fontFamily??"Arial",this.fontSize=t?.fontSize??16,this.align=t?.align??"center",this.baseline=t?.baseline??"middle",this.font=`${this.fontSize}px ${this.fontFamily}`,this.draw()}};var W=class n extends l{discriminant="imagesprite";src;width;height;outlineColor;outlineWidth;img;getBoundingBox(){return{x:this.x,y:this.y,width:this.width,height:this.height}}getPath(){let t=new Path2D;return t.rect(-this.width/2,-this.height/2,this.width,this.height),t}draw(t){let i=t?a:h;i.save();let e=this.x+s.width/2,r=-this.y+s.height/2;i.translate(e,r),i.rotate(this.toRadians(this.dir)),i.strokeStyle=this.outlineColor,i.lineWidth=this.outlineWidth,i.drawImage(this.img,0,0,this.img.width,this.img.height,-this.width/2,-this.height/2,this.width,this.height),this.outlineWidth&&i.stroke(this.getCachedPath()),i.restore()}create(t){return new n(t)}setSrc(t){this.src=t,this.refresh()}setWidth(t){this.width=t,this.invalidatePath(),this.refresh()}setHeight(t){this.height=t,this.invalidatePath(),this.refresh()}constructor(t){super(t),this.src=t?.src??"",this.img=new Image,this.img.src=this.src,this.width=t?.width??this.img.width,this.height=t?.height??this.img.height,this.outlineColor=t?.outlineColor??"black",this.outlineWidth=t?.outlineWidth??0,this.draw()}};var j={Engine:d,Sprite:l,Multiplayer:w,Rectangle:v,Square:S,Oval:C,Circle:P,Arc:B,RegularPolygon:O,CustomPolygon:M,Pen:R,Text:k,ImageSprite:W,scale:m,aspectRatio:y,setScale:Y,setAspectRatio:V,canvas:s,ctx:h},Ut=j;export{B as Arc,P as Circle,M as CustomPolygon,d as Engine,W as ImageSprite,w as Multiplayer,C as Oval,R as Pen,v as Rectangle,O as RegularPolygon,l as Sprite,S as Square,k as Text,y as aspectRatio,s as canvas,h as ctx,Ut as default,m as scale,V as setAspectRatio,Y as setScale};
2
+ //# sourceMappingURL=index.js.map