diff --git a/index.html b/index.html index 7ad1dcd..f31b08e 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ - Adventures With Anxiety! [BETA, DO NOT SHARE YET] + Adventures With Anxiety! @@ -29,24 +29,7 @@ - - - - + @@ -194,8 +177,14 @@ + +
+
+ +
+ @@ -248,11 +237,14 @@ Share on an anxiety-app: (for educators who want to avoid an awkward PTA meeting) - + + + + @@ -305,32 +297,5 @@ Share on an anxiety-app: + - - \ No newline at end of file diff --git a/scenes/PROMO.md b/scenes/PROMO.md new file mode 100644 index 0000000..888548b --- /dev/null +++ b/scenes/PROMO.md @@ -0,0 +1,126 @@ +# intro + +`SceneSetup.intro();` + +# intro-play-button + +(...51) + +[PLAY!](#intro-start) `publish("intro-to-game-1"); Game.OVERRIDE_CHOICE_LINE=true;` + +# intro-start + +(...500) + +`clearText()` + +n3: So before we start, how would *you* like to read? + +`publish("show_options_bottom")` + +# intro-start-2 + +n3: Now, let's begin our story... + +``` +publish("hide_tabs"); +clearText(); +``` + +(...1000) + +`publish("intro-to-game-2")` + +n2: THIS IS A HUMAN + +(...600) + +`clearText()` + +(...300) + +`publish("intro-to-game-3")` + +# act1 + +``` +SceneSetup.act1(); +publish("hide_tabs"); +music('battle', {volume:0.5}); +``` + +(...300) + +n: AND THIS IS THE HUMAN'S ANXIETY + +n: _YOU_ ARE THE ANXIETY + +(#act1_normal) + + +# act1_normal + +``` +hong({body:"putaway"}); +sfx("rustle"); +Game.OVERRIDE_TEXT_SPEED = 1.5; +``` + +h: Nope. No, nope, not listening. Gonna check my phone. + +``` +sfx("rustle2"); +hong({body:"phone1", mouth:"neutral", eyes:"neutral"}) +``` + +n: YOUR JOB IS TO PROTECT YOUR HUMAN FROM *DANGER* + +`bb({eyes:"look", mouth:"small_lock", body:"fear"})` + +b: Gasp! You're scrolling your life away on Twitter! Again! + +``` +bb({eyes:"normal", mouth:"normal", body:"normal"}); +hong({eyes:"annoyed"}); +``` + +h: Yeah I wonder why I don't just sit and listen to my thoughts more often. + +`hong({eyes:"neutral"});` + +n: QUICK, WARN THEM ABOUT A *DANGER!* + +``` +bb({eyes:"look"}); +``` + +[Oh no, look at that horrible news story!](#act1d_news) + +[Oh no, is that tweet secretly about *us?*](#act1d_subtweet) + +[Hey, a GIF of a cat drinking milk](#act1d_milk) + +# act1d_milk + +`hong({mouth:"smile", eyes:"surprise"});` + +h: Heh ya that's cute, I-- + +``` +hong({mouth:"shock", eyes:"shock"}); +bb({body:"scream"}); +Game.OVERRIDE_TEXT_SPEED = 1.8; +``` + +b: CATS CAN'T DIGEST MILK AND WE'RE TERRIBLE PEOPLE FOR ENJOYING ANIMAL ABUSE + +(...200) + +``` +bb({body:"normal", mouth:"normal", eyes:"fear"}); +attack("20p", "bad"); +publish("hp_show"); +``` + + + 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; iBG_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.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); - }); + ctx.globalAlpha = boxLayerAlpha * (self.whiteMode ? 0.1 : 0.03); + ctx.fillStyle = "#fff"; + 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/Character.js b/scripts/game/Character.js index 3dad49b..f29e26a 100644 --- a/scripts/game/Character.js +++ b/scripts/game/Character.js @@ -138,9 +138,10 @@ function Character(spriteConfig, animLoops){ var c = self.characterFrames; // ALLOW PARALLAX??? - ctx.save(); + var xMoved = 0; if(self.ALLOW_PARALLAX){ ctx.translate(self.x, 0); + xMoved += self.x; } // Attacked? SHAKE WHOLE CONTEXT @@ -150,6 +151,7 @@ function Character(spriteConfig, animLoops){ var shakeAmp = (shakeDuration-attackedTimer)/shakeDuration; var shakeX = Math.sin(attackedTimer*Math.TAU*10)*shakeAmp*10; ctx.translate(shakeX, 0); + xMoved += shakeX; } } @@ -253,7 +255,9 @@ function Character(spriteConfig, animLoops){ } } - ctx.restore(); + + // Instead of save / restore, just move back the amount that we moved! + ctx.translate(-xMoved, 0); }; var iconAlpha_HACK = 0; diff --git a/scripts/game/Game.js b/scripts/game/Game.js index 2fb5029..f9b7f8e 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,11 +53,16 @@ Game.init = function(){ }; +// Call to toggle debug rendering +Game.debug = function(){ + document.body.classList.toggle('show_debug'); +} + // Parse scene markdown! 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(); @@ -81,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 @@ -293,26 +306,48 @@ 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 { + const offset = 80 + if(Game.WORDS_HEIGHT_BOTTOM < 0) Game.WORDS_HEIGHT_BOTTOM = 250; + let advanceTextPosition = 0 + + // 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 + } + + // "Instant mode" was only used for clearing... so lets just do it when it's clear? + 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)`; + }); + + // The words UI depends on these things: + wordsObserver.watch(() => Game.FORCE_TEXT_Y); + wordsObserver.watch(() => Game.WORDS_HEIGHT_BOTTOM); + wordsObserver.watch(() => Game.wordsDOM.children.length); + Game.updateText = () => wordsObserver.tick(); + +})() // CLEAR TEXT Game.clearText = function(){ Game.wordsDOM.innerHTML = ""; - Game.updateText(true); + Game.updateText(); }; + Game.clearAll = function(){ Game.clearText(); Game.resetScene(); @@ -623,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"){ @@ -771,12 +807,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){ @@ -1019,24 +1055,29 @@ 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; ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height); - ctx.save(); - ctx.scale(2,2); + 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.restore(); + ctx.scale(0.5, 0.5); // Draw HP HP.draw(); diff --git a/scripts/game/HP.js b/scripts/game/HP.js index 6ab015f..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); @@ -106,7 +101,8 @@ function HitPoints(){ self.rightRed = self.rightWhite = 1; self.drawHalf = function(ctx, isRight){ - ctx.save(); + var movedY = 0; + let oldCompositeOp = ctx.globalCompositeOperation; // Which side? var side = isRight ? "right" : "left"; @@ -120,6 +116,7 @@ function HitPoints(){ var amp = self[side+"Shake"]/7; var shakeY = Math.sin(self[side+"Shake"]*1.3)*amp; ctx.translate(0,shakeY); + movedY += shakeY; self[side+"Shake"]--; } @@ -174,14 +171,14 @@ function HitPoints(){ } // Restore - ctx.restore(); + ctx.translate(0, -movedY); + ctx.globalCompositeOperation = oldCompositeOp; }; self.draw = function(){ var ctx = self.context; ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height); - ctx.save(); ctx.scale(2,2); // Draw Left & Right Sides @@ -198,7 +195,7 @@ function HitPoints(){ var sx=0, sy=200*3, sw=720, sh=200; ctx.drawImage(self.image, sx,sy,sw,sh, 0,0,sw/2,sh/2); - ctx.restore(); + ctx.scale(0.5, 0.5); }; 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(); + }) }); }; 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/scripts/game/Sprite.js b/scripts/game/Sprite.js index 4b76618..0d5afa2 100644 --- a/scripts/game/Sprite.js +++ b/scripts/game/Sprite.js @@ -82,8 +82,6 @@ function Sprite(config){ if(!self.visible) return; // nah if(self.alpha==0) return; // also nah - ctx.save(); - // Which part of image to draw? var sx = self.currentFrame % self.grid.width; var sy = Math.floor((self.currentFrame - sx)/self.grid.width); @@ -104,6 +102,7 @@ function Sprite(config){ ctx.rotate(self.rotation); // Alpha + var oldAlpha = ctx.globalAlpha; ctx.globalAlpha = self.alpha; // Draw it! @@ -113,7 +112,10 @@ function Sprite(config){ -self.anchor.x, -self.anchor.y, fw/2, fh/2 ); - ctx.restore(); + ctx.rotate(-self.rotation); + ctx.scale(1 / scaleX, 1 / scaleY); + ctx.translate(-dx, -dy); + ctx.globalAlpha = oldAlpha; }; diff --git a/scripts/intermission/Intermission_BG.js b/scripts/intermission/Intermission_BG.js index d121366..10b992f 100644 --- a/scripts/intermission/Intermission_BG.js +++ b/scripts/intermission/Intermission_BG.js @@ -35,11 +35,9 @@ function BG_Intermission(STAGE){ }; self.draw = function(ctx){ - ctx.save(); self.bgSprite.draw(ctx); self.youwinSprite.draw(ctx); self.bbSprite.draw(ctx); - ctx.restore(); }; var _subscriptions = []; 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 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/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/scripts/main.js b/scripts/main.js index bc07cdb..eb513c4 100644 --- a/scripts/main.js +++ b/scripts/main.js @@ -1,6 +1,7 @@ // Load assets Loader.addScenes([ + //"scenes/PROMO.md", "scenes/intro.md", "scenes/act1.md", "scenes/intermission.md", diff --git a/styles/game.css b/styles/game.css index 3b21d76..d3d4c1c 100644 --- a/styles/game.css +++ b/styles/game.css @@ -1,11 +1,53 @@ -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; + font-size: 20px; + font-family: Helvetica, Arial, sans-serif; + font-weight: 100; + line-height: 1.3em; +} + +/****************************************************************************************************** + +DEBUGGING + +******************************************************************************************************/ + +body:not(.show_debug) .debug { + display: none; +} + +body.show_debug #game_container * { + outline: 1px solid red; +} + +#section_debug_list { + position: absolute; + background: #fff; + padding: 20px; + height: 500px; + overflow-y: scroll; + transition: all 0.2s; + font-family: monospace; + opacity: 0.2; + transform: translateX(-95%); +} + +#section_debug_list:hover { + transform: none; + opacity: 1; } /****************************************************************************************************** @@ -14,36 +56,25 @@ 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 */ +.clear_transition, .clear_transition * { + transition: none !important; } #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; - - font-size: 20px; - font-family: Helvetica, Arial, sans-serif; - font-weight: 100; - line-height: 1.3em; - overflow: hidden; } + #game_words{ - width: auto; - position: relative; - top: 80px; + width: 100%; + position: absolute; overflow: hidden; + transition: transform 0.5s; } #game_words, #game_hp, #click_to_advance{ @@ -438,7 +469,6 @@ OPTIONS position: absolute; text-align: center; width: 100%; - top: 254px; color:#fff; } @@ -848,7 +878,7 @@ DIALOGUEZ text-align: center; } -#game_choices > div{ +#game_choices > div { width: 310px; margin: 0 auto 5px auto; @@ -858,19 +888,14 @@ DIALOGUEZ position: relative; border-radius: 20px; + opacity: 1; - /* 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-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 */ @@ -942,13 +967,15 @@ 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; } /****************************************************************************************************** @@ -1027,4 +1054,4 @@ CORNER TEXT .corner-text { display: none; } -} \ No newline at end of file +}