Compare commits
10 Commits
3201c32eac
...
9d3f4714d2
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9d3f4714d2 | ||
![]() |
4a8299e5a6 | ||
![]() |
f70c427095 | ||
![]() |
154ef7f486 | ||
![]() |
2d34f975bc | ||
![]() |
d8dcb08a46 | ||
![]() |
60f424ce1e | ||
![]() |
f26e4c553a | ||
![]() |
2052f8ed3b | ||
![]() |
02b55431a3 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -148,3 +148,5 @@ fastdeliver.db
|
|||||||
api.http
|
api.http
|
||||||
|
|
||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
|
datas
|
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"elle",
|
||||||
|
"fixée"
|
||||||
|
]
|
||||||
|
}
|
187
index.js
187
index.js
@ -1,4 +1,36 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
|
import sqlite3 from 'sqlite3';
|
||||||
|
import { open } from 'sqlite';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
|
// Déclaration de la variable db pour qu'elle soit accessible dans tout le script
|
||||||
|
let db;
|
||||||
|
|
||||||
|
// Fonction pour initialiser la base de données
|
||||||
|
async function initializeDatabase() {
|
||||||
|
// open the database - SQLite créera automatiquement le fichier s'il n'existe pas
|
||||||
|
db = await open({
|
||||||
|
filename: './datas/database.db',
|
||||||
|
driver: sqlite3.Database
|
||||||
|
});
|
||||||
|
|
||||||
|
// Créer les tables nécessaires si elles n'existent pas
|
||||||
|
await db.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS scores (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
player_name TEXT,
|
||||||
|
score INTEGER,
|
||||||
|
pathHistory TEXT,
|
||||||
|
date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
|
||||||
|
console.log('Database initialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeDatabase().catch(err => {
|
||||||
|
console.error('Error initializing database:', err);
|
||||||
|
});
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const port = 3000;
|
const port = 3000;
|
||||||
@ -6,6 +38,161 @@ const port = 3000;
|
|||||||
app.use(express.static('public'));
|
app.use(express.static('public'));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
|
app.get('/', (req, res) => {
|
||||||
|
res.sendFile('index.html', { root: '.' });
|
||||||
|
});
|
||||||
|
|
||||||
|
const templatePiece = [
|
||||||
|
[ // ok
|
||||||
|
[3, 0],
|
||||||
|
[4, 0],
|
||||||
|
[5, 0],
|
||||||
|
[6, 0],
|
||||||
|
[4.5, 0.5]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[3, 1],
|
||||||
|
[4, 1],
|
||||||
|
[5, 1],
|
||||||
|
[5, 0],
|
||||||
|
[4, 1]
|
||||||
|
],
|
||||||
|
[ // ok
|
||||||
|
[3, 1],
|
||||||
|
[4, 1],
|
||||||
|
[5, 1],
|
||||||
|
[3, 0],
|
||||||
|
[4, 1]
|
||||||
|
],
|
||||||
|
[ // ok
|
||||||
|
[3, 0],
|
||||||
|
[4, 0],
|
||||||
|
[4, 1],
|
||||||
|
[5, 1],
|
||||||
|
[4, 1]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[3, 1],
|
||||||
|
[4, 1],
|
||||||
|
[4, 0],
|
||||||
|
[5, 0],
|
||||||
|
[4, 1]
|
||||||
|
],
|
||||||
|
[ // ok
|
||||||
|
[3, 0],
|
||||||
|
[4, 0],
|
||||||
|
[4, 1],
|
||||||
|
[5, 0],
|
||||||
|
[4, 0]
|
||||||
|
],
|
||||||
|
[ // ok
|
||||||
|
[4, 0],
|
||||||
|
[5, 0],
|
||||||
|
[4, 1],
|
||||||
|
[5, 1],
|
||||||
|
[4.5, 0.5]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
const templateColor = [
|
||||||
|
[240, 87, 84, 255],
|
||||||
|
[254, 223, 92, 255],
|
||||||
|
[27, 148, 118, 255],
|
||||||
|
[36, 115, 155, 255],
|
||||||
|
[106, 190, 178, 255],
|
||||||
|
[164, 199, 218, 255],
|
||||||
|
[177, 225, 218, 255]
|
||||||
|
];
|
||||||
|
|
||||||
|
app.put('/api/sendScore', (req, res) => {
|
||||||
|
|
||||||
|
let score = req.body.score;
|
||||||
|
// let history = req.body.history;
|
||||||
|
let lines = req.body.lines;
|
||||||
|
let playerName = req.body.playerName;
|
||||||
|
|
||||||
|
// Vérifier si le score est un nombre valide
|
||||||
|
if (isNaN(score) || score < 0) {
|
||||||
|
return res.status(400).send('Invalid score');
|
||||||
|
}
|
||||||
|
// Vérifier si l'historique est un tableau valide
|
||||||
|
// if (!Array.isArray(history)) {
|
||||||
|
// return res.status(400).send('Invalid history');
|
||||||
|
// }
|
||||||
|
// Vérifier si le nom du joueur est une chaîne de caractères valide
|
||||||
|
if (typeof playerName !== 'string' || playerName.trim() === '') {
|
||||||
|
return res.status(400).send('Invalid player name');
|
||||||
|
}
|
||||||
|
// Vérifier si le score est supérieur à 0 et inférieur à 1200 * (lines/4)
|
||||||
|
if ((lines/4) * 1200 < score) {
|
||||||
|
return res.status(400).send('Invalid score');
|
||||||
|
}
|
||||||
|
// Vérifier si la line est un nombre valide
|
||||||
|
if (isNaN(lines) || lines < 0) {
|
||||||
|
return res.status(400).send('Invalid lines');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier si le dossier des historiques existe, le créer si nécessaire
|
||||||
|
// const historyDir = './datas/histories';
|
||||||
|
// if (!fs.existsSync(historyDir)) {
|
||||||
|
// fs.mkdirSync(historyDir, { recursive: true });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Date du jour
|
||||||
|
|
||||||
|
// const date = new Date();
|
||||||
|
// const dateString = date.toISOString().split('T')[0]; // Format YYYY-MM-DD
|
||||||
|
|
||||||
|
// // Vérifier si un fichier avec ce nom existe déjà et ajouter un chiffre si nécessaire
|
||||||
|
// let finalPlayerName = playerName + dateString;
|
||||||
|
// let counter = 0;
|
||||||
|
// let historyFilePath = `${historyDir}/${finalPlayerName}.json`;
|
||||||
|
|
||||||
|
// while (fs.existsSync(historyFilePath)) {
|
||||||
|
// counter++;
|
||||||
|
// finalPlayerName = `${playerName}${dateString}${counter}`;
|
||||||
|
// historyFilePath = `${historyDir}/${finalPlayerName}.json`;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Écrire l'historique dans le fichier
|
||||||
|
// try {
|
||||||
|
// fs.writeFileSync(historyFilePath, JSON.stringify(history));
|
||||||
|
// console.log(`History written to ${historyFilePath}`);
|
||||||
|
// } catch (err) {
|
||||||
|
// console.error('Error writing history file:', err);
|
||||||
|
// return res.status(500).send('Error writing history file');
|
||||||
|
// }
|
||||||
|
|
||||||
|
//
|
||||||
|
db.run('INSERT INTO scores (player_name, score, pathHistory) VALUES (?, ?, ?)', [playerName, score, "/"])
|
||||||
|
.then(() => {
|
||||||
|
console.log(`Score inserted for ${playerName}`);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
console.log('History path inserted in database');
|
||||||
|
res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
playerName: playerName,
|
||||||
|
message: 'Score and history saved'
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('Database error:', err);
|
||||||
|
res.status(500).send('Error inserting data');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/api/getHighScores', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const scores = await db.all('SELECT player_name, score FROM scores ORDER BY score DESC LIMIT 10');
|
||||||
|
res.json(scores);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Database error:', err);
|
||||||
|
res.status(500).send('Error retrieving high scores');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
app.listen(port, () => {
|
app.listen(port, () => {
|
||||||
console.log(`Server listening at http://localhost:${port}`);
|
console.log(`Server listening at http://localhost:${port}`);
|
||||||
});
|
});
|
||||||
|
1457
package-lock.json
generated
1457
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,9 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.21.2"
|
"express": "^4.21.2",
|
||||||
|
"sqlite": "^5.1.1",
|
||||||
|
"sqlite3": "^5.1.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"nodemon": "^3.1.9"
|
"nodemon": "^3.1.9"
|
||||||
|
BIN
public/font/Pixeboy-z8XGD.ttf
Normal file
BIN
public/font/Pixeboy-z8XGD.ttf
Normal file
Binary file not shown.
BIN
public/img/pause.png
Normal file
BIN
public/img/pause.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 376 B |
@ -4,41 +4,82 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>Tetris on the web</title>
|
<title>Tetris on the web</title>
|
||||||
<script src="./script/index.js" defer></script>
|
<script src="./script/element.js" defer></script>
|
||||||
|
<script src="./script/var.js" defer></script>
|
||||||
|
<script src="./script/displayGameFunction.js" defer></script>
|
||||||
|
<script src="./script/displayMenuFunction.js" defer></script>
|
||||||
|
<script src="./script/contruct.js" defer></script>
|
||||||
|
<script src="./script/magicVariable.js" defer></script>
|
||||||
|
<script src="./script/gameFunction.js" defer></script>
|
||||||
|
<script src="./script/controller.js" defer></script>
|
||||||
|
<script src="./script/menuController.js" defer></script>
|
||||||
<link rel="stylesheet" href="./style/index.css" />
|
<link rel="stylesheet" href="./style/index.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<template id="high-score-template">
|
||||||
|
<div class="high-score">
|
||||||
|
<span class="high-score-name"></span>
|
||||||
|
<span class="high-score-score"></span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="frame scoreboard">
|
||||||
|
<p>High Scores</p>
|
||||||
|
<div id="high-scores-container">
|
||||||
|
<div id="high-scores-list" class="high-scores-list">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div id="left-part" class="first">
|
<div id="left-part" class="first">
|
||||||
<p>
|
<p class="frame">
|
||||||
Score:
|
Score:
|
||||||
<span id="score-value">0</span>
|
<span id="score-value">0</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="tetris" class="tetris">
|
<div id="tetris" class="frame tetris">
|
||||||
<canvas class="hidden" id="tetris-canvas" width="300" height="600"></canvas>
|
<div class="hidden" id="board-container">
|
||||||
<div class="main-menu hidden" id="main-menu" >
|
<canvas id="tetris-canvas" width="300" height="600"></canvas>
|
||||||
<button id="start-button">Start</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="gameOver hidden">
|
<div class="main-menu menu" id="main-menu" >
|
||||||
|
<label id="start-button" class="button">Start</label>
|
||||||
|
</div>
|
||||||
|
<div class="gameOver-menu menu hidden" id="game-over-menu">
|
||||||
<p>Game Over</p>
|
<p>Game Over</p>
|
||||||
<button id="restart-button">Restart</button>
|
<label id="restart-button" class="button">Restart</label>
|
||||||
<button id="main-menu">Main Menu</button>
|
<label id="main-menu-button2">Main Menu</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="pause hidden" id="pause-menu">
|
<div class="pause-menu menu hidden" id="pause-menu">
|
||||||
<p>Paused</p>
|
<p>Paused</p>
|
||||||
<button id="resume-button">Resume</button>
|
<label id="resume-button" class="button">Resume</label>
|
||||||
<button id="main-menu">Main Menu</button>
|
<label id="main-menu-button" class="button">Main Menu</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="load-menu" id="load-menu">
|
<div class="load-menu menu hidden" id="load-menu">
|
||||||
<span class="loader"></span>
|
<span class="loader"></span>
|
||||||
<p>Loading...</p>
|
<p>Loading...</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="last"></div>
|
<div class="last">
|
||||||
|
<div class="frame">
|
||||||
|
<p>Next</p>
|
||||||
|
<div id="preview-container">
|
||||||
|
<canvas id="preview-canvas" width="100" height="100"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="frame pauseContainer" id="pause-container">
|
||||||
|
<div id="pause-button" class="icon play-pause">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="options">
|
||||||
|
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
149
public/script/controller.js
Normal file
149
public/script/controller.js
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
|
||||||
|
function initGame() {
|
||||||
|
displayGameBoard();
|
||||||
|
|
||||||
|
game = getGame();
|
||||||
|
|
||||||
|
setSpeed(game);
|
||||||
|
|
||||||
|
initOrChangeDropInterval(game.speed);
|
||||||
|
|
||||||
|
|
||||||
|
// On rafraichit le plateau toutes les 16ms (environ 60 FPS)
|
||||||
|
refreshInterval = setInterval(() => {
|
||||||
|
refreshBoard(game.board);
|
||||||
|
displayPreview(game);
|
||||||
|
scoreElement.innerText = game.score;
|
||||||
|
}, 16);
|
||||||
|
|
||||||
|
history = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function initOrChangeDropInterval(speed) {
|
||||||
|
if (dropInterval) {
|
||||||
|
clearInterval(dropInterval);
|
||||||
|
}
|
||||||
|
dropInterval = setInterval(() => {
|
||||||
|
dropPiece();
|
||||||
|
}, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveDownWithCheck(game) {
|
||||||
|
let piece = game.currentPiece;
|
||||||
|
|
||||||
|
if (ifMoveDown(piece, game)) {
|
||||||
|
opacityCurrentPiece = 1;
|
||||||
|
|
||||||
|
clearInterval(endDropInterval);
|
||||||
|
|
||||||
|
endDropInterval = null;
|
||||||
|
|
||||||
|
moveDown(piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkEnDrop(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkEnDrop(game) {
|
||||||
|
if (ifMoveDown(game.currentPiece, game)) {
|
||||||
|
opacityCurrentPiece = 1;
|
||||||
|
|
||||||
|
clearInterval(endDropInterval);
|
||||||
|
|
||||||
|
endDropInterval = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
endDrop(game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function dropPiece() {
|
||||||
|
moveDownWithCheck(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pauseGame() {
|
||||||
|
if (game.paused) {
|
||||||
|
game.paused = false;
|
||||||
|
initOrChangeDropInterval(game.speed);
|
||||||
|
refreshInterval = setInterval(() => {
|
||||||
|
refreshBoard(game.board);
|
||||||
|
displayPreview(game);
|
||||||
|
}, 16);
|
||||||
|
|
||||||
|
displayGameBoard();
|
||||||
|
} else {
|
||||||
|
game.paused = true;
|
||||||
|
clearInterval(dropInterval);
|
||||||
|
clearInterval(refreshInterval);
|
||||||
|
dropInterval = null;
|
||||||
|
refreshInterval = null;
|
||||||
|
endDropInterval = null;
|
||||||
|
|
||||||
|
displayPause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
document.addEventListener('keydown', (event) => {
|
||||||
|
if (event.key == 'Escape' && !keyPress.includes('Escape')) {
|
||||||
|
pauseGame();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (game.paused) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (game.gameOver) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((event.key == 'ArrowUp' || event.key == 'w' || event.key == 'z') && !keyPress.includes('ArrowUp') && !keyPress.includes('w') && !keyPress.includes('z')) {
|
||||||
|
rotatePiece(game.currentPiece);
|
||||||
|
checkEnDrop(game);
|
||||||
|
|
||||||
|
} else if ((event.key == 'ArrowDown' || event.key == 's') && !keyPress.includes('ArrowDown') && !keyPress.includes('s')) {
|
||||||
|
initOrChangeDropInterval(60);
|
||||||
|
} else if ((event.key == 'ArrowLeft' || event.key == 'a' || event.key == 'q') && !keyPress.includes('ArrowLeft') && !keyPress.includes('q') && !keyPress.includes('a')) {
|
||||||
|
moveLeft(game.currentPiece);
|
||||||
|
checkEnDrop(game);
|
||||||
|
|
||||||
|
leftInterval = setInterval(() => {
|
||||||
|
moveLeft(game.currentPiece);
|
||||||
|
checkEnDrop(game);
|
||||||
|
|
||||||
|
}, 100);
|
||||||
|
} else if (((event.key == 'ArrowRight') || event.key == 'd') && !keyPress.includes('ArrowRight') && !keyPress.includes('d')) {
|
||||||
|
moveRight(game.currentPiece);
|
||||||
|
|
||||||
|
checkEnDrop(game);
|
||||||
|
|
||||||
|
|
||||||
|
rightInterval = setInterval(() => {
|
||||||
|
moveRight(game.currentPiece);
|
||||||
|
|
||||||
|
checkEnDrop(game);
|
||||||
|
|
||||||
|
}, 100);
|
||||||
|
} else if (event.key == ' ' && !keyPress.includes(' ')) {
|
||||||
|
fastDrop(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(event.key);
|
||||||
|
|
||||||
|
keyPress.push(event.key);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('keyup', (event) => {
|
||||||
|
if (!game.paused && !game.gameOver) {
|
||||||
|
if (event.key == 'ArrowDown' || event.key == 's') {
|
||||||
|
initOrChangeDropInterval(game.speed);
|
||||||
|
} else if (event.key == 'ArrowLeft' || event.key == 'a' || event.key == 'q') {
|
||||||
|
clearInterval(leftInterval);
|
||||||
|
} else if (event.key == 'ArrowRight' || event.key == 'd') {
|
||||||
|
clearInterval(rightInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keyPress = keyPress.filter((key) => {
|
||||||
|
return key != event.key;
|
||||||
|
});
|
||||||
|
});
|
160
public/script/contruct.js
Normal file
160
public/script/contruct.js
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
function getGame() {
|
||||||
|
return {
|
||||||
|
board: [],
|
||||||
|
currentPiece: getRandomPiece(),
|
||||||
|
nextPiece: getRandomPiece(),
|
||||||
|
score: 0,
|
||||||
|
level: 1,
|
||||||
|
speed: 1000,
|
||||||
|
lines: 0,
|
||||||
|
linesCleared: 0,
|
||||||
|
paused: false,
|
||||||
|
gameOver: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColor(r, g, b) {
|
||||||
|
return {
|
||||||
|
red: r,
|
||||||
|
green: g,
|
||||||
|
blue: b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSquare(xPos, yPos, c) {
|
||||||
|
return {
|
||||||
|
color: c,
|
||||||
|
x: xPos,
|
||||||
|
y: yPos
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBarPiece() {
|
||||||
|
return {
|
||||||
|
squares: [
|
||||||
|
getSquare(3, 0, getColor(240, 87, 84)),
|
||||||
|
getSquare(4, 0, getColor(240, 87, 84)),
|
||||||
|
getSquare(5, 0, getColor(240, 87, 84)),
|
||||||
|
getSquare(6, 0, getColor(240, 87, 84))
|
||||||
|
],
|
||||||
|
xCenter: 4.5,
|
||||||
|
yCenter: 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLPiece() {
|
||||||
|
return {
|
||||||
|
squares: [
|
||||||
|
getSquare(3, 1, getColor(254, 223, 92)),
|
||||||
|
getSquare(4, 1, getColor(254, 223, 92)),
|
||||||
|
getSquare(5, 1, getColor(254, 223, 92)),
|
||||||
|
getSquare(5, 0, getColor(254, 223, 92))
|
||||||
|
],
|
||||||
|
xCenter: 4,
|
||||||
|
yCenter: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getJPiece() {
|
||||||
|
return {
|
||||||
|
squares: [
|
||||||
|
getSquare(3, 1, getColor(27, 148, 118)),
|
||||||
|
getSquare(4, 1, getColor(27, 148, 118)),
|
||||||
|
getSquare(5, 1, getColor(27, 148, 118)),
|
||||||
|
getSquare(3, 0, getColor(27, 148, 118))
|
||||||
|
],
|
||||||
|
xCenter: 4,
|
||||||
|
yCenter: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTPiece() {
|
||||||
|
return {
|
||||||
|
squares: [
|
||||||
|
getSquare(3, 1, getColor(36, 115, 155)),
|
||||||
|
getSquare(4, 1, getColor(36, 115, 155)),
|
||||||
|
getSquare(5, 1, getColor(36, 115, 155)),
|
||||||
|
getSquare(4, 0, getColor(36, 115, 155))
|
||||||
|
],
|
||||||
|
xCenter: 4,
|
||||||
|
yCenter: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getZPiece() {
|
||||||
|
return {
|
||||||
|
squares: [
|
||||||
|
getSquare(3, 1, getColor(106, 190, 178)),
|
||||||
|
getSquare(4, 1, getColor(106, 190, 178)),
|
||||||
|
getSquare(4, 0, getColor(106, 190, 178)),
|
||||||
|
getSquare(5, 0, getColor(106, 190, 178))
|
||||||
|
],
|
||||||
|
xCenter: 4,
|
||||||
|
yCenter: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSPiece() {
|
||||||
|
return {
|
||||||
|
squares: [
|
||||||
|
getSquare(3, 0, getColor(164, 199, 218)),
|
||||||
|
getSquare(4, 0, getColor(164, 199, 218)),
|
||||||
|
getSquare(4, 1, getColor(164, 199, 218)),
|
||||||
|
getSquare(5, 1, getColor(164, 199, 218))
|
||||||
|
],
|
||||||
|
xCenter: 4,
|
||||||
|
yCenter: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSquarePiece() {
|
||||||
|
return {
|
||||||
|
squares: [
|
||||||
|
getSquare(3, 0, getColor(177, 225, 218)),
|
||||||
|
getSquare(4, 0, getColor(177, 225, 218)),
|
||||||
|
getSquare(3, 1, getColor(177, 225, 218)),
|
||||||
|
getSquare(4, 1, getColor(177, 225, 218))
|
||||||
|
],
|
||||||
|
xCenter: 3.5,
|
||||||
|
yCenter: 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPiece(type) {
|
||||||
|
switch (type) {
|
||||||
|
case 'bar':
|
||||||
|
return getBarPiece();
|
||||||
|
case 'L':
|
||||||
|
return getLPiece();
|
||||||
|
case 'J':
|
||||||
|
return getJPiece();
|
||||||
|
case 'T':
|
||||||
|
return getTPiece();
|
||||||
|
case 'Z':
|
||||||
|
return getZPiece();
|
||||||
|
case 'S':
|
||||||
|
return getSPiece();
|
||||||
|
case 'square':
|
||||||
|
return getSquarePiece();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRandomPiece() {
|
||||||
|
const pieces = ['bar', 'L', 'J', 'T', 'Z', 'S', 'square'];
|
||||||
|
const randomIndex = Math.floor(Math.random() * pieces.length);
|
||||||
|
return getPiece(pieces[randomIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clonePiece(piece) {
|
||||||
|
let newSquares = piece.squares.map(square => ({
|
||||||
|
color: { ...square.color },
|
||||||
|
x: square.x,
|
||||||
|
y: square.y
|
||||||
|
}));
|
||||||
|
|
||||||
|
return {
|
||||||
|
squares: newSquares,
|
||||||
|
xCenter: piece.xCenter,
|
||||||
|
yCenter: piece.yCenter
|
||||||
|
};
|
||||||
|
}
|
166
public/script/displayGameFunction.js
Normal file
166
public/script/displayGameFunction.js
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
let boardContext = board.getContext('2d');
|
||||||
|
let previewContext = preview.getContext('2d');
|
||||||
|
|
||||||
|
function clearBoard() {
|
||||||
|
// Ajouter un motif subtil en arrière-plan
|
||||||
|
|
||||||
|
boardContainer.innerHTML = '';
|
||||||
|
board = boardBis.cloneNode(true);
|
||||||
|
boardContainer.appendChild(board);
|
||||||
|
|
||||||
|
boardContext = board.getContext('2d');
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
for (let j = 0; j < 20; j++) {
|
||||||
|
if ((i + j) % 2 === 0) {
|
||||||
|
boardContext.fillStyle = '#6d728020'; // Encore plus sombre
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
boardContext.fillStyle = '#3d425020'; // Presque noir-bleuté
|
||||||
|
}
|
||||||
|
boardContext.fillRect(
|
||||||
|
i * board.width/10,
|
||||||
|
j * board.height/20,
|
||||||
|
board.width/10,
|
||||||
|
board.height/20
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawGrid() {
|
||||||
|
boardContext.strokeStyle = 'gray'; // Couleur des lignes du quadrillage
|
||||||
|
boardContext.lineWidth = 0.5; // Épaisseur des lignes
|
||||||
|
|
||||||
|
// Dessiner les lignes verticales
|
||||||
|
for (let x = 0; x <= board.width; x += board.width / 10) {
|
||||||
|
boardContext.beginPath();
|
||||||
|
boardContext.moveTo(x, 0);
|
||||||
|
boardContext.lineTo(x, board.height);
|
||||||
|
boardContext.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dessiner les lignes horizontales
|
||||||
|
for (let y = 0; y <= board.height; y += board.height / 20) {
|
||||||
|
boardContext.beginPath();
|
||||||
|
boardContext.moveTo(0, y);
|
||||||
|
boardContext.lineTo(board.width, y);
|
||||||
|
boardContext.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawCurrentPiece() {
|
||||||
|
let piece = game.currentPiece;
|
||||||
|
let squares = piece.squares;
|
||||||
|
|
||||||
|
for (let i = 0; i < squares.length; i++) {
|
||||||
|
let square = squares[i];
|
||||||
|
drawSquare(square.x, square.y, square, opacityCurrentPiece);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawSquare(x, y, square, opacity = 1) {
|
||||||
|
let color = square.color;
|
||||||
|
|
||||||
|
boardContext.fillStyle = '#303f4f'; // Couleur de fond
|
||||||
|
boardContext.fillRect(
|
||||||
|
x * board.width/10,
|
||||||
|
y * board.height/20,
|
||||||
|
board.width/10,
|
||||||
|
board.height/20
|
||||||
|
);
|
||||||
|
|
||||||
|
let margin = 3;
|
||||||
|
|
||||||
|
boardContext.fillStyle = `rgba(${color.red}, ${color.green}, ${color.blue}, ${opacity})`;
|
||||||
|
boardContext.fillRect(
|
||||||
|
x * board.width/10 + margin,
|
||||||
|
y * board.height/20 + margin,
|
||||||
|
board.width/10 - margin * 2,
|
||||||
|
board.height/20 - margin * 2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshBoard() {
|
||||||
|
clearBoard();
|
||||||
|
drawGrid();
|
||||||
|
|
||||||
|
for (let i = 0; i < game.board.length; i++) {
|
||||||
|
let square = game.board[i];
|
||||||
|
drawSquare(square.x, square.y, square);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawHologram();
|
||||||
|
drawCurrentPiece();
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawHologram() {
|
||||||
|
let pieceBis = clonePiece(game.currentPiece);
|
||||||
|
|
||||||
|
while (ifMoveDown(pieceBis, game)) {
|
||||||
|
moveDown(pieceBis);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < pieceBis.squares.length; i++) {
|
||||||
|
let square = pieceBis.squares[i];
|
||||||
|
drawSquare(square.x, square.y, square, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayPreview(game) {
|
||||||
|
previewContainer.innerHTML = '';
|
||||||
|
|
||||||
|
preview = previewBis.cloneNode(true);
|
||||||
|
previewContainer.appendChild(preview);
|
||||||
|
|
||||||
|
previewContext = preview.getContext('2d');
|
||||||
|
|
||||||
|
|
||||||
|
// make damier
|
||||||
|
|
||||||
|
for (let x = 0; x < 5 ; x++) {
|
||||||
|
for (let y = 0;y < 5; y++) {
|
||||||
|
if ((x + y) % 2 === 0) {
|
||||||
|
previewContext.fillStyle = '#6d728020'; // Encore plus sombre
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
previewContext.fillStyle = '#3d425020'; // Presque noir-bleuté
|
||||||
|
}
|
||||||
|
|
||||||
|
previewContext.fillRect(
|
||||||
|
x * preview.width/5,
|
||||||
|
y * preview.height/5,
|
||||||
|
preview.width/5,
|
||||||
|
preview.height/5
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let nextPiece = game.nextPiece;
|
||||||
|
|
||||||
|
let xDif = nextPiece.xCenter - 2;
|
||||||
|
let yDif = nextPiece.yCenter - 2;
|
||||||
|
|
||||||
|
for (let i = 0; i < nextPiece.squares.length; i++) {
|
||||||
|
let square = nextPiece.squares[i];
|
||||||
|
|
||||||
|
previewContext.fillStyle = '#303f4f'; // Couleur de fond
|
||||||
|
previewContext.fillRect(
|
||||||
|
(square.x - xDif) * preview.width/5,
|
||||||
|
(square.y - yDif) * preview.height/5,
|
||||||
|
preview.width/5,
|
||||||
|
preview.height/5
|
||||||
|
);
|
||||||
|
|
||||||
|
let margin = 3;
|
||||||
|
|
||||||
|
previewContext.fillStyle = `rgba(${square.color.red}, ${square.color.green}, ${square.color.blue}, 1)`;
|
||||||
|
|
||||||
|
previewContext.fillRect(
|
||||||
|
(square.x - xDif) * preview.width/5 + margin,
|
||||||
|
(square.y - yDif) * preview.height/5 + margin,
|
||||||
|
preview.width/5 - margin * 2,
|
||||||
|
preview.height/5 - margin * 2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
39
public/script/displayMenuFunction.js
Normal file
39
public/script/displayMenuFunction.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
function displayMainMenu() {
|
||||||
|
mainMenu.classList.remove('hidden');
|
||||||
|
loadMenu.classList.add('hidden');
|
||||||
|
boardContainer.classList.add('hidden');
|
||||||
|
pauseButton.classList.remove('paused');
|
||||||
|
buttonContainer.classList.add('hidden');
|
||||||
|
|
||||||
|
gameOverMenu.classList.add('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayPause() {
|
||||||
|
mainMenu.classList.add('hidden');
|
||||||
|
loadMenu.classList.add('hidden');
|
||||||
|
boardContainer.classList.add('hidden');
|
||||||
|
|
||||||
|
pauseButton.classList.add('paused');
|
||||||
|
pauseMenu.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayGameBoard() {
|
||||||
|
mainMenu.classList.add('hidden');
|
||||||
|
loadMenu.classList.add('hidden');
|
||||||
|
pauseMenu.classList.add('hidden');
|
||||||
|
gameOverMenu.classList.add('hidden');
|
||||||
|
pauseButton.classList.remove('paused');
|
||||||
|
buttonContainer.classList.remove('hidden');
|
||||||
|
|
||||||
|
boardContainer.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayGameOver() {
|
||||||
|
mainMenu.classList.add('hidden');
|
||||||
|
loadMenu.classList.add('hidden');
|
||||||
|
boardContainer.classList.add('hidden');
|
||||||
|
pauseButton.classList.remove('paused');
|
||||||
|
buttonContainer.classList.add('hidden');
|
||||||
|
|
||||||
|
gameOverMenu.classList.remove('hidden');
|
||||||
|
}
|
28
public/script/element.js
Normal file
28
public/script/element.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
let board = document.getElementById('tetris-canvas');
|
||||||
|
const boardBis = document.getElementById('tetris-canvas').cloneNode(true);
|
||||||
|
const scoreElement = document.getElementById('score-value');
|
||||||
|
const loadMenu = document.getElementById('load-menu');
|
||||||
|
const mainMenu = document.getElementById('main-menu');
|
||||||
|
const pauseMenu = document.getElementById('pause-menu');
|
||||||
|
|
||||||
|
const startButton = document.getElementById('start-button');
|
||||||
|
const pauseButton = document.getElementById('pause-button');
|
||||||
|
|
||||||
|
let preview = document.getElementById('preview-canvas');
|
||||||
|
const previewBis = document.getElementById('preview-canvas').cloneNode(true);
|
||||||
|
|
||||||
|
const gameOverMenu = document.getElementById('game-over-menu');
|
||||||
|
const restartButton = document.getElementById('restart-button');
|
||||||
|
|
||||||
|
const boardContainer = document.getElementById('board-container');
|
||||||
|
const previewContainer = document.getElementById('preview-container');
|
||||||
|
|
||||||
|
const buttonContainer = document.getElementById('pause-container');
|
||||||
|
|
||||||
|
const highScoreTemplate = document.getElementById('high-score-template');
|
||||||
|
|
||||||
|
const highScoresList = document.getElementById('high-scores-list');
|
||||||
|
|
||||||
|
const resumeButton = document.getElementById('resume-button');
|
||||||
|
const mainMenuButton = document.getElementById('main-menu-button');
|
||||||
|
const mainMenuButtonBis = document.getElementById('main-menu-button2');
|
363
public/script/gameFunction.js
Normal file
363
public/script/gameFunction.js
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
function ifPieceInBoard(x, y) {
|
||||||
|
let board = game.board;
|
||||||
|
|
||||||
|
if (x < 0 || x >= width || y >= height) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < board.length; i++) {
|
||||||
|
if (board[i].x === x && board[i].y === y) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ifMovePiece(x, y, piece = game.currentPiece) {
|
||||||
|
for (let i = 0; i < piece.squares.length; i++) {
|
||||||
|
let square = piece.squares[i];
|
||||||
|
let newX = square.x + x;
|
||||||
|
let newY = square.y + y;
|
||||||
|
|
||||||
|
if (ifPieceInBoard(newX, newY)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ifMoveDown(piece = game.currentPiece) {
|
||||||
|
return ifMovePiece(0, 1, piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ifMoveLeft(piece = game.currentPiece) {
|
||||||
|
return ifMovePiece(-1, 0, piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ifMoveRight(piece = game.currentPiece) {
|
||||||
|
return ifMovePiece(1, 0, piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ifRotate(piece = game.currentPiece) {
|
||||||
|
let centerX = piece.xCenter;
|
||||||
|
let centerY = piece.yCenter;
|
||||||
|
|
||||||
|
for (let i = 0; i < piece.squares.length; i++) {
|
||||||
|
let square = piece.squares[i];
|
||||||
|
let x = square.x - centerX;
|
||||||
|
let y = square.y - centerY;
|
||||||
|
|
||||||
|
let newX = -y + centerX;
|
||||||
|
let newY = x + centerY;
|
||||||
|
|
||||||
|
if (ifPieceInBoard(newX, newY)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveDown(piece = game.currentPiece) {
|
||||||
|
for (let i = 0; i < piece.squares.length; i++) {
|
||||||
|
let square = piece.squares[i];
|
||||||
|
square.y += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
piece.yCenter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveLeft(piece = game.currentPiece) {
|
||||||
|
if (!ifMoveLeft(piece)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < piece.squares.length; i++) {
|
||||||
|
let square = piece.squares[i];
|
||||||
|
square.x -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
piece.xCenter -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveRight(piece = game.currentPiece) {
|
||||||
|
if (!ifMoveRight(piece)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < piece.squares.length; i++) {
|
||||||
|
let square = piece.squares[i];
|
||||||
|
square.x += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
piece.xCenter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ifCantRotate(piece, game) {
|
||||||
|
let centerX = piece.xCenter;
|
||||||
|
let centerY = piece.yCenter;
|
||||||
|
|
||||||
|
let moveX = [0, -1, 1, -2, 2];
|
||||||
|
let moveY = [0, -1];
|
||||||
|
|
||||||
|
for (let i = 0; i < moveX.length; i++) {
|
||||||
|
for (let j = 0; j < moveY.length; j++) {
|
||||||
|
let pieceBis = clonePiece(piece);
|
||||||
|
|
||||||
|
pieceBis.xCenter += moveX[i];
|
||||||
|
pieceBis.yCenter += moveY[j];
|
||||||
|
|
||||||
|
for (let k = 0; k < pieceBis.squares.length; k++) {
|
||||||
|
let square = pieceBis.squares[k];
|
||||||
|
square.x += moveX[i];
|
||||||
|
square.y += moveY[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ifRotate(pieceBis, game)) {
|
||||||
|
return [false, moveX[i], moveY[j]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [true, centerX, centerY];
|
||||||
|
}
|
||||||
|
|
||||||
|
function rotatePiece(piece) {
|
||||||
|
if (!ifRotate(piece, game)) {
|
||||||
|
let info = ifCantRotate(piece, game);
|
||||||
|
let canRotate = info[0];
|
||||||
|
let x = info[1];
|
||||||
|
let y = info[2];
|
||||||
|
|
||||||
|
if (canRotate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < piece.squares.length; i++) {
|
||||||
|
let square = piece.squares[i];
|
||||||
|
square.x += x;
|
||||||
|
square.y += y;
|
||||||
|
}
|
||||||
|
piece.xCenter += x;
|
||||||
|
piece.yCenter += y;
|
||||||
|
}
|
||||||
|
|
||||||
|
let centerX = piece.xCenter;
|
||||||
|
let centerY = piece.yCenter;
|
||||||
|
|
||||||
|
for (let i = 0; i < piece.squares.length; i++) {
|
||||||
|
let square = piece.squares[i];
|
||||||
|
let x = square.x - centerX;
|
||||||
|
let y = square.y - centerY;
|
||||||
|
|
||||||
|
square.x = -y + centerX;
|
||||||
|
square.y = x + centerY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fixPieceToBoard(piece = game.currentPiece) {
|
||||||
|
for (let i = 0; i < piece.squares.length; i++) {
|
||||||
|
let square = piece.squares[i];
|
||||||
|
game.board.push(square);
|
||||||
|
}
|
||||||
|
|
||||||
|
opacityCurrentPiece = 1;
|
||||||
|
|
||||||
|
checkLine();
|
||||||
|
// Vous pouvez également gérer ici la création d'une nouvelle pièce
|
||||||
|
// ou vérifier si des lignes doivent être supprimées.
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkLine(ifNoFall = false) {
|
||||||
|
let lineFilled = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
let filled = true;
|
||||||
|
for (let j = 0; j < 10; j++) {
|
||||||
|
if (!ifPieceInBoard(j, i)) {
|
||||||
|
filled = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filled) {
|
||||||
|
lineFilled.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < game.board.length; i++) {
|
||||||
|
let square = game.board[i];
|
||||||
|
let y = square.y;
|
||||||
|
|
||||||
|
if (!ifNoFall) {
|
||||||
|
for (let j = 0; j < lineFilled.length; j++) {
|
||||||
|
if (lineFilled[j] > y) {
|
||||||
|
square.y += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineFilled.includes(y)) {
|
||||||
|
game.board.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (lineFilled.length == 1) {
|
||||||
|
game.score += 40;
|
||||||
|
}
|
||||||
|
else if (lineFilled.length == 2) {
|
||||||
|
game.score += 100;
|
||||||
|
}
|
||||||
|
else if (lineFilled.length == 3) {
|
||||||
|
game.score += 300;
|
||||||
|
}
|
||||||
|
else if (lineFilled.length == 4) {
|
||||||
|
game.score += 1200;
|
||||||
|
}
|
||||||
|
|
||||||
|
game.lines += lineFilled.length;
|
||||||
|
game.level = Math.floor(game.lines / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
function switchPiece() {
|
||||||
|
game.currentPiece = game.nextPiece;
|
||||||
|
game.nextPiece = getRandomPiece();
|
||||||
|
|
||||||
|
for (let i = 0; i < game.currentPiece.squares.length; i++) {
|
||||||
|
let x = game.currentPiece.squares[i].x;
|
||||||
|
let y = game.currentPiece.squares[i].y;
|
||||||
|
if (ifPieceInBoard(x, y)) {
|
||||||
|
finishGame();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishGame(sendScore = true, gameOver = true) {
|
||||||
|
game.gameOver = true;
|
||||||
|
clearInterval(dropInterval);
|
||||||
|
clearInterval(leftInterval);
|
||||||
|
clearInterval(rightInterval);
|
||||||
|
clearInterval(refreshInterval);
|
||||||
|
|
||||||
|
clearInterval(endDropInterval);
|
||||||
|
endDropInterval = null;
|
||||||
|
opacityCurrentPiece = 1;
|
||||||
|
game.currentPiece = null;
|
||||||
|
dropInterval = null;
|
||||||
|
refreshInterval = null;
|
||||||
|
|
||||||
|
if (gameOver) {
|
||||||
|
displayGameOver();
|
||||||
|
} else {
|
||||||
|
displayMainMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sendScore) {
|
||||||
|
const playerName = prompt('Enter your name:');
|
||||||
|
|
||||||
|
sendScore(game, playerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendScore(playerName) {
|
||||||
|
if (playerName) {
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
score: game.score,
|
||||||
|
lines: game.lines,
|
||||||
|
playerName
|
||||||
|
};
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Send a PUT request to the server
|
||||||
|
const query = await fetch('/api/sendScore', {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if the response is ok before parsing
|
||||||
|
if (!query.ok) {
|
||||||
|
throw new Error(`Server returned ${query.status}: ${query.statusText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the content type to ensure it's JSON
|
||||||
|
const contentType = query.headers.get('content-type');
|
||||||
|
if (!contentType || !contentType.includes('application/json')) {
|
||||||
|
throw new Error('Server did not return JSON');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the response body
|
||||||
|
const response = await query.json();
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
console.log('Score and history saved successfully');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error('Error saving score and history:', response.error);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to save score:', error.message);
|
||||||
|
alert('Could not save your score. Please try again later.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSpeed() {
|
||||||
|
if (game.level > 29) {
|
||||||
|
game.speed = (speedSecondsToBottomPerLevel[29] / 20) * 1000;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
game.speed = (speedSecondsToBottomPerLevel[game.level] / 20) * 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function endDrop() {
|
||||||
|
let piece = game.currentPiece;
|
||||||
|
|
||||||
|
// La pièce ne peut plus descendre, elle est fixée sur le plateau
|
||||||
|
if (!endDropInterval) { // Vérifiez qu'il n'y a pas déjà un intervalle actif
|
||||||
|
endDropInterval = setInterval(() => {
|
||||||
|
opacityCurrentPiece -= 0.1;
|
||||||
|
if (opacityCurrentPiece <= 0) {
|
||||||
|
|
||||||
|
fixPieceToBoard(piece, game);
|
||||||
|
|
||||||
|
clearInterval(endDropInterval);
|
||||||
|
endDropInterval = null; // Réinitialisez après l'arrêt
|
||||||
|
opacityCurrentPiece = 1;
|
||||||
|
switchPiece(game);
|
||||||
|
setSpeed(game);
|
||||||
|
initOrChangeDropInterval(game.speed);
|
||||||
|
}
|
||||||
|
}, 60);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fastDrop(piece = game.currentPiece) {
|
||||||
|
if (piece) {
|
||||||
|
let canMoveDown = true;
|
||||||
|
|
||||||
|
while (canMoveDown) {
|
||||||
|
canMoveDown = ifMoveDown();
|
||||||
|
if (canMoveDown) {
|
||||||
|
moveDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fixPieceToBoard();
|
||||||
|
|
||||||
|
clearInterval(endDropInterval);
|
||||||
|
endDropInterval = null; // Réinitialisez après l'arrêt
|
||||||
|
opacityCurrentPiece = 1;
|
||||||
|
setSpeed(game);
|
||||||
|
initOrChangeDropInterval(game.speed);
|
||||||
|
switchPiece(game);
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,48 @@
|
|||||||
const board = document.getElementById('tetris-canvas');
|
let board = document.getElementById('tetris-canvas');
|
||||||
|
const boardBis = document.getElementById('tetris-canvas').cloneNode(true);
|
||||||
const scoreElement = document.getElementById('score-value');
|
const scoreElement = document.getElementById('score-value');
|
||||||
const loadMenu = document.getElementById('load-menu');
|
const loadMenu = document.getElementById('load-menu');
|
||||||
const mainMenu = document.getElementById('main-menu');
|
const mainMenu = document.getElementById('main-menu');
|
||||||
const pauseMenu = document.getElementById('pause-menu');
|
const pauseMenu = document.getElementById('pause-menu');
|
||||||
|
|
||||||
const startButton = document.getElementById('start-button');
|
const startButton = document.getElementById('start-button');
|
||||||
|
const pauseButton = document.getElementById('pause-button');
|
||||||
|
|
||||||
|
let preview = document.getElementById('preview-canvas');
|
||||||
|
const previewBis = document.getElementById('preview-canvas').cloneNode(true);
|
||||||
|
|
||||||
|
const gameOverMenu = document.getElementById('game-over-menu');
|
||||||
|
const restartButton = document.getElementById('restart-button');
|
||||||
|
|
||||||
|
const boardContainer = document.getElementById('board-container');
|
||||||
|
const previewContainer = document.getElementById('preview-container');
|
||||||
|
|
||||||
|
const buttonContainer = document.getElementById('pause-container');
|
||||||
|
|
||||||
|
const highScoreTemplate = document.getElementById('high-score-template');
|
||||||
|
|
||||||
|
const highScoresList = document.getElementById('high-scores-list');
|
||||||
|
|
||||||
|
restartButton.addEventListener('click', () =>
|
||||||
|
{
|
||||||
|
displayGameBoard();
|
||||||
|
startGame();
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
startButton.addEventListener('click', () =>
|
startButton.addEventListener('click', () =>
|
||||||
{
|
{
|
||||||
startGame();
|
startGame();
|
||||||
});
|
});
|
||||||
|
|
||||||
const boardContext = board.getContext('2d');
|
pauseButton.addEventListener('click', () =>
|
||||||
|
{
|
||||||
|
pauseGame();
|
||||||
|
});
|
||||||
|
|
||||||
|
let boardContext = board.getContext('2d');
|
||||||
|
let previewContext = preview.getContext('2d');
|
||||||
|
|
||||||
boardContext.fillStyle = 'black';
|
boardContext.fillStyle = 'black';
|
||||||
boardContext.fillRect(0, 0, board.width, board.height);
|
boardContext.fillRect(0, 0, board.width, board.height);
|
||||||
@ -36,6 +67,9 @@ let level = 0;
|
|||||||
let lines = 0;
|
let lines = 0;
|
||||||
let speed = 1000;
|
let speed = 1000;
|
||||||
|
|
||||||
|
let pause = false;
|
||||||
|
let gameOver = true;
|
||||||
|
|
||||||
const templatePiece = [
|
const templatePiece = [
|
||||||
[ // ok
|
[ // ok
|
||||||
[3, 0],
|
[3, 0],
|
||||||
@ -88,16 +122,14 @@ const templatePiece = [
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const templateColor = [
|
const templateColor = [
|
||||||
[255, 0, 0, 255],
|
[240, 87, 84, 255],
|
||||||
[0, 255, 0, 255],
|
[254, 223, 92, 255],
|
||||||
[0, 0, 255, 255],
|
[27, 148, 118, 255],
|
||||||
[255, 255, 0, 255],
|
[36, 115, 155, 255],
|
||||||
[0, 255, 255, 255],
|
[106, 190, 178, 255],
|
||||||
[255, 0, 255, 255],
|
[164, 199, 218, 255],
|
||||||
[255, 40, 130, 255]
|
[177, 225, 218, 255]
|
||||||
];
|
];
|
||||||
|
|
||||||
const speedSecondsToBotomPerLevel = [
|
const speedSecondsToBotomPerLevel = [
|
||||||
@ -134,7 +166,9 @@ const speedSecondsToBotomPerLevel = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
let currentPiece = [];
|
let currentPiece = [];
|
||||||
let color = []
|
let nextPiece = [];
|
||||||
|
let color = [];
|
||||||
|
let nextColor = [];
|
||||||
|
|
||||||
let boardData = [];
|
let boardData = [];
|
||||||
|
|
||||||
@ -144,14 +178,19 @@ const MOVEDOWN = 3;
|
|||||||
const ROTATE = 4;
|
const ROTATE = 4;
|
||||||
const MOVEDOWNFAST = 5;
|
const MOVEDOWNFAST = 5;
|
||||||
const RESPAWN = 6;
|
const RESPAWN = 6;
|
||||||
|
const CHANGENEXTPIECE = 7;
|
||||||
|
|
||||||
let history = [];
|
let history = [];
|
||||||
|
|
||||||
function startGame() {
|
function startGame() {
|
||||||
|
pause = false;
|
||||||
|
gameOver = false;
|
||||||
|
|
||||||
boardData = [];
|
boardData = [];
|
||||||
currentPiece = [];
|
currentPiece = [];
|
||||||
color = [];
|
color = [];
|
||||||
history = [];
|
history = [];
|
||||||
|
keyPress = [];
|
||||||
|
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
boardData[i] = [];
|
boardData[i] = [];
|
||||||
@ -166,20 +205,33 @@ function startGame() {
|
|||||||
speed = 1000;
|
speed = 1000;
|
||||||
scoreElement.innerText = score;
|
scoreElement.innerText = score;
|
||||||
|
|
||||||
mainMenu.classList.add('hidden');
|
displayGameBoard();
|
||||||
loadMenu.classList.add('hidden');
|
|
||||||
board.classList.add('hidden');
|
|
||||||
|
|
||||||
board.classList.remove('hidden');
|
|
||||||
|
|
||||||
iniGame();
|
iniGame();
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pauseGame() {
|
||||||
|
if (gameOver) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pause) {
|
||||||
|
pause = false;
|
||||||
|
displayGameBoard();
|
||||||
|
//initAndChangeSpeedDrop();
|
||||||
|
} else {
|
||||||
|
pause = true;
|
||||||
|
displayPause();
|
||||||
|
clearDownInterval();
|
||||||
|
clearInterval(endDownInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function iniGame() {
|
function iniGame() {
|
||||||
// Initialisation de la vitesse de chute
|
// Initialisation de la vitesse de chute
|
||||||
speed = (speedSecondsToBotomPerLevel[level]/20) * 1000;
|
speed = (speedSecondsToBottomPerLevel[level]/20) * 1000;
|
||||||
|
|
||||||
spawnPiece();
|
spawnPiece();
|
||||||
|
|
||||||
@ -191,77 +243,6 @@ function iniGame() {
|
|||||||
}, speed);
|
}, speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawTetisWithOppacity(x, y, color, oppacity) {
|
|
||||||
boardContext.drawImage(img, x, y, board.width/10, board.width/10);
|
|
||||||
|
|
||||||
const imageData = boardContext.getImageData(x, y, board.width/10, board.width/10);
|
|
||||||
const data = imageData.data;
|
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i += 4) {
|
|
||||||
data[i] = data[i] * color[0] / 255;
|
|
||||||
data[i + 1] = data[i + 1] * color[1] / 255;
|
|
||||||
data[i + 2] = data[i + 2] * color[2] / 255;
|
|
||||||
data[i + 3] = data[i + 3] * oppacity / 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
boardContext.putImageData(imageData, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function drawTetris(x, y, color) {
|
|
||||||
drawTetisWithOppacity(x, y, color, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawCurrentPiece() {
|
|
||||||
for (let i = 0 ; i < currentPiece.length - 1; i++) {
|
|
||||||
let piece = currentPiece[i];
|
|
||||||
drawTetisWithOppacity(piece[0] * board.width/10, piece[1] * board.width/10, color, oppacity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawBoard() {
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
for (let j = 0; j < 20; j++) {
|
|
||||||
if (!(boardData[i][j][0] == 0 && boardData[i][j][1] == 0 && boardData[i][j][2] == 0)) {
|
|
||||||
drawTetris(i * board.width/10, j * board.width/10, boardData[i][j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearBoard() {
|
|
||||||
boardContext.fillStyle = 'black';
|
|
||||||
boardContext.fillRect(0, 0, board.width, board.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawGrid() {
|
|
||||||
boardContext.strokeStyle = 'gray'; // Couleur des lignes du quadrillage
|
|
||||||
boardContext.lineWidth = 0.5; // Épaisseur des lignes
|
|
||||||
|
|
||||||
// Dessiner les lignes verticales
|
|
||||||
for (let x = 0; x <= board.width; x += board.width / 10) {
|
|
||||||
boardContext.beginPath();
|
|
||||||
boardContext.moveTo(x, 0);
|
|
||||||
boardContext.lineTo(x, board.height);
|
|
||||||
boardContext.stroke();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dessiner les lignes horizontales
|
|
||||||
for (let y = 0; y <= board.height; y += board.height / 20) {
|
|
||||||
boardContext.beginPath();
|
|
||||||
boardContext.moveTo(0, y);
|
|
||||||
boardContext.lineTo(board.width, y);
|
|
||||||
boardContext.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function refresh() {
|
|
||||||
clearBoard();
|
|
||||||
drawGrid();
|
|
||||||
drawBoard();
|
|
||||||
drawCurrentPiece();
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadTetris() {
|
function loadTetris() {
|
||||||
clearDownInterval();
|
clearDownInterval();
|
||||||
clearInterval(endDownInterval);
|
clearInterval(endDownInterval);
|
||||||
@ -270,6 +251,8 @@ function loadTetris() {
|
|||||||
currentPieceToBoard();
|
currentPieceToBoard();
|
||||||
checkLine();
|
checkLine();
|
||||||
spawnPiece();
|
spawnPiece();
|
||||||
|
|
||||||
|
//checkEndDrop();
|
||||||
}
|
}
|
||||||
|
|
||||||
function currentPieceToBoard() {
|
function currentPieceToBoard() {
|
||||||
@ -282,18 +265,100 @@ function currentPieceToBoard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function spawnPiece() {
|
function spawnPiece() {
|
||||||
const random = Math.floor(Math.random() * templatePiece.length);
|
let random = 0;
|
||||||
|
|
||||||
currentPiece = [];
|
if (nextPiece.length == 0) {
|
||||||
for (let i = 0; i < templatePiece[random].length; i++) {
|
random = Math.floor(Math.random() * templatePiece.length);
|
||||||
currentPiece.push([templatePiece[random][i][0], templatePiece[random][i][1]]);
|
|
||||||
|
for (let i = 0; i < templatePiece[random].length; i++) {
|
||||||
|
nextPiece.push([templatePiece[random][i][0], templatePiece[random][i][1]]);
|
||||||
|
}
|
||||||
|
nextColor = templateColor[random];
|
||||||
|
|
||||||
|
history.push([CHANGENEXTPIECE, random]);
|
||||||
|
}
|
||||||
|
currentPiece = nextPiece;
|
||||||
|
|
||||||
|
|
||||||
|
if (gameOver) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
color = templateColor[random];
|
for (let i = 0; i < currentPiece.length - 1; i++) {
|
||||||
|
if (boardData[currentPiece[i][0]][currentPiece[i][1]][0] != 0 &&
|
||||||
|
boardData[currentPiece[i][0]][currentPiece[i][1]][1] != 0 &&
|
||||||
|
boardData[currentPiece[i][0]][currentPiece[i][1]][2] != 0) {
|
||||||
|
|
||||||
history.push([RESPAWN, random]);
|
gameOver = true;
|
||||||
|
clearDownInterval();
|
||||||
|
clearInterval(endDownInterval);
|
||||||
|
oppacity = 255;
|
||||||
|
displayGameOver();
|
||||||
|
sendScore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
random = Math.floor(Math.random() * templatePiece.length);
|
||||||
|
nextPiece = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < templatePiece[random].length; i++) {
|
||||||
|
nextPiece.push([templatePiece[random][i][0], templatePiece[random][i][1]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
history.push([CHANGENEXTPIECE, random]);
|
||||||
|
|
||||||
|
color = nextColor;
|
||||||
|
nextColor = templateColor[random];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function sendScore() {
|
||||||
|
const playerName = prompt('Enter your name:');
|
||||||
|
if (playerName) {
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
score,
|
||||||
|
history,
|
||||||
|
playerName
|
||||||
|
};
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Send a PUT request to the server
|
||||||
|
const query = await fetch('/api/sendScore', {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if the response is ok before parsing
|
||||||
|
if (!query.ok) {
|
||||||
|
throw new Error(`Server returned ${query.status}: ${query.statusText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the content type to ensure it's JSON
|
||||||
|
const contentType = query.headers.get('content-type');
|
||||||
|
if (!contentType || !contentType.includes('application/json')) {
|
||||||
|
throw new Error('Server did not return JSON');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the response body
|
||||||
|
const response = await query.json();
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
console.log('Score and history saved successfully');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error('Error saving score and history:', response.error);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to save score:', error.message);
|
||||||
|
alert('Could not save your score. Please try again later.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function ifMoveTo(x, y) {
|
function ifMoveTo(x, y) {
|
||||||
return canMoveTo(x, y, currentPiece);
|
return canMoveTo(x, y, currentPiece);
|
||||||
@ -360,7 +425,7 @@ function rotate() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (let x = -1; x <= 1; x++) {
|
for (let x = -1; x <= 1; x++) {
|
||||||
for (let y = -1; y <= 1; y++) {
|
for (let y = 0; y >= -1; y--) {
|
||||||
if (canMoveTo(x, y, currentPieceCopy)) {
|
if (canMoveTo(x, y, currentPieceCopy)) {
|
||||||
moveToPiece(x, y, currentPieceCopy);
|
moveToPiece(x, y, currentPieceCopy);
|
||||||
currentPiece = currentPieceCopy;
|
currentPiece = currentPieceCopy;
|
||||||
@ -368,7 +433,7 @@ function rotate() {
|
|||||||
history.push([ROTATE, 0]);
|
history.push([ROTATE, 0]);
|
||||||
|
|
||||||
x = 2;
|
x = 2;
|
||||||
y = 2;
|
y = -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,7 +467,6 @@ function checkEndDrop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function clearDownInterval() {
|
function clearDownInterval() {
|
||||||
clearInterval(downInterval);
|
clearInterval(downInterval);
|
||||||
downInterval = null;
|
downInterval = null;
|
||||||
@ -457,10 +521,10 @@ function checkLine() {
|
|||||||
|
|
||||||
function initAndChangeSpeedDrop() {
|
function initAndChangeSpeedDrop() {
|
||||||
if (level > 29) {
|
if (level > 29) {
|
||||||
speed = (speedSecondsToBotomPerLevel[29]/20) * 1000;
|
speed = (speedSecondsToBottomPerLevel[29]/20) * 1000;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
speed = (speedSecondsToBotomPerLevel[level]/20) * 1000;
|
speed = (speedSecondsToBottomPerLevel[level]/20) * 1000;
|
||||||
}
|
}
|
||||||
clearDownInterval();
|
clearDownInterval();
|
||||||
downInterval = setInterval(() => {
|
downInterval = setInterval(() => {
|
||||||
@ -518,7 +582,7 @@ function moveRight() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fasteDrop() {
|
function fastDrop() {
|
||||||
while (ifMoveTo(0, 1)) {
|
while (ifMoveTo(0, 1)) {
|
||||||
moveDown();
|
moveDown();
|
||||||
}
|
}
|
||||||
@ -528,20 +592,30 @@ function fasteDrop() {
|
|||||||
oppacity = 255;
|
oppacity = 255;
|
||||||
|
|
||||||
loadTetris();
|
loadTetris();
|
||||||
history.push([MOVEDOWNFAST, 0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('keydown', (event) => {
|
document.addEventListener('keydown', (event) => {
|
||||||
if (event.key == 'ArrowUp' && !keyPress.includes('ArrowUp')) {
|
if (event.key == 'Escape' && !keyPress.includes('Escape')) {
|
||||||
|
pauseGame();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pause) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (gameOver) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((event.key == 'ArrowUp' || event.key == 'w' || event.key == 'z') && !keyPress.includes('ArrowUp') && !keyPress.includes('w') && !keyPress.includes('z')) {
|
||||||
rotate();
|
rotate();
|
||||||
} else if (event.key == 'ArrowDown' && !keyPress.includes('ArrowDown')) {
|
} else if ((event.key == 'ArrowDown' || event.key == 's') && !keyPress.includes('ArrowDown') && !keyPress.includes('s')) {
|
||||||
clearDownInterval();
|
clearDownInterval();
|
||||||
downInterval = setInterval(() => {
|
downInterval = setInterval(() => {
|
||||||
moveDown();
|
moveDown();
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
}, 50);
|
}, 50);
|
||||||
} else if (event.key == 'ArrowLeft' && !keyPress.includes('ArrowLeft')) {
|
} else if ((event.key == 'ArrowLeft' || event.key == 'a' || event.key == 'q') && !keyPress.includes('ArrowLeft') && !keyPress.includes('q') && !keyPress.includes('a')) {
|
||||||
moveLeft();
|
moveLeft();
|
||||||
|
|
||||||
leftInterval = setInterval(() => {
|
leftInterval = setInterval(() => {
|
||||||
@ -549,7 +623,7 @@ document.addEventListener('keydown', (event) => {
|
|||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
}, 100);
|
}, 100);
|
||||||
} else if (event.key == 'ArrowRight' && !keyPress.includes('ArrowRight')) {
|
} else if (((event.key == 'ArrowRight') || event.key == 'd') && !keyPress.includes('ArrowRight') && !keyPress.includes('d')) {
|
||||||
moveRight();
|
moveRight();
|
||||||
|
|
||||||
rightInterval = setInterval(() => {
|
rightInterval = setInterval(() => {
|
||||||
@ -557,7 +631,7 @@ document.addEventListener('keydown', (event) => {
|
|||||||
refresh();
|
refresh();
|
||||||
}, 100);
|
}, 100);
|
||||||
} else if (event.key == ' ' && !keyPress.includes(' ')) {
|
} else if (event.key == ' ' && !keyPress.includes(' ')) {
|
||||||
fasteDrop();
|
fastDrop();
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
@ -568,12 +642,14 @@ document.addEventListener('keydown', (event) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('keyup', (event) => {
|
document.addEventListener('keyup', (event) => {
|
||||||
if (event.key == 'ArrowDown') {
|
if (!pause && !gameOver) {
|
||||||
initAndChangeSpeedDrop();
|
if (event.key == 'ArrowDown' || event.key == 's') {
|
||||||
} else if (event.key == 'ArrowLeft') {
|
initAndChangeSpeedDrop();
|
||||||
clearInterval(leftInterval);
|
} else if (event.key == 'ArrowLeft' || event.key == 'a' || event.key == 'q') {
|
||||||
} else if (event.key == 'ArrowRight') {
|
clearInterval(leftInterval);
|
||||||
clearInterval(rightInterval);
|
} else if (event.key == 'ArrowRight' || event.key == 'd') {
|
||||||
|
clearInterval(rightInterval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keyPress = keyPress.filter((key) => {
|
keyPress = keyPress.filter((key) => {
|
||||||
@ -582,8 +658,5 @@ document.addEventListener('keyup', (event) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
loadMenu.classList.add('hidden');
|
displayMainMenu();
|
||||||
mainMenu.classList.remove('hidden');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
42
public/script/magicVariable.js
Normal file
42
public/script/magicVariable.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
const speedSecondsToBottomPerLevel = [
|
||||||
|
15.974, //0
|
||||||
|
14.31, //1
|
||||||
|
12.646, //2
|
||||||
|
10.982, //3
|
||||||
|
9.318, //4
|
||||||
|
7.654, //5
|
||||||
|
5.99, //6
|
||||||
|
4.326, //7
|
||||||
|
2.662, //8
|
||||||
|
1.997, //9
|
||||||
|
1.664, //10
|
||||||
|
1.664, //11
|
||||||
|
1.664, //12
|
||||||
|
1.331, //13
|
||||||
|
1.331, //14
|
||||||
|
1.331, //15
|
||||||
|
0.998, //16
|
||||||
|
0.998, //17
|
||||||
|
0.998, //18
|
||||||
|
0.666, //19
|
||||||
|
0.666, //20
|
||||||
|
0.666, //21
|
||||||
|
0.666, //22
|
||||||
|
0.666, //23
|
||||||
|
0.666, //24
|
||||||
|
0.666, //25
|
||||||
|
0.666, //26
|
||||||
|
0.666, //27
|
||||||
|
0.666, //28
|
||||||
|
0.333 //29
|
||||||
|
];
|
||||||
|
|
||||||
|
const width = 10;
|
||||||
|
const height = 20;
|
||||||
|
|
||||||
|
const DOWNHISTORY = 1;
|
||||||
|
const LEFTHISTORY = 2;
|
||||||
|
const RIGHTHISTORY = 3;
|
||||||
|
const ROTATEHISTORY = 4;
|
||||||
|
const ENDPARTYHISTORY = 5;
|
||||||
|
const ISNEXTHISTORY = 6;
|
18
public/script/menuController.js
Normal file
18
public/script/menuController.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
startButton.addEventListener('click', function() {
|
||||||
|
initGame();
|
||||||
|
});
|
||||||
|
pauseButton.addEventListener('click', function() {
|
||||||
|
pauseGame();
|
||||||
|
});
|
||||||
|
restartButton.addEventListener('click', function() {
|
||||||
|
initGame();
|
||||||
|
});
|
||||||
|
resumeButton.addEventListener('click', function() {
|
||||||
|
pauseGame();
|
||||||
|
});
|
||||||
|
mainMenuButton.addEventListener('click', function() {
|
||||||
|
finishGame(false, false);
|
||||||
|
});
|
||||||
|
mainMenuButtonBis.addEventListener('click', function() {
|
||||||
|
finishGame(false, false);
|
||||||
|
});
|
13
public/script/var.js
Normal file
13
public/script/var.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
let game = null;
|
||||||
|
let keyPress = [];
|
||||||
|
let dropInterval = null;
|
||||||
|
let leftInterval = null;
|
||||||
|
let rightInterval = null;
|
||||||
|
|
||||||
|
let refreshInterval = null;
|
||||||
|
|
||||||
|
let endDropInterval = null;
|
||||||
|
|
||||||
|
let opacityCurrentPiece = 1;
|
||||||
|
|
||||||
|
let history = [];
|
218
public/script/view.js
Normal file
218
public/script/view.js
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
let gapPiece = 6;
|
||||||
|
|
||||||
|
function drawTetisWithOppacity(x, y, color, oppacity) {
|
||||||
|
boardContext.fillStyle = '#303f4f'; // Couleur de fond
|
||||||
|
boardContext.fillRect(x, y, board.width/10, board.width/10);
|
||||||
|
boardContext.fillStyle = `rgba(${color[0]}, ${color[1]}, ${color[2]}, ${oppacity/255})`
|
||||||
|
boardContext.fillRect(x + gapPiece/2, y + gapPiece/2, board.width/10 - gapPiece, board.width/10 - gapPiece);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawTetrisOnThePreview(x, y, color) {
|
||||||
|
previewContext.fillStyle = '#303f4f'; // Couleur de fond
|
||||||
|
previewContext.fillRect(x, y, preview.width/5, preview.width/5);
|
||||||
|
previewContext.fillStyle = `rgba(${color[0]}, ${color[1]}, ${color[2]}, ${oppacity})`
|
||||||
|
previewContext.fillRect(x + gapPiece/2, y + gapPiece/2, preview.width/5 - gapPiece, preview.width/5 - gapPiece);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function drawTetris(x, y, color) {
|
||||||
|
drawTetisWithOppacity(x, y, color, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawCurrentPiece() {
|
||||||
|
for (let i = 0 ; i < currentPiece.length - 1; i++) {
|
||||||
|
let piece = currentPiece[i];
|
||||||
|
drawTetisWithOppacity(piece[0] * board.width/10, piece[1] * board.width/10, color, oppacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawHologram() {
|
||||||
|
let hologramPiece = [];
|
||||||
|
for (let i = 0; i < currentPiece.length; i++) {
|
||||||
|
let piece = currentPiece[i];
|
||||||
|
hologramPiece.push([piece[0], piece[1]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (canMoveTo(0, 1, hologramPiece)) {
|
||||||
|
moveToPiece(0, 1, hologramPiece);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < hologramPiece.length - 1; i++) {
|
||||||
|
let piece = hologramPiece[i];
|
||||||
|
drawTetisWithOppacity(piece[0] * board.width/10, piece[1] * board.width/10, color, 120);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawGrid() {
|
||||||
|
boardContext.strokeStyle = 'gray'; // Couleur des lignes du quadrillage
|
||||||
|
boardContext.lineWidth = 0.5; // Épaisseur des lignes
|
||||||
|
|
||||||
|
// Dessiner les lignes verticales
|
||||||
|
for (let x = 0; x <= board.width; x += board.width / 10) {
|
||||||
|
boardContext.beginPath();
|
||||||
|
boardContext.moveTo(x, 0);
|
||||||
|
boardContext.lineTo(x, board.height);
|
||||||
|
boardContext.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dessiner les lignes horizontales
|
||||||
|
for (let y = 0; y <= board.height; y += board.height / 20) {
|
||||||
|
boardContext.beginPath();
|
||||||
|
boardContext.moveTo(0, y);
|
||||||
|
boardContext.lineTo(board.width, y);
|
||||||
|
boardContext.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawBoard() {
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
for (let j = 0; j < 20; j++) {
|
||||||
|
if (!(boardData[i][j][0] == 0 && boardData[i][j][1] == 0 && boardData[i][j][2] == 0)) {
|
||||||
|
drawTetris(i * board.width/10, j * board.width/10, boardData[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearBoard() {
|
||||||
|
// Ajouter un motif subtil en arrière-plan
|
||||||
|
|
||||||
|
boardContainer.innerHTML = '';
|
||||||
|
board = boardBis.cloneNode(true);
|
||||||
|
boardContainer.appendChild(board);
|
||||||
|
|
||||||
|
boardContext = board.getContext('2d');
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
for (let j = 0; j < 20; j++) {
|
||||||
|
if ((i + j) % 2 === 0) {
|
||||||
|
boardContext.fillStyle = '#6d728020'; // Encore plus sombre
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
boardContext.fillStyle = '#3d425020'; // Presque noir-bleuté
|
||||||
|
}
|
||||||
|
boardContext.fillRect(
|
||||||
|
i * board.width/10,
|
||||||
|
j * board.height/20,
|
||||||
|
board.width/10,
|
||||||
|
board.height/20
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function displayPreview() {
|
||||||
|
previewContainer.innerHTML = '';
|
||||||
|
|
||||||
|
preview = previewBis.cloneNode(true);
|
||||||
|
previewContainer.appendChild(preview);
|
||||||
|
|
||||||
|
previewContext = preview.getContext('2d');
|
||||||
|
|
||||||
|
|
||||||
|
// make damier
|
||||||
|
|
||||||
|
for (let x = 0; x < 5 ; x++) {
|
||||||
|
for (let y = 0;y < 5; y++) {
|
||||||
|
if ((x + y) % 2 === 0) {
|
||||||
|
previewContext.fillStyle = '#6d728020'; // Encore plus sombre
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
previewContext.fillStyle = '#3d425020'; // Presque noir-bleuté
|
||||||
|
}
|
||||||
|
|
||||||
|
previewContext.fillRect(
|
||||||
|
x * preview.width/5,
|
||||||
|
y * preview.height/5,
|
||||||
|
preview.width/5,
|
||||||
|
preview.height/5
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let xDif = nextPiece[nextPiece.length - 1][0] - 2;
|
||||||
|
let yDif = nextPiece[nextPiece.length - 1][1] + 0.5;
|
||||||
|
|
||||||
|
for (let i = 0; i < nextPiece.length - 1; i++) {
|
||||||
|
let piece = nextPiece[i];
|
||||||
|
drawTetrisOnThePreview((piece[0] - xDif) * preview.width/5, (piece[1] + yDif) * preview.width/5, nextColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh() {
|
||||||
|
clearBoard();
|
||||||
|
drawGrid();
|
||||||
|
drawBoard();
|
||||||
|
drawHologram();
|
||||||
|
drawCurrentPiece();
|
||||||
|
displayPreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayMainMenu() {
|
||||||
|
mainMenu.classList.remove('hidden');
|
||||||
|
loadMenu.classList.add('hidden');
|
||||||
|
boardContainer.classList.add('hidden');
|
||||||
|
pauseButton.classList.remove('paused');
|
||||||
|
buttonContainer.classList.add('hidden');
|
||||||
|
|
||||||
|
gameOverMenu.classList.add('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayPause() {
|
||||||
|
mainMenu.classList.add('hidden');
|
||||||
|
loadMenu.classList.add('hidden');
|
||||||
|
boardContainer.classList.add('hidden');
|
||||||
|
|
||||||
|
pauseButton.classList.add('paused');
|
||||||
|
pauseMenu.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayGameBoard() {
|
||||||
|
mainMenu.classList.add('hidden');
|
||||||
|
loadMenu.classList.add('hidden');
|
||||||
|
pauseMenu.classList.add('hidden');
|
||||||
|
gameOverMenu.classList.add('hidden');
|
||||||
|
pauseButton.classList.remove('paused');
|
||||||
|
buttonContainer.classList.remove('hidden');
|
||||||
|
|
||||||
|
boardContainer.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayGameOver() {
|
||||||
|
mainMenu.classList.add('hidden');
|
||||||
|
loadMenu.classList.add('hidden');
|
||||||
|
boardContainer.classList.add('hidden');
|
||||||
|
pauseButton.classList.remove('paused');
|
||||||
|
buttonContainer.classList.add('hidden');
|
||||||
|
|
||||||
|
gameOverMenu.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
let intervalDisplayScoreBoard = null;
|
||||||
|
|
||||||
|
displayScoreBoard();
|
||||||
|
|
||||||
|
function displayScoreBoard() {
|
||||||
|
if (intervalDisplayScoreBoard) {
|
||||||
|
clearInterval(intervalDisplayScoreBoard);
|
||||||
|
intervalDisplayScoreBoard = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
intervalDisplayScoreBoard = setInterval(() => {
|
||||||
|
fetch('/api/getHighScores')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
highScoresList.innerHTML = '';
|
||||||
|
|
||||||
|
data.forEach(score => {
|
||||||
|
// Clone template content properly
|
||||||
|
const scoreElement = document.importNode(highScoreTemplate.content, true).firstElementChild;
|
||||||
|
scoreElement.querySelector('.high-score-name').innerHTML = score.player_name;
|
||||||
|
scoreElement.querySelector('.high-score-score').innerHTML = score.score;
|
||||||
|
highScoresList.appendChild(scoreElement);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error fetching high scores:', error));
|
||||||
|
}, 1000);
|
||||||
|
}
|
@ -1,107 +1,249 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'PixelatedElegance';
|
||||||
|
src: url('../font/Pixeboy-z8XGD.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100svh;
|
height: 100svh;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
background: repeating-conic-gradient(
|
background: repeating-conic-gradient(from 45deg,
|
||||||
from 45deg,
|
#7FB196 0% 25%,
|
||||||
#253a5e 0% 25%,
|
#3C425A 0% 50%);
|
||||||
#3c5e8b 0% 50%
|
background-size: max(10vw, 10svh) max(10vw, 10svh);
|
||||||
);
|
|
||||||
background-size: max(10vw, 10svh) max(10vw, 10svh);
|
|
||||||
background-color: #3c5e8b;
|
|
||||||
|
|
||||||
font-family: 'Roboto', sans-serif;
|
font-family: 'Roboto', sans-serif;
|
||||||
|
|
||||||
align-self: center;
|
align-self: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
gap: 1rem;
|
justify-content: space-evenly;
|
||||||
|
|
||||||
|
gap: 1rem;
|
||||||
|
|
||||||
|
font-family: 'PixelatedElegance', monospace;
|
||||||
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
display: flex;
|
gap: 1rem;
|
||||||
flex-direction: row;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tetris {
|
.tetris {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 600px;
|
height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
background: black;
|
.frame {
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0px;
|
||||||
|
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6);
|
||||||
|
|
||||||
|
background: #414241a0;
|
||||||
|
position: relative;
|
||||||
|
/* Nécessaire pour le positionnement du pseudo-élément */
|
||||||
|
|
||||||
|
p {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.frame::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: #4E4F4DA0;
|
||||||
|
border-radius: 10px;
|
||||||
|
/* Même border-radius que le parent */
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
-webkit-backdrop-filter: blur(8px);
|
||||||
|
/* Pour Safari */
|
||||||
|
z-index: -1;
|
||||||
|
/* Assure que le fond est derrière le contenu */
|
||||||
}
|
}
|
||||||
|
|
||||||
.first {
|
.first {
|
||||||
width: 150px;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
background: white;
|
gap: 1rem;
|
||||||
|
align-items: end;
|
||||||
|
width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.last {
|
.last {
|
||||||
width: 150px;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
background: white;
|
gap: 1rem;
|
||||||
|
align-items: start;
|
||||||
|
width: 100px;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-menu {
|
.main-menu {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
background-color: black;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.load-menu {
|
.load-menu {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
color: white;
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon.play-pause {
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 0;
|
||||||
|
height: 37px;
|
||||||
|
/* Réduit de moitié (était 74px) */
|
||||||
|
|
||||||
|
border-color: transparent transparent transparent #74dc74;
|
||||||
|
transition: 100ms all ease;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 18.5px 0 18.5px 30px;
|
||||||
|
/* Réduit proportionnellement (était 37px 0 37px 60px) */
|
||||||
|
|
||||||
|
&.paused {
|
||||||
|
border-style: double;
|
||||||
|
border-width: 0px 0 0px 30px;
|
||||||
|
/* Réduit (était 60px) */
|
||||||
|
border-color: transparent transparent transparent #ff5e5e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon.play-pause.play::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pauseContainer {
|
||||||
|
width: min-content;
|
||||||
|
height: min-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loader {
|
.loader {
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
border: 5px solid #FFF;
|
border: 5px solid #FFF;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
position: relative;
|
position: relative;
|
||||||
animation: pulse 1s linear infinite;
|
animation: pulse 1s linear infinite;
|
||||||
}
|
}
|
||||||
.loader:after {
|
|
||||||
content: '';
|
.loader:after {
|
||||||
position: absolute;
|
content: '';
|
||||||
width: 48px;
|
position: absolute;
|
||||||
height: 48px;
|
width: 48px;
|
||||||
border: 5px solid #FFF;
|
height: 48px;
|
||||||
border-radius: 50%;
|
border: 5px solid #FFF;
|
||||||
display: inline-block;
|
border-radius: 50%;
|
||||||
box-sizing: border-box;
|
display: inline-block;
|
||||||
left: 50%;
|
box-sizing: border-box;
|
||||||
top: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
top: 50%;
|
||||||
animation: scaleUp 1s linear infinite;
|
transform: translate(-50%, -50%);
|
||||||
}
|
animation: scaleUp 1s linear infinite;
|
||||||
|
}
|
||||||
@keyframes scaleUp {
|
|
||||||
0% { transform: translate(-50%, -50%) scale(0) }
|
@keyframes scaleUp {
|
||||||
60% , 100% { transform: translate(-50%, -50%) scale(1)}
|
0% {
|
||||||
}
|
transform: translate(-50%, -50%) scale(0)
|
||||||
@keyframes pulse {
|
}
|
||||||
0% , 60% , 100%{ transform: scale(1) }
|
|
||||||
80% { transform: scale(1.2)}
|
60%,
|
||||||
}
|
100% {
|
||||||
|
transform: translate(-50%, -50%) scale(1)
|
||||||
.hidden {
|
}
|
||||||
display: none;
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
60%,
|
||||||
|
100% {
|
||||||
|
transform: scale(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
transform: scale(1.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scoreboard {
|
||||||
|
width: 200px;
|
||||||
|
height: 600px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.options {
|
||||||
|
width: 200px;
|
||||||
|
height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
background: #4E4F4DA0;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0px;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user