Multiple pages, background sound, success animation

This commit is contained in:
Daniel Bulant 2021-02-22 13:08:26 +01:00
parent 7b6058290c
commit 1cabad9339
8 changed files with 166 additions and 14 deletions

5
package-lock.json generated
View file

@ -326,6 +326,11 @@
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"howler": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/howler/-/howler-2.2.1.tgz",
"integrity": "sha512-0iIXvuBO/81CcrQ/HSSweYmbT50fT2mIc9XMFb+kxIfk2pW/iKzDbX1n3fZmDXMEIpYvyyfrB+gXwPYSDqUxIQ=="
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",

View file

@ -18,6 +18,7 @@
"svelte": "^3.0.0"
},
"dependencies": {
"howler": "^2.2.1",
"sirv-cli": "^1.0.0"
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

After

Width:  |  Height:  |  Size: 316 KiB

View file

@ -1,5 +1,6 @@
<script>
import Dialog from "./pages/dialog.svelte";
import { Howl } from "howler";
var page = "game";
const characters = [{
@ -11,15 +12,36 @@
name: "michael_heretic",
background: "/sprite/fin_backg.png",
character: "Michael",
pose: null,
text: "How did you... You know I don't even care. Heretic like you needs to be punished.",
buttons: [{
text: "Jokes on you I'm into that shit."
text: "Jokes on you I'm into that shit.",
next: "michael_success"
}, {
text: "I have something to offer."
}]
}, {
name: "michael_success",
background: "/sprite/fin_backg.png",
character: "Michael",
text: "Really then? If you survive this whole ordeal, prepare a room and we'll see how into this shit you really are.",
flags: ["success"],
next: "michael_heretic"
}];
var current = 0;
var current = localStorage.getItem("dialog-page") || 0;
for(let character of characters) {
(new Image).src = character.art; // preload art
}
for(let d of dialog) {
(new Image).src = d.background; // preload art
}
var music = new Howl({
src: "/sound/thought_patterns.m4a",
html5: true,
loop: true,
autoplay: true
});
</script>
<svelte:head>

View file

@ -1,8 +1,9 @@
<script>
export var self;
export var active = false;
export var self = null;
</script>
<div class="button" on:click tabindex="-1" bind:this={self}>
<div class="button" on:click tabindex="-1" bind:this={self} class:active>
<slot />
</div>
@ -19,15 +20,16 @@
text-align: center;
background-position-x: center;
cursor: pointer;
opacity: 0.7;
opacity: 0.8;
margin-top: 15px;
margin-bottom: 15px;
transition: opacity .3s, margin .3s, transform .3s;
}
.button:first-child:hover, .button:first-child:focus {
.button:first-child:hover, .button:first-child:focus, .button:first-child.active {
margin-top: 15px;
}
.button:hover, .button:focus {
.button:hover, .button:focus, .button.active {
outline: none;
opacity: 1;
margin-top: 5px;
margin-bottom: 5px;

View file

@ -1,6 +1,7 @@
<script>
import Button from "./button.svelte";
import Button from "./button.svelte";
/** @type {any[]} */
export var dialog;
export var current;
/** @type {any[]} */
@ -15,8 +16,62 @@ import Button from "./button.svelte";
var art;
$: art = d.character_art || d.pose ? character.poses[d.pose] : character.art;
var activeButton = -1;
function select(i) {
var next;
if(d.buttons) {
if(!d.buttons[i]) return;
next = dialog.findIndex(t => t.name === d.buttons[i].next);
} else {
next = dialog.findIndex(t => t.name === d.next);
}
if(next === -1) return;
current = next;
localStorage.setItem("dialog-page", next);
}
function keydown(e) {
switch(e.key) {
case "ArrowUp":
activeButton--;
if(activeButton < 0) activeButton = 0;
break;
case "ArrowDown":
activeButton++;
if(d.buttons && activeButton > d.buttons.length - 1) activeButton = d.buttons.length - 1;
break;
case "Enter":
select(activeButton);
break;
}
}
function reset() {
activeButton = -1;
}
var buttons;
function next(e) {
if(e.path.includes(buttons)) return;
reset();
select();
}
var success = false;
$: success = d.flags && d.flags.includes("success");
var textElement;
$: {
if(textElement) {
d; // everytime d is changed
textElement.classList.remove("animate");
void textElement.offsetWidth;
textElement.classList.add("animate");
}
}
</script>
<svelte:window on:keydown={keydown} on:mousemove={reset} on:click={next} />
<div class="dialog">
<div class="background">
<img src={d.background} alt="" class="full" draggable={false}>
@ -24,12 +79,17 @@ import Button from "./button.svelte";
</div>
<div class="text">
<h1>{character.name}, {character.title}</h1>
<p>{d.text}</p>
<div class="buttons">
{#each d.buttons as button}
<Button>{button.text}</Button>
{/each}
<p class="animate" bind:this={textElement}>{d.text}</p>
<div class="buttons" bind:this={buttons}>
{#if d.buttons}
{#each d.buttons as button, i}
<Button active={i === activeButton} on:click={() => select(i)}>{button.text}</Button>
{/each}
{/if}
</div>
{#if success}
<h2>SUCCESS</h2>
{/if}
</div>
</div>
@ -50,12 +110,74 @@ import Button from "./button.svelte";
text-align: center;
letter-spacing: 2px;
}
h2 {
position: relative;
width: 400px;
color: white;
font-size: 70px;
letter-spacing: 12px;
text-align: center;
margin: 15px auto;
text-shadow: 0 0 6px white;
}
h2::before, h2::after {
position: absolute;
content: "";
background: white;
box-shadow: 0 0 15px white;
border-radius: 50%;
top: 50%;
transform: translateY(-50%);
}
h2::before {
animation: successLeft .4s;
animation-timing-function: ease-out;
}
h2::after {
animation: successRight .4s;
animation-timing-function: ease-out;
}
@keyframes successLeft {
0% {
left: 50%;
width: 100px;
height: 10px;
}
100% {
left: -60px;
width: 50px;
height: 2px;
}
}
@keyframes successRight {
0% {
right: 50%;
width: 100px;
height: 10px;
}
100% {
right: -60px;
width: 50px;
height: 2px;
}
}
p {
margin: 0;
text-align: center;
font-size: 25px;
font-weight: 600;
}
.animate {
animation: appear .3s;
}
@keyframes appear {
from {
transform: scale(0.7);
}
to {
transform: scale(1);
}
}
.text {
max-width: 700px;
margin: 0 auto;