2025-05-07 08:26:27 +02:00

662 lines
15 KiB
JavaScript

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');
restartButton.addEventListener('click', () =>
{
displayGameBoard();
startGame();
refresh();
}
);
startButton.addEventListener('click', () =>
{
startGame();
});
pauseButton.addEventListener('click', () =>
{
pauseGame();
});
let boardContext = board.getContext('2d');
let previewContext = preview.getContext('2d');
boardContext.fillStyle = 'black';
boardContext.fillRect(0, 0, board.width, board.height);
const img = new Image();
img.src = '../img/PieceTetris.png';
let endDownInterval;
let oppacity = 255;
let downInterval;
let rightInterval;
let leftInterval;
let keyPress = [];
let score = 0;
let level = 0;
let lines = 0;
let speed = 1000;
let pause = false;
let gameOver = true;
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]
];
const speedSecondsToBotomPerLevel = [
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
];
let currentPiece = [];
let nextPiece = [];
let color = [];
let nextColor = [];
let boardData = [];
const MOVELEFT = 1;
const MOVERIGHT = 2;
const MOVEDOWN = 3;
const ROTATE = 4;
const MOVEDOWNFAST = 5;
const RESPAWN = 6;
const CHANGENEXTPIECE = 7;
let history = [];
function startGame() {
pause = false;
gameOver = false;
boardData = [];
currentPiece = [];
color = [];
history = [];
keyPress = [];
for (let i = 0; i < 10; i++) {
boardData[i] = [];
for (let j = 0; j < 20; j++) {
boardData[i][j] = [0, 0, 0, 255];
}
}
score = 0;
lines = 0;
level = 0;
speed = 1000;
scoreElement.innerText = score;
displayGameBoard();
iniGame();
refresh();
}
function pauseGame() {
if (gameOver) {
return;
}
if (pause) {
pause = false;
displayGameBoard();
//initAndChangeSpeedDrop();
} else {
pause = true;
displayPause();
clearDownInterval();
clearInterval(endDownInterval);
}
}
function iniGame() {
// Initialisation de la vitesse de chute
speed = (speedSecondsToBottomPerLevel[level]/20) * 1000;
spawnPiece();
// Intervalle pour faire tomber la pièce
downInterval = setInterval(() => {
moveDown();
refresh();
}, speed);
}
function loadTetris() {
clearDownInterval();
clearInterval(endDownInterval);
oppacity = 255;
currentPieceToBoard();
checkLine();
spawnPiece();
//checkEndDrop();
}
function currentPieceToBoard() {
if (currentPiece.length != 0) {
for (let i = 0; i < currentPiece.length - 1; i++) {
let piece = currentPiece[i];
boardData[piece[0]][piece[1]] = color; // Copie du tableau color
}
}
}
function spawnPiece() {
let random = 0;
if (nextPiece.length == 0) {
random = Math.floor(Math.random() * templatePiece.length);
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;
}
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) {
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) {
return canMoveTo(x, y, currentPiece);
}
function canMoveTo(x, y, piece) {
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)) {
return false;
}
}
return true;
}
function ifRotate(piece) {
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])) {
return false;
}
}
return true;
}
function ifPiece(x, y) {
if (x < 0 || x >= 10 || y >= 20) {
return true;
}
if (y < 0) {
return false;
}
if (boardData[x][y][0] == 0 && boardData[x][y][1] == 0 && boardData[x][y][2] == 0) {
return false;
}
return true;
}
function rotate() {
if (currentPiece.length == 0) {
return;
}
let currentPieceCopy = [];
for (let i = 0; i < currentPiece.length; i++) {
currentPieceCopy.push([currentPiece[i][0], currentPiece[i][1]]);
}
const center = currentPieceCopy[currentPieceCopy.length - 1];
for (let i = 0; i < currentPiece.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)) {
currentPiece = currentPieceCopy;
history.push([ROTATE, 0]);
}
else {
for (let x = -1; x <= 1; x++) {
for (let y = 0; y >= -1; y--) {
if (canMoveTo(x, y, currentPieceCopy)) {
moveToPiece(x, y, currentPieceCopy);
currentPiece = currentPieceCopy;
history.push([ROTATE, 0]);
x = 2;
y = -2;
}
}
}
}
checkEndDrop();
}
function checkEndDrop() {
clearInterval(endDownInterval);
oppacity = 255;
if (!ifMoveTo(0, 1)) {
clearDownInterval();
endDownInterval = setInterval(() => {
oppacity -= 5;
if (oppacity <= 60) {
loadTetris();
}
refresh();
}
, 11);
}
else if (!downInterval) {
clearDownInterval();
initAndChangeSpeedDrop();
}
}
function clearDownInterval() {
clearInterval(downInterval);
downInterval = null;
}
function checkLine() {
let lineFilled = 0;
for (let i = 0; i < 20; i++) {
let check = true;
for (let j = 0; j < 10; j++) {
if (boardData[j][i][0] == 0 && boardData[j][i][1] == 0 && boardData[j][i][2] == 0) {
check = false;
break;
}
}
if (check) {
for (let j = i; j > 0; j--) {
for (let k = 0; k < 10; k++) {
boardData[k][j] = boardData[k][j - 1];
}
}
for (let k = 0; k < 10; k++) {
boardData[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;
}
scoreElement.innerText = score;
lines += lineFilled;
level = Math.floor(lines / 10);
initAndChangeSpeedDrop();
}
function initAndChangeSpeedDrop() {
if (level > 29) {
speed = (speedSecondsToBottomPerLevel[29]/20) * 1000;
}
else {
speed = (speedSecondsToBottomPerLevel[level]/20) * 1000;
}
clearDownInterval();
downInterval = setInterval(() => {
moveDown();
refresh();
}, speed);
}
function moveTo(x, y) {
moveToPiece(x, y, currentPiece);
}
function moveToPiece(x, y, piece) {
for (let i = 0; i < piece.length; i++) {
piece[i][0] += x;
piece[i][1] += y;
}
checkEndDrop();
}
function moveDown() {
if (!ifMoveTo(0, 1) || currentPiece.length == 1) {
return false;
}
moveTo(0, 1);
history.push([MOVEDOWN, 0]);
return true;
}
function moveLeft() {
if (!ifMoveTo(-1, 0) || currentPiece.length == 1) {
return false;
}
moveTo(-1, 0);
history.push([MOVELEFT, 0]);
return true;
}
function moveRight() {
if (!ifMoveTo(1, 0) || currentPiece.length == 1) {
return false;
}
moveTo(1, 0);
history.push([MOVERIGHT, 0]);
return true;
}
function fastDrop() {
while (ifMoveTo(0, 1)) {
moveDown();
}
clearDownInterval();
clearInterval(endDownInterval);
oppacity = 255;
loadTetris();
}
document.addEventListener('keydown', (event) => {
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();
} else if ((event.key == 'ArrowDown' || event.key == 's') && !keyPress.includes('ArrowDown') && !keyPress.includes('s')) {
clearDownInterval();
downInterval = setInterval(() => {
moveDown();
refresh();
}, 50);
} else if ((event.key == 'ArrowLeft' || event.key == 'a' || event.key == 'q') && !keyPress.includes('ArrowLeft') && !keyPress.includes('q') && !keyPress.includes('a')) {
moveLeft();
leftInterval = setInterval(() => {
moveLeft();
refresh();
}, 100);
} else if (((event.key == 'ArrowRight') || event.key == 'd') && !keyPress.includes('ArrowRight') && !keyPress.includes('d')) {
moveRight();
rightInterval = setInterval(() => {
moveRight();
refresh();
}, 100);
} else if (event.key == ' ' && !keyPress.includes(' ')) {
fastDrop();
}
refresh();
console.log(event.key);
keyPress.push(event.key);
});
document.addEventListener('keyup', (event) => {
if (!pause && !gameOver) {
if (event.key == 'ArrowDown' || event.key == 's') {
initAndChangeSpeedDrop();
} 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;
});
});
img.onload = () => {
displayMainMenu();
}