Skip to content
Snippets Groups Projects
spniEpilogue.js 89.1 KiB
Newer Older
/* Epilogue UI elements */
$epilogueScreen = $('#epilogue-screen');
var epilogueContainer = document.getElementById('epilogue-container');

/* Epilogue selection modal elements */
$epilogueSelectionModal = $('#epilogue-modal'); //the modal box
$epilogueHeader = $('#epilogue-header-text'); //the header text for the epilogue selection box
$epilogueList = $('#epilogue-list'); //the list of epilogues
$epilogueAcceptButton = $('#epilogue-modal-accept-button'); //click this button to go with the chosen ending

var epilogueSelections = []; //references to the epilogue selection UI elements

var winStr = "You've won the game, and possibly made some friends. Who among these players did you become close with?"; //Winning the game, with endings available
var winStrNone = "You've won the game, and possibly made some friends? Unfortunately, none of your competitors are ready for a friend like you.<br>(None of the characters you played with have an ending written.)"; //Player won the game, but none of the characters have an ending written
var lossStr = "Well you lost. And you didn't manage to make any new friends. But you saw some people strip down and show off, and isn't that what life is all about?<br>(You may only view an ending when you win.)"; //Player lost the game. Currently no support for ending scenes when other players win

// Player won the game, but epilogues are disabled.
var winEpiloguesDisabledStr = "You won... but epilogues have been disabled.";

// Player lost the game with epilogues disabled.
var lossEpiloguesDisabledStr = "You lost... but epilogues have been disabled.";

var epilogues = []; //list of epilogue data objects
var chosenEpilogue = null;
var epiloguePlayer = null;
var epilogueSuffix = 0;
// Attach some event listeners
var previousButton = document.getElementById('epilogue-previous');
var nextButton = document.getElementById('epilogue-next');
spnati_edit's avatar
spnati_edit committed
previousButton.addEventListener('click', function (e) {
  e.preventDefault();
  e.stopPropagation();
  moveEpilogueBack();
spnati_edit's avatar
spnati_edit committed
nextButton.addEventListener('click', function (e) {
  e.preventDefault();
  e.stopPropagation();
  moveEpilogueForward();
spnati_edit's avatar
spnati_edit committed
document.getElementById('epilogue-restart').addEventListener('click', function (e) {
  e.preventDefault();
  e.stopPropagation();
  showRestartModal();
});
spnati_edit's avatar
spnati_edit committed
document.getElementById('epilogue-buttons').addEventListener('click', function () {
  if (!previousButton.disabled) {
    moveEpilogueBack();
spnati_edit's avatar
spnati_edit committed
epilogueContainer.addEventListener('click', function () {
  if (!nextButton.disabled) {
    moveEpilogueForward();
/************************************************************
 * Animation class. Used instead of CSS animations for the control over stopping/rewinding/etc.
 ************************************************************/
function Animation(id, frames, updateFunc, loop, easingFunction, clampFunction, iterations) {
  this.id = id;
  this.looped = loop === "1" || loop === "true";
  this.keyframes = frames;
  this.iterations = iterations;
  this.easingFunction = easingFunction || "smooth";
  this.clampFunction = clampFunction || "wrap";
  for (var i = 0; i < frames.length; i++) {
    frames[i].index = i;
    frames[i].keyframes = frames;
  }
  this.duration = frames[frames.length - 1].end;
  this.elapsed = 0;
  this.updateFunc = updateFunc;
}
Animation.prototype.easingFunctions = {
  "linear": function (t) { return t; },
  "smooth": function (t) { return 3 * t * t - 2 * t * t * t; },
spnati_edit's avatar
spnati_edit committed
  "ease-in": function (t) { return t * t; },
  "ease-out": function (t) { return t * (2 - t); },
  "elastic": function (t) { return (.04 - .04 / t) * Math.sin(25 * t) + 1; },
  "ease-in-cubic": function (t) { return t * t * t; },
  "ease-out-cubic": function (t) { t--; return 1 + t * t * t; },
  "ease-in-sin": function (t) { return 1 + Math.sin(Math.PI / 2 * t - Math.PI / 2); },
  "ease-out-sin": function (t) { return Math.sin(Math.PI / 2 * t); },
  "ease-in-out-cubic": function (t) { return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; },
spnati_edit's avatar
spnati_edit committed
  "ease-out-in": function (t) { return t < .5 ? Animation.prototype.easingFunctions["ease-out"](2 * t) * 0.5 : Animation.prototype.easingFunctions["ease-in"](2 * (t - 0.5)) * 0.5 + 0.5; },
  "ease-out-in-cubic": function (t) { return t < .5 ? Animation.prototype.easingFunctions["ease-out-cubic"](2 * t) * 0.5 : Animation.prototype.easingFunctions["ease-in-cubic"](2 * (t - 0.5)) * 0.5 + 0.5; },
  "bounce": function (t) {
    if (t < 0.3636) {
      return 7.5625 * t * t;
    }
    else if (t < 0.7273) {
      t -= 0.5455;
      return 7.5625 * t * t + 0.75;
    }
    else if (t < 0.9091) {
      t -= 0.8182;
      return 7.5625 * t * t + 0.9375;
    }
    else {
      t -= 0.9545;
      return 7.5625 * t * t + 0.984375;
    }
  },
Animation.prototype.isComplete = function () {
  var life = this.elapsed;
  if (this.looped) {
    return this.iterations > 0 ? life / this.duration >= this.iterations : false;
  }
  return life >= this.duration;
Animation.prototype.update = function (elapsedMs) {
  this.elapsed += elapsedMs;

  if (!this.updateFunc) { return; }

  //determine what keyframes we're between
  var last;
  var t = this.elapsed;
    var easingFunction = this.easingFunction;
    t /= this.duration;
    if (this.looped) {
      t = clampingFunctions[this.clampFunction](t);
      if (this.isComplete()) {
        t = 1;
      }
    }
    else {
      t = Math.min(1, t);
    }
    t = this.easingFunctions[easingFunction](t)
    t *= this.duration;
  for (var i = this.keyframes.length - 1; i >= 0; i--) {
    var frame = this.keyframes[i];
    if (isNaN(frame.start)) { frame.start = 0; frame.end = 0; }
    if (t >= frame.start) {
      last = (i > 0 ? this.keyframes[i - 1] : frame);
      //normalize the time between frames
      var time;
      if (frame.end === frame.start) {
        time = 1;
      }
      else {
        time = t === 0 ? 0 : (t - frame.start) / (frame.end - frame.start);
      }
      this.updateFunc(this.id, last, frame, time);
      return;
    }
  }
}
Animation.prototype.halt = function () {
  var frame = this.keyframes[this.keyframes.length - 1];
  this.updateFunc && this.updateFunc(this.id, frame, frame, 1);
}

/************************************************************
 * Linear interpolation
 ************************************************************/
spnati_edit's avatar
spnati_edit committed
function lerp(a, b, t) {
  return (b - a) * t + a;
/************************************************************
 * Clamping functions for what to do with values that go outside [0:1] to put them back inside.
 ************************************************************/
var clampingFunctions = {
  "clamp": function (t) { return Math.max(0, Math.min(1, t)); },  //everything after 1 is clamped to 1
  "wrap": function (t) { return t % 1.0; },                       //passing 1 wraps back to 0 (ex. 1.1 => 0.1)
  "mirror": function (t) { t %= 2.0; return t > 1 ? 2 - t : t; }, //bouncing back and forth from 0->1->0 (ex. 1.1 => 0.9, 2.1 => 0.1)
};

/************************************************************
 * Interpolation functions for animation movement interpolation
 ************************************************************/
var interpolationModes = {
spnati_edit's avatar
spnati_edit committed
  "none": function noInterpolation(prop, start, end, t, frames, index) {
    return t >= 1 ? end : start;

  },
  "linear": function linear(prop, start, end, t, frames, index) {
    return lerp(start, end, t);
  },
  "spline": function catmullrom(prop, start, end, t, frames, index) {
    var p0 = index > 0 ? frames[index - 1][prop] : start;
    var p1 = start;
    var p2 = end;
spnati_edit's avatar
spnati_edit committed
    var p3 = index < frames.length - 1 ? frames[index + 1][prop] : end;
spnati_edit's avatar
spnati_edit committed

    if (typeof p0 === "undefined" || isNaN(p0)) {
      p0 = start;
    }
Loading
Loading full blame...