tscratch 0.6.2 → 0.6.3

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.
@@ -1,2 +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:()=>O,Engine:()=>d,ImageSprite:()=>W,Multiplayer:()=>w,Oval:()=>C,Pen:()=>R,Rectangle:()=>v,RegularPolygon:()=>M,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=0;y=0;dir=0;scene="main";hidden=!1;layer=0;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),this.sceneMap.set("main",{loop:null,sprites:[]}),this.sceneMap.set("*",{loop:null,sprites:[]}),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 M=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 O=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:M,CustomPolygon:O,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});
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:()=>O,Engine:()=>d,ImageSprite:()=>W,Multiplayer:()=>w,Oval:()=>C,Pen:()=>R,Rectangle:()=>v,RegularPolygon:()=>M,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=0;y=0;dir=0;scene="main";hidden=!1;layer=0;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-this.y,t-this.x)),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),this.sceneMap.set("main",{loop:null,sprites:[]}),this.sceneMap.set("*",{loop:null,sprites:[]}),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 M=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 O=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:M,CustomPolygon:O,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
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +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 = 0;\r\n public y: number = 0;\r\n public dir: number = 0;\r\n public scene: string = 'main';\r\n public hidden: boolean = false;\r\n public layer: number = 0;\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 this.sceneMap.set('main', { loop: null, sprites: [] });\r\n this.sceneMap.set('*', { loop: null, sprites: [] });\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"]}
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 = 0;\r\n public y: number = 0;\r\n public dir: number = 0;\r\n public scene: string = 'main';\r\n public hidden: boolean = false;\r\n public layer: number = 0;\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 - this.y, x - this.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 this.sceneMap.set('main', { loop: null, sprites: [] });\r\n this.sceneMap.set('*', { loop: null, sprites: [] });\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"]}
@@ -1,2 +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=0;y=0;dir=0;scene="main";hidden=!1;layer=0;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),this.sceneMap.set("main",{loop:null,sprites:[]}),this.sceneMap.set("*",{loop:null,sprites:[]}),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 M=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 O=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:M,CustomPolygon:O,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,O as CustomPolygon,d as Engine,W as ImageSprite,w as Multiplayer,C as Oval,R as Pen,v as Rectangle,M 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};
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=0;y=0;dir=0;scene="main";hidden=!1;layer=0;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-this.y,t-this.x)),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),this.sceneMap.set("main",{loop:null,sprites:[]}),this.sceneMap.set("*",{loop:null,sprites:[]}),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 M=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 O=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:M,CustomPolygon:O,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,O as CustomPolygon,d as Engine,W as ImageSprite,w as Multiplayer,C as Oval,R as Pen,v as Rectangle,M 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
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../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","../../src/client/index.ts"],"sourcesContent":["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 = 0;\r\n public y: number = 0;\r\n public dir: number = 0;\r\n public scene: string = 'main';\r\n public hidden: boolean = false;\r\n public layer: number = 0;\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 this.sceneMap.set('main', { loop: null, sprites: [] });\r\n this.sceneMap.set('*', { loop: null, sprites: [] });\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}","// 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};"],"mappings":"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","names":["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","io","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"]}
1
+ {"version":3,"sources":["../../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","../../src/client/index.ts"],"sourcesContent":["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 = 0;\r\n public y: number = 0;\r\n public dir: number = 0;\r\n public scene: string = 'main';\r\n public hidden: boolean = false;\r\n public layer: number = 0;\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 - this.y, x - this.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 this.sceneMap.set('main', { loop: null, sprites: [] });\r\n this.sceneMap.set('*', { loop: null, sprites: [] });\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}","// 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};"],"mappings":"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","names":["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","io","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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tscratch",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "A Scratch-style game engine for TypeScript.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",