ANGRY SNEK



LOG | FILES | OVERVIEW


F diff --git a/snek.js b/snek.js --- a/snek.js +++ b/snek.js
let 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;
+ }