F diff --git a/snek.js b/snek.js
--- a/snek.js
+++ b/snek.js
+ let cursor = {
+ 'x' : 0,
+ 'y' : 0
+ };
+
let canvas;
let context;
+
let mice;
+ let explosions;
let drawInterval=20/1000;
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;
context.clearRect(0, 0, canvas.width, canvas.height);
+ drawExplosions(timeElapsed);
drawMice(timeElapsed);
+ drawSnake(timeElapsed);
- window.requestAnimationFrame(draw);
+ 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 };
+ return { 'x':x, 'y':y, 'direction':direction, 'speed':speed,'size':size ,'tailLag':0, 'animation':0, 'animationCounter':0, 'hitbox':size*90 };
}
function main()
{
initialise();
- window.requestAnimationFrame(draw);
+ frameId=window.requestAnimationFrame(draw);
setInterval(spawnMouse,1000/micePerSecond);
setInterval(cleanUpMice,100);
+ setInterval(cleanUpBlood,maxExplosionAge);
}
function spawnMouse()
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()
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;
+ 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].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]));
+ }
+ }
+ function cleanUpBlood()
+ {
+ let i=0;
+ for(i;i<explosions.length;++i)
+ {
+ if(explosions[i].animation>maxExplosionAge)
+ 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;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)
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.8*(timeElapsed/drawInterval);
+ mouse.animation+=0.4*(timeElapsed/drawInterval);
/*
mouse.direction+=0.1;
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<numberOfParticles;++i)
+ {
+ ret.particles.push({ 'x':mouse.x , 'y':mouse.y, 'direction':Math.random()*2*Math.PI, 'size':Math.random() });
+ }
+
+ return ret;
+ }
F diff --git a/tags b/tags
--- a/tags
+++ b/tags
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
!_TAG_PROGRAM_VERSION 0.0.0 //
- #canvas2 snek.css /^#canvas2 {$/;" i
+ animation snek.js /^ let ret={ 'mouse': mouse, 'animation':0, 'particles':[] };$/;" p class:makeExplosion.ret
canvas snek.js /^let canvas;$/;" v
canvas1 snek.html /^ <canvas id="canvas1"><\/canvas>$/;" I
- canvas2 snek.html /^ <canvas id="canvas2"><\/canvas>$/;" I
+ cleanUpBlood snek.js /^function cleanUpBlood()$/;" f signature:()
+ cleanUpMice snek.js /^function cleanUpMice()$/;" f signature:()
context snek.js /^let context;$/;" v
createMouse snek.js /^function createMouse(x,y,direction,speed,size)$/;" f signature:(x,y,direction,speed,size)
+ cursor snek.js /^let cursor = {$/;" c
draw snek.js /^function draw(timeStamp)$/;" f signature:(timeStamp)
- drawInterval snek.js /^let drawInterval=1000\/30;$/;" v
- drawMice snek.js /^function drawMice()$/;" f signature:()
- drawMouse snek.js /^function drawMouse(mouse)$/;" f signature:(mouse)
+ drawExplosion snek.js /^function drawExplosion(explosion,timeElapsed)$/;" f signature:(explosion,timeElapsed)
+ drawExplosions snek.js /^function drawExplosions(timeElapsed)$/;" f signature:(timeElapsed)
+ drawInterval snek.js /^let drawInterval=20\/1000;$/;" v
+ drawMice snek.js /^function drawMice(timeElapsed)$/;" f signature:(timeElapsed)
+ drawMouse snek.js /^function drawMouse(mouse,timeElapsed)$/;" f signature:(mouse,timeElapsed)
+ drawSnake snek.js /^function drawSnake(timeElapsed)$/;" f signature:(timeElapsed)
+ explosions snek.js /^let explosions;$/;" v
+ gravitate snek.js /^function gravitate(subject,gravitas,doesItPull,pullStrength,nearDistance)$/;" f signature:(subject,gravitas,doesItPull,pullStrength,nearDistance)
initialise snek.js /^function initialise()$/;" f signature:()
lastTimeStamp snek.js /^let lastTimeStamp;$/;" v
main snek.js /^function main()$/;" f signature:()
+ makeExplosion snek.js /^function makeExplosion(mouse)$/;" f signature:(mouse)
+ maxExplosionAge snek.js /^let maxExplosionAge=100;$/;" v
+ maxNumberOfExplosionParticles snek.js /^let maxNumberOfExplosionParticles=50;$/;" v
mice snek.js /^let mice;$/;" v
micePerSecond snek.js /^let micePerSecond=0.3;$/;" v
+ mouse snek.js /^ let ret={ 'mouse': mouse, 'animation':0, 'particles':[] };$/;" p class:makeExplosion.ret
normalMouseSize snek.js /^let normalMouseSize=1;$/;" v
- normalMouseSpeed snek.js /^let normalMouseSpeed=10;$/;" v
+ normalMouseSpeed snek.js /^let normalMouseSpeed=3;$/;" v
+ particles snek.js /^ let ret={ 'mouse': mouse, 'animation':0, 'particles':[] };$/;" p class:makeExplosion.ret
+ ret snek.js /^ let ret={ 'mouse': mouse, 'animation':0, 'particles':[] };$/;" c class:makeExplosion
+ snake snek.js /^let snake = { $/;" c
snek.css snek.css 1;" F
snek.html snek.html 1;" F
snek.js snek.js 1;" F
spawnMouse snek.js /^function spawnMouse()$/;" f signature:()
+ x snek.js /^ 'x' : 0,$/;" p class:cursor
+ x snek.js /^ 'x':window.innerWidth\/2,$/;" p class:snake
+ y snek.js /^ 'y' : 0$/;" p class:cursor
+ y snek.js /^ 'y':window.innerHeight\/2 $/;" p class:snake