let cursor = { 'x' : 0, 'y' : 0 }; let canvas; let context; let mice; let explosions; let drawInterval=20/1000; let micePerSecond=0.3; let normalMouseSpeed=3; let normalMouseSize=1; let maxNumberOfExplosionParticles=20; let minNumberOfExplosionParticles=5; let maxParticleSize=50; let maxExplosionAge=100; let lastTimeStamp; let snake = { 'x':window.innerWidth/2, 'y':window.innerHeight/2 }; let health=10; let frameId; 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; context.clearRect(0, 0, canvas.width, canvas.height); drawExplosions(timeElapsed); drawMice(timeElapsed); drawSnake(timeElapsed); frameId=window.requestAnimationFrame(draw); } 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); } function spawnMouse() { mice.push(createMouse(5+window.innerWidth*Math.random()*0.9,window.innerHeight+normalMouseSize*90,-Math.PI/2,normalMouseSpeed,normalMouseSize)); } 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;iwindow.innerHeight+300 || mice[i].x<-100 || mice[i].x>window.innerWidth+300) { mice.splice(i,1); --health; if(health==0) { window.cancelAnimationFrame(frameId); alert("Too many of the filthy rats escaped! Your snake died of despair."); } } else if(mice[i].x-mice[i].hitboxsnake.x && mice[i].y+mice[i].hitbox>snake.y && mice[i].y-mice[i].hitboxmaxExplosionAge) explosions.splice(i,1); } } /*it is clear that I am bad at geometry :P*/ function drawSnake(timeElapsed) { let distance; 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)); vx=(window.innerWidth/2-snake.x)/distance; vy=(window.innerHeight/2-snake.y)/distance; gravitate(snake,cursor,true,10000*(timeElapsed/drawInterval),100); /*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(); /*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); if(wx>0) { context.rotate(Math.PI-Math.acos(wy)); }else { context.rotate(Math.PI+Math.acos(wy)); } context.beginPath(); context.ellipse(0,50,30,70,0,0,3*Math.PI); context.fillStyle = "#00FF00"; 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;i1) 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; for(i;i