From c8ee042ef796e03b8743b000d8e8f95c676c121f Mon Sep 17 00:00:00 2001 From: spaciecat <5057054+spaciecat@users.noreply.github.com> Date: Thu, 12 Sep 2019 13:34:40 +1000 Subject: [PATCH 01/11] remove carriage teturns from script when parsing markdown newlines on windows are weird... it wouldnt even let me start the game unless i did this --- scripts/game/Game.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/game/Game.js b/scripts/game/Game.js index 2fb5029..74a7fa1 100644 --- a/scripts/game/Game.js +++ b/scripts/game/Game.js @@ -47,7 +47,7 @@ Game.init = function(){ Game.parseSceneMarkdown = function(md){ // Split into sections... - md = md.trim(); + md = md.trim().replace(/\r/g, ""); md = "\n" + md; var sections = md.split(/\n\#\s*/); sections.shift(); From bed2b0b22f7c8072b5c451d0a6d787173ff81aa3 Mon Sep 17 00:00:00 2001 From: spaciecat <5057054+spaciecat@users.noreply.github.com> Date: Thu, 12 Sep 2019 14:39:45 +1000 Subject: [PATCH 02/11] remove all save/restore pairs! --- scripts/act2/Act2_BG.js | 4 ++-- scripts/act3/Act3_BG.js | 4 ++-- scripts/act4/Act4_BG.js | 4 ++-- scripts/game/Character.js | 8 ++++++-- scripts/game/Game.js | 5 ++--- scripts/game/HP.js | 10 ++++++---- scripts/game/Sprite.js | 8 +++++--- scripts/intermission/Intermission_BG.js | 2 -- 8 files changed, 25 insertions(+), 20 deletions(-) diff --git a/scripts/act2/Act2_BG.js b/scripts/act2/Act2_BG.js index c66ef68..b45a431 100644 --- a/scripts/act2/Act2_BG.js +++ b/scripts/act2/Act2_BG.js @@ -318,7 +318,7 @@ function BG_Party(){ self.draw = function(ctx, delta){ - ctx.save(); + var oldAlpha = ctx.globalAlpha; for(var i=0; i Date: Thu, 12 Sep 2019 14:55:54 +1000 Subject: [PATCH 03/11] markup and styling updates removed dynamic viewport meta tag based scaling, it caused issues where a mobile browser's header wasnt able to be hidden removed #topleft and #bottomright (corner text) elements because they aren't being used anywhere for anything and made mobile scaling weird modified the css the new grid standards to vertically and horizontally center the game in a larger window, css can do that now and we dont need weird position absolute and `margin: auto` hacks! --- index.html | 9 +++---- styles/game.css | 68 ++++++++++--------------------------------------- 2 files changed, 17 insertions(+), 60 deletions(-) diff --git a/index.html b/index.html index fecdad4..c6bf657 100644 --- a/index.html +++ b/index.html @@ -29,9 +29,10 @@ + - + @@ -206,10 +207,6 @@ - - -
-
diff --git a/styles/game.css b/styles/game.css index 6e8d661..b4abe53 100644 --- a/styles/game.css +++ b/styles/game.css @@ -1,9 +1,16 @@ -html,body{ - width: 100%; - height: 100%; - overflow: hidden; +* { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } -body{ + +body { + width: 100%; + height: 100vh; + display: grid; + place-items: center; + overflow: hidden; margin:0; background: #111; } @@ -14,19 +21,9 @@ MAIN GAME ******************************************************************************************************/ -div{ /*, #game_words, #game_choices, #paused, #options, #loading, #gear, #about, #click_to_advance{*/ - -webkit-user-select: none; /* Safari 3.1+ */ - -moz-user-select: none; /* Firefox 2+ */ - -ms-user-select: none; /* IE 10+ */ - user-select: none; /* Standard syntax */ -} - #game_container{ - - position: absolute; - top:0; left:0; bottom:0; right:0; - margin: auto; - + position: relative; + display: inline-block; width: 360px; height: 600px; background: #000; @@ -1046,40 +1043,3 @@ canvas{ left:0; transition: top 0.5s ease-in-out; } - -/****************************************************************************************************** - -CORNER TEXT - -******************************************************************************************************/ - -#topleft, #bottomright{ - width: 200px; - color: #555; - font-family: Helvetica, Arial, sans-serif; - font-weight: 500; - font-size: 14px; - line-height: 1.3em; - position: absolute; -} -#topleft a, #bottomright a{ - color: #666; -} -#topleft a:hover, #bottomright a:hover{ - color: #888; -} -#topleft{ - top:10px; - left:10px; - text-align: left; -} -#bottomright{ - bottom:10px; - right:10px; - text-align: right; -} -@media screen and (max-width: 800px) { - #topleft, #bottomright { - display: none; - } -} \ No newline at end of file From c56eea3b4974287b3adf72bf744a4f4784c0d6b6 Mon Sep 17 00:00:00 2001 From: spaciecat <5057054+spaciecat@users.noreply.github.com> Date: Thu, 12 Sep 2019 15:58:12 +1000 Subject: [PATCH 04/11] dialogue animation + debugger refactored all the dialogue text animations to use css animation and transforms rather than frame by frame positioning this causes some issues and the code isnt the cleanest, but its already feels smoother so thats a good start! using the devtools for debugging was getting annoying so I added a `Game.debug()` method that toggles a custom debugger that includes a drawer containing links to all points in the script --- index.html | 6 +++- scripts/game/Game.js | 76 +++++++++++++++++++++++++++++++++++--------- styles/game.css | 51 +++++++++++++++++++++++------ 3 files changed, 108 insertions(+), 25 deletions(-) diff --git a/index.html b/index.html index c6bf657..e41af11 100644 --- a/index.html +++ b/index.html @@ -206,8 +206,12 @@ + +
+
+ - +
diff --git a/scripts/game/Game.js b/scripts/game/Game.js index 62c0b4f..3b3c522 100644 --- a/scripts/game/Game.js +++ b/scripts/game/Game.js @@ -29,12 +29,22 @@ window.attackBB = function(damage, type){ // Init Game.init = function(){ + // Create the section debug menu + Object.keys(Game.sections).forEach(function(key){ + const link = document.createElement('div'); + link.className = "section_link"; + link.innerText = key; + link.addEventListener('click', function() { + Game.goto(key); + }); + document.getElementById("section_debug_list").appendChild(link); + }) + // HP! window.HP = new HitPoints(); // Animation! console.log("init"); - Game.wordsDOM.style.top = "80px"; var animloop = function(){ Game.update(); requestAnimationFrame(animloop); @@ -43,6 +53,11 @@ Game.init = function(){ }; +// Call to toggle debug rendering +Game.debug = function(){ + document.body.classList.toggle('show_debug'); +} + // Parse scene markdown! Game.parseSceneMarkdown = function(md){ @@ -293,20 +308,51 @@ Game.immediatePromise = function(){ // Move the text DOM to latest Game.FORCE_TEXT_Y = -1; -Game.WORDS_HEIGHT_BOTTOM = 250; -Game.updateText = function(instant){ - if(Game.WORDS_HEIGHT_BOTTOM<0) Game.WORDS_HEIGHT_BOTTOM=250; // back to default - if(Game.FORCE_TEXT_Y<0){ - var wordsHeight = 80 + Game.wordsDOM.getBoundingClientRect().height; - var currentY = Game.wordsDOM.style.top=="" ? 80 : parseFloat(Game.wordsDOM.style.top); - var gotoY = (wordsHeight Date: Thu, 12 Sep 2019 16:23:41 +1000 Subject: [PATCH 05/11] move the "click to advance" text the click to advance text is now moved into the right location using css transforms! this still runs every frame when we're forcing a specific text position. but it's getting better! --- scripts/game/Game.js | 16 ++++++++++------ scripts/game/Options.js | 5 ----- styles/game.css | 1 - 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/scripts/game/Game.js b/scripts/game/Game.js index 3b3c522..148d2e8 100644 --- a/scripts/game/Game.js +++ b/scripts/game/Game.js @@ -322,16 +322,20 @@ Game.WORDS_HEIGHT_BOTTOM = -1; if(updated) return updated = true + let advanceTextPosition = 0 if(Game.FORCE_TEXT_Y != -1){ Game.wordsDOM.style.transform = `translateY(${Game.FORCE_TEXT_Y}px)`; - return + advanceTextPosition = Game.wordsDOM.clientHeight + Game.FORCE_TEXT_Y + 5 + } else { + const wordsHeight = Game.wordsDOM.clientHeight; + let diff = wordsHeight - (Game.WORDS_HEIGHT_BOTTOM - offset) + if(diff < 0) diff = 0 + Game.wordsDOM.style.transform = `translateY(${offset - diff}px)`; + advanceTextPosition = offset - diff + wordsHeight + 5 } - const wordsHeight = Game.wordsDOM.clientHeight; - let diff = wordsHeight - (Game.WORDS_HEIGHT_BOTTOM - offset) - if(diff < 0) diff = 0 - - Game.wordsDOM.style.transform = `translateY(${offset - diff}px)`; + // Also, move click_to_advance DOM + $('#click_to_advance').style.transform = `translateY(${Math.round(advanceTextPosition)}px)`; } if(Game.wordsDOM.children.length != lastCount){ diff --git a/scripts/game/Options.js b/scripts/game/Options.js index 29f7f57..7dff887 100644 --- a/scripts/game/Options.js +++ b/scripts/game/Options.js @@ -111,11 +111,6 @@ Loader.addSounds([ } } - // Also, move click_to_advance DOM - var wordsTop = parseInt($("#game_words").style.top); - var wordsHeight = $("#game_words").getBoundingClientRect().height; - click_to_advance.style.top = Math.round(wordsTop+wordsHeight+5) + "px"; - }; var _timeoutCallbacks = []; diff --git a/styles/game.css b/styles/game.css index dfe9da7..3886614 100644 --- a/styles/game.css +++ b/styles/game.css @@ -564,7 +564,6 @@ OPTIONS position: absolute; text-align: center; width: 100%; - top: 254px; color:#fff; } From 45e3f27c7925c17df83ef2bfd7c20ee2b34eba32 Mon Sep 17 00:00:00 2001 From: spaciecat <5057054+spaciecat@users.noreply.github.com> Date: Thu, 12 Sep 2019 17:21:12 +1000 Subject: [PATCH 06/11] seperate observer logic i split apart the code that tells the dialogue when to update into a seperate file so that i can use it in other places! seemed like a faster solution to have observable-esque behaviour without using very new features, setting up compilers, and including huge libraries! (not 100% sure its totally working, but i havn't caught it failing yet!) --- index.html | 1 + scripts/game/Game.js | 78 ++++++++++++++------------------ scripts/lib/tickable_observer.js | 36 +++++++++++++++ styles/game.css | 2 +- 4 files changed, 72 insertions(+), 45 deletions(-) create mode 100644 scripts/lib/tickable_observer.js diff --git a/index.html b/index.html index e41af11..8891e02 100644 --- a/index.html +++ b/index.html @@ -216,6 +216,7 @@ + diff --git a/scripts/game/Game.js b/scripts/game/Game.js index 148d2e8..4f29a34 100644 --- a/scripts/game/Game.js +++ b/scripts/game/Game.js @@ -310,59 +310,49 @@ Game.immediatePromise = function(){ Game.FORCE_TEXT_Y = -1; Game.WORDS_HEIGHT_BOTTOM = -1; (function(){ - const offset = 80 - let lastCount = 0 - let lastBottom = -1 - Game.updateText = function(instant) { + var wordsObserver = new TickableObserver(function(){ + var offset = 80 + if(Game.WORDS_HEIGHT_BOTTOM < 0) Game.WORDS_HEIGHT_BOTTOM = 250; + let advanceTextPosition = 0 - if(Game.WORDS_HEIGHT_BOTTOM < 0) Game.WORDS_HEIGHT_BOTTOM = 250; - - let updated = false - function updateTransform(){ - if(updated) return - updated = true - - let advanceTextPosition = 0 - if(Game.FORCE_TEXT_Y != -1){ - Game.wordsDOM.style.transform = `translateY(${Game.FORCE_TEXT_Y}px)`; - advanceTextPosition = Game.wordsDOM.clientHeight + Game.FORCE_TEXT_Y + 5 - } else { - const wordsHeight = Game.wordsDOM.clientHeight; - let diff = wordsHeight - (Game.WORDS_HEIGHT_BOTTOM - offset) - if(diff < 0) diff = 0 - Game.wordsDOM.style.transform = `translateY(${offset - diff}px)`; - advanceTextPosition = offset - diff + wordsHeight + 5 - } + // Either force the text somewhere... + if(Game.FORCE_TEXT_Y != -1){ + Game.wordsDOM.style.transform = `translateY(${Game.FORCE_TEXT_Y}px)`; + advanceTextPosition = Game.wordsDOM.clientHeight + Game.FORCE_TEXT_Y + 5 + } + // Or calculate its position based on a window... + else { + const wordsHeight = Game.wordsDOM.clientHeight; + let diff = wordsHeight - (Game.WORDS_HEIGHT_BOTTOM - offset) + if(diff < 0) diff = 0 + Game.wordsDOM.style.transform = `translateY(${offset - diff}px)`; + advanceTextPosition = offset - diff + wordsHeight + 5 + } - // Also, move click_to_advance DOM - $('#click_to_advance').style.transform = `translateY(${Math.round(advanceTextPosition)}px)`; - } + // "Instant mode" was only used for clearing... so lets just do it when it's clear? + if(Game.wordsDOM.children.length == 0){ + Game.wordsDOM.classList.add("clear_transition"); + Game.wordsDOM.clientHeight; + Game.wordsDOM.classList.remove("clear_transition"); + } - if(Game.wordsDOM.children.length != lastCount){ - updateTransform() - lastCount = Game.wordsDOM.children.length; - } - - if(Game.WORDS_HEIGHT_BOTTOM != lastBottom){ - updateTransform() - lastBottom = Game.WORDS_HEIGHT_BOTTOM; - } - - if(instant || Game.FORCE_TEXT_Y != -1){ - updateTransform() - Game.wordsDOM.classList.add("clear_transition"); - Game.wordsDOM.clientHeight; - Game.wordsDOM.classList.remove("clear_transition"); - } - - }; + // Also, move the click_to_advance DOM + $('#click_to_advance').style.transform = `translateY(${Math.round(advanceTextPosition)}px)`; + }); + + // The words UI depends on these things: + wordsObserver.watch(function(){ return Game.FORCE_TEXT_Y }); + wordsObserver.watch(function(){ return Game.WORDS_HEIGHT_BOTTOM }); + wordsObserver.watch(function(){ return Game.wordsDOM.children.length }); + Game.updateText = function() { wordsObserver.tick() }; })() // CLEAR TEXT Game.clearText = function(){ Game.wordsDOM.innerHTML = ""; - Game.updateText(true); + Game.updateText(); }; + Game.clearAll = function(){ Game.clearText(); Game.resetScene(); diff --git a/scripts/lib/tickable_observer.js b/scripts/lib/tickable_observer.js new file mode 100644 index 0000000..76ad08d --- /dev/null +++ b/scripts/lib/tickable_observer.js @@ -0,0 +1,36 @@ + +/* + Lots of things in this game were written to happen every frame, but they often don't need to! + + Here's something I call a `Tickable Obersver`, it lets you (every frame) check if some values + have changed, and only then run the expensive code! + + It's kinda like an observable, but it's tiny and runs on a frame-by-frame basis! + - Spacie +*/ + +class TickableObserver { + + constructor(event){ + this.depCount = 0; + this.previousValues = []; + this.watchers = []; + this.event = event; + } + + tick(){ + for(let i = 0; i < this.depCount; i++){ + if(this.watchers[i]() != this.previousValues[i]){ + this.previousValues[i] = this.watchers[i](); + if(this.event != null) return this.event(); + } + } + } + + watch(watcher){ + this.depCount++; + this.watchers.push(watcher); + this.previousValues.push(null); + } + +} \ No newline at end of file diff --git a/styles/game.css b/styles/game.css index 3886614..2a7f810 100644 --- a/styles/game.css +++ b/styles/game.css @@ -70,7 +70,7 @@ MAIN GAME width: 100%; position: absolute; overflow: hidden; - transition: transform 0.3s; + transition: transform 0.5s; } #game_words.clear_transition { transition: none !important; From 35495207c7caf731d6e7afef066107e5d57670f0 Mon Sep 17 00:00:00 2001 From: spaciecat <5057054+spaciecat@users.noreply.github.com> Date: Thu, 12 Sep 2019 17:51:08 +1000 Subject: [PATCH 07/11] animate choices with css transitions --- scripts/game/Game.js | 10 +++++----- styles/game.css | 15 +++++++++------ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/scripts/game/Game.js b/scripts/game/Game.js index 4f29a34..3e86516 100644 --- a/scripts/game/Game.js +++ b/scripts/game/Game.js @@ -344,7 +344,7 @@ Game.WORDS_HEIGHT_BOTTOM = -1; wordsObserver.watch(function(){ return Game.FORCE_TEXT_Y }); wordsObserver.watch(function(){ return Game.WORDS_HEIGHT_BOTTOM }); wordsObserver.watch(function(){ return Game.wordsDOM.children.length }); - Game.updateText = function() { wordsObserver.tick() }; + Game.updateText = function() { wordsObserver.tick() }; })() // CLEAR TEXT @@ -811,12 +811,12 @@ Game.executeChoice = function(line){ } // Add choice, animated! - div.style.top = "150px"; + div.classList.add("hidden"); Game.choicesDOM.appendChild(div); - setTimeout(function(){ - div.style.top = "0px"; + requestAnimationFrame(function(){ + div.classList.remove("hidden"); sfx("ui_show_choice", {volume:0.4}); - },10); + }); // Or... FORCE if(Game.OVERRIDE_FONT_SIZE){ diff --git a/styles/game.css b/styles/game.css index 2a7f810..1e7bc76 100644 --- a/styles/game.css +++ b/styles/game.css @@ -973,7 +973,7 @@ DIALOGUEZ text-align: center; } -#game_choices > div{ +#game_choices > div { width: 310px; margin: 0 auto 5px auto; @@ -985,11 +985,11 @@ DIALOGUEZ border-radius: 20px; /* Spring OUT only */ - -webkit-transition: top 500ms cubic-bezier(0.350, 0.005, 0.370, 1); /* older webkit */ - -webkit-transition: top 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390); - -moz-transition: top 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390); - -o-transition: top 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390); - transition: top 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390); /* custom */ + -webkit-transition: transform 500ms cubic-bezier(0.350, 0.005, 0.370, 1); /* older webkit */ + -webkit-transition: transform 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390); + -moz-transition: transform 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390); + -o-transition: transform 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390); + transition: transform 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390); /* custom */ -webkit-transition-timing-function: cubic-bezier(0.350, 0.005, 0.370, 1); /* older webkit */ -webkit-transition-timing-function: cubic-bezier(0.350, 0.005, 0.370, 1.390); @@ -997,6 +997,9 @@ DIALOGUEZ -o-transition-timing-function: cubic-bezier(0.350, 0.005, 0.370, 1.390); transition-timing-function: cubic-bezier(0.350, 0.005, 0.370, 1.390); /* custom */ } +#game_choices > div.hidden { + transform: translateY(150px); +} #game_choices > div > * { pointer-events: none; /* so italics and stuff doesn't trigger sound */ } From 4f7d5209b98826af031a28ab077fde806cc788da Mon Sep 17 00:00:00 2001 From: spaciecat <5057054+spaciecat@users.noreply.github.com> Date: Thu, 12 Sep 2019 23:04:08 +1000 Subject: [PATCH 08/11] animate HP canvas with css transforms switched the hp canvas from setting position to a css transform i also added a lil fade in to the choice buttons here, makes it look less janky because they dont pop in and out of reality as much --- scripts/game/Game.js | 6 +----- scripts/game/HP.js | 11 +++-------- scripts/lib/helpers.js | 8 ++++++++ styles/game.css | 34 +++++++++++++++------------------- 4 files changed, 27 insertions(+), 32 deletions(-) diff --git a/scripts/game/Game.js b/scripts/game/Game.js index 3e86516..b093d14 100644 --- a/scripts/game/Game.js +++ b/scripts/game/Game.js @@ -330,11 +330,7 @@ Game.WORDS_HEIGHT_BOTTOM = -1; } // "Instant mode" was only used for clearing... so lets just do it when it's clear? - if(Game.wordsDOM.children.length == 0){ - Game.wordsDOM.classList.add("clear_transition"); - Game.wordsDOM.clientHeight; - Game.wordsDOM.classList.remove("clear_transition"); - } + if(Game.wordsDOM.children.length == 0) flushElementTransitions(Game.wordsDOM); // Also, move the click_to_advance DOM $('#click_to_advance').style.transform = `translateY(${Math.round(advanceTextPosition)}px)`; diff --git a/scripts/game/HP.js b/scripts/game/HP.js index 0b1243d..4da8f19 100644 --- a/scripts/game/HP.js +++ b/scripts/game/HP.js @@ -38,16 +38,11 @@ function HitPoints(){ // Show/hide self.show = function(){ - self.dom.style.top = "0px"; + self.dom.classList.add('show'); }; self.hide = function(instant){ - if(instant){ - self.dom.style.display = "none"; - setTimeout(function(){ - self.dom.style.display = "block"; - },2000); - } - self.dom.style.top = "-100px"; + self.dom.classList.remove('show'); + if(instant) flushElementTransitions(self.dom); }; subscribe("hp_show", self.show); subscribe("hp_hide", self.hide); diff --git a/scripts/lib/helpers.js b/scripts/lib/helpers.js index cbae6bb..af19f51 100644 --- a/scripts/lib/helpers.js +++ b/scripts/lib/helpers.js @@ -4,4 +4,12 @@ Math.TAU = Math.PI*2; // The poor man's jQuery function $(query){ return document.querySelector(query); +} + +// Flush an element's transitions +function flushElementTransitions(element){ + if(typeof element == "string") element = $(element); + element.classList.add('clear_transition') + element.clientHeight; + element.classList.remove('clear_transition'); } \ No newline at end of file diff --git a/styles/game.css b/styles/game.css index 1e7bc76..ce544e4 100644 --- a/styles/game.css +++ b/styles/game.css @@ -56,6 +56,10 @@ MAIN GAME ******************************************************************************************************/ +.clear_transition { + transition: none !important; +} + #game_container{ position: relative; display: inline-block; @@ -72,9 +76,6 @@ MAIN GAME overflow: hidden; transition: transform 0.5s; } -#game_words.clear_transition { - transition: none !important; -} #game_words, #game_hp, #click_to_advance{ pointer-events: none; @@ -983,22 +984,14 @@ DIALOGUEZ position: relative; border-radius: 20px; + opacity: 1; - /* Spring OUT only */ - -webkit-transition: transform 500ms cubic-bezier(0.350, 0.005, 0.370, 1); /* older webkit */ - -webkit-transition: transform 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390); - -moz-transition: transform 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390); - -o-transition: transform 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390); - transition: transform 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390); /* custom */ - - -webkit-transition-timing-function: cubic-bezier(0.350, 0.005, 0.370, 1); /* older webkit */ - -webkit-transition-timing-function: cubic-bezier(0.350, 0.005, 0.370, 1.390); - -moz-transition-timing-function: cubic-bezier(0.350, 0.005, 0.370, 1.390); - -o-transition-timing-function: cubic-bezier(0.350, 0.005, 0.370, 1.390); - transition-timing-function: cubic-bezier(0.350, 0.005, 0.370, 1.390); /* custom */ + /* TODO: Add vendor prefixes again, just removed them while working on css animation stuff [Spacie] */ + transition: transform 500ms cubic-bezier(0.350, 0.005, 0.370, 1.390), opacity 300ms ease-in-out; } #game_choices > div.hidden { transform: translateY(150px); + opacity: 0; } #game_choices > div > * { pointer-events: none; /* so italics and stuff doesn't trigger sound */ @@ -1070,11 +1063,14 @@ canvas{ top:0; left:0; } -#game_hp{ +#game_hp { position: absolute; width: 360px; height: 100px; - top:-100px; - left:0; - transition: top 0.5s ease-in-out; + transition: transform 0.5s ease-in-out; + transform: translateY(-100px); } + +#game_hp.show { + transform: none; +} \ No newline at end of file From a172bc72544d4737f23bf101496bcecf74bc4f72 Mon Sep 17 00:00:00 2001 From: spaciecat <5057054+spaciecat@users.noreply.github.com> Date: Fri, 13 Sep 2019 21:50:55 +1000 Subject: [PATCH 09/11] started working on canvas related improvements --- scripts/game/BG_Anxiety.js | 63 ++++++++++++++++++-------------------- scripts/game/Game.js | 63 ++++++++++++++++++++------------------ styles/game.css | 2 +- 3 files changed, 64 insertions(+), 64 deletions(-) diff --git a/scripts/game/BG_Anxiety.js b/scripts/game/BG_Anxiety.js index e88f310..161098c 100644 --- a/scripts/game/BG_Anxiety.js +++ b/scripts/game/BG_Anxiety.js @@ -62,61 +62,56 @@ function BG_Anxiety(whiteMode){ } }; + self.isBoxOutOfSight = function(box){ - if(box.x<-box.w) return true; - if(box.y<-box.h) return true; - if(box.x>BG_WIDTH) return true; - if(box.y>BG_HEIGHT) return true; + if(box.x < -box.w) return true; + if(box.y < -box.h) return true; + if(box.x > BG_WIDTH) return true; + if(box.y > BG_HEIGHT) return true; return false; }; + self.updateBox = function(box, delta){ - // Move it - box.x += box.velX * delta/(1/60); - box.y += box.velY * delta/(1/60); + const speedMultiplier = 60; + box.x += box.velX * delta * speedMultiplier; + box.y += box.velY * delta * speedMultiplier; // If it's out of sight, reset it - if(self.isBoxOutOfSight(box)){ - self.resetBox(box); - } - + if(self.isBoxOutOfSight(box)) self.resetBox(box); }; + + var boxLayerAlpha = 1; + self.updateAlpha = function(alpha){ + boxLayerAlpha = alpha; + }; + + self.update = function(delta){ + for(const box of self.boxes) self.updateBox(box, delta); + }; + self.drawBox = function(box, ctx){ - ctx.fillStyle = self.whiteMode ? "rgba(255,255,255,0.1)" : "rgba(255,255,255,0.03)"; + ctx.globalAlpha = boxLayerAlpha * self.whiteMode ? 0.1 : 0.03; + ctx.fillStyle = "#fff"; ctx.fillRect(box.x, box.y, box.w, box.h); }; - for(var i=0; i<40; i++){ - var box = {}; - self.resetBox(box, true); - self.boxes.push(box); - } - var allBoxAlpha = 1; - self.updateAlpha = function(alpha){ - allBoxAlpha = alpha; - }; - self.update = function(delta){ - self.boxes.forEach(function(box){ - self.updateBox(box, delta); - }); - }; self.draw = function(ctx){ // A big ol' black box ctx.fillStyle = self.whiteMode ? "#dddddd" : "#111111"; ctx.fillRect(0,0, BG_WIDTH, BG_HEIGHT); - // All-box alpha - // allBoxAlpha += 1/30; - // if(allBoxAlpha>1) allBoxAlpha=1; - // Moving white boxes - ctx.globalAlpha = allBoxAlpha; - self.boxes.forEach(function(box){ - self.drawBox(box, ctx); - }); + for(const box of self.boxes) self.drawBox(box, ctx); ctx.globalAlpha = 1; }; + for(var i=0; i<40; i++){ + var box = {}; + self.resetBox(box, true); + self.boxes.push(box); + } + } \ No newline at end of file diff --git a/scripts/game/Game.js b/scripts/game/Game.js index b093d14..91a7a41 100644 --- a/scripts/game/Game.js +++ b/scripts/game/Game.js @@ -96,35 +96,33 @@ Game.start = function(){ window._ = {}; // global var, reset }; -var LAST_TIME = (new Date()).getTime(); +var last_frame = Date.now(); Game.update = function(){ // TIME - var NOW = (new Date()).getTime(); - var DELTA = (NOW - LAST_TIME)/1000; - DELTA = Math.min(DELTA, 1/20); // no slower than 20fps - LAST_TIME = NOW; + const now = Date.now(); + const delta = (now - last_frame) / 1000; + last_frame = now; + + // Removing this till I can see why it's needed... + // Reshaping the passing of time will come back to haunt you! [Spacie] + // DELTA = Math.min(DELTA, 1/20); // no slower than 20fps if(!Game.paused){ // Timeout callbacks... - for(var i=0; i { + tc.timeLeft -= 1000 * delta; + if(tc.timeLeft <= 0) tc.callback(); + }); + Game.timeoutCallbacks = Game.timeoutCallbacks.filter(tc => tc.timeLeft > 0); // The interface Game.updateText(); - Game.updateCanvas(DELTA); + Game.updateCanvas(delta); // Ayyy publish("update"); - } // Options update @@ -310,8 +308,8 @@ Game.immediatePromise = function(){ Game.FORCE_TEXT_Y = -1; Game.WORDS_HEIGHT_BOTTOM = -1; (function(){ - var wordsObserver = new TickableObserver(function(){ - var offset = 80 + const wordsObserver = new TickableObserver(() => { + const offset = 80 if(Game.WORDS_HEIGHT_BOTTOM < 0) Game.WORDS_HEIGHT_BOTTOM = 250; let advanceTextPosition = 0 @@ -337,10 +335,11 @@ Game.WORDS_HEIGHT_BOTTOM = -1; }); // The words UI depends on these things: - wordsObserver.watch(function(){ return Game.FORCE_TEXT_Y }); - wordsObserver.watch(function(){ return Game.WORDS_HEIGHT_BOTTOM }); - wordsObserver.watch(function(){ return Game.wordsDOM.children.length }); - Game.updateText = function() { wordsObserver.tick() }; + wordsObserver.watch(() => Game.FORCE_TEXT_Y); + wordsObserver.watch(() => Game.WORDS_HEIGHT_BOTTOM); + wordsObserver.watch(() => Game.wordsDOM.children.length); + Game.updateText = () => wordsObserver.tick(); + })() // CLEAR TEXT @@ -1055,7 +1054,16 @@ Game.resetScene = function(){ Game.resetScene(); // Update & draw all the kids! -Game.updateCanvas = function(DELTA){ +Game.updateCanvas = function(delta){ + + // UPDATING: + // ------------------------------------------------------------- + for(const child of Game.scene.children) { + if(child.update) child.update(delta); + } + + // RENDERING: + // ------------------------------------------------------------- // For retina var ctx = Game.context; @@ -1063,12 +1071,9 @@ Game.updateCanvas = function(DELTA){ ctx.scale(2, 2); // Update/Draw all kids - Game.scene.children.forEach(function(child){ - if(child.update) child.update(DELTA); - }); - Game.scene.children.forEach(function(child){ - child.draw(ctx, DELTA); - }); + + for(const child of Game.scene.children) child.draw(ctx, delta); + // Restore ctx.scale(0.5, 0.5); diff --git a/styles/game.css b/styles/game.css index ce544e4..5307dd7 100644 --- a/styles/game.css +++ b/styles/game.css @@ -56,7 +56,7 @@ MAIN GAME ******************************************************************************************************/ -.clear_transition { +.clear_transition, .clear_transition * { transition: none !important; } From 5ba626b73bc8d5eb1deb63ae7f05428932b46cc2 Mon Sep 17 00:00:00 2001 From: spaciecat <5057054+spaciecat@users.noreply.github.com> Date: Sat, 14 Sep 2019 23:01:57 +1000 Subject: [PATCH 10/11] FINALLY SOMETHING HELPED PERFORMANCE browsers try to get all cute and cozy with your images, like... no pal just let me load things and have them stay loaded? --- scripts/game/Game.js | 3 ++- scripts/game/Loader.js | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/scripts/game/Game.js b/scripts/game/Game.js index 91a7a41..f9b7f8e 100644 --- a/scripts/game/Game.js +++ b/scripts/game/Game.js @@ -658,7 +658,8 @@ Game.executeText = function(line){ span.innerHTML = ""; span.style.display = "block"; var iconName = word.slice(1,-1) - var icon = Library.images["fear_"+iconName]; + var icon = new Image(); + icon.src = Library.images["fear_"+iconName].hackSrc; div.children[i].appendChild(icon); icon.style.display = "block"; if(speaker!="i"){ diff --git a/scripts/game/Loader.js b/scripts/game/Loader.js index ad9d72e..e39ad89 100644 --- a/scripts/game/Loader.js +++ b/scripts/game/Loader.js @@ -48,14 +48,16 @@ Loader.addImages = function(imageConfigs){ }; Loader.loadImage = function(imageConfig){ return new RSVP.Promise(function(resolve){ - var img = new Image(); - var id = imageConfig.id; - Library.images[id] = img; // ADD TO LIBRARY - img.onload = function(){ - publish("assetLoaded"); - resolve(); - } - img.src = imageConfig.src; + const id = imageConfig.id; + fetch(imageConfig.src) + .then(response => response.blob()) + .then(blobData => createImageBitmap(blobData)) + .then(bitmap => { + bitmap.hackSrc = imageConfig.src; + Library.images[id] = bitmap; + publish("assetLoaded"); + resolve(); + }) }); }; From 0f99d8e10bf384623dbc3dc598b805ac5ea08d92 Mon Sep 17 00:00:00 2001 From: spaciecat <5057054+spaciecat@users.noreply.github.com> Date: Sat, 14 Sep 2019 23:11:31 +1000 Subject: [PATCH 11/11] add createImageBitmap polyfill the changes i made to the image pipeline required stuff that needs a polyfill, so here it is! --- index.html | 1 + scripts/lib/createImageBitmap.js | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 scripts/lib/createImageBitmap.js diff --git a/index.html b/index.html index 8891e02..73a95f0 100644 --- a/index.html +++ b/index.html @@ -216,6 +216,7 @@ + diff --git a/scripts/lib/createImageBitmap.js b/scripts/lib/createImageBitmap.js new file mode 100644 index 0000000..f4173d3 --- /dev/null +++ b/scripts/lib/createImageBitmap.js @@ -0,0 +1,33 @@ +/* +* Safari and Edge polyfill for createImageBitmap +* https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap +* +* Support source image types Blob and ImageData. +* +* From: https://dev.to/nektro/createimagebitmap-polyfill-for-safari-and-edge-228 +* Updated by Yoan Tournade +*/ +if (!('createImageBitmap' in window)) { + window.createImageBitmap = async function (data) { + return new Promise((resolve,reject) => { + let dataURL; + if (data instanceof Blob) { + dataURL = URL.createObjectURL(data); + } else if (data instanceof ImageData) { + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + canvas.width = data.width; + canvas.height = data.height; + ctx.putImageData(data,0,0); + dataURL = canvas.toDataURL(); + } else { + throw new Error('createImageBitmap does not handle the provided image source type'); + } + const img = document.createElement('img'); + img.addEventListener('load',function () { + resolve(this); + }); + img.src = dataURL; + }); + }; +} \ No newline at end of file