0
0
Fork 0

Add an overlay style representing a health bar.

This commit is contained in:
Oliver-Akins 2024-03-10 15:41:49 -06:00
parent c74c635ce0
commit bed4a2709d
4 changed files with 1798 additions and 0 deletions

1605
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,96 @@
const app = new Vue({
el: `#app`,
data: {
io: null,
gameActive: false,
current: null,
incorrect: 0,
max_incorrect: 0,
channel: null,
close_timeout_id: null,
},
computed: {
showOverlay() {
return this.channel
&& this.gameActive
&& this.current
&& this.max_incorrect > 0;
},
totalHealth() {
return this.max_incorrect;
},
lostHealth() {
return this.incorrect;
},
currentHealth() {
return this.totalHealth - this.lostHealth;
},
parsedText() {
return this.current.split(``).join(`<br>`);
},
},
methods: {
connected() {
this.io.on(`finish`, this.finishGame);
this.io.on(`update`, this.newState);
this.io.on(`state`, this.activity);
this.io.emit(`state`, this.channel);
},
/*
{
active: boolean,
current: string,
incorrect: {
current: number,
max: number,
},
}
*/
activity(d) {
console.log(`active listeners`, d)
if (d.active) {
this.newState(d);
this.gameActive = true;
};
},
newState(d) {
clearTimeout(this.close_timeout_id);
this.close_timeout_id = null;
this.current = d.current;
this.incorrect = d.incorrect.current;
this.max_incorrect = d.incorrect.max;
},
finishGame(d) {
if (d.win == null) {
this.close_timeout_id = setTimeout(() => {
this.current = null;
this.incorrect = 0;
this.max_incorrect = 0;
this.gameActive = false;
}, 5_000);
}
if (d.win) {
this.incorrect = -2;
};
this.incorrect = this.max_incorrect;
this.current = d.solution;
this.close_timeout_id = setTimeout(() => {
this.current = null;
this.incorrect = 0;
this.max_incorrect = 0;
this.gameActive = false;
}, 5_000);
},
},
mounted() {
const url = new URL(window.location.href);
let path = url.pathname.split(`/`);
this.channel = path[1];
this.io = io(window.location.host, { path: path[0] });
this.io.on(`connect`, this.connected);
},
});

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="standard-health/style.css">
<script src="../../vue.js"></script>
<script src="standard-health/app.js" defer></script>
<script src="../../socket.io/socket.io.js"></script>
</head>
<body>
<div id="app">
<transition
name="grow"
>
<div
v-if="showOverlay"
v-cloak
class="container"
>
<h1>Chatman</h1>
<div id="main-play-area">
<div id="health-bar">
<div v-for="_ in currentHealth" class="health filled"></div>
<div v-for="_ in lostHealth" class="health empty"></div>
</div>
<h2 id="word" v-html="parsedText"></h2>
</div>
</div>
</transition>
</div>
</body>
</html>

View file

@ -0,0 +1,63 @@
@import url('https://fonts.googleapis.com/css2?family=Teko&display=swap');
:root {
font-family: 'Teko', sans-serif;
}
[v-cloak] {
display: none;
}
html, body, #app {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
.container {
margin: 0;
padding: 0;
overflow: hidden;
background: rgba(0, 0, 0, .5);
position: relative;
text-align: center;
border-radius: 15px;
}
h1 {
margin-bottom: 5px;
}
#health-bar {
display: flex;
flex-direction: row;
border-width: 1px;
border-style: solid;
border-color: black;
}
#health-bar .health {
height: 20px;
flex-grow: 1;
border-radius: 2px;
border-style: solid;
border-color: black;
border-width: 1px;
}
#health-bar .health.filled {
background-color: red;
}
#health-bar .health.empty {
background-color: darkred;
}
.grow-enter-active, .grow-leave-active {
transition: transform 1s;
}
.grow-enter, .grow-leave-to {
transform: scale(0);
}