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 або ↑ ← → ↓");
}