implement basic game mechanics
BIN
potain05/assets/icons/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
potain05/assets/icons/android-chrome-256x256.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
potain05/assets/icons/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
9
potain05/assets/icons/browserconfig.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<browserconfig>
|
||||||
|
<msapplication>
|
||||||
|
<tile>
|
||||||
|
<square150x150logo src="/icons/mstile-150x150.png?v=potain"/>
|
||||||
|
<TileColor>#da532c</TileColor>
|
||||||
|
</tile>
|
||||||
|
</msapplication>
|
||||||
|
</browserconfig>
|
BIN
potain05/assets/icons/favicon-16x16.png
Normal file
After Width: | Height: | Size: 724 B |
BIN
potain05/assets/icons/favicon-32x32.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
potain05/assets/icons/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
potain05/assets/icons/mstile-150x150.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
29
potain05/assets/icons/safari-pinned-tab.svg
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="256.000000pt" height="256.000000pt" viewBox="0 0 256.000000 256.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<metadata>
|
||||||
|
Created by potrace 1.14, written by Peter Selinger 2001-2017
|
||||||
|
</metadata>
|
||||||
|
<g transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M1515 2548 c-2 -7 -5 -24 -7 -38 -3 -22 -61 -50 -638 -307 -485 -216
|
||||||
|
-645 -283 -675 -283 -37 0 -47 -7 -118 -78 -72 -72 -77 -80 -77 -120 l0 -42
|
||||||
|
80 0 80 0 0 -280 0 -280 -40 0 -40 0 0 -160 0 -160 36 0 35 0 -35 -34 c-32
|
||||||
|
-30 -36 -39 -36 -86 0 -46 4 -56 34 -86 30 -30 40 -34 86 -34 46 0 56 4 86 34
|
||||||
|
21 21 34 44 34 60 0 24 -3 26 -45 26 -32 0 -45 -4 -45 -14 0 -7 -8 -16 -17
|
||||||
|
-18 -53 -14 -58 32 -8 78 19 17 35 41 35 53 0 18 6 21 40 21 l40 0 0 160 0
|
||||||
|
160 -40 0 -40 0 0 280 0 280 520 0 520 0 0 -98 c0 -90 2 -100 23 -120 18 -17
|
||||||
|
36 -22 80 -22 l57 0 0 -640 0 -640 -160 0 -160 0 0 -80 0 -80 480 0 480 0 0
|
||||||
|
80 0 80 -160 0 -160 0 0 640 c0 613 1 640 18 640 10 0 28 10 40 23 19 21 22
|
||||||
|
34 22 120 l0 97 80 0 80 0 0 -80 0 -80 280 0 280 0 0 240 0 240 -113 0 -113 0
|
||||||
|
-316 230 c-320 232 -328 240 -328 303 l0 27 -85 0 c-60 0 -87 -4 -90 -12z
|
||||||
|
m-25 -175 c0 -5 -9 -66 -20 -138 -11 -71 -20 -136 -20 -142 0 -8 -12 -13 -29
|
||||||
|
-13 -55 0 -141 -83 -141 -136 l0 -24 -412 1 c-325 0 -408 3 -388 12 61 30 996
|
||||||
|
446 1003 446 4 1 7 -2 7 -6z m600 -371 l-90 -3 0 -39 0 -40 -80 0 -80 0 0 59
|
||||||
|
c0 52 -3 62 -26 80 -15 12 -34 21 -44 21 -14 0 -20 20 -33 118 -10 64 -17 122
|
||||||
|
-17 129 0 7 103 -63 230 -155 l230 -167 -90 -3z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
19
potain05/assets/icons/site.webmanifest
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"short_name": "",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/icons/android-chrome-192x192.png?v=potain",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/icons/android-chrome-256x256.png?v=potain",
|
||||||
|
"sizes": "256x256",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#ffffff",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
83
potain05/assets/jeu.js
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const GAME_NOT_STARTED = 0;
|
||||||
|
const GAME_STARTED = 1;
|
||||||
|
const GAME_WON = 2;
|
||||||
|
const GAME_LOST = 3;
|
||||||
|
|
||||||
|
let gameState = GAME_NOT_STARTED;
|
||||||
|
|
||||||
|
let zones = undefined;
|
||||||
|
let endTimeout = undefined;
|
||||||
|
let roundTimeout = undefined;
|
||||||
|
let timeBetween = 2000;
|
||||||
|
const MIN_TIME_BETWEEN = 1000;
|
||||||
|
const ACCELERATION = 100;
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
zones = document.getElementsByClassName("zone");
|
||||||
|
for (const zone of zones) {
|
||||||
|
zone.addEventListener("click", event => {
|
||||||
|
if (gameState !== GAME_STARTED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(event.target.classList);
|
||||||
|
if (event.target.classList.contains("inactive")) {
|
||||||
|
gameState = GAME_LOST;
|
||||||
|
end();
|
||||||
|
} else {
|
||||||
|
event.target.style.transition = "";
|
||||||
|
event.target.classList.remove("fade-out");
|
||||||
|
event.target.classList.add("inactive");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
console.log("start!");
|
||||||
|
document.getElementsByTagName("button")[0].disabled = true;
|
||||||
|
gameState = GAME_STARTED;
|
||||||
|
endTimeout = setTimeout(end, 30_000);
|
||||||
|
roundTimeout = setTimeout(round, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function round() {
|
||||||
|
if (gameState !== GAME_STARTED) {
|
||||||
|
end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let zone = zones[Math.floor(Math.random() * zones.length)];
|
||||||
|
zone.classList.remove("inactive");
|
||||||
|
setTimeout(function () {
|
||||||
|
zone.style.transition = `background-color ${timeBetween}ms`;
|
||||||
|
}, 100);
|
||||||
|
setTimeout(function () {
|
||||||
|
zone.classList.add("fade-out");
|
||||||
|
}, MIN_TIME_BETWEEN / 2);
|
||||||
|
let zoneTimeout = setTimeout(() => {
|
||||||
|
if (!zone.classList.contains("inactive")) {
|
||||||
|
console.log("lost because didn't click fast enough", zone.id);
|
||||||
|
gameState = GAME_LOST;
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
}, timeBetween);
|
||||||
|
zone.addEventListener("click", () => {clearTimeout(zoneTimeout)})
|
||||||
|
|
||||||
|
// Recursive call
|
||||||
|
timeBetween -= ACCELERATION;
|
||||||
|
if (timeBetween <= MIN_TIME_BETWEEN) {timeBetween = MIN_TIME_BETWEEN;}
|
||||||
|
roundTimeout = setTimeout(round, timeBetween);
|
||||||
|
}
|
||||||
|
|
||||||
|
function end() {
|
||||||
|
clearTimeout(roundTimeout);
|
||||||
|
clearTimeout(endTimeout);
|
||||||
|
if (gameState === GAME_STARTED) {
|
||||||
|
gameState = GAME_WON;
|
||||||
|
document.getElementsByClassName("success stamp")[0].classList.remove("hidden");
|
||||||
|
} else if (gameState === GAME_LOST) {
|
||||||
|
document.getElementsByClassName("failure stamp")[0].classList.remove("hidden");
|
||||||
|
}
|
||||||
|
}
|
96
potain05/assets/style.css
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
html {
|
||||||
|
height:100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto 1fr auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
background-color: rgb(40,53,131);
|
||||||
|
color: white;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main, footer {
|
||||||
|
max-width: 1600px;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stamp {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 60px;
|
||||||
|
transform: rotate(-20deg);
|
||||||
|
display: inline-block;
|
||||||
|
padding: .2em .5em;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success.stamp {
|
||||||
|
top: 120px;
|
||||||
|
left: 60px;
|
||||||
|
color: #0f5132;
|
||||||
|
background-color: #d1e7dd;
|
||||||
|
border: 3px solid #859a99;
|
||||||
|
}
|
||||||
|
|
||||||
|
.failure.stamp {
|
||||||
|
/* TODO center the stamp */
|
||||||
|
top: 120px;
|
||||||
|
left: 60px;
|
||||||
|
color: #510f0f;
|
||||||
|
background-color: #e7d1d1;
|
||||||
|
border: 3px solid #9a8585;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.failure {
|
||||||
|
color: #a71717;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header h1 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: rgb(40,53,131);
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-holder {
|
||||||
|
position: relative;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-holder .zone {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-holder .zone.inactive,
|
||||||
|
.img-holder .zone.fade-out {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
BIN
potain05/images/fond.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
49
potain05/index.html
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Potain de chantier #5</title>
|
||||||
|
<link rel="stylesheet" href="assets/style.css">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="assets/icons/apple-touch-icon.png?v=potain">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="assets/icons/favicon-32x32.png?v=potain">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="assets/icons/favicon-16x16.png?v=potain">
|
||||||
|
<link rel="manifest" href="assets/icons/site.webmanifest?v=potain">
|
||||||
|
<link rel="mask-icon" href="assets/icons/safari-pinned-tab.svg?v=potain" color="#5bbad5">
|
||||||
|
<link rel="shortcut icon" href="assets/icons/favicon.ico?v=potain">
|
||||||
|
<meta name="msapplication-TileColor" content="#da532c">
|
||||||
|
<meta name="msapplication-config" content="assets/icons/browserconfig.xml?v=potain">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
<meta property="og:image" content="https://static.augendre.info/potain3/images/fond.png">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Potain de chantier #5</h1>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<h2>Jeu interactif</h2>
|
||||||
|
<p>
|
||||||
|
Aide Pimpin le technicien à reboucher les fuites ! <br>
|
||||||
|
<button onclick="start()">Commencer</button>
|
||||||
|
</p>
|
||||||
|
<div class="img-holder">
|
||||||
|
<img src="images/fond.png" width="727" height="330" alt="Plan Cecolyon">
|
||||||
|
<div id="bureau-1" class="zone inactive" style="width:50px; height: 50px; top: 0; left: 0;"></div>
|
||||||
|
<div id="bureau-2" class="zone inactive" style="width:50px; height: 50px; top: 55px; left: 0;"></div>
|
||||||
|
<div id="bureau-3" class="zone inactive" style="width:50px; height: 50px; top: 0; left: 55px;"></div>
|
||||||
|
<div id="bureau-4" class="zone inactive" style="width:50px; height: 50px; top: 55px; left: 55px;"></div>
|
||||||
|
<span class="success stamp hidden">FÉLICITATIONS 🎉</span>
|
||||||
|
<span class="failure stamp hidden">PERDU 😞</span>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<footer>
|
||||||
|
<p>
|
||||||
|
Made with ♥ by <a href="https://gabnotes.org/about-me/">Gabriel Augendre</a>.
|
||||||
|
Ce programme est un <a href="https://fr.wikipedia.org/wiki/Logiciel_libre">logiciel libre</a>.
|
||||||
|
<a href="https://git.augendre.info/gaugendre/potain">Code source</a>.
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
<script src="assets/jeu.js"></script>
|
||||||
|
<!--<script data-goatcounter="https://static.gc.augendre.info/count"-->
|
||||||
|
<!-- async src="https://static.gc.augendre.info/count.js"></script>-->
|
||||||
|
</body>
|
||||||
|
</html>
|