diff options
author | Galin Simeonov <gts@volconst.com> | 2021-09-29 04:17:58 +0300 |
---|---|---|
committer | Galin Simeonov <gts@volconst.com> | 2021-09-29 04:17:58 +0300 |
commit | d4c75508509eb46c2647488f8d111373abd80a22 (patch) | |
tree | c1a2be2f5f22746fccc62cc116063a56fc39e81c | |
parent | 20c04c8dec132112fdef2356a22890df8e064e91 (diff) | |
download | snek-d4c75508509eb46c2647488f8d111373abd80a22.tar.gz |
basic game functionality
-rw-r--r-- | snek.js | 205 | ||||
-rw-r--r-- | tags | 30 |
2 files changed, 225 insertions, 10 deletions
@@ -1,7 +1,14 @@ +let cursor = { + 'x' : 0, + 'y' : 0 +}; + let canvas; let context; + let mice; +let explosions; let drawInterval=20/1000; @@ -10,7 +17,22 @@ 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; @@ -26,23 +48,26 @@ function draw(timeStamp) 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() @@ -56,9 +81,11 @@ 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() @@ -69,7 +96,137 @@ 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) @@ -85,7 +242,7 @@ 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.8*(timeElapsed/drawInterval); + mouse.animation+=0.4*(timeElapsed/drawInterval); /* mouse.direction+=0.1; @@ -165,3 +322,43 @@ function drawMouse(mouse,timeElapsed) 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; +} @@ -7,24 +7,42 @@ !_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 |