From b011530fdc4d718056727a14aa1866f1f1aa9f87 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 4 Sep 2023 14:06:06 +0200 Subject: [PATCH] add autoPlay and title options --- index.html | 2 +- index.js | 2 +- index.ts | 9 ++++++++- package.json | 3 ++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index ca0492c..b07c774 100644 --- a/index.html +++ b/index.html @@ -38,5 +38,5 @@ diff --git a/index.js b/index.js index 72d7030..68c6fc2 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -export function startGame(b={}){const oe=/Chrome/.test(navigator.userAgent)&&/Google Inc/.test(navigator.vendor),a=b.width||640,r=b.height||640,le="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAEACAYAAAADRnAGAAACGUlEQVR42u3aSQ7CMBAEQIsn8P+/hiviAAK8zFIt5QbELiTHmfEYE3L9mZE9AAAAqAVwBQ8AAAD6THY5CgAAAKbfbPX3AQAAYBEEAADAuZrC6UUyfMEEAIBiAN8OePXnAQAAsLcmmKFPAQAAgHMbm+gbr3Sdo/LtcAAAANR6GywPAgBAM4D2JXAAABoBzBjA7AmlOx8AAEAzAOcDAADovTc4vQim6wUCABAYQG8QAADd4dPd2fRVYQAAANQG0B4HAABAawDnAwAA6AXgfAAAALpA2uMAAABwPgAAgPoAM9Ci/R4AAAD2dmqcEQIAIC/AiQGuAAYAAECcRS/a/cJXkUf2AAAAoBaA3iAAALrD+gIAAADY9baX/nwAAADNADwFAADo9YK0e5FMX/UFACA5QPSNEAAAAHKtCekmDAAAAADvBljtfgAAAGgMMGOrunvCy2uCAAAACFU6BwAAwF6AGQPa/XsAAADYB+B8AAAAtU+ItD4OAwAAAFVhAACaA0T7B44/BQAAANALwGMQAAAAADYO8If2+P31AgAAQN0SWbhFDwCAZlXgaO1xAAAA1FngnA8AACAeQPSNEAAAAM4CnC64AAAA4GzN4N9NSfgKEAAAAACszO26X8/X6BYAAAD0Anid8KcLAAAAAAAAAJBnwNEvAAAA9Jns1ygAAAAAAAAAAAAAAAAAAABAQ4COCENERERERERERBrnAa1sJuUVr3rsAAAAAElFTkSuQmCC",w=37,x=39,ae=32,re=500,ce={x:0,y:204,w:62,h:32},ue=[{x:0,y:0,w:51,h:34},{x:0,y:102,w:51,h:34}],he=[{x:0,y:137,w:50,h:33},{x:0,y:170,w:50,h:34}],Ae=[{x:0,y:68,w:50,h:32},{x:0,y:34,w:50,h:32}],I=40,me=11*I;function de(i,e){return Math.random()*(e-i)+i}function pe(i,e,t){return Math.min(Math.max(i,e),t)}function E(i,e,t){return i<=t&&i>=e}function _(i,e){const t=E(i.x,e.x,e.x+e.w)||E(e.x,i.x,i.x+i.w),n=E(i.y,e.y,e.y+e.h)||E(e.y,i.y,i.y+i.h);return t&&n}class Q{x;y;constructor(e,t){this.x=typeof e>"u"?0:e,this.y=typeof t>"u"?0:t}set(e,t){this.x=e,this.y=t}}class be{x;y;w;h;constructor(e,t,n,s){this.x=typeof e>"u"?0:e,this.y=typeof t>"u"?0:t,this.w=typeof n>"u"?0:n,this.h=typeof s>"u"?0:s}set(e,t,n,s){this.x=e,this.y=t,this.w=n,this.h=s}}let A,o,f,S,u=[],M=[],O=0,l,h=[],v,R=!1,g=-1,L=0,y=0,N=1,d=!1;class H{img;position;scale;bounds;doLogic;constructor(e,t,n){this.img=e,this.position=new Q(t,n),this.scale=new Q(1,1),this.bounds=new be(t,n,this.img.width,this.img.height),this.doLogic=!0}update(e){}_updateBounds(){this.bounds.set(this.position.x,this.position.y,~~(.5+this.img.width*this.scale.x),~~(.5+this.img.height*this.scale.y))}_drawImage(){o.drawImage(this.img,this.position.x,this.position.y)}draw(e){this._updateBounds(),this._drawImage()}}class G extends H{clipRect;constructor(e,t,n,s){super(e,n,s),this.clipRect=t,this.bounds.set(n,s,this.clipRect.w,this.clipRect.h)}update(e){}_updateBounds(){const e=~~(.5+this.clipRect.w*this.scale.x),t=~~(.5+this.clipRect.h*this.scale.y);this.bounds.set(this.position.x-e/2,this.position.y-t/2,e,t)}_drawImage(){o.save(),o.transform(this.scale.x,0,0,this.scale.y,this.position.x,this.position.y),o.drawImage(this.img,this.clipRect.x,this.clipRect.y,this.clipRect.w,this.clipRect.h,~~(.5+-this.clipRect.w*.5),~~(.5+-this.clipRect.h*.5),this.clipRect.w,this.clipRect.h),o.restore()}draw(e){super.draw(e)}}class fe extends G{lives;xVel;bullets;bulletDelayAccumulator;score;constructor(){super(f,ce,a/2,r-70),this.scale.set(.85,.85),this.lives=3,this.xVel=0,this.bullets=[],this.bulletDelayAccumulator=0,this.score=0}reset(){this.lives=3,this.score=0,this.position.set(a/2,r-70)}shoot(){const e=new Y(this.position.x,this.position.y-this.bounds.h/2,1,1e3);this.bullets.push(e),C("shoot")}handleInput(){X(w)?this.xVel=-175:X(x)?this.xVel=175:this.xVel=0,U(ae)&&this.bulletDelayAccumulator>.5&&(this.shoot(),this.bulletDelayAccumulator=0)}updateBullets(e){for(let t=this.bullets.length-1;t>=0;t--){let n=this.bullets[t];n.alive?n.update(e):(this.bullets.splice(t,1),n=void 0)}}update(e){this.bulletDelayAccumulator+=e,this.position.x+=this.xVel*e,this.position.x=pe(this.position.x,this.bounds.w/2,a-this.bounds.w/2),this.updateBullets(e)}draw(e){super.draw(e);for(let t=0,n=this.bullets.length;t=this.stepDelay){this.position.xa-this.bounds.w/2-20&&(R=!0),this.position.y>a-50&&Ee();const t=Math.floor(Math.random()*(this.stepDelay+1));de(0,1e3)<=5*(this.stepDelay+1)&&(this.doShoot=!0),this.position.x+=10*g,this.toggleFrame(),this.stepAccumulator=0}this.position.y+=L,this.bullet&&this.bullet.alive?this.bullet.update(e):this.bullet=void 0}draw(e){super.draw(e),this.bullet!==void 0&&this.bullet.alive&&this.bullet.draw(e)}}class ye{particlePool;particles;constructor(){this.particlePool=[],this.particles=[]}draw(){for(let e=this.particles.length-1;e>=0;e--){const t=this.particles[e];t.moves++,t.x+=t.xunits,t.y+=t.yunits+t.gravity*t.moves,t.life--,t.life<=0?this.particlePool.length<100?this.particlePool.push(this.particles.splice(e,1)):this.particles.splice(e,1):(o.globalAlpha=t.life/t.maxLife,o.fillStyle=t.color,o.fillRect(t.x,t.y,t.width,t.height),o.globalAlpha=1)}}createExplosion(e,t,n,s,m,p,j,Z,$){for(let ee=0;ee0){const c=this.particlePool.pop();c.x=e,c.y=t,c.xunits=ne,c.yunits=se,c.life=D,c.color=n,c.width=m,c.height=p,c.gravity=Z,c.moves=0,c.alpha=1,c.maxLife=D,this.particles.push(c)}else this.particles.push({x:e,y:t,xunits:ne,yunits:se,life:D,color:n,width:m,height:p,gravity:Z,moves:0,alpha:1,maxLife:D})}}}function we(){if(b.canvas)A=b.canvas;else{const i=b.selector||"#invaders",e=document.querySelector(i)||document.body;A=document.createElement("canvas"),e.appendChild(A)}A.width=a,A.height=r,o=A.getContext("2d"),K(!1),f=new Image,f.src=le,xe(),window.addEventListener("resize",J),document.addEventListener("keydown",Fe),document.addEventListener("keyup",Be)}function xe(){const i=Me(2,8,e=>{e.fillStyle="white",e.fillRect(0,0,e.canvas.width,e.canvas.height)});S=new Image,S.src=i.toDataURL()}function K(i){o.imageSmoothingEnabled=i,o.mozImageSmoothingEnabled=i,o.oImageSmoothingEnabled=i,o.webkitImageSmoothingEnabled=i,o.msImageSmoothingEnabled=i}function k(){h=[],l=new fe,v=new ye,P(),W()}function P(){y=0;for(let i=0,e=5*11;i=0;e--){let t=h[e];if(!t.alive){h.splice(e,1),t=void 0,y--,y<1&&(N++,P());return}if(t.stepDelay=(y*20-N*10)/1e3,t.stepDelay<=.05&&(t.stepDelay=.05),t.update(i),t.doShoot){t.doShoot=!1,t.shoot();const n=String(Math.round(Math.random()*3+1));C(`fastinvader${n}`)}}L=0}function Ce(){const i=l.bullets;for(let e=0,t=i.length;e100&&(e=100),U(13)&&!d&&(k(),d=!0),d&&Se(e/1e3),o.fillStyle="black",o.fillRect(0,0,a,r),d?Pe(!1):Te(),O=i,requestAnimationFrame(z)}function J(){const i=window.innerWidth,e=window.innerHeight,t=Math.min(i/a,e/r);oe?(A.width=a*t,A.height=r*t,K(!1),o.transform(t,0,0,t,0,0)):(A.style.width=a*t+"px",A.style.height=r*t+"px")}function Fe(i){i.preventDefault(),u[i.keyCode]=!0}function Be(i){i.preventDefault(),u[i.keyCode]=!1}let q;document.addEventListener("touchstart",i=>{q={x:i.touches[0].clientX,y:i.touches[0].clientY},d?l.shoot():(k(),d=!0)}),document.addEventListener("touchmove",i=>{const t={x:i.touches[0].clientX,y:i.touches[0].clientY}.x-q.x;t>0?(u[x]=!0,u[w]=!1):t<0&&(u[w]=!0,u[x]=!1)}),document.addEventListener("touchend",i=>{u[w]=!1,u[x]=!1});const B=document.createElement("link");B.rel="stylesheet",B.href="https://fonts.googleapis.com/css?family=Play:400,700",document.head.appendChild(B),ve(),z();async function C(i){}} +export function startGame(p={}){const le=/Chrome/.test(navigator.userAgent)&&/Google Inc/.test(navigator.vendor),a=p.width||640,r=p.height||640,oe="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAEACAYAAAADRnAGAAACGUlEQVR42u3aSQ7CMBAEQIsn8P+/hiviAAK8zFIt5QbELiTHmfEYE3L9mZE9AAAAqAVwBQ8AAAD6THY5CgAAAKbfbPX3AQAAYBEEAADAuZrC6UUyfMEEAIBiAN8OePXnAQAAsLcmmKFPAQAAgHMbm+gbr3Sdo/LtcAAAANR6GywPAgBAM4D2JXAAABoBzBjA7AmlOx8AAEAzAOcDAADovTc4vQim6wUCABAYQG8QAADd4dPd2fRVYQAAANQG0B4HAABAawDnAwAA6AXgfAAAALpA2uMAAABwPgAAgPoAM9Ci/R4AAAD2dmqcEQIAIC/AiQGuAAYAAECcRS/a/cJXkUf2AAAAoBaA3iAAALrD+gIAAADY9baX/nwAAADNADwFAADo9YK0e5FMX/UFACA5QPSNEAAAAHKtCekmDAAAAADvBljtfgAAAGgMMGOrunvCy2uCAAAACFU6BwAAwF6AGQPa/XsAAADYB+B8AAAAtU+ItD4OAwAAAFVhAACaA0T7B44/BQAAANALwGMQAAAAADYO8If2+P31AgAAQN0SWbhFDwCAZlXgaO1xAAAA1FngnA8AACAeQPSNEAAAAM4CnC64AAAA4GzN4N9NSfgKEAAAAACszO26X8/X6BYAAAD0Anid8KcLAAAAAAAAAJBnwNEvAAAA9Jns1ygAAAAAAAAAAAAAAAAAAABAQ4COCENERERERERERBrnAa1sJuUVr3rsAAAAAElFTkSuQmCC",w=37,x=39,ae=32,re=500,ce={x:0,y:204,w:62,h:32},ue=[{x:0,y:0,w:51,h:34},{x:0,y:102,w:51,h:34}],he=[{x:0,y:137,w:50,h:33},{x:0,y:170,w:50,h:34}],Ae=[{x:0,y:68,w:50,h:32},{x:0,y:34,w:50,h:32}],I=40,me=11*I;function de(i,e){return Math.random()*(e-i)+i}function pe(i,e,t){return Math.min(Math.max(i,e),t)}function E(i,e,t){return i<=t&&i>=e}function Q(i,e){const t=E(i.x,e.x,e.x+e.w)||E(e.x,i.x,i.x+i.w),n=E(i.y,e.y,e.y+e.h)||E(e.y,i.y,i.y+i.h);return t&&n}class O{x;y;constructor(e,t){this.x=typeof e>"u"?0:e,this.y=typeof t>"u"?0:t}set(e,t){this.x=e,this.y=t}}class be{x;y;w;h;constructor(e,t,n,s){this.x=typeof e>"u"?0:e,this.y=typeof t>"u"?0:t,this.w=typeof n>"u"?0:n,this.h=typeof s>"u"?0:s}set(e,t,n,s){this.x=e,this.y=t,this.w=n,this.h=s}}let A,l,f,S,u=[],M=[],N=0,o,h=[],v,R=!1,g=-1,P=0,y=0,H=1,m=!1;class G{img;position;scale;bounds;doLogic;constructor(e,t,n){this.img=e,this.position=new O(t,n),this.scale=new O(1,1),this.bounds=new be(t,n,this.img.width,this.img.height),this.doLogic=!0}update(e){}_updateBounds(){this.bounds.set(this.position.x,this.position.y,~~(.5+this.img.width*this.scale.x),~~(.5+this.img.height*this.scale.y))}_drawImage(){l.drawImage(this.img,this.position.x,this.position.y)}draw(e){this._updateBounds(),this._drawImage()}}class Y extends G{clipRect;constructor(e,t,n,s){super(e,n,s),this.clipRect=t,this.bounds.set(n,s,this.clipRect.w,this.clipRect.h)}update(e){}_updateBounds(){const e=~~(.5+this.clipRect.w*this.scale.x),t=~~(.5+this.clipRect.h*this.scale.y);this.bounds.set(this.position.x-e/2,this.position.y-t/2,e,t)}_drawImage(){l.save(),l.transform(this.scale.x,0,0,this.scale.y,this.position.x,this.position.y),l.drawImage(this.img,this.clipRect.x,this.clipRect.y,this.clipRect.w,this.clipRect.h,~~(.5+-this.clipRect.w*.5),~~(.5+-this.clipRect.h*.5),this.clipRect.w,this.clipRect.h),l.restore()}draw(e){super.draw(e)}}class fe extends Y{lives;xVel;bullets;bulletDelayAccumulator;score;constructor(){super(f,ce,a/2,r-70),this.scale.set(.85,.85),this.lives=3,this.xVel=0,this.bullets=[],this.bulletDelayAccumulator=0,this.score=0}reset(){this.lives=3,this.score=0,this.position.set(a/2,r-70)}shoot(){const e=new K(this.position.x,this.position.y-this.bounds.h/2,1,1e3);this.bullets.push(e),C("shoot")}handleInput(){X(w)?this.xVel=-175:X(x)?this.xVel=175:this.xVel=0,U(ae)&&this.bulletDelayAccumulator>.5&&(this.shoot(),this.bulletDelayAccumulator=0)}updateBullets(e){for(let t=this.bullets.length-1;t>=0;t--){let n=this.bullets[t];n.alive?n.update(e):(this.bullets.splice(t,1),n=void 0)}}update(e){this.bulletDelayAccumulator+=e,this.position.x+=this.xVel*e,this.position.x=pe(this.position.x,this.bounds.w/2,a-this.bounds.w/2),this.updateBullets(e)}draw(e){super.draw(e);for(let t=0,n=this.bullets.length;t=this.stepDelay){this.position.xa-this.bounds.w/2-20&&(R=!0),this.position.y>a-50&&Ee();const t=Math.floor(Math.random()*(this.stepDelay+1));de(0,1e3)<=5*(this.stepDelay+1)&&(this.doShoot=!0),this.position.x+=10*g,this.toggleFrame(),this.stepAccumulator=0}this.position.y+=P,this.bullet&&this.bullet.alive?this.bullet.update(e):this.bullet=void 0}draw(e){super.draw(e),this.bullet!==void 0&&this.bullet.alive&&this.bullet.draw(e)}}class ye{particlePool;particles;constructor(){this.particlePool=[],this.particles=[]}draw(){for(let e=this.particles.length-1;e>=0;e--){const t=this.particles[e];t.moves++,t.x+=t.xunits,t.y+=t.yunits+t.gravity*t.moves,t.life--,t.life<=0?this.particlePool.length<100?this.particlePool.push(this.particles.splice(e,1)):this.particles.splice(e,1):(l.globalAlpha=t.life/t.maxLife,l.fillStyle=t.color,l.fillRect(t.x,t.y,t.width,t.height),l.globalAlpha=1)}}createExplosion(e,t,n,s,d,b,j,Z,$){for(let ee=0;ee0){const c=this.particlePool.pop();c.x=e,c.y=t,c.xunits=ne,c.yunits=se,c.life=D,c.color=n,c.width=d,c.height=b,c.gravity=Z,c.moves=0,c.alpha=1,c.maxLife=D,this.particles.push(c)}else this.particles.push({x:e,y:t,xunits:ne,yunits:se,life:D,color:n,width:d,height:b,gravity:Z,moves:0,alpha:1,maxLife:D})}}}function we(){if(p.canvas)A=p.canvas;else{const i=p.selector||"#invaders",e=document.querySelector(i)||document.body;A=document.createElement("canvas"),e.appendChild(A)}A.width=a,A.height=r,l=A.getContext("2d"),k(!1),f=new Image,f.src=oe,xe(),window.addEventListener("resize",J),document.addEventListener("keydown",Fe),document.addEventListener("keyup",Be)}function xe(){const i=Me(2,8,e=>{e.fillStyle="white",e.fillRect(0,0,e.canvas.width,e.canvas.height)});S=new Image,S.src=i.toDataURL()}function k(i){l.imageSmoothingEnabled=i,l.mozImageSmoothingEnabled=i,l.oImageSmoothingEnabled=i,l.webkitImageSmoothingEnabled=i,l.msImageSmoothingEnabled=i}function L(){h=[],o=new fe,v=new ye,T(),W()}function T(){y=0;for(let i=0,e=5*11;i=0;e--){let t=h[e];if(!t.alive){h.splice(e,1),t=void 0,y--,y<1&&(H++,T());return}if(t.stepDelay=(y*20-H*10)/1e3,t.stepDelay<=.05&&(t.stepDelay=.05),t.update(i),t.doShoot){t.doShoot=!1,t.shoot();const n=String(Math.round(Math.random()*3+1));C(`fastinvader${n}`)}}P=0}function Ce(){const i=o.bullets;for(let e=0,t=i.length;e100&&(e=100),U(13)&&!m&&(L(),m=!0),m&&Se(e/1e3),l.fillStyle="black",l.fillRect(0,0,a,r),m?Le(!1):Te(),N=i,requestAnimationFrame(z)}function J(){const i=window.innerWidth,e=window.innerHeight,t=Math.min(i/a,e/r);le?(A.width=a*t,A.height=r*t,k(!1),l.transform(t,0,0,t,0,0)):(A.style.width=a*t+"px",A.style.height=r*t+"px")}function Fe(i){i.preventDefault(),u[i.keyCode]=!0}function Be(i){i.preventDefault(),u[i.keyCode]=!1}let q;document.addEventListener("touchstart",i=>{q={x:i.touches[0].clientX,y:i.touches[0].clientY},m?o.shoot():(L(),m=!0)}),document.addEventListener("touchmove",i=>{const t={x:i.touches[0].clientX,y:i.touches[0].clientY}.x-q.x;t>0?(u[x]=!0,u[w]=!1):t<0&&(u[w]=!0,u[x]=!1)}),document.addEventListener("touchend",i=>{u[w]=!1,u[x]=!1});const _=document.createElement("link");_.rel="stylesheet",_.href="https://fonts.googleapis.com/css?family=Play:400,700",document.head.appendChild(_),ve(),z(),p.autoPlay&&(L(),m=!0);async function C(i){}} diff --git a/index.ts b/index.ts index b97fc64..1e5421d 100644 --- a/index.ts +++ b/index.ts @@ -6,6 +6,8 @@ export interface InvadersOptions { canvas?: HTMLCanvasElement; width?: number; height?: number; + autoPlay?: boolean; + title?: string; } export function startGame(options: InvadersOptions = {}) { @@ -815,7 +817,7 @@ export function startGame(options: InvadersOptions = {}) { function drawStartScreen() { fillCenteredText( - "Space Invaders", + options.title || "Space Invaders", CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2.75, "#FFFFFF", @@ -938,6 +940,11 @@ export function startGame(options: InvadersOptions = {}) { init(); animate(); + if (options.autoPlay) { + initGame(); + hasGameStarted = true; + } + // ################################################################### // Sounds // ################################################################### diff --git a/package.json b/package.json index 23e08ac..aaa7e85 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,9 @@ "private": true, "repository": "pi0/space-invaders", "scripts": { + "push": "pnpm build && git commit -am $1", "build": "esbuild ./index.ts --outdir=. --minify", - "dev": "esbuild --serve --servedir=." + "dev": "esbuild ./index.ts --outfile=index.js --serve --servedir=." }, "devDependencies": { "esbuild": "^0.19.2",