<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Змейка</title>
<style>
html, body {
height: 100%;
margin: 0;
}
/* задаем стиль для игрового поля*/
body {
background: whitesmoke;
display: flex;
align-items: center;
justify-content: center;
}
canvas {
border: 2px solid black;
}
</style>
</head>
<body>
<!-- Задаем игровое поле -->
<canvas width="640" height="704" id="game"></canvas>
<!-- Сама программа -->
<script>
var canvas = document.getElementById('game');
var ctx = canvas.getContext('2d');
// ширина сетки для движения змейки
var grid = 16;
ctx.font = grid + 'px Arial';
// количество пикселей между полосками
var Npols = 4;
// смещение полосок на теле змейки
var pols = 1;
// счетчик прореживания кадров для задания скорости змейки
var count = 0;
// Счетчик времени отображения сообщения в нижней строке
var timeMessage = 0;
// переменные для головы, тела и хвоста змейки
var head, body, tail;
// Задаем объект для змейки
var snake = {
x: 160, y: 160, // Координаты головы (начальное положение)
tekNapr: 1, // направление движения змейки 0 - стоим, 1 - вправо, 2 - вверх, 3 - влево, 4 - вниз
tekPov: 0, // для прорисовки углов змейки - поворот NM N - предыдущее направление, M - текущее направление. 0 - нет поворота
cells: [], // массив для элементов тела змейки
maxCells: grid / 2 + 3, // первоначальная длина змейки
timeHungry: 100, // время до голодания змейки
dtHungry: 10, // время голодания, через которое уменьшаем по одному кусочку
cross: false // Точка пересечения змейки самой себя.
};
let Hungry = 200;
let deltaHungry = 20;
//let colorTest;
// Задаем массив объектов для кроликов и мангустов: позиция x:y, тип ty = 0 - кролик, 2 - магнуст, вес p - от 1 до 4, t - время жизни в тиках 0 - постоянный, 1000 - максимальный,
// dt - дельта времени(в тиках) для перемещения кролика или мангуста, 0 - не двигается, до 40 - скорость,
var rabbmang = [];
// функция для задания случаной позиции
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
// функция проверки, что позиция x:y не находится в теле змейки
function intoSnake(x, y) {
var flag = false;
snake.cells.forEach(function (cell, i, c) {
if ((cell.x === x) && (cell.y === y)) flag = true;
})
return flag;
}
// функция установки признака пересечения змейки самой себя в позиции x:y
function setCrossSnake(x, y) {
snake.cells.forEach(function (cell, i, c) {
if ((cell.x === x) && (cell.y === y)) cell.cross = true;
})
}
// функция проверки, что позиция x:y не попала на кролика или мангуста
function intoRabbit(x, y) {
var flag = false;
for (let rabbit of rabbmang) { // для каждого кролика или мангуста
if ((rabbit.x === x) && (rabbit.y === y)) {
flag = true;
break;
}
}
return flag;
}
// функция вывода кролика (мангуста) на игровое поле
function drawRabbit(rm) {
// прорисовываем кролика
if (rm.ty == 0) {
ctx.fillStyle = 'red';
ctx.fillRect(rm.x + rm.p/2, rm.y, grid - rm.p/2, grid);
ctx.fillStyle = 'black';
ctx.fillText(rm.p, rm.x + 3 + rm.p/4, rm.y + grid - 3);
}
// прорисовываем мангуста
if (rm.ty == 1) {
ctx.fillStyle = 'blue'
ctx.fillRect(rm.x + rm.p/2, rm.y, grid - rm.p/2, grid - 1);
ctx.fillStyle = 'black';
ctx.fillText('&', rm.x + 3 + rm.p/4, rm.y + grid - 3);
}
}
// функция создания кролика (мангуста) на игровом поле в случайной позиции
function setRabbit() {
let rabbit = { x: 0, y: 0, ty: 0, p: 0, t: 100, dt: 0 };
// Находим случайную позицию на игровом поле
rabbit.x = getRandomInt(0, canvas.width / grid) * grid;
rabbit.y = getRandomInt(2, (canvas.height-32) / grid) * grid;
// проверяем, что позиция не должна попадать на тело змейки
while ((intoSnake(rabbit.x, rabbit.y) === true) || (intoRabbit(rabbit.x, rabbit.y) === true)) {
rabbit.x = getRandomInt(0, canvas.width / grid) * grid;
rabbit.y = getRandomInt(2, (canvas.height-32) / grid) * grid;
}
rabbit.ty = 0; // задаем тип - кролик (0) и мангуст (1)
if (getRandomInt(0, 20) > 18) { // кроликов в 9 раз чаще чем мангуста
rabbit.ty = 1;
}
rabbit.p = getRandomInt(1, 10); // задаем вес кролика - от 1 до 9
rabbit.t = getRandomInt(0, 40) * 20; // задаем время жизни кролика или мангуста 0 - вечный
rabbit.dt = getRandomInt(1, 3) * 4; // задаем скачок - то есть дельту времени или иначе - скорость передвижения кролика.
drawRabbit(rabbit); // прорисовываем кролика или мангуста заданном месте
rabbmang.push(rabbit); // заносим в массив кроликов и мангустов
}
// Начальное положение змейки
function initSnake() {
// задаем положение для головы змейки и запускаем змейку с начала
snake.tekNapr = 1;
snake.x = 160;
snake.y = 160;
snake.cells = [];
snake.cells.push({ x: snake.x, y: snake.y, napr: snake.tekNapr }) // заносим голову
snake.cells.push({ x: snake.x - grid, y: snake.y, napr: snake.tekNapr }) // и первый кусочек тела змеи - он же хвост
snake.maxCells = grid/2 + 3;
snake.timeHungry = Hungry;
snake.dtHungry = deltaHungry;
snake.cross = false;
pols = 0;
// обнуляем игровое поле
ctx.clearRect(0, 0, canvas.width, canvas.height);
// прорисовываем верхную границу игрового поля
ctx.fillStyle = 'black'; // границы рисуем черным
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(0, 31);
ctx.lineTo(640, 31);
ctx.stroke();
// прорисовываем нижную границу игрового поля
ctx.beginPath();
ctx.moveTo(0, 673);
ctx.lineTo(640, 673);
ctx.stroke();
// при перезагрузке змейки также убираем старых кроликов
let temp = rabbmang.splice(0, rabbmang.length);
for (let rabbit of temp) {
ctx.clearRect(rabbit.x, rabbit.y, grid, grid);
}
// ставим первого кролика
//setRabbit();
}
// Укус мангуста
function cutSnake(cutX, cutY, napr) {
let flag = false;
if ((snake.cells[0].x === cutX) && (snake.cells[0].y === cutY)) {
switch (napr) { // и тестируем новое место одновременно смотрим не вышли ли из игрового поля
case 1: if (snake.cells[0].napr != 3) { flag = true; break; } // кусаем вправо - если голова не идет навстречу
case 2: if (snake.cells[0].napr != 4) { flag = true; break; } // кусаем вверх (голова вниз)
case 3: if (snake.cells[0].napr != 1) { flag = true; break; } // кусаем влево (голова вправо)
case 4: if (snake.cells[0].napr != 2) { flag = true; break; } // кусаем вниз (голова враво)
}
}
if ((snake.cells[1].x === cutX) && (snake.cells[1].y === cutY)) {
flag = true; // укус за шею (второй кусочек тела змейки после головы) - тоже смерть змейки
}
if (flag) { // укус за голову - мгновенная смерть змейки
alert('Увы - мангуст слопал змейку - игра окончена');
// Задаем новую змейку
initSnake();
}
if (!flag) { // укус не за голову змейки
for (let tekPos of snake.cells) {
if ((tekPos.x === cutX) && (tekPos.y === cutY)) { // нашли место укуса мангуста
let indexSnake = snake.cells.indexOf(tekPos) - 1; // и с этого места
let temp = snake.cells.splice(indexSnake, snake.maxCells - indexSnake); // удаляем все тело змейки до хвоста
for (let cutPos of temp) {
ctx.clearRect(cutPos.x, cutPos.y, grid, grid); // тело змейки на канве
}
snake.maxCells = snake.cells.length;
ctx.fillText('Ой - мангуст откусил половину змейки', 200, 675);
timeMessage = 100;
break;
}
}
}
}
// Цикл отображения одного шага анимации игрового поля со змейкой
function loop() {
// Каждый кадр видиосистемы перезапускаем основной цикл игры
requestAnimationFrame(loop);
// прореживаем кадры для того чтобы прорисовывать змейку 8 раз в секунду. (60/8 - 7.5) - задает скорость змейки
if (++count < 8) return;
count = 0; // обнуляем счетчик прореживания
// выводим длину змейки, количество кроликов и мангустов, время жизни змейки и другую статистику
ctx.fillStyle = 'black'; // рисуем черным
ctx.clearRect(600, 675, 40, 32);
ctx.fillText(snake.maxCells, 600, 700);
// При отображении сообщения ждем заданное время
if (timeMessage-- > 0) {
if (timeMessage === 0) {
ctx.clearRect(180, 675, 400, 40);
ctx.fillText("_____________________", 180, 700); // и вытираем сообщение
// ctx.stroke;
}
}
// выставляем случайным способом нового кролика в случайном месте игрового поля
if (getRandomInt(0, 50) == 0) { setRabbit() };
// обрабатываем массив кроликов и мангустов
for (let rabbit of rabbmang) { // для каждого кролика или мангуста
// время жизни кролика или мангуста
if (rabbit.t > 0) { // если кролик или мангуст не вечный (0), то уменьшаем время жизни кроликов и убираем тех, чье время истекло
if (--rabbit.t === 0) { // если время жизни кончилось
let indexRabbit = rabbmang.indexOf(rabbit); // то этого кролика или мангуста
let temp = rabbmang.splice(indexRabbit, 1); // удаляем
ctx.clearRect(rabbit.x, rabbit.y, grid, grid); // очищаем место кроллика на канве
}
}
// скачок кролика или мангуста
if (rabbit.dt > 0) { // отсчитываем время до следующего перемещения кролика или мангуста 0 - неподвижный кролик или мангуст
if (--rabbit.dt === 0) { // если время для следующего скачка кролика кончилось
rabbit.dt = getRandomInt(1, 4) * 4; // задаем новый скачок
let posX = rabbit.x; posY = rabbit.y; // то перемещаем этого кролика или мангуста на один шаг в случайную сторону
let napr = getRandomInt(0, 5); // определяем направление смещения
let flag = false; // признак
switch (napr) { // и тестируем новое место одновременно смотрим не вышли ли из игрового поля
case 0: break; // не двигаемся
case 1: if (rabbit.x < canvas.width - grid) { posX += grid; flag = true; break; } // двигаемся вправо
case 2: if (rabbit.y > 32 + grid) { posY -= grid; flag = true; break; } // двигаемся вверх
case 3: if (rabbit.x > grid) { posX -= grid; flag = true; break; } // двигаемся влево
case 4: if (rabbit.y < canvas.height - 32 - grid) { posY += grid; flag = true; break; } // двигаемся вниз
}
// проверяем не попали ли мы на змейку
if (flag && (intoSnake(posX, posY) === false) && (intoRabbit(posX, posY) === false)) { // если перемещение допустимо, то меняем кролика в массиве
ctx.clearRect(rabbit.x, rabbit.y, grid, grid); // очищаем старое место кролика на канве
rabbit.x = posX; rabbit.y = posY; // задаем новое положение в массив
drawRabbit(rabbit); // прорисовываем кролика или мангуста на новом месте
}
}
}
// укус мангуста
if (rabbit.ty == 1) {
if (intoSnake(rabbit.x + grid, rabbit.y) && !(intoSnake(rabbit.x + 2 * grid, rabbit.y))) { // если справа от мангуста тело змейки '#', но неприкрытое '##'
cutSnake(rabbit.x + grid, rabbit.y, 1); // то кусаем
}
if (intoSnake(rabbit.x, rabbit.y - grid) && !(intoSnake(rabbit.x, rabbit.y - 2 * grid))) { // если сверху от мангуста тело змейки '#', но неприкрытое '##'
cutSnake(rabbit.x, rabbit.y - grid, 2); // то кусаем
}
if (intoSnake(rabbit.x - grid, rabbit.y) && !(intoSnake(rabbit.x - 2 * grid, rabbit.y))) { // если слева от мангуста тело змейки '#', но неприкрытое '##'
cutSnake(rabbit.x - grid, rabbit.y, 3); // то кусаем
}
if (intoSnake(rabbit.x, rabbit.y + grid) && !(intoSnake(rabbit.x, rabbit.y + 2 * grid))) { // если снизу от мангуста тело змейки '#', но неприкрытое '##'
cutSnake(rabbit.x, rabbit.y + grid, 4); // то кусаем
}
}
}
// пока нет голодания змейки
if (snake.timeHungry > 0) { // пока не голодаем (>0)
snake.timeHungry--; // уменьшаем счетчик сытости
}
// змейка голодает
if (snake.timeHungry === 0) { // голодаем (0) - да
if (--snake.dtHungry === 0) { // отсчитываем очередную дельту до уменьшения длины змейки на 1 кусочек
let temp = snake.cells[--snake.maxCells-1]; // умираем с хвоста
ctx.clearRect(temp.x, temp.y, grid, grid); // стираем хвост змеи (рисуем фоном)
snake.cells.pop(); //
snake.dtHungry = deltaHungry; // новая дельта времени голодания
ctx.fillText("Кушать хочу ", 200, 700);
timeMessage = 4;
// а может сдохли уже - проверяем
if (snake.maxCells === 1) {
snake.tekNapr = 0; // останавливаем змейку
alert('Увы - змейка сдохла от голода - игра окончена')
// Задаем новую змейку
initSnake();
};
}
}
// по заданому направлению смещаем голову змеи
switch (snake.tekNapr) {
case 0: break; // не двигаемся
case 1: snake.x += grid; break; // двигаемся вправо
case 2: snake.y -= grid; break; // двигаемся вверх
case 3: snake.x -= grid; break; // двигаемся влево
case 4: snake.y += grid; break; // двигаемся вниз
}
// ### to do.добавляем параметр для сглаживания углов - pov - поворот 12 - вправо-вверх, 14 - вправо-вниз, 21 - вверх-вправо, 23 - вверх-влево
// 32 - влево-вверх, 34 - влево-вниз, 41 - вниз-вправо, 43 - вниз-влево
if (snake.tekNapr != snake.cells[1].napr) {
snake.tekPov = 0;
switch (snake.cells[1].napr) {
case 0: break; //
case 1: if (snake.tekNapr === 2) snake.tekPov = 12; else if (snake.tekNapr === 4) snake.tekPov = 14; break; // 12 - вправо-вверх, 14 - вправо-вниз
case 2: if (snake.tekNapr === 1) snake.tekPov = 21; else if (snake.tekNapr === 3) snake.tekPov = 23; break; // 21 - вверх-вправо, 23 - вверх-влево
case 3: if (snake.tekNapr === 2) snake.tekPov = 32; else if (snake.tekNapr === 4) snake.tekPov = 34; break; // 32 - влево-вверх, 34 - влево-вниз
case 4: if (snake.tekNapr === 1) snake.tekPov = 41; else if (snake.tekNapr === 3) snake.tekPov = 43; break; // 41 - вниз-вправо, 43 - вниз-влево
}
}
// останова перед вертикальной и горизонтальной границей игрового поля не делаем - а просто перепрыгиваем на противоположную сторону
if (snake.x < 0) snake.x = canvas.width - grid; // при движении влево
else if (snake.x >= canvas.width) snake.x = 0; // при движении вправо
if (snake.y < 32) snake.y = canvas.height - 32 - grid; // при движении вверх
else if (snake.y >= canvas.height - 32) snake.y = 32; // при движении вниз
// проверяем не заткнулась ли змейка на саму себя
// if (colorTest[1] != 0) {
snake.cross = false; // задаем признак что нет пересечения змейки самой себя
if (intoSnake(snake.x, snake.y)) { // и проверяем не пересечет ли голова змейки свое тело (причем проверяем толщину змейки - одиночную или двойную)
let prEnd = false;
setCrossSnake(snake.x, snake.y); // при пересечении змейки самой себя, ставим признак в старое тело змейки, не в голову.
switch (snake.tekNapr) {
case 1: if (intoSnake(snake.x+grid, snake.y) === true) prEnd = true; break; // двигаемся вправо
case 2: if (intoSnake(snake.x, snake.y-grid) === true) prEnd = true; break; // двигаемся вверх
case 3: if (intoSnake(snake.x-grid, snake.y) === true) prEnd = true; break; // двигаемся влево
case 4: if (intoSnake(snake.x, snake.y+grid) === true) prEnd = true; break; // двигаемся вниз
}
if (prEnd) { // но если делее по ходу движения змейки есть кусочек ее тела, то через двойную толщину змеки не переползаем
snake.tekNapr = 0; // останавливаем змейку
alert('Увы - змейка укусила сама себя и скончалась в конвульсиях - игра окончена');
// Задаем новую змейку
initSnake();
}
};
// вводим новое положение головы змейки в массив тела змейки
if (snake.tekNapr > 0) snake.cells.unshift({ x: snake.x, y: snake.y, napr: snake.tekNapr, pov: snake.tekPov, cross: snake.cross });
// убираем хвост из массива. А если длина змейки не выросла, тогда пропускаем удаление последнего элемента массива тела змеи
if (snake.cells.length > snake.maxCells) snake.cells.pop();
/*
ctx.fillStyle = 'green'; // змейку рисуем зеленым
ctx.fillRect(10, 674, grid, grid); // Прорисовываем кусочки тела змеи в качестве легенды
ctx.fillRect(50, 674, grid, grid); // для отладки смещения полосок
ctx.fillRect(90, 674, grid, grid);
ctx.fillRect(130, 674, grid, grid);
//alert('===11111===');
ctx.fillStyle = 'black'; // а полоски на змейке рисуем чёрным
ctx.lineWidth = 1;
for (let j = pols; j < grid; j = j + Npols) {
// движение вправо
ctx.beginPath(); ctx.moveTo(10 + grid - j, 675); ctx.lineTo(10 + grid - j, 674 + grid - 1); ctx.stroke();
// движение вверх
ctx.beginPath(); ctx.moveTo(51, 674 + grid - j); ctx.lineTo(50 + grid - 1, 674 + grid - j); ctx.stroke();
// движение влево
ctx.beginPath(); ctx.moveTo(90 + j, 675); ctx.lineTo(90 + j, 674 + grid - 1); ctx.stroke();
// движение вниз
ctx.beginPath(); ctx.moveTo(131, 674 + j); ctx.lineTo(130 + grid - 1, 674 + j); ctx.stroke();
//alert('===22222===')
}
//alert('===33333===')
*/
let len = snake.cells.length - 1 // текущая длина змейки
ctx.fillStyle = 'green'; // змейку рисуем зеленым
head = snake.cells[0]; // новая позиция головы змейки
body = snake.cells[1]; // прежняя позиция головы змейки - становиться телом
tail = snake.cells[len]; // позиция хвоста змейки - для того чтобы стереть ее
//colorTest = ctx.getImageData(head.x, head.y, 1, 1).data; // для проверки пустоты новой позиции змейки
// Прорисовываем голову змейки (рисуем зеленым)
ctx.fillRect(head.x+1, head.y+1, grid-2, grid-2); // Прорисовываем голову змеи
// и глазки змеи в зависимости от направления
switch (snake.tekNapr) { // левый глаз правый глаз
case 1: ctx.clearRect(head.x + grid - 5, head.y + grid - 5, 2, 2); ctx.clearRect(head.x + grid - 5, head.y + 3, 2, 2); break; // двигаемся вправо
case 2: ctx.clearRect(head.x + grid - 5, head.y + 3, 2, 2); ctx.clearRect(head.x + 3, head.y + 3, 2, 2); break; // двигаемся вверх
case 3: ctx.clearRect(head.x + 3, head.y + 3, 2, 2); ctx.clearRect(head.x + 3, head.y + grid - 5, 2, 2); break; // двигаемся влево
case 4: ctx.clearRect(head.x + 3, head.y + grid - 5, 2, 2); ctx.clearRect(head.x + grid - 5, head.y + grid - 5, 2, 2); break; // двигаемся вниз
}
// прорисовываем тело змеи
for (let i = 1; i <= len; i++) {
body = snake.cells[i];
ctx.fillStyle = 'green'; // змейку рисуем зеленым
ctx.fillRect(body.x, body.y, grid, grid); // Прорисовываем I-й кусочек тела змеи
// прорисовываем полоски на теле змеи в зависимости от направления движения змейки, через два пикселя
// смещая полоски каждый раз на один пиксель за тик.
ctx.fillStyle = 'black'; // а полоски на змейке рисуем чёрным
ctx.lineWidth = 1;
for (let j = pols; j < grid; j = j + Npols) {
ctx.beginPath();
switch (body.napr) {
// двигаемся вправо
case 1: ctx.moveTo(body.x + grid - j, body.y + 1 ); ctx.lineTo(body.x + grid - j, body.y + grid - 1); break;
// двигаемся вверх
case 2: ctx.moveTo(body.x + 1, body.y + grid - j); ctx.lineTo(body.x + grid - 1, body.y + grid - j); break;
// двигаемся ввлево
case 3: ctx.moveTo(body.x + j, body.y + 1 ); ctx.lineTo(body.x + j, body.y + grid - 1); break;
// двигаемся вниз
case 4: ctx.moveTo(body.x + 1, body.y + j ); ctx.lineTo(body.x + grid - 1, body.y + j ); break;
}
ctx.stroke();
}
}
// смещаемся на следующую позицию для полосок
pols++
if (pols > Npols) pols = 1;
// уменьшаем хвост змейки - последние grid/2 (8) кусочки стираем с боков линии в зависимости от направления текущего кусочка и предыдущего
let i = 3; // для последних grid/2 (8) кусочков делаем
if (len > grid / 2 + 2) i = len - grid / 2;
for (let j = 1; i <= len; j++) {
let pred = snake.cells[i - 1].napr // Направление предыдующего кусочка
body = snake.cells[i++];
if (body.cross) continue; // пересечение змейки самой с собой - хвост не рисуем, чтобы не было разрыва в теле змейки
switch (body.napr) { //левый бок правый бок
// двигаемся вправо
case 1: ctx.clearRect(body.x, body.y, grid, j); ctx.clearRect(body.x, body.y + grid - j, grid, j);
switch (pred) {
// повернули наверх
case 2: ctx.clearRect(body.x + grid - j, body.y, j, grid); // срезали правый бок
ctx.fillRect(body.x + j, body.y, grid - j - j, j); break; // дорисовали верх
// повернули вниз
case 4: ctx.clearRect(body.x + grid - j, body.y, j, grid); // срезали правый бок
ctx.fillRect(body.x + j, body.y + grid - j, grid - j - j, j); break; // дорисовали низ
} // для 0, 1, 3 - ничего не меняем
break;
// двигаемся вверх
case 2: ctx.clearRect(body.x + grid - j, body.y, j, grid); ctx.clearRect(body.x, body.y, j, grid);
switch (pred) {
// повернули налево
case 3: ctx.clearRect(body.x, body.y, grid, j); // срезали верхний бок
ctx.fillRect(body.x, body.y + j, j, grid - j - j); break; // дорисовали слева
// повернули направо
case 1: ctx.clearRect(body.x, body.y, grid, j); // срезали верхний бок
ctx.fillRect(body.x + grid - j, body.y + j, j, grid - j - j); break; // дорисовали справа
} // для 0, 2, 4 - ничего не меняем
break;
// двигаемся влево
case 3: ctx.clearRect(body.x, body.y, grid, j); ctx.clearRect(body.x, body.y + grid - j, grid, j);
switch (pred) {
// повернули наверх
case 2: ctx.clearRect(body.x, body.y, j, grid); // срезали левый бок
ctx.fillRect(body.x + j, body.y, grid - j - j, j); break; // дорисовали верх
// повернули вниз
case 4: ctx.clearRect(body.x, body.y, j, grid); // срезали левый бок
ctx.fillRect(body.x + j, body.y + grid - j, grid - j - j, j); break; // дорисовали низ
} // для 0, 1, 3 - ничего не меняем
break;
// двигаемся вниз
case 4: ctx.clearRect(body.x + grid - j, body.y, j, grid); ctx.clearRect(body.x, body.y, j, grid);
switch (pred) {
// повернули налево
case 3: ctx.clearRect(body.x, body.y + grid - j, grid, j); // срезали нижний бок
ctx.fillRect(body.x, body.y + j, j, grid - j - j); break; // дорисовали слева
// повернули направо
case 1: ctx.clearRect(body.x, body.y + grid - j, grid, j); // срезали нижний бок
ctx.fillRect(body.x + grid - j, body.y + j, j, grid - j - j); break; // дорисовали справа
} // для 0, 2, 4 - ничего не меняем
break;
}
}
// Стираем хвост змеи (рисуем фоном)/ Но если хвост сползает с точки пересечения, то не убираем точку пересечения, чтобы не было разрыва в змейке.
if (tail.cross === false) ctx.clearRect(tail.x, tail.y, grid, grid);
// проверяем не съели ли кролика
// if ((colorTest[0] == 255) || (colorTest[0] == 127)) { // - это была проверка по цвету элемента
for (let rabbit of rabbmang) {
if (head.x === rabbit.x && head.y === rabbit.y /* && rabbit.ty == 0*/ ) {
// если съели - увеличиваем тело змейки на вес кролика - но на следующем ходе оставим p кусочеков тела змейки нестертыми
for (let i = 0; i < rabbit.p; i++) { snake.maxCells++ };
let indexRabbit = rabbmang.indexOf(rabbit);
let temp = rabbmang.splice(indexRabbit, 1);
// выключаем голодание змейки
snake.timeHungry = Hungry;
snake.dtHungry = deltaHungry;
break;
}
}
}
// обработчик событий - нажатия на кнопки "влево" (37) и вправо (39)
document.addEventListener('keydown', function (e) {
if (e.which === 37) { // при нажатии влево смещаем направление по кругу на следующее
snake.tekNapr += 1;
if (snake.tekNapr == 5) { // замыкаем круг по следующему направлению
snake.tekNapr = 1;
}
}
if (e.which === 39) { // при нажатии вправо смещаем направление по кругу на предыдующее
snake.tekNapr -= 1;
if (snake.tekNapr == 0) { // замыкаем круг по предыдующему направлению
snake.tekNapr = 4;
}
}
});
// Начало игры
// обнуляем игровое поле
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Задаем змейку и выставляем первого кролика в случайном месте игрового поля
initSnake();
// Запускаем первый анимационный цикл
requestAnimationFrame(loop);
</script>
</body>
</html>