Survive The Winter Test

by Sam Fereday

HTML

<div id="hud">
  <!--<div class="icon cooldown"></div>
  <div class="icon full"></div>-->
  <div class="icon">
    Temp
    <br />{{0}}
  </div>
  <div class="icon">
    Hunger
    <br />{{0}}
  </div>
  <div class="icon">
    Fuel
    <br />{{0}}
  </div>
  <div class="icon">
    Health
    <br />{{0}}
  </div>
</div>
<div id="actions">
  <button id="food">
    Give Food
  </button>
  <button id="sleep">
    Give Sleep
  </button>
  <button id="move">
    Give Move
  </button>
  <button id="fuel">
    Give Fuel
  </button>
</div>

SCSS

body {
  font: 85%/1.4em Consolas, Arial;
  color: #fff;
}


/* Modify me for different cooldown speed! */

$cooldown_len:1.4s;

/* Modify me for a different cooldown color! */

$cooldown_clr: #BADA55;

/* Modify me to be 'infinite' or a number! */

$cooldown_count: infinite;
@-webkit-keyframes anim-cooldown-inner {
  0% {
    background: rgba(0, 0, 0, 0.5);
  }
  90% {
    background: rgba(0, 0, 0, 0.5);
  }
  91% {
    background: rgba(0, 0, 0, 0);
  }
  100% {
    background: rgba(0, 0, 0, 0);
  }
}

@-webkit-keyframes anim-cooldown {
  0% {
    background-size: 46px 0px;
    background-position: 0px 100%;
  }
  90% {
    background-size: 46px 46px;
    background-position: 0px 100%;
    box-shadow: 0px 0px 12px rgba(255, 255, 255, 0);
  }
  95% {
    box-shadow: 0px 0px 12px rgba(255, 255, 255, 0.6);
  }
  100% {
    box-shadow: 0px 0px 12px rgba(255, 255, 255, 0);
  }
}

body {
  background: #444;
}

*,
*:after,
*:before {
  border-radius: 6px;
}

#hud {
  overflow: auto;
  border: 2px solid #888;
}

.icon {
  border: 1px solid #222;
  width: 60px;
  height: 60px;
  background: #eee;
  float: left;
  margin: 20px;
  margin-left: 20px;
  position: relative;
  background: #888;
  background-size: 36px 36px;
  background-position: 3px 3px;
  background-repeat: no-repeat;
  text-align: center;
}

.icon:before {
  content: "";
  width: 66px;
  height: 66px;
  position: absolute;
  left: -3px;
  top: -3px;
  z-index: -1;
  background: #222;
  border-radius: 8px;
}

.icon.full:before {
  background: $cooldown_clr;
}

.icon.cooldown:before {
  background-color: #222;
  background-image: -webkit-linear-gradient(bottom, $cooldown_clr 0%, $cooldown_clr 100%);
  background-size: 46px 46px;
  background-position: 0px 100%;
  background-repeat: no-repeat;
  -webkit-animation: anim-cooldown $cooldown_len linear $cooldown_count;
  box-shadow: 0px 0px 12px rgba(255, 255, 255, 0);
}

.icon.cooldown:after {
  content: "";
  width: 40px;
  height: 40px;
  background: rgba(0, 0,...

JavaScript

console.clear();
// ----
var gameloop = (function() {
  'use strict';
  var reqAnimFrame = window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    function(callback) {
      window.setTimeout(callback, 1000 / 60);
    };

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

function roundNumber(num, scale) {
  if (!("" + num).includes("e")) {
    return +(Math.round(num + "e+" + scale) + "e-" + scale);
  } else {
    var arr = ("" + num).split("e");
    var sig = ""
    if (+arr[1] + scale > 0) {
      sig = "+";
    }
    return +(Math.round(+arr[0] + "e" + sig + (+arr[1] + scale)) + "e-" + scale);
  }
}

// ----
var StateMachine = function(initialState) {

  //this.states = states || {};
  this.initialeState = initialState;
  this.states = [];

  return this;

};

StateMachine.prototype.Top = function() {

  return this.states.length > 0 ? this.states[this.states.length - 1] : this.initialeState;

}

StateMachine.prototype.Pop = function() {

  // Don't pop the initial state.
  if (this.states.length === 0)
    return;

  this.Top().Exit();
  this.states.pop();

}

StateMachine.prototype.Clear = function() {

  // Not sure if will need to perform exit routines on all before clear.
  this.states.length = 0;

}

StateMachine.prototype.Push = function(state, params) {

  if (this.states.find(x => x.id === state.id))
    return;

  this.states.push(state);
  this.Top().Enter(params);

}

StateMachine.prototype.Interrupt = function(state, params) {

  this.Clear();
  this.Push(state, params);

}

StateMachine.prototype.Update = function(dt) {

  this.Top().Update(dt);

  if (this.Top().isFinished)
    this.Pop();

};

// ---- States
var StateIdle = function(owner, stats) {
  this.id = "st_idle";
  this.statModel = stats;
  this.owner =...