function viv() { let s = ".\n"; for (let i in arr) { for (let j in arr[i]) { s += arr[i][j] + " "; } s = s.trim() + "\n"; } console.log(s); } let snake_length_start = 4; let snake_length = snake_length_start; let snake_direction = 0; // 0 = right, 1 = down, 2 = left, 3 = up var game_interval = null; var game_ended_time = null; var game_speed_start = 350; var game_speed_min = 100; var game_speed = game_speed_start; var last_game_loop = null; function rnd(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function generateSnake() { let start_pos_j = rnd(2, (arr[0].length / 3)); let start_pos_i = rnd(2, 3); if (start_pos_i == 3) start_pos_i = 4; for (let i = 0; i < snake_length; i++) { arr[start_pos_i][start_pos_j + i] = i + 1; } } function getMaxBelow1000() { let maxVal = 0; for (let i = 0; i < arr.length; i++) { for (let j = 0; j < arr[i].length; j++) { if (arr[i][j] < 1000 && arr[i][j] > maxVal) { maxVal = arr[i][j]; } } } return maxVal; } function printText(text) { $("#label_for_table").html(text); } function printTextOnScreen(text) { clearTextFromScreen(); var el = $("
"); el.css({ 'font-size': '40px', 'text-align': 'center', 'width': '100%', 'position': 'absolute', 'top': '330px', 'z-index': '999' }); var el_text = $("" + text + ""); el_text.css({ "text-shadow": "rgba(0, 0, 0, 0.2) 2px 2px 10px" }); el.append(el_text); $("body").append(el); $("#inside_container").css({ "opacity": "0.35", "pointer-events": "none", }); } function clearTextFromScreen() { $("#onscreentext").remove(); $("#inside_container").css({ "opacity": "1", "pointer-events": "auto", }); } function getScore() { return snake_length - snake_length_start; } function printScore() { printText("Отримано світла: " + getScore()); } function sendScoreToLeaderboard(score) { let query = "https://api.svitlobot.in.ua/snakeGame/gameOverScore?score=" + score; $.get(query); } function gameOver() { let score = getScore(); sendScoreToLeaderboard(score); printText("Отримано світла: " + score); printTextOnScreen("Game Over!
Натисніть WASD або ↑ ← → ↓"); clearInterval(game_interval); game_interval = null; game_ended_time = new Date().getTime(); printTable(); viv(); } function moveSnake() { let head; let tail; let maxSnakeVal = getMaxBelow1000(); // Find the head and the tail of the snake for (let i = 0; i < arr.length; i++) { for (let j = 0; j < arr[i].length; j++) { if (arr[i][j] === 1) { tail = [i, j]; } else if (arr[i][j] === maxSnakeVal) { head = [i, j]; } } } // Determine the new head position based on the direction let newHead = [...head]; switch (snake_direction) { case 0: newHead[1]++; break; case 1: newHead[0]++; break; case 2: newHead[1]--; break; case 3: newHead[0]--; break; } if (newHead[0] >= arr.length) newHead[0] = 0; if (newHead[0] < 0) newHead[0] = arr.length - 1; if (newHead[1] >= arr[0].length) newHead[1] = 0; if (newHead[1] < 0) newHead[1] = arr[0].length - 1; let isAppleEaten = false; // Check for apple if (arr[newHead[0]][newHead[1]] === 1000) { // Add apple consumption logic here, e.g., increase snake length // For now, let's just reset the apple snake_length++; isAppleEaten = true; game_speed = getGameSpeed(getScore()); } if (!isAppleEaten) { // Move the snake by incrementing all body parts for (let i = 0; i < arr.length; i++) { for (let j = 0; j < arr[i].length; j++) { if (arr[i][j] > 0 && arr[i][j] < 1000) { arr[i][j]--; } } } } if (!isAppleEaten && arr[newHead[0]][newHead[1]] > 0) { arr[newHead[0]][newHead[1]] = -100; gameOver(); return; } // Place the new head arr[newHead[0]][newHead[1]] = snake_length; } function spawnApple() { let applePlaced = false; while (!applePlaced) { let i = rnd(0, arr.length - 1); let j = rnd(0, arr[0].length - 1); let maxSnakeVal = getMaxBelow1000(); let head = []; // Find the head of the snake for (let x = 0; x < arr.length; x++) { for (let y = 0; y < arr[x].length; y++) { if (arr[x][y] === maxSnakeVal) { head = [x, y]; } } } let distance = Math.abs(head[0] - i) + Math.abs(head[1] - j); // Check if the position is valid if (arr[i][j] === 0 && distance > 5 && distance < 20) { arr[i][j] = 1000; applePlaced = true; } } } function checkApple() { for (let i = 0; i < arr.length; i++) { for (let j = 0; j < arr[i].length; j++) { if (arr[i][j] == 1000) return; } } spawnApple(); } let last_key_press = 0; let movementInputArray = []; function changeDirection(new_direction) { if (!game_interval) { startGame(); } let t = new Date().getTime(); let diff = t - last_key_press; let trs = game_speed; if (diff < trs) { movementInputArray.push(new_direction); } else { movementInputArray = [new_direction]; } last_key_press = t; } function setButtonListeners() { for (let i = 0; i < 4; i++) { $("#btn_control_" + i).on("click", function(){ changeDirection(i); }); } } function keyboardListener(event) { switch (event.key) { case 'ArrowUp': case 'w': case 'W': case 'ц': case 'Ц': changeDirection(3); break; case 'ArrowDown': case 's': case 'S': case 'ы': case 'Ы': changeDirection(1); break; case 'ArrowLeft': case 'a': case 'A': case 'ф': case 'Ф': changeDirection(2); break; case 'ArrowRight': case 'd': case 'D': case 'в': case 'В': changeDirection(0); break; } } function handleMovementInput() { if (!movementInputArray || movementInputArray.length == 0) return; let direction = movementInputArray[0]; if (Math.abs(snake_direction - direction) == 2 && movementInputArray.length != 2) { movementInputArray.shift(); return; // opposite movement } if (movementInputArray.length > 1 && (Math.abs(snake_direction - direction) == 2 || snake_direction == direction)) { //swap if (Math.abs(movementInputArray[1] - snake_direction) != 2) snake_direction = movementInputArray[1]; movementInputArray[1] = direction; movementInputArray.shift(); return; } snake_direction = direction; movementInputArray.shift(); } function getGameSpeed(score) { const max_score = 25; if (score < 0) { throw new Error("Score must be a positive number."); } var max_speed = game_speed_start * 0.7; // Calculate the speed factor (linear decrease) const speedFactor = (max_speed - game_speed_min) / max_score; // Calculate the new speed let newSpeed = max_speed - (score * speedFactor); // Ensure the speed doesn't go below the minimum speed if (score >= max_score) { newSpeed = game_speed_min; } return newSpeed; } function gameLoop() { /* let s = ""; for (let i = 0; i < movementInputArray.length; i++) { s += movementInputArray[i]; if (i != movementInputArray - 1) s += ", "; } printText("Moves: " + s); */ let t = new Date().getTime(); if (last_game_loop) { if (t - last_game_loop < game_speed) return; } last_game_loop = t; handleMovementInput(); moveSnake(); if (!game_interval) return; //viv(); printTable(); checkApple(); printScore(); } function initGameState() { //clear array for (let i = 0; i < arr.length; i++) { for (let j = 0; j < arr[0].length; j++) { arr[i][j] = 0; } } movementInputArray = [] snake_length = snake_length_start; snake_direction = 0; game_speed = game_speed_start; generateSnake(); spawnApple(); printTable(); } function startGame() { if (game_ended_time) { if (new Date().getTime() - game_ended_time < 400) return; initGameState(); } game_interval = setInterval(gameLoop, 10); clearTextFromScreen(); } function initGame() { setButtonListeners(); initGameState(); document.addEventListener('keydown', keyboardListener); printTextOnScreen("Натисніть WASD або ↑ ← → ↓"); }