Zombies

HTML

<input type="button" value="Pause" onclick="pause();this.value=paused?'Resume':'Pause'">
<input type="button" value="Manual Step" onclick="update();draw()">
<input type="button" value="Manual Update" onclick="update()">
<input type="button" value="Manual Draw" onclick="draw()">

JavaScript

// requestAnimationFrame shim
window.requestAnimFrame = function() {
  return window.requestAnimationFrame       ||
         window.webkitRequestAnimationFrame ||
         window.mozRequestAnimationFrame    ||
         window.oRequestAnimationFrame      ||
         window.msRequestAnimationFrame     ||
         function(cb) {
           window.setTimeout(cb, 1000 / 60)
         }
}()

// Mixin for movable entities which have: x, y, d(egrees), speed
var asMovable = function() {
  function moveForward() {
    this.x = this.x + Math.cos(this.d * (Math.PI / 180)) * this.speed
    this.y = this.y + Math.sin(this.d * (Math.PI / 180)) * this.speed
  }

  function moveTowards(x, y) {
    var dx = x - this.x
      , dy = y - this.y
      , hyp = Math.sqrt(dx * dx + dy * dy)
    this.x += this.speed * dx / hyp
    this.y += this.speed * dy / hyp
    this.d = Math.atan2(dy, dx) * 180 / Math.PI
  }

  return function(proto) {
    proto.moveForward = moveForward
    proto.moveTowards = moveTowards
    return proto
  }
}()

function Player(kwargs) {
  this.x = kwargs.x
  this.y = kwargs.y
  this.d = kwargs.d || 0
  this.size = 10
  this.speed = 2
  // XXX
  this.stepFrame = 0
  this.shootFrame = Math.floor(Math.random() * 5000)
}

asMovable(Player.prototype)

function Zombie(kwargs) {
  this.x = kwargs.x
  this.y = kwargs.y
  this.d = kwargs.d || 0
  this.size = kwargs.size || 10
  this.speed = kwargs.speed || Math.max(0.5, Math.random() * 1.5)
  this.los = kwargs.los || 50 + Math.floor(Math.random() * 50)
  this.fov = kwargs.fov || 25 + Math.floor(Math.random() * 15)
  // XXX
  this.moanFrame = Math.floor(Math.random() * 5000)
}

asMovable(Zombie.prototype)

function Sound(kwargs) {
  this.x = kwargs.x
  this.y = kwargs.y
  this.radius = kwargs.radius || 50
  this.text = kwargs.text || 'BANG!'
  this.progress = 0
}

var WIDTH = 512
  , HEIGHT = 372

var canvas, context
var player, zombies, sounds

function init() {
  canvas = document.createElement('canvas')
  canvas.width =...