Merge front & back
This commit is contained in:
parent
9108f2e726
commit
829926dddf
6 changed files with 140 additions and 18 deletions
11
index.html
11
index.html
|
@ -4,6 +4,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>KyFlo Snake</title>
|
<title>KyFlo Snake</title>
|
||||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
|
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="sources/css/style.css">
|
<link rel="stylesheet" type="text/css" href="sources/css/style.css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
@ -14,13 +15,13 @@
|
||||||
<div class="col s10 offset-s1" style="padding: 0">
|
<div class="col s10 offset-s1" style="padding: 0">
|
||||||
<input type="text" id="nickname" placeholder="Choose a nickname :">
|
<input type="text" id="nickname" placeholder="Choose a nickname :">
|
||||||
</div>
|
</div>
|
||||||
<button class="col s8 offset-s2">Level 1</button>
|
<div class="menu-level col s12 row">
|
||||||
<button class="col s8 offset-s2">Level 2</button>
|
</div>
|
||||||
<button class="col s8 offset-s2">Level 3</button>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<canvas></canvas>
|
<div id="game">
|
||||||
|
<canvas id="canvas" class="invisible"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script type="module" src="sources/js/index.js"></script>
|
<script type="module" src="sources/js/index.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
html{
|
html{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
body{
|
body{
|
||||||
|
@ -26,7 +30,7 @@ h1{
|
||||||
#menu{
|
#menu{
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-top: 150px;
|
margin-top: 150px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#menu>div{
|
#menu>div{
|
||||||
|
@ -58,16 +62,16 @@ h1{
|
||||||
background-color: rgba(0, 0, 0, 0.8);
|
background-color: rgba(0, 0, 0, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
.linear-wipe {
|
.linear-wipe {
|
||||||
background: linear-gradient(to right, rgb(255, 136, 0) 20%, #FF0 40%, #FF0 45%, rgb(255, 136, 0) 80%);
|
background: linear-gradient(to right, #FF4294 20%, #d919ff 35%, #3af8ff 40%, #d919ff 65%, #FF4294 80%);
|
||||||
background-size: 200% auto;
|
background-size: 200% auto;
|
||||||
|
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
text-fill-color: transparent;
|
text-fill-color: transparent;
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
|
|
||||||
animation: shine 1s linear infinite;
|
animation: shine 1.5s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes shine {
|
@keyframes shine {
|
||||||
|
@ -94,3 +98,59 @@ h1{
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-level{
|
||||||
|
height: 25vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-button {
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: #FF4294;
|
||||||
|
border: 0px none #ffffff;
|
||||||
|
border-radius: 0px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #FF4294;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-thumb:active {
|
||||||
|
background: #a800a3;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: #000000;
|
||||||
|
border: 0px none #ffffff;
|
||||||
|
border-radius: 50px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-track:hover {
|
||||||
|
background: #000000;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-track:active {
|
||||||
|
background: #000000;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-corner {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
#canvas {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
border: 3px double rgb(0, 255, 200);
|
||||||
|
color: rgb(0, 255, 200);
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.invisible{
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#game{
|
||||||
|
height: 75vh;
|
||||||
|
width: 75vh;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ export class Game {
|
||||||
throw new InvalidGameOption("size");
|
throw new InvalidGameOption("size");
|
||||||
|
|
||||||
if (direction && Object.values(directions).find(([x,y]) => direction[0] === x && direction[1] === y))
|
if (direction && Object.values(directions).find(([x,y]) => direction[0] === x && direction[1] === y))
|
||||||
this.direction = this.lastDirection = direction;
|
this.direction = this.startDirection = this.lastDirection = direction;
|
||||||
else
|
else
|
||||||
throw new InvalidGameOption("direction");
|
throw new InvalidGameOption("direction");
|
||||||
|
|
||||||
|
@ -42,6 +42,8 @@ export class Game {
|
||||||
this.apple = false;
|
this.apple = false;
|
||||||
this.score = 0;
|
this.score = 0;
|
||||||
this.lives = lives;
|
this.lives = lives;
|
||||||
|
this.onStart = null;
|
||||||
|
this.onStop = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,9 +62,6 @@ export class Game {
|
||||||
* Init the canvas
|
* Init the canvas
|
||||||
*/
|
*/
|
||||||
initCanvas() {
|
initCanvas() {
|
||||||
this.ctx.canvas.width = window.innerWidth;
|
|
||||||
this.ctx.canvas.height = window.innerHeight;
|
|
||||||
|
|
||||||
this.ctx.canvas.ownerDocument.addEventListener("keyup", ev => {
|
this.ctx.canvas.ownerDocument.addEventListener("keyup", ev => {
|
||||||
switch (ev.key) {
|
switch (ev.key) {
|
||||||
case "ArrowUp":
|
case "ArrowUp":
|
||||||
|
@ -98,6 +97,10 @@ export class Game {
|
||||||
* Start the party
|
* Start the party
|
||||||
*/
|
*/
|
||||||
start() {
|
start() {
|
||||||
|
if (this.onStart && typeof this.onStart === "function")
|
||||||
|
this.onStart();
|
||||||
|
|
||||||
|
this.direction = this.lastDirection = this.startDirection;
|
||||||
this.snake = new Snake({startPos: this.size.map(s => Math.floor(s/2))});
|
this.snake = new Snake({startPos: this.size.map(s => Math.floor(s/2))});
|
||||||
|
|
||||||
this.initWorld();
|
this.initWorld();
|
||||||
|
@ -120,6 +123,8 @@ export class Game {
|
||||||
this.ctx.globalCompositeOperation = "destination-out";
|
this.ctx.globalCompositeOperation = "destination-out";
|
||||||
this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
||||||
this.ctx.globalCompositeOperation = "source-over";
|
this.ctx.globalCompositeOperation = "source-over";
|
||||||
|
if (this.onStop && typeof this.onStop === "function")
|
||||||
|
this.onStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -44,7 +44,7 @@ export class Tile {
|
||||||
|
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case tiles.EMPTY:
|
case tiles.EMPTY:
|
||||||
this.game.ctx.strokeStyle = "#000000";
|
this.game.ctx.strokeStyle = "#999999";
|
||||||
this.game.ctx.rect(...canvasPos, ...size);
|
this.game.ctx.rect(...canvasPos, ...size);
|
||||||
break;
|
break;
|
||||||
case tiles.APPLE:
|
case tiles.APPLE:
|
||||||
|
|
|
@ -1,8 +1,59 @@
|
||||||
import { Game } from "./Game.js"
|
import { Game } from "./Game.js"
|
||||||
|
const req = new XMLHttpRequest();
|
||||||
|
const canvas = document.getElementById("canvas");
|
||||||
|
const menu = document.getElementById("menu");
|
||||||
|
const menuLevel = document.querySelector(".menu-level");
|
||||||
|
const gameZone = document.getElementById("game");
|
||||||
|
let game;
|
||||||
|
|
||||||
|
req.open("GET", "sources/levels.json");
|
||||||
|
req.onerror = () => console.error("Fail to load XML request");
|
||||||
|
|
||||||
|
req.onload = () => {
|
||||||
|
let levels;
|
||||||
|
if (req.status === 200)
|
||||||
|
levels = JSON.parse(req.responseText);
|
||||||
|
else
|
||||||
|
levels = null;
|
||||||
|
loadLevels(levels);
|
||||||
|
}
|
||||||
|
|
||||||
|
req.send();
|
||||||
|
|
||||||
|
function loadLevels(levels) {
|
||||||
|
if (!levels) {
|
||||||
|
menuLevel.innerHTML = "";
|
||||||
|
menuLevel.insertAdjacentHTML("beforeend", "<button class=\"col s8 offset-s2\" disabled>Fail to load levels :/</button>")
|
||||||
|
} else {
|
||||||
|
for (const [name, level] of Object.entries(levels)) {
|
||||||
|
const b = document.createElement("button");
|
||||||
|
b.classList.add("col", "s8", "offset-s2");
|
||||||
|
b.innerText = name;
|
||||||
|
menuLevel.insertAdjacentElement("beforeend", b);
|
||||||
|
b.addEventListener("click", () => loadGame(level))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadGame = data => {
|
||||||
|
game = new Game(canvas, data);
|
||||||
|
|
||||||
|
game.onStart = () => {
|
||||||
|
menu.classList.add("invisible");
|
||||||
|
canvas.classList.remove("invisible");
|
||||||
|
};
|
||||||
|
|
||||||
|
game.onStop = () => {
|
||||||
|
menu.classList.remove("invisible");
|
||||||
|
canvas.classList.add("invisible");
|
||||||
|
};
|
||||||
|
|
||||||
|
game.start();
|
||||||
|
};
|
||||||
|
|
||||||
const game = new Game(document.getElementById("canvas"), {snakeSpeed: 200});
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
M.AutoInit();
|
M.AutoInit();
|
||||||
game.start();
|
canvas.width = gameZone.offsetWidth;
|
||||||
|
canvas.height = gameZone.offsetHeight;
|
||||||
});
|
});
|
||||||
|
|
5
sources/levels.json
Normal file
5
sources/levels.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"Level 1": {
|
||||||
|
"snakeSpeed": 500
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue