remake hologram

This commit is contained in:
florian 2025-05-07 08:26:27 +02:00
parent 4a8299e5a6
commit 9d3f4714d2
14 changed files with 336 additions and 410 deletions

6
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"cSpell.words": [
"elle",
"fixée"
]
}

313
index.js
View File

@ -104,292 +104,67 @@ const templateColor = [
[177, 225, 218, 255] [177, 225, 218, 255]
]; ];
const MOVELEFT = 1;
const MOVERIGHT = 2;
const MOVEDOWN = 3;
const ROTATE = 4;
const MOVEDOWNFAST = 5;
const RESPAWN = 6;
const CHANGENEXTPIECE = 7;
function ifPiece(x, y, board) {
if (x < 0 || x >= 10 || y >= 20) {
return true;
}
if (y < 0) {
return false;
}
if (board[x][y][0] == 0 && board[x][y][1] == 0 && board[x][y][2] == 0) {
return false;
}
return true;
}
function canMoveTo(x, y, piece, board) {
for (let i = 0; i < piece.length - 1; i++) {
if (piece[i][0] + x < 0 || piece[i][0] + x >= 10 || piece[i][1] + y >= 20 || ifPiece(piece[i][0] + x, piece[i][1] + y, board)) {
return false;
}
}
return true;
}
function ifRotate(piece, board) {
for (let i = 0; i < piece.length - 1; i++) {
if (piece[i][0] < 0 || piece[i][0] >= 10 || piece[i][1] >= 20 || ifPiece(piece[i][0], piece[i][1], board)) {
return false;
}
}
return true;
}
function moveDown(piece, board) {
if (canMoveTo(0, 1, piece, board)) {
for (let i = 0; i < piece.length; i++) {
piece[i][1]++;
}
}
}
function moveLeft(piece, board) {
if (canMoveTo(-1, 0, piece, board)) {
for (let i = 0; i < piece.length; i++) {
piece[i][0]--;
}
}
}
function moveRight(piece, board) {
if (canMoveTo(1, 0, piece, board)) {
for (let i = 0; i < piece.length; i++) {
piece[i][0]++;
}
}
}
function rotate(piece, board) {
if (piece.length == 0) {
return;
}
let currentPieceCopy = [];
for (let i = 0; i < piece.length; i++) {
currentPieceCopy.push([piece[i][0], piece[i][1]]);
}
const center = currentPieceCopy[currentPieceCopy.length - 1];
for (let i = 0; i < piece.length - 1; i++) {
const x = currentPieceCopy[i][0] - center[0];
const y = currentPieceCopy[i][1] - center[1];
currentPieceCopy[i][0] = center[0] - y;
currentPieceCopy[i][1] = center[1] + x;
}
if (ifRotate(currentPieceCopy, board)) {
piece = currentPieceCopy;
// Don't modify history in verification function
}
else {
for (let x = -1; x <= 1; x++) {
for (let y = 0; y >= -1; y--) {
if (canMoveTo(x, y, currentPieceCopy, board)) {
moveToPiece(x, y, currentPieceCopy);
piece = currentPieceCopy;
x = 2;
y = -2;
}
}
}
}
}
function moveToPiece(x, y, piece) {
for (let i = 0; i < piece.length; i++) {
piece[i][0] += x;
piece[i][1] += y;
}
}
function checkLine(board, scoreObject) {
let lineFilled = 0;
let score = 0;
let lines = 0;
let level = 0;
for (let i = 0; i < 20; i++) {
let check = true;
for (let j = 0; j < 10; j++) {
if (board[j][i][0] == 0 && board[j][i][1] == 0 && board[j][i][2] == 0) {
check = false;
break;
}
}
if (check) {
for (let j = i; j > 0; j--) {
for (let k = 0; k < 10; k++) {
board[k][j] = board[k][j - 1];
}
}
for (let k = 0; k < 10; k++) {
board[k][0] = [0, 0, 0, 255];
}
lineFilled++;
}
}
if (lineFilled == 1) {
score += 40;
}
else if (lineFilled == 2) {
score += 100;
}
else if (lineFilled == 3) {
score += 300;
}
else if (lineFilled == 4) {
score += 1200;
}
lines += lineFilled;
level = Math.floor(lines / 10);
scoreObject.score += score;
scoreObject.lines += lineFilled;
scoreObject.level = Math.floor(scoreObject.lines / 10);
}
function verifieHystoryAndScore(score, history) {
let board = [];
for (let i = 0; i < 10; i++) {
board[i] = [];
for (let j = 0; j < 20; j++) {
board[i][j] = [0, 0, 0, 255];
}
}
let piece = [];
let nextPiece = [];
let nextIndex = 0;
let scoreObject = {
score: 0,
lines: 0,
level: 0
};
for (let i = 0; i < history.length; i++) {
if (history[i][0] === CHANGENEXTPIECE) {
// Only place non-fractional coordinates on the board
for (let j = 0; j < piece.length - 1; j++) {
if (Number.isInteger(piece[j][0]) && Number.isInteger(piece[j][1]) &&
piece[j][0] >= 0 && piece[j][0] < 10 &&
piece[j][1] >= 0 && piece[j][1] < 20) {
board[piece[j][0]][piece[j][1]] = [templateColor[nextIndex][0], templateColor[nextIndex][1], templateColor[nextIndex][2], templateColor[nextIndex][3]];
}
}
checkLine(board, scoreObject);
nextIndex = history[i][1];
// Reset piece and copy from template
piece = [];
for (let j = 0; j < templatePiece[nextIndex].length; j++) {
piece.push([templatePiece[nextIndex][j][0], templatePiece[nextIndex][j][1]]);
}
// Set up next piece
nextPiece = [];
let nextNextIndex = (i+1 < history.length && history[i+1][0] === CHANGENEXTPIECE) ? history[i+1][1] : 0;
for (let j = 0; j < templatePiece[nextNextIndex].length; j++) {
nextPiece.push([templatePiece[nextNextIndex][j][0], templatePiece[nextNextIndex][j][1]]);
}
}
else if (history[i][0] === MOVEDOWN) {
moveDown(piece, board);
}
else if (history[i][0] === MOVELEFT) {
moveLeft(piece, board);
}
else if (history[i][0] === MOVERIGHT) {
moveRight(piece, board);
}
else if (history[i][0] === ROTATE) {
rotate(piece, board);
}
}
console.log("Calculated score:", scoreObject.score, "Submitted score:", score);
return score === scoreObject.score;
}
app.put('/api/sendScore', (req, res) => { app.put('/api/sendScore', (req, res) => {
let score = req.body.score; let score = req.body.score;
let history = req.body.history; // let history = req.body.history;
let lines = req.body.lines;
let playerName = req.body.playerName; let playerName = req.body.playerName;
// if (score === null || history === null || playerName === null) { // Vérifier si le score est un nombre valide
// return res.status(400).send('Missing required fields'); 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 (score < 0) { if (typeof playerName !== 'string' || playerName.trim() === '') {
// return res.status(400).send('Score cannot be negative'); return res.status(400).send('Invalid player name');
// } }
// Vérifier si le score est supérieur à 0 et inférieur à 1200 * (lines/4)
// if (history.length === 0) { if ((lines/4) * 1200 < score) {
// return res.status(400).send('History cannot be empty'); return res.status(400).send('Invalid score');
// } }
// Vérifier si la line est un nombre valide
if (!verifieHystoryAndScore(score, history)) { if (isNaN(lines) || lines < 0) {
return res.status(400).send('Invalid history or score'); return res.status(400).send('Invalid lines');
} }
// Vérifier si le dossier des historiques existe, le créer si nécessaire // Vérifier si le dossier des historiques existe, le créer si nécessaire
const historyDir = './datas/histories'; // const historyDir = './datas/histories';
if (!fs.existsSync(historyDir)) { // if (!fs.existsSync(historyDir)) {
fs.mkdirSync(historyDir, { recursive: true }); // fs.mkdirSync(historyDir, { recursive: true });
} // }
// Date du jour // Date du jour
const date = new Date(); // const date = new Date();
const dateString = date.toISOString().split('T')[0]; // Format YYYY-MM-DD // 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 // // Vérifier si un fichier avec ce nom existe déjà et ajouter un chiffre si nécessaire
let finalPlayerName = playerName + dateString; // let finalPlayerName = playerName + dateString;
let counter = 0; // let counter = 0;
let historyFilePath = `${historyDir}/${finalPlayerName}.json`; // let historyFilePath = `${historyDir}/${finalPlayerName}.json`;
while (fs.existsSync(historyFilePath)) { // while (fs.existsSync(historyFilePath)) {
counter++; // counter++;
finalPlayerName = `${playerName}${dateString}${counter}`; // finalPlayerName = `${playerName}${dateString}${counter}`;
historyFilePath = `${historyDir}/${finalPlayerName}.json`; // historyFilePath = `${historyDir}/${finalPlayerName}.json`;
} // }
// Écrire l'historique dans le fichier // // Écrire l'historique dans le fichier
try { // try {
fs.writeFileSync(historyFilePath, JSON.stringify(history)); // fs.writeFileSync(historyFilePath, JSON.stringify(history));
console.log(`History written to ${historyFilePath}`); // console.log(`History written to ${historyFilePath}`);
} catch (err) { // } catch (err) {
console.error('Error writing history file:', err); // console.error('Error writing history file:', err);
return res.status(500).send('Error writing history file'); // return res.status(500).send('Error writing history file');
} // }
// //
db.run('INSERT INTO scores (player_name, score, pathHistory) VALUES (?, ?, ?)', [playerName, score, historyFilePath]) db.run('INSERT INTO scores (player_name, score, pathHistory) VALUES (?, ?, ?)', [playerName, score, "/"])
.then(() => { .then(() => {
console.log(`Score inserted for ${playerName}`); console.log(`Score inserted for ${playerName}`);
}) })

Binary file not shown.

View File

@ -44,20 +44,20 @@
<div class="hidden" id="board-container"> <div class="hidden" id="board-container">
<canvas id="tetris-canvas" width="300" height="600"></canvas> <canvas id="tetris-canvas" width="300" height="600"></canvas>
</div> </div>
<div class="main-menu" id="main-menu" > <div class="main-menu menu" id="main-menu" >
<button id="start-button">Start</button> <label id="start-button" class="button">Start</label>
</div> </div>
<div class="gameOver hidden" id="game-over-menu"> <div class="gameOver-menu menu hidden" id="game-over-menu">
<p>Game Over</p> <p>Game Over</p>
<label id="restart-button">Restart</label> <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 hidden" 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>

View File

@ -13,7 +13,10 @@ function initGame() {
refreshInterval = setInterval(() => { refreshInterval = setInterval(() => {
refreshBoard(game.board); refreshBoard(game.board);
displayPreview(game); displayPreview(game);
scoreElement.innerText = game.score;
}, 16); }, 16);
history = [];
} }
function initOrChangeDropInterval(speed) { function initOrChangeDropInterval(speed) {

View File

@ -90,8 +90,8 @@ function refreshBoard() {
drawSquare(square.x, square.y, square); drawSquare(square.x, square.y, square);
} }
drawCurrentPiece();
drawHologram(); drawHologram();
drawCurrentPiece();
} }
function drawHologram() { function drawHologram() {

View File

@ -22,3 +22,7 @@ const buttonContainer = document.getElementById('pause-container');
const highScoreTemplate = document.getElementById('high-score-template'); const highScoreTemplate = document.getElementById('high-score-template');
const highScoresList = document.getElementById('high-scores-list'); 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');

View File

@ -1,4 +1,4 @@
function ifPieceInBoard(x, y, game) { function ifPieceInBoard(x, y) {
let board = game.board; let board = game.board;
if (x < 0 || x >= width || y >= height) { if (x < 0 || x >= width || y >= height) {
@ -14,32 +14,32 @@ function ifPieceInBoard(x, y, game) {
return false; return false;
} }
function ifMovePiece(x, y, piece, game) { function ifMovePiece(x, y, piece = game.currentPiece) {
for (let i = 0; i < piece.squares.length; i++) { for (let i = 0; i < piece.squares.length; i++) {
let square = piece.squares[i]; let square = piece.squares[i];
let newX = square.x + x; let newX = square.x + x;
let newY = square.y + y; let newY = square.y + y;
if (ifPieceInBoard(newX, newY, game)) { if (ifPieceInBoard(newX, newY)) {
return false; return false;
} }
} }
return true; return true;
} }
function ifMoveDown(piece, game) { function ifMoveDown(piece = game.currentPiece) {
return ifMovePiece(0, 1, piece, game); return ifMovePiece(0, 1, piece);
} }
function ifMoveLeft(piece, game) { function ifMoveLeft(piece = game.currentPiece) {
return ifMovePiece(-1, 0, piece, game); return ifMovePiece(-1, 0, piece);
} }
function ifMoveRight(piece, game) { function ifMoveRight(piece = game.currentPiece) {
return ifMovePiece(1, 0, piece, game); return ifMovePiece(1, 0, piece);
} }
function ifRotate(piece, game) { function ifRotate(piece = game.currentPiece) {
let centerX = piece.xCenter; let centerX = piece.xCenter;
let centerY = piece.yCenter; let centerY = piece.yCenter;
@ -51,14 +51,14 @@ function ifRotate(piece, game) {
let newX = -y + centerX; let newX = -y + centerX;
let newY = x + centerY; let newY = x + centerY;
if (ifPieceInBoard(newX, newY, game)) { if (ifPieceInBoard(newX, newY)) {
return false; return false;
} }
} }
return true; return true;
} }
function moveDown(piece) { function moveDown(piece = game.currentPiece) {
for (let i = 0; i < piece.squares.length; i++) { for (let i = 0; i < piece.squares.length; i++) {
let square = piece.squares[i]; let square = piece.squares[i];
square.y += 1; square.y += 1;
@ -67,8 +67,8 @@ function moveDown(piece) {
piece.yCenter += 1; piece.yCenter += 1;
} }
function moveLeft(piece) { function moveLeft(piece = game.currentPiece) {
if (!ifMoveLeft(piece, game)) { if (!ifMoveLeft(piece)) {
return; return;
} }
@ -80,8 +80,8 @@ function moveLeft(piece) {
piece.xCenter -= 1; piece.xCenter -= 1;
} }
function moveRight(piece) { function moveRight(piece = game.currentPiece) {
if (!ifMoveRight(piece, game)) { if (!ifMoveRight(piece)) {
return; return;
} }
@ -155,7 +155,7 @@ function rotatePiece(piece) {
} }
} }
function fixPieceToBoard(piece, game) { function fixPieceToBoard(piece = game.currentPiece) {
for (let i = 0; i < piece.squares.length; i++) { for (let i = 0; i < piece.squares.length; i++) {
let square = piece.squares[i]; let square = piece.squares[i];
game.board.push(square); game.board.push(square);
@ -163,18 +163,18 @@ function fixPieceToBoard(piece, game) {
opacityCurrentPiece = 1; opacityCurrentPiece = 1;
checkLine(game); checkLine();
// Vous pouvez également gérer ici la création d'une nouvelle pièce // Vous pouvez également gérer ici la création d'une nouvelle pièce
// ou vérifier si des lignes doivent être supprimées. // ou vérifier si des lignes doivent être supprimées.
} }
function checkLine(game, ifNoFall = false) { function checkLine(ifNoFall = false) {
let lineFilled = []; let lineFilled = [];
for (let i = 0; i < 20; i++) { for (let i = 0; i < 20; i++) {
let filled = true; let filled = true;
for (let j = 0; j < 10; j++) { for (let j = 0; j < 10; j++) {
if (!ifPieceInBoard(j, i, game)) { if (!ifPieceInBoard(j, i)) {
filled = false; filled = false;
break; break;
} }
@ -217,46 +217,108 @@ function checkLine(game, ifNoFall = false) {
game.score += 1200; game.score += 1200;
} }
scoreElement.innerText = game.score;
game.lines += lineFilled.length; game.lines += lineFilled.length;
game.level = Math.floor(game.lines / 10); game.level = Math.floor(game.lines / 10);
} }
function switchPiece(game) { function switchPiece() {
game.currentPiece = game.nextPiece; game.currentPiece = game.nextPiece;
game.nextPiece = getRandomPiece(); game.nextPiece = getRandomPiece();
for (let i = 0; i < game.currentPiece.squares.length; i++) { for (let i = 0; i < game.currentPiece.squares.length; i++) {
if (ifPieceInBoard(game.currentPiece.squares[i].x, game.currentPiece.squares[i].y, game)) { let x = game.currentPiece.squares[i].x;
game.gameOver = true; let y = game.currentPiece.squares[i].y;
clearInterval(dropInterval); if (ifPieceInBoard(x, y)) {
clearInterval(leftInterval); finishGame();
clearInterval(rightInterval);
clearInterval(refreshInterval);
clearInterval(endDropInterval);
endDropInterval = null;
opacityCurrentPiece = 1;
game.currentPiece = null;
dropInterval = null;
refreshInterval = null;
displayGameOver();
return; return;
} }
} }
} }
function setSpeed(game) { function finishGame(sendScore = true, gameOver = true) {
if (game.level > 29) { game.gameOver = true;
game.speed = (speedSecondsToBotomPerLevel[29] / 20) * 1000; 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();
} }
else {
game.speed = (speedSecondsToBotomPerLevel[game.level] / 20) * 1000; if (sendScore) {
const playerName = prompt('Enter your name:');
sendScore(game, playerName);
} }
} }
function endDrop(game) { 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; let piece = game.currentPiece;
// La pièce ne peut plus descendre, elle est fixée sur le plateau // La pièce ne peut plus descendre, elle est fixée sur le plateau
@ -278,18 +340,18 @@ function endDrop(game) {
} }
} }
function fastDrop(game, piece = game.currentPiece) { function fastDrop(piece = game.currentPiece) {
if (piece) { if (piece) {
let canMoveDown = true; let canMoveDown = true;
while (canMoveDown) { while (canMoveDown) {
canMoveDown = ifMoveDown(piece, game); canMoveDown = ifMoveDown();
if (canMoveDown) { if (canMoveDown) {
moveDown(piece); moveDown();
} }
} }
fixPieceToBoard(piece, game); fixPieceToBoard();
clearInterval(endDropInterval); clearInterval(endDropInterval);
endDropInterval = null; // Réinitialisez après l'arrêt endDropInterval = null; // Réinitialisez après l'arrêt

View File

@ -231,7 +231,7 @@ function pauseGame() {
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();
@ -521,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(() => {

View File

@ -1,4 +1,4 @@
const speedSecondsToBotomPerLevel = [ const speedSecondsToBottomPerLevel = [
15.974, //0 15.974, //0
14.31, //1 14.31, //1
12.646, //2 12.646, //2
@ -33,3 +33,10 @@ const speedSecondsToBotomPerLevel = [
const width = 10; const width = 10;
const height = 20; const height = 20;
const DOWNHISTORY = 1;
const LEFTHISTORY = 2;
const RIGHTHISTORY = 3;
const ROTATEHISTORY = 4;
const ENDPARTYHISTORY = 5;
const ISNEXTHISTORY = 6;

View File

@ -7,3 +7,12 @@ pauseButton.addEventListener('click', function() {
restartButton.addEventListener('click', function() { restartButton.addEventListener('click', function() {
initGame(); initGame();
}); });
resumeButton.addEventListener('click', function() {
pauseGame();
});
mainMenuButton.addEventListener('click', function() {
finishGame(false, false);
});
mainMenuButtonBis.addEventListener('click', function() {
finishGame(false, false);
});

View File

@ -9,3 +9,5 @@ let refreshInterval = null;
let endDropInterval = null; let endDropInterval = null;
let opacityCurrentPiece = 1; let opacityCurrentPiece = 1;
let history = [];

View File

@ -1,24 +1,30 @@
@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%, #7FB196 0% 25%,
#3C425A 0% 50% #3C425A 0% 50%);
); background-size: max(10vw, 10svh) max(10vw, 10svh);
background-size: max(10vw, 10svh) max(10vw, 10svh);
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;
justify-content: space-evenly; justify-content: space-evenly;
gap: 1rem; gap: 1rem;
font-family: 'PixelatedElegance', monospace;
font-size: 1.5rem;
} }
.container { .container {
@ -28,8 +34,8 @@ body {
} }
.tetris { .tetris {
width: 300px; width: 300px;
height: 600px; height: 600px;
} }
.frame { .frame {
@ -41,7 +47,8 @@ body {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6); box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6);
background: #414241a0; background: #414241a0;
position: relative; /* Nécessaire pour le positionnement du pseudo-élément */ position: relative;
/* Nécessaire pour le positionnement du pseudo-élément */
p { p {
padding: 0px; padding: 0px;
@ -57,10 +64,13 @@ body {
right: 0; right: 0;
bottom: 0; bottom: 0;
background: #4E4F4DA0; background: #4E4F4DA0;
border-radius: 10px; /* Même border-radius que le parent */ border-radius: 10px;
/* Même border-radius que le parent */
backdrop-filter: blur(8px); backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px); /* Pour Safari */ -webkit-backdrop-filter: blur(8px);
z-index: -1; /* Assure que le fond est derrière le contenu */ /* Pour Safari */
z-index: -1;
/* Assure que le fond est derrière le contenu */
} }
.first { .first {
@ -81,25 +91,25 @@ body {
} }
.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;
} }
.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 { .icon.play-pause {
@ -107,18 +117,21 @@ body {
background: transparent; background: transparent;
box-sizing: border-box; box-sizing: border-box;
width: 0; width: 0;
height: 37px; /* Réduit de moitié (était 74px) */ height: 37px;
/* Réduit de moitié (était 74px) */
border-color: transparent transparent transparent #74dc74; border-color: transparent transparent transparent #74dc74;
transition: 100ms all ease; transition: 100ms all ease;
cursor: pointer; cursor: pointer;
border-style: solid; border-style: solid;
border-width: 18.5px 0 18.5px 30px; /* Réduit proportionnellement (était 37px 0 37px 60px) */ border-width: 18.5px 0 18.5px 30px;
/* Réduit proportionnellement (était 37px 0 37px 60px) */
&.paused { &.paused {
border-style: double; border-style: double;
border-width: 0px 0 0px 30px; /* Réduit (était 60px) */ border-width: 0px 0 0px 30px;
/* Réduit (était 60px) */
border-color: transparent transparent transparent #ff5e5e; border-color: transparent transparent transparent #ff5e5e;
} }
} }
@ -138,41 +151,53 @@ body {
} }
.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%,
0% { transform: translate(-50%, -50%) scale(0) } 100% {
60% , 100% { transform: translate(-50%, -50%) scale(1)} transform: translate(-50%, -50%) scale(1)
} }
@keyframes pulse { }
0% , 60% , 100%{ transform: scale(1) }
80% { transform: scale(1.2)} @keyframes pulse {
0%,
60%,
100% {
transform: scale(1)
} }
.hidden { 80% {
display: none; transform: scale(1.2)
}
} }
.scoreboard { .scoreboard {
@ -189,3 +214,36 @@ body {
width: 200px; width: 200px;
height: 600px; 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;
}