-
-
Save Kuzcoo/dfa838ea8c5aca367bbe8743ea0851f1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let setSize = function (w,h=w) { | |
this.width = w; | |
this.height = h; | |
}; | |
let createCanvas = (w,h) => { | |
let canvas = document.createElement('canvas'); | |
if (w) { | |
setSize.call(canvas,w,h); | |
} | |
return canvas; | |
}; | |
let createContext = function (c) { | |
return c.getContext('2d'); | |
}; | |
let appendCanvas = function (c) { | |
document.body.appendChild(c); | |
}; | |
let clearCanvas = function (ctx) { | |
ctx.clearRect(0,0,this.width,this.height); | |
}; | |
///////////////////////////////////////////////////////////////////// | |
let random = n => { | |
return Math.floor(Math.random()*n); | |
}; | |
let randomAmong = function () { | |
return arguments[random(arguments.length-1)]; | |
}; | |
///////////////////////////////////////////////////////////////////// | |
let Keyboarder = function () { | |
let keys = {}, | |
KEYS = { | |
LEFT: 37, | |
UP: 38, | |
RIGHT: 39, | |
DOWN: 40, | |
SPACE: 32 | |
}, | |
lastKey = 'RIGHT'; | |
window.addEventListener('keydown', e => { | |
keys[e.keyCode] = true; | |
}); | |
window.addEventListener('keyup', e => { | |
keys[e.keyCode] = false; | |
}); | |
return { | |
isPressed(key) { | |
return keys[KEYS[key]]; | |
} | |
}; | |
}(); | |
///////////////////////////////////////////////////////////////////// | |
class Hero { | |
constructor(ctx,bullets) { | |
this.bullets = bullets; | |
this.ctx = ctx; | |
this.lives = 4; | |
this.pos = new Vector(200,200); | |
this.size = 10; | |
} | |
drawLife() { | |
for (let i = 0; i < this.lives; i++) { | |
this.ctx.fillRect(15*i,0,10,10); | |
}; | |
} | |
checkEdges() { | |
if (this.pos.x <= 0) {this.pos.x=0} | |
if (this.pos.x >= 390) {this.pos.x=390} | |
if (this.pos.y <= 0) {this.pos.y=0} | |
if (this.pos.y >= 390) {this.pos.y=390} | |
} | |
shoot(direction) { | |
console.log('ammo:',this.bullets.ammo); | |
this.bullets.add(this.pos,direction); | |
}; | |
drawWeapon() { | |
switch (Keyboarder.lastKey) { | |
case 'LEFT': | |
ctx.fillRect(this.pos.x-15,this.pos.y+3.5,5,5); | |
break; | |
case 'UP': | |
ctx.fillRect(this.pos.x+2.5,this.pos.y-15,5,5); | |
break; | |
case 'RIGHT': | |
ctx.fillRect(this.pos.x+15,this.pos.y+3.5,5,5); | |
break; | |
case 'DOWN': | |
ctx.fillRect(this.pos.x+2.5,this.pos.y+15,5,5); | |
break; | |
} | |
} | |
update() { | |
let kb = Keyboarder; | |
if (kb.isPressed('LEFT')) {this.pos.x-=4;kb.lastKey='LEFT';} | |
if (kb.isPressed('UP')) {this.pos.y-=4;kb.lastKey='UP';} | |
if (kb.isPressed('RIGHT')) {this.pos.x+=4;kb.lastKey='RIGHT';} | |
if (kb.isPressed('DOWN')) {this.pos.y+=4;kb.lastKey='DOWN';} | |
// | |
if (kb.isPressed('SPACE')) {this.shoot(kb.lastKey);} | |
this.checkEdges(); | |
} | |
draw() { | |
this.ctx.fillStyle = '#000'; | |
this.drawLife(); | |
this.ctx.fillRect(this.pos.x,this.pos.y,this.size,this.size); | |
this.drawWeapon(); | |
} | |
}; | |
///////////////////////////////////////////////////////////////////// | |
class Zombie { | |
constructor(ctx) { | |
this.isAlive = true; | |
this.speed = random(2)+1; | |
this.ctx = ctx; | |
this.hit = false; | |
this.pos = new Vector(random(400),-10); | |
this.acc = new Vector(0,0); | |
this.size = 15; | |
} | |
collideWith(p) { | |
return (this.pos.x < p.pos.x + p.size && | |
this.pos.x + this.size > p.pos.x && | |
this.pos.y < p.pos.y + p.size && | |
this.size + this.pos.y > p.pos.y); | |
} | |
die() { | |
//console.log('zombie dies'); | |
this.isAlive = false; | |
} | |
wound(hero) { | |
if (!this.hit) { | |
this.hit = true; | |
hero.lives-=!hero.lives?0:1; | |
setTimeout(() => this.hit = false,500); | |
} | |
} | |
goTo(heroPos) { | |
this.acc = Vector.sub(heroPos,this.pos); | |
this.acc.norm(); | |
this.acc.mul(this.speed); | |
} | |
update(hero) { | |
this.goTo(hero.pos); | |
this.pos.add(this.acc); | |
this.acc.mul(0); | |
} | |
draw() { | |
this.ctx.fillStyle = '#ff0000'; | |
this.ctx.fillRect(this.pos.x,this.pos.y,this.size,this.size); | |
} | |
} | |
class ZombieGenerator { | |
constructor(ctx, n) { | |
this.zombies = []; | |
this.enableSpawn = true; | |
this.spawnTime = 5000; | |
this.spawnZombies(n); | |
} | |
spawnZombies(n) { | |
if (this.enableSpawn) { | |
this.enableSpawn = false; | |
for (let i = 0; i < n; i++) { | |
this.zombies.push(new Zombie(ctx)); | |
} | |
setTimeout( () => { | |
this.enableSpawn = true; | |
},this.spawnTime); | |
} | |
} | |
update(hero) { | |
this.zombies = this.zombies.filter(z => z.isAlive); | |
this.zombies.forEach(z => { | |
z.update(hero); | |
if (z.collideWith(hero)) { | |
z.wound(hero); | |
} | |
}); | |
} | |
draw() { | |
this.zombies.forEach(z => { | |
z.draw(); | |
}); | |
} | |
} | |
///////////////////////////////////////////////////////////////////// | |
class Bullet { | |
constructor(v,dir) { | |
this.alive = true; | |
this.size = 4; | |
this.pos = v.get(); | |
this.dir = this.setDirection(dir); | |
this.dir.mul(10); | |
} | |
setDirection(dir) { | |
switch (dir) { | |
case 'LEFT': return new Vector(-1,0) ;break; | |
case 'UP': return new Vector(0,-1) ;break; | |
case 'RIGHT': return new Vector(1,0) ;break; | |
case 'DOWN': return new Vector(0,1) ;break; | |
} | |
} | |
die() { | |
this.alive = false; | |
} | |
update() { | |
this.pos.add(this.dir); | |
} | |
draw() { | |
ctx.fillStyle = '#00f'; | |
ctx.fillRect(this.pos.x,this.pos.y,4,4); | |
} | |
} | |
class Bullets { | |
constructor() { | |
this.bullets = []; | |
this.ammo = 50; | |
} | |
add(pos,dir) { | |
if (this.ammo > 0) { | |
this.ammo--; | |
this.bullets.push(new Bullet(pos,dir)); | |
} | |
} | |
update(zombies) { | |
this.bullets = this.bullets.filter(b => b.alive); | |
this.bullets.forEach(b => { | |
zombies.forEach(z => { | |
if (z.collideWith(b)) { | |
score++; | |
this.ammo+=5; | |
b.die(); | |
z.die(); | |
} | |
}); | |
b.update(); | |
}); | |
} | |
draw() { | |
this.bullets.forEach(b => { | |
b.draw(); | |
}); | |
} | |
} | |
///////////////////////////////////////////////////////////////////// | |
let c = null, | |
ctx = null, | |
p = null, | |
zombies = null, | |
bullets = null, | |
score = 0, run = true; | |
///////////////////////////////////////////////////////////////////// | |
let setup = () => { | |
c = createCanvas(400); | |
ctx = createContext(c); | |
appendCanvas(c); | |
// | |
bullets = new Bullets(); | |
p = new Hero(ctx,bullets); | |
zombies = new ZombieGenerator(ctx,10); | |
}; | |
let update = () => { | |
zombies.spawnZombies(5); | |
p.update(); | |
zombies.update(p); | |
bullets.update(zombies.zombies); | |
}; | |
let draw = () => { | |
if (!p.lives) {return;} | |
clearCanvas.call(c,ctx); | |
update(); | |
p.draw(); | |
zombies.draw(); | |
bullets.draw(); | |
requestAnimationFrame(draw); | |
}; | |
///////////////////////////////////////////////////////////////////// | |
setup(); | |
draw(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment