2019-02-11 17:04:23 +00:00
|
|
|
window._ = {};
|
|
|
|
window.Game = {};
|
|
|
|
|
|
|
|
Game.sections = {};
|
2019-02-12 19:59:45 +00:00
|
|
|
Game.queue = [];
|
|
|
|
|
2019-04-18 11:40:22 +00:00
|
|
|
Game.dom = $("#game_container");
|
|
|
|
Game.wordsDOM = $("#game_words");
|
|
|
|
Game.choicesDOM = $("#game_choices");
|
|
|
|
Game.canvas = $("#game_canvas");
|
2019-02-18 20:59:10 +00:00
|
|
|
|
2019-04-18 11:40:22 +00:00
|
|
|
window.SceneSetup = {}; // A big ol' singleton class that just makes it easy to create scenes.
|
2019-02-22 23:48:24 +00:00
|
|
|
|
2019-03-17 18:41:19 +00:00
|
|
|
// HELPER FUNCS
|
|
|
|
window.bb = function(){
|
|
|
|
publish("bb", arguments);
|
|
|
|
};
|
2019-04-18 11:40:22 +00:00
|
|
|
window.hong = function(){
|
|
|
|
publish("hong", arguments);
|
|
|
|
};
|
|
|
|
window.attack = function(damage, type){
|
|
|
|
publish("attack", ["hong", damage, type]);
|
2019-04-29 15:35:25 +00:00
|
|
|
_["attack_"+type]++; // HACK
|
2019-04-18 11:40:22 +00:00
|
|
|
};
|
|
|
|
window.attackBB = function(damage, type){
|
|
|
|
publish("attack", ["bb", damage, type]);
|
|
|
|
};
|
2019-03-17 18:41:19 +00:00
|
|
|
|
2019-02-18 20:59:10 +00:00
|
|
|
// Init
|
|
|
|
Game.init = function(){
|
|
|
|
|
2019-04-09 18:59:19 +00:00
|
|
|
// HP!
|
|
|
|
window.HP = new HitPoints();
|
|
|
|
|
2019-02-18 20:59:10 +00:00
|
|
|
// Animation!
|
2019-04-11 18:44:15 +00:00
|
|
|
console.log("init");
|
2019-02-18 20:59:10 +00:00
|
|
|
Game.wordsDOM.style.top = "80px";
|
|
|
|
var animloop = function(){
|
|
|
|
Game.update();
|
|
|
|
requestAnimationFrame(animloop);
|
|
|
|
};
|
|
|
|
requestAnimationFrame(animloop);
|
|
|
|
|
|
|
|
};
|
2019-02-11 17:04:23 +00:00
|
|
|
|
2019-02-18 20:59:10 +00:00
|
|
|
// Parse scene markdown!
|
|
|
|
Game.parseSceneMarkdown = function(md){
|
2019-02-11 17:04:23 +00:00
|
|
|
|
|
|
|
// Split into sections...
|
2019-02-18 20:59:10 +00:00
|
|
|
md = md.trim();
|
|
|
|
md = "\n" + md;
|
|
|
|
var sections = md.split(/\n\#\s*/);
|
2019-02-11 17:04:23 +00:00
|
|
|
sections.shift();
|
|
|
|
sections.forEach(function(section){
|
|
|
|
|
|
|
|
var split_index = section.indexOf("\n\n");
|
|
|
|
var id = section.slice(0, split_index).toLocaleLowerCase();
|
|
|
|
var text = section.slice(split_index+2);
|
|
|
|
|
|
|
|
// Split into lines
|
|
|
|
text = text.trim();
|
|
|
|
var lines = text.split("\n\n");
|
|
|
|
for(var i=0; i<lines.length; i++) lines[i]=lines[i].trim(); // trim it all!
|
|
|
|
|
|
|
|
// New section
|
|
|
|
Game.sections[id] = {
|
|
|
|
id: id,
|
|
|
|
lines: lines
|
|
|
|
};
|
|
|
|
|
|
|
|
});
|
|
|
|
|
2019-02-18 20:59:10 +00:00
|
|
|
};
|
2019-02-11 17:04:23 +00:00
|
|
|
|
2019-02-17 21:54:29 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// SCENE MANAGEMENT ////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
Game.start = function(){
|
|
|
|
window._ = {}; // global var, reset
|
|
|
|
};
|
|
|
|
|
2019-02-12 19:59:45 +00:00
|
|
|
Game.update = function(){
|
2019-02-20 18:45:23 +00:00
|
|
|
|
|
|
|
if(!Game.paused){
|
|
|
|
|
|
|
|
// Timeout callbacks...
|
2019-02-22 23:48:24 +00:00
|
|
|
for(var i=0; i<Game.timeoutCallbacks.length; i++){
|
2019-02-20 18:45:23 +00:00
|
|
|
var tc = Game.timeoutCallbacks[i];
|
|
|
|
tc.timeLeft -= 1000/60;
|
|
|
|
if(tc.timeLeft<=0){
|
|
|
|
tc.callback();
|
|
|
|
Game.timeoutCallbacks.splice(i,1); // delete that one
|
2019-02-22 23:48:24 +00:00
|
|
|
i -= 1; // set index back one
|
2019-02-20 18:45:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The interface
|
|
|
|
Game.updateText();
|
|
|
|
Game.updateCanvas();
|
|
|
|
|
|
|
|
// Ayyy
|
|
|
|
publish("update");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-04-28 16:02:55 +00:00
|
|
|
// Options update
|
|
|
|
Options.update();
|
|
|
|
|
2019-02-20 18:45:23 +00:00
|
|
|
};
|
|
|
|
|
2019-02-20 20:22:23 +00:00
|
|
|
// PAUSING THE GAME
|
2019-02-20 18:45:23 +00:00
|
|
|
Game.paused = false;
|
2019-04-18 11:40:22 +00:00
|
|
|
Game.pausedDOM = $("#paused");
|
2019-02-20 18:45:23 +00:00
|
|
|
Game.pause = function(){
|
2019-04-29 19:19:44 +00:00
|
|
|
|
2019-02-20 18:45:23 +00:00
|
|
|
Game.paused = true;
|
2019-02-20 20:22:23 +00:00
|
|
|
Game.pausedDOM.style.display = "block";
|
2019-04-23 19:12:41 +00:00
|
|
|
Howler.mute(true);
|
2019-04-29 19:19:44 +00:00
|
|
|
|
2019-04-30 15:20:45 +00:00
|
|
|
$("#paused").setAttribute("modal", (Options.showing||About.showing) ? "yes" : "no" );
|
2019-04-29 19:19:44 +00:00
|
|
|
|
2019-02-20 18:45:23 +00:00
|
|
|
};
|
|
|
|
window.addEventListener("blur", Game.pause);
|
|
|
|
Game.onUnpause = function(){
|
2019-04-30 15:20:45 +00:00
|
|
|
if(Game.paused && !(Options.showing||About.showing)){
|
2019-02-20 18:45:23 +00:00
|
|
|
Game.paused = false;
|
2019-02-20 20:22:23 +00:00
|
|
|
Game.pausedDOM.style.display = "none";
|
2019-04-23 19:12:41 +00:00
|
|
|
Howler.mute(false);
|
2019-02-20 18:45:23 +00:00
|
|
|
}
|
|
|
|
};
|
2019-04-30 15:20:45 +00:00
|
|
|
Game.pausedDOM.onclick = function(){
|
|
|
|
if(Options.showing){
|
|
|
|
publish("hide_options");
|
|
|
|
}
|
|
|
|
if(About.showing){
|
|
|
|
$("#close_about").onclick();
|
|
|
|
}
|
|
|
|
};
|
2019-02-20 18:45:23 +00:00
|
|
|
window.addEventListener("click", Game.onUnpause);
|
|
|
|
window.addEventListener("touchstart", Game.onUnpause);
|
|
|
|
|
2019-02-20 20:22:23 +00:00
|
|
|
// "SET TIMEOUT" for text and stuff
|
2019-02-20 18:45:23 +00:00
|
|
|
Game.timeoutCallbacks = [];
|
|
|
|
Game.setTimeout = function(callback, interval){
|
|
|
|
Game.timeoutCallbacks.push({
|
|
|
|
callback: callback,
|
|
|
|
timeLeft: interval
|
|
|
|
});
|
2019-02-12 19:59:45 +00:00
|
|
|
};
|
2019-05-03 16:13:22 +00:00
|
|
|
// SKIP TEXT WHEN CLICK ANYWHERE (but NOT capture in choice)
|
2019-02-20 20:22:23 +00:00
|
|
|
Game.clearAllTimeouts = function(){
|
2019-05-02 15:55:41 +00:00
|
|
|
|
|
|
|
// Is this DURING while someone is talking?
|
|
|
|
var isInterrupting = (Game.WHO_IS_SPEAKING!=null);
|
|
|
|
|
|
|
|
// If not, clear all
|
|
|
|
// Otherwise, clear all BUT last one... UNLESS there's only one left
|
|
|
|
if(Game.timeoutCallbacks.length==1) isInterrupting=false;
|
|
|
|
for(var i=0; i<Game.timeoutCallbacks.length; i++){
|
|
|
|
if(isInterrupting && i==Game.timeoutCallbacks.length-1) break;
|
|
|
|
Game.timeoutCallbacks[i].callback();
|
|
|
|
}
|
|
|
|
if(isInterrupting){
|
|
|
|
Game.timeoutCallbacks = [ Game.timeoutCallbacks[Game.timeoutCallbacks.length-1] ]; // last one
|
|
|
|
}else{
|
|
|
|
Game.timeoutCallbacks = [];
|
|
|
|
}
|
|
|
|
|
2019-02-20 20:22:23 +00:00
|
|
|
};
|
|
|
|
Game.canvas.addEventListener("click", Game.clearAllTimeouts);
|
|
|
|
Game.canvas.addEventListener("touchstart", Game.clearAllTimeouts);
|
2019-04-29 19:19:44 +00:00
|
|
|
Game.choicesDOM.addEventListener("click", Game.clearAllTimeouts);
|
|
|
|
Game.choicesDOM.addEventListener("touchstart", Game.clearAllTimeouts);
|
2019-02-12 19:59:45 +00:00
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
Game.goto = function(sectionID){
|
|
|
|
|
|
|
|
// Clear choices
|
|
|
|
Game.choicesDOM.innerHTML = "";
|
|
|
|
|
|
|
|
// Show each line...
|
|
|
|
var section = Game.sections[sectionID];
|
2019-02-12 19:59:45 +00:00
|
|
|
if(!section){
|
|
|
|
throw "NO SECTION NAMED "+sectionID;
|
|
|
|
}
|
2019-02-11 17:04:23 +00:00
|
|
|
var lines = section.lines;
|
2019-02-12 19:59:45 +00:00
|
|
|
Game.queue = Game.queue.concat(lines);
|
|
|
|
Game.executeNextLine();
|
2019-02-11 17:04:23 +00:00
|
|
|
|
2019-02-12 19:59:45 +00:00
|
|
|
};
|
|
|
|
|
2019-02-17 21:54:29 +00:00
|
|
|
Game.executeNextLine = function(){
|
2019-02-12 19:59:45 +00:00
|
|
|
|
|
|
|
// Parse handlebars
|
|
|
|
var originalLine = Game.queue.shift();
|
|
|
|
if(!originalLine) return; // END OF QUEUE.
|
|
|
|
line = Game.parseLine(originalLine);
|
|
|
|
|
|
|
|
// Execute line
|
|
|
|
var promiseNext;
|
2019-02-17 21:54:29 +00:00
|
|
|
if(line==""){
|
|
|
|
// If no line, get immediate promise...
|
2019-02-18 20:59:10 +00:00
|
|
|
promiseNext = Game.immediatePromise();
|
2019-02-17 21:54:29 +00:00
|
|
|
}else{
|
2019-02-12 19:59:45 +00:00
|
|
|
|
|
|
|
// Execute based on what type it is!
|
|
|
|
var lineType = Game.getLineType(line);
|
|
|
|
switch(lineType){
|
|
|
|
case "text":
|
|
|
|
promiseNext = Game.executeText(line);
|
2019-02-11 17:04:23 +00:00
|
|
|
break;
|
2019-02-12 19:59:45 +00:00
|
|
|
case "choice":
|
|
|
|
promiseNext = Game.executeChoice(line);
|
|
|
|
break;
|
|
|
|
case "code":
|
|
|
|
promiseNext = Game.executeCode(line);
|
|
|
|
break;
|
2019-02-18 17:24:52 +00:00
|
|
|
case "wait":
|
|
|
|
promiseNext = Game.executeWait(line);
|
|
|
|
break;
|
2019-02-12 19:59:45 +00:00
|
|
|
}
|
2019-02-11 17:04:23 +00:00
|
|
|
|
2019-02-12 19:59:45 +00:00
|
|
|
// If it's a goto, end THIS section immediately.
|
|
|
|
if(lineType=="goto"){
|
|
|
|
Game.clearQueue(); // CLEAR ALL ELSE IN QUEUE
|
|
|
|
Game.executeGoto(line);
|
|
|
|
return;
|
2019-02-11 17:04:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-02-12 19:59:45 +00:00
|
|
|
// Do next line?
|
|
|
|
if(Game.queue.length>0){
|
|
|
|
promiseNext.then(function(){
|
|
|
|
Game.executeNextLine();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
Game.clearQueue = function(){
|
|
|
|
Game.queue = [];
|
2019-02-11 17:04:23 +00:00
|
|
|
};
|
2019-02-12 19:59:45 +00:00
|
|
|
Game.addToQueue = function(line){
|
|
|
|
Game.queue.push(line);
|
|
|
|
}
|
2019-02-11 17:04:23 +00:00
|
|
|
|
2019-02-17 21:54:29 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// TEXT AND STUFF //////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2019-02-18 20:59:10 +00:00
|
|
|
// Immediate Promise
|
|
|
|
Game.immediatePromise = function(){
|
|
|
|
return new RSVP.Promise(function(resolve){
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2019-02-17 21:54:29 +00:00
|
|
|
// Move the text DOM to latest
|
2019-04-26 17:08:31 +00:00
|
|
|
Game.FORCE_TEXT_Y = -1;
|
2019-04-19 15:57:10 +00:00
|
|
|
Game.updateText = function(instant){
|
2019-04-26 17:08:31 +00:00
|
|
|
if(Game.FORCE_TEXT_Y<0){
|
|
|
|
var wordsHeight = 80 + Game.wordsDOM.getBoundingClientRect().height;
|
|
|
|
var currentY = parseFloat(Game.wordsDOM.style.top) || 80;
|
|
|
|
var gotoY = (wordsHeight<250) ? 0 : wordsHeight-250;
|
|
|
|
gotoY = 80 - gotoY;
|
|
|
|
var nextY = instant ? gotoY : currentY*0.9 + gotoY*0.1;
|
|
|
|
Game.wordsDOM.style.top = nextY+"px";
|
|
|
|
}else{
|
|
|
|
Game.wordsDOM.style.top = Game.FORCE_TEXT_Y+"px";
|
|
|
|
}
|
2019-02-17 21:54:29 +00:00
|
|
|
};
|
|
|
|
|
2019-02-22 23:48:24 +00:00
|
|
|
// CLEAR TEXT
|
|
|
|
Game.clearText = function(){
|
2019-04-19 15:57:10 +00:00
|
|
|
Game.wordsDOM.innerHTML = "";
|
|
|
|
Game.updateText(true);
|
2019-02-22 23:48:24 +00:00
|
|
|
};
|
2019-04-18 11:40:22 +00:00
|
|
|
window.clearText = Game.clearText;
|
2019-02-22 23:48:24 +00:00
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
// Execute text! Just add it to text DOM.
|
2019-05-02 15:55:41 +00:00
|
|
|
Game.TEXT_SPEED = 50;
|
|
|
|
Game.CLICK_TO_ADVANCE = true;
|
2019-02-18 20:59:10 +00:00
|
|
|
Game.OVERRIDE_TEXT_SPEED = 1;
|
2019-04-25 18:07:41 +00:00
|
|
|
Game.FORCE_TEXT_DURATION = -1;
|
2019-03-17 18:41:19 +00:00
|
|
|
Game.WHO_IS_SPEAKING = null; // "h", "b", "n" etc...
|
|
|
|
Game.CURRENT_SPEAKING_SPEED = 1;
|
2019-04-25 18:07:41 +00:00
|
|
|
Game.FORCE_NO_VOICE = false;
|
2019-02-11 17:04:23 +00:00
|
|
|
Game.executeText = function(line){
|
2019-02-12 19:59:45 +00:00
|
|
|
|
2019-02-18 20:59:10 +00:00
|
|
|
return new RSVP.Promise(function(resolve){
|
2019-02-12 19:59:45 +00:00
|
|
|
|
2019-02-20 18:45:23 +00:00
|
|
|
// Who's speaking?
|
2019-04-29 15:35:25 +00:00
|
|
|
// b: Beebee, h: Hong, n: Narrator, n2: Narrator 2, n3: Narrator 3
|
|
|
|
var regex = /^([^\:]+)\:(.*)/
|
2019-02-20 18:45:23 +00:00
|
|
|
var speaker = line.match(regex)[1].trim();
|
|
|
|
var dialogue = line.match(regex)[2].trim();
|
2019-02-18 20:59:10 +00:00
|
|
|
|
|
|
|
// Add the bubble, with animation
|
|
|
|
var div = document.createElement("div");
|
|
|
|
Game.wordsDOM.appendChild(div);
|
2019-03-17 18:41:19 +00:00
|
|
|
Game.WHO_IS_SPEAKING = speaker; // WHO'S SPEAKING?!
|
|
|
|
Game.CURRENT_SPEAKING_SPEED = Game.OVERRIDE_TEXT_SPEED;
|
2019-02-20 18:45:23 +00:00
|
|
|
switch(speaker){
|
|
|
|
case "b":
|
|
|
|
div.className = "beebee-bubble";
|
|
|
|
break;
|
|
|
|
case "h":
|
|
|
|
div.className = "hong-bubble";
|
|
|
|
break;
|
|
|
|
case "n":
|
|
|
|
div.className = "narrator-bubble";
|
|
|
|
break;
|
2019-04-29 15:35:25 +00:00
|
|
|
case "n2": // narrator 2
|
2019-04-24 19:42:13 +00:00
|
|
|
div.className = "narrator-bubble-2";
|
|
|
|
break;
|
2019-04-29 15:35:25 +00:00
|
|
|
case "n3": // narrator 3
|
|
|
|
div.className = "narrator-bubble-3";
|
|
|
|
break;
|
|
|
|
case "n4": // narrator 3
|
|
|
|
div.className = "narrator-bubble-4";
|
|
|
|
break;
|
2019-02-20 18:45:23 +00:00
|
|
|
}
|
2019-02-12 19:59:45 +00:00
|
|
|
requestAnimationFrame(function(){
|
2019-02-18 20:59:10 +00:00
|
|
|
requestAnimationFrame(function(){
|
|
|
|
div.style.opacity = 1;
|
|
|
|
div.style.left = 0;
|
|
|
|
});
|
2019-02-12 19:59:45 +00:00
|
|
|
});
|
|
|
|
|
2019-03-17 18:41:19 +00:00
|
|
|
// Clear both
|
|
|
|
var clearBoth = document.createElement("div");
|
|
|
|
clearBoth.className = "clear-both";
|
|
|
|
Game.wordsDOM.appendChild(clearBoth);
|
|
|
|
|
2019-02-20 18:45:23 +00:00
|
|
|
// Add the text
|
2019-02-18 20:59:10 +00:00
|
|
|
var interval = 0;
|
2019-02-20 20:22:23 +00:00
|
|
|
var SPEED = Math.round(Game.TEXT_SPEED / Game.OVERRIDE_TEXT_SPEED);
|
2019-04-25 18:07:41 +00:00
|
|
|
if(Game.FORCE_TEXT_DURATION>0){
|
|
|
|
SPEED = Math.round(Game.FORCE_TEXT_DURATION/dialogue.length);
|
|
|
|
}
|
2019-04-29 15:35:25 +00:00
|
|
|
|
|
|
|
// IF IT'S BEEBEE, HONG, or NARRATOR 3
|
|
|
|
if(speaker=="b" || speaker=="h" || speaker=="n3"){
|
2019-02-20 18:45:23 +00:00
|
|
|
|
2019-03-17 18:41:19 +00:00
|
|
|
// Put in the text, each character a DIFFERENT SPAN...
|
|
|
|
var span, chr;
|
|
|
|
var isItalicized = false;
|
|
|
|
for(var i=0; i<dialogue.length; i++){
|
|
|
|
|
|
|
|
// Is it italicized?
|
|
|
|
chr = dialogue[i];
|
|
|
|
if(chr=="*") isItalicized = !isItalicized; // toggle!
|
|
|
|
|
|
|
|
// Add letter span
|
|
|
|
span = document.createElement("span");
|
|
|
|
if(chr=="*"){
|
|
|
|
// else, empty. can't NOT add span, coz screws up indexing.
|
|
|
|
}else{
|
|
|
|
span.innerHTML = isItalicized ? "<i>"+chr+"</i>" : chr;
|
|
|
|
}
|
|
|
|
span.style.opacity = 0;
|
|
|
|
div.appendChild(span);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Then REVEAL letters one-by-one
|
2019-02-20 18:45:23 +00:00
|
|
|
for(var i=0; i<dialogue.length; i++){
|
|
|
|
|
|
|
|
var chr = dialogue[i];
|
|
|
|
|
|
|
|
// If it's the last char & it's "-", skip
|
|
|
|
if(i==dialogue.length-1 && chr=="-") break;
|
|
|
|
|
|
|
|
// for scopin'
|
2019-04-25 18:07:41 +00:00
|
|
|
(function(index, interval, speaker, forceNoSound){
|
2019-02-20 18:45:23 +00:00
|
|
|
Game.setTimeout(function(){
|
2019-04-23 19:12:41 +00:00
|
|
|
|
|
|
|
// Show it
|
2019-03-17 18:41:19 +00:00
|
|
|
div.children[index].style.opacity = 1;
|
2019-04-23 19:12:41 +00:00
|
|
|
|
|
|
|
// And SOUND?
|
2019-04-25 18:07:41 +00:00
|
|
|
if(!forceNoSound){
|
|
|
|
var chr = div.children[index].innerHTML;
|
|
|
|
if(chr!=" "){
|
|
|
|
if(speaker=="h"){
|
|
|
|
voice("hong", {volume:0.3});
|
|
|
|
}
|
|
|
|
if(speaker=="b"){
|
|
|
|
voice("beebee", {volume:0.5});
|
|
|
|
}
|
2019-05-03 16:13:22 +00:00
|
|
|
if(speaker=="n3"){
|
|
|
|
voice("typewriter", {volume:0.5});
|
|
|
|
}
|
2019-04-23 19:12:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-20 18:45:23 +00:00
|
|
|
}, interval);
|
2019-04-25 18:07:41 +00:00
|
|
|
})(i, interval, speaker, Game.FORCE_NO_VOICE);
|
2019-02-20 18:45:23 +00:00
|
|
|
|
|
|
|
// Bigger interval
|
|
|
|
if(i!=dialogue.length-1){ // NOT last
|
2019-04-19 15:57:10 +00:00
|
|
|
if(chr=="."){
|
|
|
|
if(dialogue[i+1]=="\""){ // UNLESS next one's a punctuation!
|
|
|
|
interval += 0;
|
|
|
|
}else{
|
|
|
|
interval += SPEED*10;
|
|
|
|
}
|
|
|
|
}else if(chr=="?" || chr=="!"){ // gap unless next one's ALSO punctuation.
|
|
|
|
if(dialogue[i+1]==" "){ // next one's a space? gap!
|
|
|
|
interval += SPEED*10;
|
|
|
|
}else{ // if not, no!
|
|
|
|
interval += SPEED;
|
|
|
|
}
|
2019-04-29 15:35:25 +00:00
|
|
|
}else if(chr=="," || chr==":"){
|
2019-02-20 18:45:23 +00:00
|
|
|
interval += SPEED*5;
|
|
|
|
}else{
|
|
|
|
interval += SPEED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
2019-04-29 15:35:25 +00:00
|
|
|
// IF NARRATOR 1 or 2 or 4
|
2019-02-20 18:45:23 +00:00
|
|
|
|
|
|
|
// *Emphasize multiple words* => *Emphasize* *multiple* *words*
|
|
|
|
var regex = /\*([^\*]*)\*/g;
|
|
|
|
var emphasized = dialogue.match(regex) || [];
|
|
|
|
for(var i=emphasized.length-1; i>=0; i--){ // backwards coz replacing
|
|
|
|
|
|
|
|
// Convert
|
|
|
|
var originalEm = emphasized[i]
|
|
|
|
var em = originalEm;
|
|
|
|
em = em.substr(1,em.length-2); // remove *
|
|
|
|
var ems = em.split(" ");
|
|
|
|
ems = ems.map(function(word){
|
|
|
|
return "*"+word+"*";
|
|
|
|
});
|
|
|
|
em = ems.join(" ");
|
|
|
|
|
|
|
|
// Replace in main string
|
|
|
|
var startIndex = dialogue.indexOf(originalEm);
|
|
|
|
dialogue = dialogue.slice(0, startIndex) + em + dialogue.slice(startIndex+originalEm.length);
|
|
|
|
|
2019-02-18 20:59:10 +00:00
|
|
|
}
|
|
|
|
|
2019-03-17 18:41:19 +00:00
|
|
|
// Put in the text, each word a DIFFERENT SPAN
|
|
|
|
var span;
|
2019-02-20 18:45:23 +00:00
|
|
|
var dialogueWords = dialogue.split(" ");
|
|
|
|
for(var i=0; i<dialogueWords.length; i++){
|
|
|
|
|
2019-03-17 18:41:19 +00:00
|
|
|
// Is it an emphasized word?
|
2019-04-29 15:35:25 +00:00
|
|
|
var reggie = /\*(.*)\*/;
|
2019-02-20 18:45:23 +00:00
|
|
|
var word = dialogueWords[i];
|
2019-04-29 15:35:25 +00:00
|
|
|
if(reggie.test(word)){
|
|
|
|
word = "<i>" + word.match(reggie)[1].trim() + "</i>";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Actual emphasis
|
|
|
|
reggie = /\_(.*)\_/;
|
|
|
|
if(reggie.test(word)){
|
|
|
|
word = "<i class='italics'>" + word.match(reggie)[1].trim() + "</i>";
|
2019-02-20 18:45:23 +00:00
|
|
|
}
|
|
|
|
|
2019-03-17 18:41:19 +00:00
|
|
|
// Add the span
|
|
|
|
span = document.createElement("span");
|
|
|
|
span.innerHTML = word+" ";
|
|
|
|
span.style.opacity = 0;
|
|
|
|
div.appendChild(span);
|
2019-02-20 18:45:23 +00:00
|
|
|
|
2019-03-17 18:41:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Then REVEAL words one-by-one
|
|
|
|
for(var i=0; i<dialogueWords.length; i++){
|
2019-02-20 18:45:23 +00:00
|
|
|
|
2019-03-17 18:41:19 +00:00
|
|
|
var word = dialogueWords[i];
|
|
|
|
|
|
|
|
// for scopin'
|
2019-04-23 19:12:41 +00:00
|
|
|
(function(index, interval, word){
|
2019-03-17 18:41:19 +00:00
|
|
|
Game.setTimeout(function(){
|
2019-04-23 19:12:41 +00:00
|
|
|
|
|
|
|
// Show
|
2019-03-17 18:41:19 +00:00
|
|
|
div.children[index].style.opacity = 1;
|
2019-04-23 19:12:41 +00:00
|
|
|
|
|
|
|
// SOUND
|
|
|
|
var chr = word.slice(-1);
|
|
|
|
var isEmphasis = (chr=="*");
|
|
|
|
voice(isEmphasis ? "narrator_emphasis" : "narrator");
|
|
|
|
|
2019-02-20 18:45:23 +00:00
|
|
|
}, interval);
|
2019-04-23 19:12:41 +00:00
|
|
|
})(i, interval, word);
|
2019-02-20 18:45:23 +00:00
|
|
|
|
|
|
|
// Interval
|
2019-02-22 23:48:24 +00:00
|
|
|
interval += SPEED*6;
|
2019-02-20 18:45:23 +00:00
|
|
|
|
|
|
|
// Larger interval if punctuation...
|
2019-03-17 18:41:19 +00:00
|
|
|
var chr = word.slice(-1);
|
2019-04-19 17:44:45 +00:00
|
|
|
var isIcon = (word[0]=="#" && chr=="#");
|
2019-03-17 18:41:19 +00:00
|
|
|
if(chr=="*") chr = word[word.length-2]; // coz emphasis
|
2019-02-22 23:48:24 +00:00
|
|
|
if(chr=="," || chr==":") interval += SPEED*5;
|
|
|
|
if(chr=="." || chr=="?" || chr=="!") interval += SPEED*10;
|
2019-03-17 18:41:19 +00:00
|
|
|
if(word.slice(-3)=="...") interval += SPEED*15;
|
2019-02-20 18:45:23 +00:00
|
|
|
|
2019-04-19 17:44:45 +00:00
|
|
|
// Oh, was it an ICON?
|
|
|
|
if(word[0]=="#" && chr=="#"){
|
|
|
|
interval += SPEED*10;
|
|
|
|
|
|
|
|
var span = div.children[i];
|
|
|
|
span.innerHTML = "";
|
|
|
|
span.style.display = "block";
|
|
|
|
var iconName = word.slice(1,-1)
|
|
|
|
var icon = Library.images["fear_"+iconName];
|
|
|
|
div.children[i].appendChild(icon);
|
|
|
|
icon.style.display = "block";
|
|
|
|
icon.style.margin = "0 auto";
|
|
|
|
icon.style.width = "80px";
|
|
|
|
icon.style.height = "80px";
|
|
|
|
|
|
|
|
}
|
2019-02-20 18:45:23 +00:00
|
|
|
|
2019-04-19 17:44:45 +00:00
|
|
|
}
|
2019-02-20 18:45:23 +00:00
|
|
|
|
2019-02-12 19:59:45 +00:00
|
|
|
}
|
|
|
|
|
2019-02-20 20:22:23 +00:00
|
|
|
// Return overrides to default
|
|
|
|
Game.OVERRIDE_TEXT_SPEED = 1;
|
2019-04-25 18:07:41 +00:00
|
|
|
Game.FORCE_TEXT_DURATION = -1;
|
|
|
|
Game.FORCE_NO_VOICE = false;
|
2019-02-20 20:22:23 +00:00
|
|
|
|
2019-02-18 20:59:10 +00:00
|
|
|
// Return promise
|
2019-04-19 15:57:10 +00:00
|
|
|
var nextLineDelay = Game.TEXT_SPEED*7; // don't override this
|
2019-02-18 20:59:10 +00:00
|
|
|
if(dialogue.slice(-1)=="-") nextLineDelay=0; // sudden interrupt!
|
2019-05-02 15:55:41 +00:00
|
|
|
if(Game.CLICK_TO_ADVANCE){ // IF IT'S CLICK-TO-ADVANCE, "INFINITE" TIMEOUT.
|
2019-04-29 19:19:44 +00:00
|
|
|
nextLineDelay = 1000*10000; // ten thousand seconds
|
2019-04-28 16:02:55 +00:00
|
|
|
}
|
2019-05-02 15:55:41 +00:00
|
|
|
|
|
|
|
// No one's speaking anymore.
|
|
|
|
Game.setTimeout(function(){
|
|
|
|
Game.WHO_IS_SPEAKING = null;
|
|
|
|
}, interval);
|
|
|
|
|
|
|
|
// Show the clicky UI
|
|
|
|
if(Game.CLICK_TO_ADVANCE){
|
|
|
|
Game.setTimeout(function(){
|
|
|
|
publish("show_click_to_advance");
|
|
|
|
}, interval+Game.TEXT_SPEED*2);
|
|
|
|
}
|
|
|
|
|
|
|
|
// DONE WITH IT
|
2019-03-17 18:41:19 +00:00
|
|
|
Game.setTimeout(function(){
|
2019-05-02 15:55:41 +00:00
|
|
|
publish("hide_click_to_advance");
|
|
|
|
resolve(); // DONE WITH IT.
|
2019-03-17 18:41:19 +00:00
|
|
|
}, interval+nextLineDelay);
|
2019-02-12 19:59:45 +00:00
|
|
|
|
2019-02-18 20:59:10 +00:00
|
|
|
});
|
2019-02-12 19:59:45 +00:00
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
}
|
|
|
|
|
2019-04-25 18:07:41 +00:00
|
|
|
// CHOICE UI SOUNDS
|
|
|
|
Loader.addSounds([
|
|
|
|
{ id:"ui_show_choice", src:"sounds/ui/show_choice.mp3" },
|
|
|
|
{ id:"ui_click", src:"sounds/ui/click.mp3" },
|
|
|
|
{ id:"ui_hover", src:"sounds/ui/hover.mp3" }
|
|
|
|
]);
|
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
// Execute choice! Add it to choice DOM.
|
2019-02-18 20:59:10 +00:00
|
|
|
Game.OVERRIDE_CHOICE_LINE = false;
|
2019-02-11 17:04:23 +00:00
|
|
|
Game.executeChoice = function(line){
|
|
|
|
|
2019-02-18 20:59:10 +00:00
|
|
|
var choiceText = line.match(/\[([^\]]*)\]/)[1].trim();
|
|
|
|
var choiceID = line.match(/\(\#([^\)]*)\)/)[1].trim().toLocaleLowerCase();
|
|
|
|
|
|
|
|
var preChoiceCodeIfAny = null;
|
|
|
|
if(/\`(.*)\`/.test(line)){
|
|
|
|
preChoiceCodeIfAny = line.match(/\`(.*)\`/)[0]; // 0, with backticks
|
|
|
|
}
|
2019-02-11 17:04:23 +00:00
|
|
|
|
2019-04-19 15:57:10 +00:00
|
|
|
// Choice text, add italics where *word word words*
|
|
|
|
var originalChoiceText = choiceText;
|
|
|
|
var italicsRegex = /\*([^\*]*)\*/g;
|
|
|
|
var results;
|
|
|
|
while(results=italicsRegex.exec(choiceText)){
|
|
|
|
// Modify choiceText in place, it's fine.
|
|
|
|
var startOfMatch = results.index;
|
|
|
|
var endOfMatch = results.index + results[0].length;
|
|
|
|
choiceText = choiceText.slice(0,startOfMatch) + "<i>" + results[1] + "</i>" + choiceText.slice(endOfMatch);
|
|
|
|
}
|
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
var div = document.createElement("div");
|
|
|
|
div.innerHTML = choiceText;
|
2019-04-29 19:19:44 +00:00
|
|
|
div.onclick = function(event){
|
2019-02-18 20:59:10 +00:00
|
|
|
|
|
|
|
// Any pre-choice code?
|
|
|
|
if(preChoiceCodeIfAny) Game.executeCode(preChoiceCodeIfAny);
|
|
|
|
|
|
|
|
// Override line... ONCE
|
|
|
|
if(!Game.OVERRIDE_CHOICE_LINE){
|
2019-04-19 15:57:10 +00:00
|
|
|
Game.addToQueue("b: "+originalChoiceText);
|
2019-02-18 20:59:10 +00:00
|
|
|
}
|
2019-02-22 23:48:24 +00:00
|
|
|
Game.OVERRIDE_CHOICE_LINE = false;
|
2019-02-18 20:59:10 +00:00
|
|
|
|
2019-04-25 18:07:41 +00:00
|
|
|
// Play sound
|
|
|
|
sfx("ui_click");
|
|
|
|
|
2019-02-18 20:59:10 +00:00
|
|
|
// Goto that choice, now!
|
2019-02-11 17:04:23 +00:00
|
|
|
Game.goto(choiceID);
|
2019-02-18 20:59:10 +00:00
|
|
|
|
2019-04-29 19:19:44 +00:00
|
|
|
// STOP THE PROP
|
|
|
|
event.stopPropagation();
|
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
};
|
2019-04-25 18:07:41 +00:00
|
|
|
div.onmouseover = function(){
|
|
|
|
sfx("ui_hover");
|
|
|
|
};
|
2019-02-11 17:04:23 +00:00
|
|
|
|
2019-04-18 11:40:22 +00:00
|
|
|
// Add choice, animated!
|
|
|
|
div.style.top = "150px";
|
2019-02-11 17:04:23 +00:00
|
|
|
Game.choicesDOM.appendChild(div);
|
2019-04-18 11:40:22 +00:00
|
|
|
setTimeout(function(){
|
|
|
|
div.style.top = "0px";
|
2019-04-25 18:07:41 +00:00
|
|
|
sfx("ui_show_choice", {volume:0.4});
|
2019-04-18 11:40:22 +00:00
|
|
|
},0);
|
2019-02-11 17:04:23 +00:00
|
|
|
|
2019-04-19 15:57:10 +00:00
|
|
|
// If it's too big, shrink font size
|
|
|
|
setTimeout(function(){
|
|
|
|
var choiceHeight = div.getBoundingClientRect().height;
|
|
|
|
if(choiceHeight>40) div.style.fontSize = "18px";
|
|
|
|
// And if still too much???
|
|
|
|
setTimeout(function(){
|
|
|
|
var choiceHeight = div.getBoundingClientRect().height;
|
|
|
|
if(choiceHeight>40) div.style.fontSize = "16px";
|
|
|
|
// And if still too much???
|
|
|
|
setTimeout(function(){
|
|
|
|
var choiceHeight = div.getBoundingClientRect().height;
|
|
|
|
if(choiceHeight>40) div.style.fontSize = "14px";
|
|
|
|
},0);
|
|
|
|
},0);
|
|
|
|
},0);
|
|
|
|
|
2019-04-18 11:40:22 +00:00
|
|
|
// Wait a bit before adding new line
|
|
|
|
return new RSVP.Promise(function(resolve){
|
|
|
|
Game.setTimeout(resolve, 100);
|
|
|
|
});
|
2019-02-12 19:59:45 +00:00
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Execute code!
|
|
|
|
Game.executeCode = function(line){
|
2019-02-12 19:59:45 +00:00
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
var code = line.match(/\`+([^\`]*)\`+/)[1].trim();
|
|
|
|
try{
|
|
|
|
eval(code);
|
|
|
|
}catch(e){
|
|
|
|
console.log(e);
|
|
|
|
}
|
2019-02-12 19:59:45 +00:00
|
|
|
|
2019-02-18 20:59:10 +00:00
|
|
|
// Return immediate promise
|
|
|
|
return Game.immediatePromise();
|
2019-02-12 19:59:45 +00:00
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
}
|
|
|
|
|
2019-02-18 17:24:52 +00:00
|
|
|
// Execute wait! Just wait.
|
|
|
|
Game.executeWait = function(line){
|
|
|
|
|
|
|
|
// Get integer from (...NN)
|
|
|
|
var waitTime = parseInt(line.match(/^\(\.\.\.(\d+)\)/)[1].trim());
|
2019-04-28 16:02:55 +00:00
|
|
|
|
|
|
|
// Unless it's click to advance, then IGNORE ALL WAITS
|
2019-05-02 15:55:41 +00:00
|
|
|
if(Game.CLICK_TO_ADVANCE && waitTime<=1000){ // hack: unless the wait is long.
|
2019-04-28 16:02:55 +00:00
|
|
|
waitTime = 0; // TODO: Tag anim-waits, do not ignore.
|
|
|
|
}
|
2019-02-18 17:24:52 +00:00
|
|
|
|
|
|
|
// Delayed promise
|
2019-02-22 23:48:24 +00:00
|
|
|
return new RSVP.Promise(function(resolve){
|
2019-02-20 18:45:23 +00:00
|
|
|
Game.setTimeout(resolve, waitTime);
|
2019-02-18 20:59:10 +00:00
|
|
|
});
|
2019-02-18 17:24:52 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
// Execute goto! Just goto.
|
|
|
|
Game.executeGoto = function(line){
|
|
|
|
var gotoID = line.match(/^\(\#(.*)\)/)[1].trim().toLocaleLowerCase();
|
|
|
|
Game.goto(gotoID);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine line type... text, choice, or code?
|
|
|
|
Game.getLineType = function(line){
|
|
|
|
|
|
|
|
// Is it a choice?
|
|
|
|
var isChoice = /\[.*\]\(\#.*\)/.test(line);
|
|
|
|
if(isChoice) return "choice";
|
|
|
|
|
|
|
|
// Is it a goto?
|
|
|
|
var isGoto = /^\(\#(.*)\)/.test(line);
|
|
|
|
if(isGoto) return "goto";
|
|
|
|
|
|
|
|
// Is it code?
|
|
|
|
var isCode = /^\`/.test(line);
|
|
|
|
if(isCode) return "code";
|
|
|
|
|
2019-02-18 17:24:52 +00:00
|
|
|
// Is it a wait?
|
|
|
|
var isWait = /^\(\.\.\.\d+\)/.test(line);
|
|
|
|
if(isWait) return "wait";
|
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
// Otherwise, it's text.
|
|
|
|
return "text";
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
// Parse all the handlebars...
|
|
|
|
Game.parseLine = function(line){
|
|
|
|
|
2019-02-22 23:48:24 +00:00
|
|
|
// Get rid of newlines
|
|
|
|
line = line.replace(/\n/gi,"");
|
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
// Get the IFs, if any
|
|
|
|
var lookForIfs = true;
|
|
|
|
while(lookForIfs){
|
|
|
|
|
|
|
|
lookForIfs = false;
|
|
|
|
|
|
|
|
// Look for an IF!
|
2019-04-29 19:19:44 +00:00
|
|
|
var regex = /\{\{if[^\/]*\/if\}\}/ig; // the reason it's inside here is to reset .exec
|
2019-02-11 17:04:23 +00:00
|
|
|
var regexResult = regex.exec(line);
|
|
|
|
if(regexResult){
|
|
|
|
|
|
|
|
// The result...
|
|
|
|
var fullConditional = regexResult[0];
|
|
|
|
var startsAtIndex = regexResult.index;
|
|
|
|
var endsAtIndex = startsAtIndex + fullConditional.length;
|
|
|
|
|
|
|
|
// Extract the condition
|
|
|
|
var condition = fullConditional.match(/\{\{if\s+([^\{\}]*)\}\}/)[1];
|
|
|
|
|
|
|
|
// Extract the inside text
|
|
|
|
var insideText = fullConditional.match(/\}\}([^\{\}]*)\{\{/)[1].trim();
|
|
|
|
|
|
|
|
// Eval condition!
|
|
|
|
var conditionIsTrue = false;
|
|
|
|
try{
|
|
|
|
conditionIsTrue = eval(condition);
|
|
|
|
}catch(e){
|
|
|
|
console.log(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Edit the line
|
|
|
|
var insert = conditionIsTrue ? insideText : "";
|
|
|
|
line = line.slice(0,startsAtIndex) + insert + line.slice(endsAtIndex);
|
|
|
|
|
|
|
|
// Keep searching...
|
|
|
|
lookForIfs = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-04-28 16:02:55 +00:00
|
|
|
// Evaluate {{expressions}}, if any
|
|
|
|
var lookForExpressions = true;
|
|
|
|
while(lookForExpressions){
|
|
|
|
|
|
|
|
lookForExpressions = false;
|
|
|
|
|
|
|
|
// Look for an IF!
|
2019-04-29 19:19:44 +00:00
|
|
|
var regex = /\{\{[^\}]*\}\}/ig; // the reason it's inside here is to reset .exec
|
2019-04-28 16:02:55 +00:00
|
|
|
var regexResult = regex.exec(line);
|
|
|
|
if(regexResult){
|
|
|
|
|
|
|
|
// The result...
|
|
|
|
var fullExpression = regexResult[0];
|
|
|
|
var startsAtIndex = regexResult.index;
|
|
|
|
var endsAtIndex = startsAtIndex + fullExpression.length;
|
|
|
|
|
|
|
|
// Extract the expression
|
|
|
|
var expression = fullExpression.match(/\{\{([^\}]*)\}\}/)[1];
|
|
|
|
|
|
|
|
// Eval condition!
|
|
|
|
var evaluated = "";
|
|
|
|
try{
|
|
|
|
evaluated = eval(expression);
|
|
|
|
}catch(e){
|
|
|
|
console.log(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Edit the line
|
|
|
|
line = line.slice(0,startsAtIndex) + evaluated + line.slice(endsAtIndex);
|
|
|
|
|
|
|
|
// Keep searching...
|
|
|
|
lookForExpressions = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-02-11 17:04:23 +00:00
|
|
|
// Return line!
|
|
|
|
return line;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2019-02-17 21:54:29 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// WHERE STUFF WILL BE DRAWN ///////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
2019-02-12 19:59:45 +00:00
|
|
|
|
|
|
|
Game.canvas.width = 360 * 2;
|
|
|
|
Game.canvas.height = 450 * 2;
|
|
|
|
Game.canvas.style.width = Game.canvas.width/2 + "px";
|
|
|
|
Game.canvas.style.height = Game.canvas.height/2 + "px";
|
2019-02-17 21:54:29 +00:00
|
|
|
Game.context = Game.canvas.getContext("2d");
|
|
|
|
|
|
|
|
// A blank scene
|
2019-04-18 11:40:22 +00:00
|
|
|
Game.scene = null;
|
2019-02-17 21:54:29 +00:00
|
|
|
Game.resetScene = function(){
|
2019-04-18 11:40:22 +00:00
|
|
|
|
|
|
|
// Kill all of previous scene
|
|
|
|
if(Game.scene){
|
|
|
|
Game.scene.children.forEach(function(child){
|
|
|
|
if(child.kill) child.kill();
|
|
|
|
});
|
|
|
|
if(Game.scene.kill) Game.scene.kill();
|
|
|
|
}
|
|
|
|
|
|
|
|
// New scene!
|
2019-02-17 21:54:29 +00:00
|
|
|
Game.scene = {};
|
|
|
|
Game.scene.children = [];
|
2019-04-18 11:40:22 +00:00
|
|
|
|
2019-02-17 21:54:29 +00:00
|
|
|
};
|
|
|
|
Game.resetScene();
|
|
|
|
|
|
|
|
// Update & draw all the kids!
|
|
|
|
Game.updateCanvas = function(){
|
|
|
|
|
|
|
|
// For retina
|
|
|
|
var ctx = Game.context;
|
|
|
|
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
|
|
|
|
ctx.save();
|
|
|
|
ctx.scale(2,2);
|
|
|
|
|
|
|
|
// Update/Draw all kids
|
|
|
|
Game.scene.children.forEach(function(child){
|
|
|
|
child.draw(ctx);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Restore
|
|
|
|
ctx.restore();
|
|
|
|
|
|
|
|
// Draw HP
|
2019-04-11 18:44:15 +00:00
|
|
|
HP.draw();
|
2019-02-17 21:54:29 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2019-02-12 19:59:45 +00:00
|
|
|
|
|
|
|
|