F diff --git a/snek.js b/snek.js --- a/snek.js +++ b/snek.jslet mice;let explosions;- let drawInterval=20/1000;+ const drawInterval=20/1000;let micePerSecond=0.3;+ const chargeDepletionRate=200;let normalMouseSpeed=3;let normalMouseSize=1;- let maxNumberOfExplosionParticles=20;- let minNumberOfExplosionParticles=5;- let maxParticleSize=50;- let maxExplosionAge=100;+ const maxNumberOfExplosionParticles=20;+ const minNumberOfExplosionParticles=5;+ const maxParticleSize=50;+ const maxExplosionAge=100;+let lastTimeStamp;let snake = {'x':window.innerWidth/2,- 'y':window.innerHeight/2+ 'y':window.innerHeight/2,+ 'discharging': false,+ 'direction' : 0+};let health=10;+ let score=0;let frameId;+ let snakeLaserId;++ let charge=0;+ const chargeTipoffPoint=10;function draw(timeStamp){canvas.width = window.innerWidth;canvas.height = window.innerHeight;+ /*the only clear thing here is that I am very bad at geometry*/context.clearRect(0, 0, canvas.width, canvas.height);+drawExplosions(timeElapsed);drawMice(timeElapsed);drawSnake(timeElapsed);+ drawHealth();frameId=window.requestAnimationFrame(draw);}+ function drawHealth()+ {+ context.save();+ context.font='48px serif';+ context.fillText(`Health: ${health}`,10,70);+ context.font='48px serif';+ context.fillText(`Score: ${score}/30`,window.innerWidth-48*10,70);+ context.restore();+ }function createMouse(x,y,direction,speed,size){return { 'x':x, 'y':y, 'direction':direction, 'speed':speed,'size':size ,'tailLag':0, 'animation':0, 'animationCounter':0, 'hitbox':size*90 };setInterval(spawnMouse,1000/micePerSecond);setInterval(cleanUpMice,100);setInterval(cleanUpBlood,maxExplosionAge);++ setInterval(depleteCharge,chargeDepletionRate);}function spawnMouse(){- mice.push(createMouse(5+window.innerWidth*Math.random()*0.9,window.innerHeight+normalMouseSize*90,-Math.PI/2,normalMouseSpeed,normalMouseSize));+ mice.push(createMouse(5+window.innerWidth*Math.random()*0.9,window.innerHeight+normalMouseSize*90,-Math.PI/2,(normalMouseSpeed*(Math.random()+1)),normalMouseSize*(Math.random()+1)));}function initialise()mice.push(createMouse(200,100,1,normalMouseSpeed,normalMouseSize));explosions=[];-}function cleanUpMice(){if(health==0){window.cancelAnimationFrame(frameId);- alert("Too many of the filthy rats escaped! Your snake died of despair.");+ alert(`Too many of the filthy rats escaped! Your snake has died of despair. Your score is ${score}`);}}else if(mice[i].x-mice[i].hitbox<snake.x && mice[i].x+mice[i].hitbox>snake.x && mice[i].y+mice[i].hitbox>snake.y && mice[i].y-mice[i].hitbox<snake.y)+ {+ explosions.push( makeExplosion(mice.splice(i,1)[0]));+ checkScore();+ }+ else if(snake.discharging && mouseColidesWithLaserBeam(mice[i]))+ {explosions.push( makeExplosion(mice.splice(i,1)[0]));+ checkScore();+ }+}}function cleanUpBlood()explosions.splice(i,1);}}- /*it is clear that I am bad at geometry :P*/function drawSnake(timeElapsed){let distance;+ let distance2;let vx;let vy;let wx;let wy;- distance=Math.sqrt(Math.pow(window.innerWidth/2-snake.x,2) + Math.pow(window.innerHeight/2-snake.y,2));+ distance2=Math.sqrt(Math.pow(window.innerWidth/2-snake.x,2) + Math.pow(window.innerHeight/2-snake.y,2))+0.1;+ wx=((window.innerWidth/2)-snake.x)/distance2;++ gravitate(snake,cursor,true,10000*(timeElapsed/drawInterval),100);++ distance=Math.sqrt(Math.pow(window.innerWidth/2-snake.x,2) + Math.pow(window.innerHeight/2-snake.y,2))+0.1;vx=(window.innerWidth/2-snake.x)/distance;vy=(window.innerHeight/2-snake.y)/distance;- gravitate(snake,cursor,true,10000*(timeElapsed/drawInterval),100);++ if(charge>chargeTipoffPoint && snake.discharging==false)+ {+ snake.discharging=true;+ snakeLaserId=setInterval(cleanUpMice,drawInterval);+ }else if(snake.discharging==true && charge<=0)+ {+ snake.discharging=false;+ clearInterval(snakeLaserId);+ }+ if(snake.discharging==true)+ {+ gravitate(snake,{'x':Math.random()*window.innerWidth,'y':Math.random()*window.innerHeight/4},false,10000*(timeElapsed/drawInterval),1);+ charge+=Math.abs(Math.asin(wx)-Math.asin(vx))*0.5;+ }else+ {+ charge+=Math.abs(Math.asin(wx)-Math.asin(vx));+ }++ context.save();+ context.shadowBlur=charge;+ context.shadowColor="yellow";/*body*/context.beginPath();context.strokeStyle="#00FF00";context.stroke();context.closePath();-- /*head*/- distance=Math.sqrt(Math.pow(vx*300,2) + Math.pow(vy*100,2));- wx=(vx*300)/distance;- wy=(vy*100)/distance;-- context.save();--context.translate(snake.x,snake.y);+ snake.direction=Math.atan2(vy,vx);+ context.rotate(Math.PI/2+snake.direction);+ /*if(wx>0){- context.rotate(Math.PI-Math.acos(wy));+ snake.direction=Math.acos(wy);+ context.rotate(Math.PI-snake.direction);}else{- context.rotate(Math.PI+Math.acos(wy));+ snake.direction=Math.acos(wy);+ context.rotate(Math.PI+snake.direction);+ }+ */++ if(snake.discharging==true)+ {+ context.beginPath();+ context.fillStyle="#FF0000";+ context.rect(-15,0,30,10000);+ context.fill();+ context.closePath();}+ context.strokeStyle="#00FF00";context.beginPath();- context.ellipse(0,50,30,70,0,0,3*Math.PI);context.fillStyle = "#00FF00";+ context.ellipse(0,50,30,70,0,0,3*Math.PI);context.fill();context.stroke();context.closePath();mouse.y+=mouse.speed*(timeElapsed/drawInterval)*Math.sin(mouse.direction);mouse.animation+=0.4*(timeElapsed/drawInterval);- /*- mouse.direction+=0.1;- if(mouse.direction>1) mouse.direction-=1;- */+ if(score>=0)+ {+ gravitate(mouse,snake,false,(timeElapsed/drawInterval)*500,10);+ }context.save();let numberOfParticles=Math.floor(Math.random()*(maxNumberOfExplosionParticles-minNumberOfExplosionParticles))+minNumberOfExplosionParticles;let i=0;+ ++score;for(i;i<numberOfParticles;++i){ret.particles.push({ 'x':mouse.x , 'y':mouse.y, 'direction':Math.random()*2*Math.PI, 'size':Math.random() });return ret;}+ function depleteCharge()+ {+ charge=Math.max(0,charge-1);+ }+ function possiblyDischarge()+ {++ }+ function mouseColidesWithLaserBeam(mouse)+ {+ let vx=(mouse.x-snake.x);+ let vy=(mouse.y-snake.y);+ let direction=Math.atan2(vy,vx);++ if(direction<0)+ direction=Math.PI*2+direction;++ if(Math.abs(direction-Math.PI-snake.direction)<0.1)+ return true;+ else+ return false;+ }+ function checkScore()+ {+ if(score==20 || score==10 || score==5)+ {+ normalMouseSpeed*=2;+ normalMouseSize*=0.7;+ setInterval(spawnMouse,1000/micePerSecond);+ }++ if(score>=30)+ {+ window.cancelAnimationFrame(frameId);+ alert("You are winner!");+ }+ }F diff --git a/w b/w new file mode 100644 --- /dev/null +++ b/w++ let cursor = {+ 'x' : 0,+ 'y' : 0+ };++ let canvas;+ let context;++ let mice;+ let explosions;++ const drawInterval=20/1000;++ let micePerSecond=0.3;+ const chargeDepletionRate=200;++ const normalMouseSpeed=3;+ const normalMouseSize=1;++ const maxNumberOfExplosionParticles=20;+ const minNumberOfExplosionParticles=5;+ const maxParticleSize=50;+ const maxExplosionAge=100;+++ let lastTimeStamp;++ let snake = {+ 'x':window.innerWidth/2,+ 'y':window.innerHeight/2,+ 'discharging': false,+ 'direction' : 0++ };++ let health=10;+ let score=0;++ let frameId;+ let snakeLaserId;++ let charge=0;+ const chargeTipoffPoint=10;++ function draw(timeStamp)+ {+ let timeElapsed;++ if(lastTimeStamp==undefined)+ lastTimeStamp=timeStamp;++ timeElapsed=Math.min((timeStamp-lastTimeStamp)/1000,0.1);+ lastTimeStamp=timeStamp;++ canvas.width = window.innerWidth;+ canvas.height = window.innerHeight;++ /*the only clear thing here is that I am very bad at geometry*/+ context.clearRect(0, 0, canvas.width, canvas.height);+++ drawExplosions(timeElapsed);+ drawMice(timeElapsed);+ drawSnake(timeElapsed);+ drawHealth();++ frameId=window.requestAnimationFrame(draw);+ }+ function drawHealth()+ {+ context.save();+ context.font='48px serif';+ context.fillText(`Health: ${health}`,10,70);++ context.font='48px serif';+ context.fillText(`Score: ${score}/30`,window.innerWidth-48*10,70);+ context.restore();+ }+ function createMouse(x,y,direction,speed,size)+ {+ return { 'x':x, 'y':y, 'direction':direction, 'speed':speed,'size':size ,'tailLag':0, 'animation':0, 'animationCounter':0, 'hitbox':size*90 };+ }+++ function main()+ {+ initialise();+ frameId=window.requestAnimationFrame(draw);+ setInterval(spawnMouse,1000/micePerSecond);+ setInterval(cleanUpMice,100);+ setInterval(cleanUpBlood,maxExplosionAge);++ setInterval(depleteCharge,chargeDepletionRate);+ }++ function spawnMouse()+ {+ mice.push(createMouse(5+window.innerWidth*Math.random()*0.9,window.innerHeight+normalMouseSize*90,-Math.PI/2,(normalMouseSpeed*(Math.random()+1)),normalMouseSize*(Math.random()+1)));+ }++ function initialise()+ {++ canvas=document.getElementById("canvas1");+ context=canvas.getContext("2d");++ canvas.addEventListener('mousemove', e => { cursor.x=e.offsetX; cursor.y=e.offsetY; });+ mice=[];+ mice.push(createMouse(200,100,1,normalMouseSpeed,normalMouseSize));++ explosions=[];+ }+ function cleanUpMice()+ {+ let i=0;+ for(i;i<mice.length;++i)+ {+ if(mice[i].y<-200 || mice[i].y>window.innerHeight+300 || mice[i].x<-100 || mice[i].x>window.innerWidth+300)+ {+ mice.splice(i,1);+ --health;+ }+ else if(mice[i].x-mice[i].hitbox<snake.x && mice[i].x+mice[i].hitbox>snake.x && mice[i].y+mice[i].hitbox>snake.y && mice[i].y-mice[i].hitbox<snake.y)+ {+ explosions.push( makeExplosion(mice.splice(i,1)[0]));+ }+ else if(snake.discharging && mouseColidesWithLaserBeam(mice[i]))+ {+ explosions.push( makeExplosion(mice.splice(i,1)[0]));+ }++ if(health==0)+ {+ window.cancelAnimationFrame(frameId);+ alert(`Too many of the filthy rats escaped! Your snake has died of despair. Your score is ${score}`);+ }+ if(score==20);+ if(score>=30)+ {+ window.cancelAnimationFrame(frameId);+ alert("You are winner!");+ }+ }+ }+ function cleanUpBlood()+ {+ let i=0;+ for(i;i<explosions.length;++i)+ {+ if(explosions[i].animation>maxExplosionAge)+ explosions.splice(i,1);+ }+ }+ function drawSnake(timeElapsed)+ {+ let distance;+ let distance2;+ let vx;+ let vy;+ let wx;+ let wy;++ distance2=Math.sqrt(Math.pow(window.innerWidth/2-snake.x,2) + Math.pow(window.innerHeight/2-snake.y,2))+0.1;+ wx=((window.innerWidth/2)-snake.x)/distance2;++ gravitate(snake,cursor,true,10000*(timeElapsed/drawInterval),100);++ distance=Math.sqrt(Math.pow(window.innerWidth/2-snake.x,2) + Math.pow(window.innerHeight/2-snake.y,2))+0.1;+ vx=(window.innerWidth/2-snake.x)/distance;+ vy=(window.innerHeight/2-snake.y)/distance;+++ if(charge>chargeTipoffPoint && snake.discharging==false)+ {+ snake.discharging=true;+ snakeLaserId=setInterval(cleanUpMice,drawInterval);+ }else if(snake.discharging==true && charge<=0)+ {+ snake.discharging=false;+ clearInterval(snakeLaserId);+ }++ if(snake.discharging==true)+ {+ gravitate(snake,{'x':Math.random()*window.innerWidth,'y':Math.random()*window.innerHeight/4},false,10000*(timeElapsed/drawInterval),1);+ charge+=Math.abs(Math.asin(wx)-Math.asin(vx))*0.5;+ }else+ {+ charge+=Math.abs(Math.asin(wx)-Math.asin(vx));+ }++ context.save();++ context.shadowBlur=charge;+ context.shadowColor="yellow";+ /*body*/+ context.beginPath();+ context.strokeStyle="#00FF00";+ context.moveTo(window.innerWidth/2,-10);+ context.bezierCurveTo(+ window.innerWidth/2,+ window.innerHeight/4,+ snake.x+vx*300,+ snake.y+vy*100,+ snake.x,+ snake.y+ );+ context.lineWidth=40;+ context.stroke();+ context.closePath();++ context.translate(snake.x,snake.y);+ snake.direction=Math.atan2(vy,vx);+ context.rotate(Math.PI/2+snake.direction);+ /*+ if(wx>0)+ {+ snake.direction=Math.acos(wy);+ context.rotate(Math.PI-snake.direction);+ }else+ {+ snake.direction=Math.acos(wy);+ context.rotate(Math.PI+snake.direction);+ }+ */++ if(snake.discharging==true)+ {+ context.beginPath();+ context.fillStyle="#FF0000";+ context.rect(-15,0,30,10000);+ context.fill();+ context.closePath();+ }++ context.strokeStyle="#00FF00";+ context.beginPath();+ context.fillStyle = "#00FF00";+ context.ellipse(0,50,30,70,0,0,3*Math.PI);+ context.fill();+ context.stroke();+ context.closePath();++ /*right eye*/+ context.beginPath();+ context.fillStyle="#FF0000"+ context.moveTo(20,80);+ context.lineTo(30,80);+ context.lineTo(15,100);+ context.fill();+ context.closePath();++ /*right eye*/+ context.beginPath();+ context.fillStyle="#FF0000"+ context.moveTo(-20,80);+ context.lineTo(-30,80);+ context.lineTo(-15,100);+ context.fill();+ context.closePath();+++ context.restore();++ }++ function drawExplosions(timeElapsed)+ {+ let i=0;+ for(i;i<explosions.length;++i)+ {+ drawExplosion(explosions[i],timeElapsed);+ }+ }+ function drawExplosion(explosion,timeElapsed)+ {+ let i=0;+ explosion.animation+=timeElapsed/drawInterval;+ for(i;i<explosion.particles.length;++i)+ {+ explosion.particles[i].x+=(1000/explosion.animation)*0.1*Math.cos(explosion.particles[i].direction);+ explosion.particles[i].y+=(1000/explosion.animation)*0.1*Math.sin(explosion.particles[i].direction);+++ context.fillStyle=`rgb(+ 255,+ ${Math.floor(255*(explosion.animation/(maxExplosionAge+30)))},+ ${Math.floor(255*(explosion.animation/(maxExplosionAge+30)))}++ )`;+ context.rect(+ explosion.particles[i].x,+ explosion.particles[i].y,+ maxParticleSize*explosion.particles[i].size,+ maxParticleSize*explosion.particles[i].size,+ );+ context.fill();+ }+ }+ function drawMice(timeElapsed)+ {+ let i=0;+ for(i;i<mice.length;++i)+ {+ drawMouse(mice[i],timeElapsed);+ }+ }+ function drawMouse(mouse,timeElapsed)+ {+ mouse.animationCounter+=drawInterval;+ mouse.x+=mouse.speed*(timeElapsed/drawInterval)*Math.cos(mouse.direction);+ mouse.y+=mouse.speed*(timeElapsed/drawInterval)*Math.sin(mouse.direction);+ mouse.animation+=0.4*(timeElapsed/drawInterval);++ /*+ mouse.direction+=0.1;+ if(mouse.direction>1) mouse.direction-=1;+ */++ context.save();++ context.translate(mouse.x, mouse.y);+ context.rotate(mouse.direction);+ context.scale(mouse.size,mouse.size);++ /*body*/+ context.beginPath();+ context.ellipse(0,0,90,40,0,0,2*Math.PI);+ context.fillStyle = "#8f8f8f";+ context.fill();+ context.stroke();+ context.closePath();+ /*right ear*/+ context.beginPath();+ context.arc(50, 20, 20, 0, Math.PI*1.5, false);+ context.fillStyle = "#8f8f8f";+ context.fill();+ context.stroke();+ context.closePath();+ /*left ear*/+ context.beginPath();+ context.arc(50, -22, 20, 0,- Math.PI*1.5, true);+ context.fillStyle = "#8f8f8f";+ context.fill();+ context.stroke();+ context.closePath();+ /*left eye*/+ context.beginPath();+ context.ellipse(80,7,5,3,-1/2,0,2*Math.PI);+ context.fillStyle = "#000000";+ context.fill();+ context.closePath();+ /*right eye*/+ context.beginPath();+ context.ellipse(80,-7,5,3,1/2,0,2*Math.PI);+ context.fillStyle = "#000000";+ context.fill();+ context.closePath();+ /*right wiskers*/+ context.beginPath();+ context.moveTo(89,0);+ context.lineTo(95,20);+ context.stroke();+ context.closePath();+ context.beginPath();+ context.moveTo(89,0);+ context.lineTo(90,20);+ context.stroke();+ context.closePath();+ /*left wiskers*/+ context.beginPath();+ context.moveTo(89,0);+ context.lineTo(95,-20);+ context.stroke();+ context.closePath();+ context.beginPath();+ context.moveTo(89,0);+ context.lineTo(90,-20);+ context.stroke();+ context.closePath();++ /*tail*/+ context.beginPath();+ context.moveTo(-90,0);+ context.bezierCurveTo(-100,0,-150,Math.cos(mouse.animation)*30,-200,Math.sin(mouse.animation)*10);+ context.lineWidth+=2;+ context.stroke();+ context.closePath();++ context.restore();+ }++ function gravitate(subject,gravitas,doesItPull,pullStrength,nearDistance)+ {+ let distance=Math.sqrt( (subject.x-gravitas.x)*(subject.x-gravitas.x) + (subject.y-gravitas.y)*(subject.y-gravitas.y));++ if(distance==0)+ {+ return ;+ }++ if(doesItPull==false)+ {+ subject.x+=(((subject.x-gravitas.x)*pullStrength)/(distance*distance));+ subject.y+=(((subject.y-gravitas.y)*pullStrength)/(distance*distance));+ }else+ {+ if(distance<=nearDistance)+ {+ subject.x=gravitas.x;+ subject.y=gravitas.y;+ }else+ {+ subject.x-=(((subject.x-gravitas.x)*pullStrength)/(distance*distance));+ subject.y-=(((subject.y-gravitas.y)*pullStrength)/(distance*distance));+ }++ }+ }+ function makeExplosion(mouse)+ {+ let ret={ 'mouse': mouse, 'animation':0, 'particles':[] };+ let numberOfParticles=Math.floor(Math.random()*(maxNumberOfExplosionParticles-minNumberOfExplosionParticles))+minNumberOfExplosionParticles;+ let i=0;++ ++score;+ for(i;i<numberOfParticles;++i)+ {+ ret.particles.push({ 'x':mouse.x , 'y':mouse.y, 'direction':Math.random()*2*Math.PI, 'size':Math.random() });+ }++ return ret;+ }+ function depleteCharge()+ {+ charge=Math.max(0,charge-1);+ }+ function possiblyDischarge()+ {++ }+ function mouseColidesWithLaserBeam(mouse)+ {+ let vx=(mouse.x-snake.x);+ let vy=(mouse.y-snake.y);+ let direction=Math.atan2(vy,vx);++ if(direction<0)+ direction=Math.PI*2+direction;++ if(Math.abs(direction-Math.PI-snake.direction)<0.1)+ return true;+ else+ return false;+ }