Hero Manager

by Sam Fereday

HTML

<div id="output">
  ...
  <br />
</div>
<button id="btn">
  Go!
</button>

CSS

body {
  font: 85%/1.4em 'consolas', arial;
  padding: 1em;
  margin: 0;
  background: #333;
  color: #fff;
}

* {
  box-sizing: border-box;
}

#output {
  padding: 1em;
  margin-bottom: 1em;
  background: #111;
  overflow-y: auto;
  height: 20em;
}

input {
  width: 100%;
  padding: 1em;
  display: block;
  background: #222;
  color: #fff;
  border: 0;
}

button {
  margin-top: 1em;
  padding: 1em;
  border: 0;
}

JavaScript

var o = document.getElementById("output");

function log(str) {
  o.innerHTML += str + "<br />";
  o.scrollTop = o.scrollHeight;
}

var gameloop = (function() {
  'use strict';
  var reqAnimFrame = window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame;

  return function(callback) {
    var lastUpdate = +new Date();
    (function loop() {
      callback(((+new Date()) - lastUpdate) / 1000);
      reqAnimFrame(loop);
      lastUpdate = +new Date();
    }());
  };
}());

// https://gist.github.com/aurbano/4693462
function distanceApprox(p1, p2) {
  // Approximation by using octagons approach
  var x = p2.x - p1.x;
  var y = p2.y - p1.y;
  return 1.426776695 * Math.min(0.7071067812 * (Math.abs(x) + Math.abs(y)), Math.max(Math.abs(x), Math.abs(y)));
}

// Other stuff
var names = [];
var heroes = [];

var States = {
  Idle: 0,
  Travelling: 1,
  Returning: 2,
  ActionComplete: 3,
  Battle: 4
}

var DestinationTypes = {
  Home: 0,
  Quest: 1,
  Inn: 2
}

// Leveling
var LevelWeights = {
  getExpForLevel: function(n) {
    return Math.floor(n * 200)
  },
  getHealthForLevel: function(n) {
  	return Math.floor(n * 1.2);
  },
  getCombatAbilityForLevel: function(n) {
  	return Math.floor(n * 1.1);
  }
}

// Managers
var HeroManager = {

  update: function() {

    if (heroes.length > 0)
      heroes.forEach(x => x.update());

  }

}

// Global layer
var Global = function() {
  this.userData = {
    name: ""
  }
}

// Guild layer
var Guild = function() {
  this.data = {
    name: "",
    type: DestinationTypes.Home,
    x: 2,
    y: 2
  }
}

var _guild = new Guild();

// Hero layer
var Hero = function(_name) {

  this.state = States.Idle;

  this.data = {
    name: _name,
    level: 1,
    location: {
      x: 2,
      y: 2
    },
    destination: {
      name: "",
      type: null,
      x: 0,
      y: 0
    },
    leveling: {
      exp: 0,
      expToNext: 0
    },
    stats: {
    	maxHealth: 100,
     ...