Змейка 2021 — различия между версиями
Материал из Department of Theoretical and Applied Mechanics
(Новая страница: «{{#widget:Iframe |url=https://jlg8457.github.io/Zmeyka2021/Snake.html |width=900 |height=900 |border=0 }}») |
|||
Строка 1: | Строка 1: | ||
− | {{#widget:Iframe |url=https://jlg8457.github.io/Zmeyka2021/Snake.html |width= | + | Работу выполнили студенты гр. 3630103/00003 [[Корнелюк Алексей|Корнелюк Алексей]], [[Гришина Юлия|Гришина Юлия]]. |
+ | |||
+ | {{#widget:Iframe |url=https://jlg8457.github.io/Zmeyka2021/Snake.html |width=1525 |height=900 |border=0 }} | ||
+ | |||
+ | ==Код программы== | ||
+ | <div class="mw-collapsible mw-collapsed"> | ||
+ | '''Код программы на языке JavaScript:''' <div class="mw-collapsible-content"> | ||
+ | <syntaxhighlight lang="javascript" line start="1" enclose="div"> | ||
+ | |||
+ | Описание кода JavaScript: | ||
+ | |||
+ | <script type="text/javascript"> | ||
+ | |||
+ | var isCrash = false; //если true, произошло столкновение | ||
+ | var IsClicked = false; //если true, за одно перемещение змейки нажата какая-то стрелка | ||
+ | //иначе, если нажать стрелку несколько раз, может случиться "столкновение" без реального столкновения | ||
+ | //связано с функцией, пропускающей несколько кадров (но не кликов) для замедления змейки | ||
+ | var canvas = document.getElementById('game'); | ||
+ | var context = canvas.getContext('2d'); | ||
+ | |||
+ | var current = 3; //текущий счет, стартовый | ||
+ | |||
+ | function reload () { //перегрузка страницы (кнопка «Play again») | ||
+ | window.location.reload(); | ||
+ | } | ||
+ | |||
+ | function again(){ //запускается после Play again, воссоздает начальные условия | ||
+ | current = 3; | ||
+ | current1.innerHTML = current; | ||
+ | snake.x = 150; | ||
+ | snake.y = 150; | ||
+ | snake.cells = []; | ||
+ | snake.maxCells = 3; | ||
+ | snake.dx = grid; | ||
+ | snake.dy = 0; | ||
+ | //ставим яблоко в случайное место | ||
+ | apple.x = getRandomInt(0, 28) * grid; | ||
+ | apple.y = getRandomInt(0, 28) * grid; | ||
+ | } | ||
+ | |||
+ | // генератор случайных чисел в заданном диапазоне | ||
+ | function getRandomInt(min, max) { | ||
+ | return Math.floor(Math.random() * (max - min)) + min; | ||
+ | } | ||
+ | |||
+ | |||
+ | // размер одной клеточки — 25 пикселей | ||
+ | var grid = 25; | ||
+ | // переменная, которая отвечает за скорость змейки | ||
+ | var count = 0; | ||
+ | |||
+ | var snake = { | ||
+ | // начальные координаты | ||
+ | x: 150, | ||
+ | y: 150, | ||
+ | // скорость змейки — в каждом новом кадре змейка смещается по оси Х или У. | ||
+ | //изначально будет двигаться горизонтально, поэтому скорость по игреку равна нулю. | ||
+ | dx: grid, | ||
+ | dy: 0, | ||
+ | // массив с координатами хвоста, изначально пустой | ||
+ | cells: [], | ||
+ | // стартовая длина змейки — 3 клеточки | ||
+ | maxCells: 3 | ||
+ | }; | ||
+ | |||
+ | var apple = { | ||
+ | // начальные координаты яблока | ||
+ | x: 300, | ||
+ | y: 300 | ||
+ | } | ||
+ | // игровой цикл — основной процесс, внутри которого будет всё происходить | ||
+ | function loop() { | ||
+ | // функция, которая замедляет скорость игры. | ||
+ | // для этого она пропускает (stop-1) кадр, то есть срабатывает каждый кадр с номером stop | ||
+ | |||
+ | if (!isCrash){ //но только в случае, если нет столкновения, иначе ничего не делать | ||
+ | requestAnimationFrame(loop); | ||
+ | } | ||
+ | |||
+ | //далее сам замедляющий механизм | ||
+ | if (current <= 15){ // замедляем до 7 кадров, не более | ||
+ | stop = 12 - Math.ceil(current / 3); | ||
+ | } | ||
+ | count+= 1; | ||
+ | |||
+ | if (count < stop) { | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | // обнуляем переменную скорости кадров | ||
+ | count = 0; | ||
+ | // Очищаем игровое поле | ||
+ | context.clearRect(0, 0, canvas.width, canvas.height); | ||
+ | // Двигаем змейку с нужной скоростью | ||
+ | snake.x += snake.dx; | ||
+ | snake.y += snake.dy; | ||
+ | // Если змейка достигла края поля по — продолжаем её движение с противоположной стороны | ||
+ | if (snake.x < 0) { | ||
+ | snake.x = canvas.width - grid; | ||
+ | } | ||
+ | else if (snake.x >= canvas.width) { | ||
+ | snake.x = 0; | ||
+ | } | ||
+ | if (snake.y < 0) { | ||
+ | snake.y = canvas.height - grid; | ||
+ | } | ||
+ | else if (snake.y >= canvas.height) { | ||
+ | snake.y = 0; | ||
+ | } | ||
+ | |||
+ | // Продолжаем двигаться в выбранном направлении. Голова всегда впереди, поэтому добавляем её координаты в начало массива, который отвечает за всю змейку. | ||
+ | snake.cells.unshift({ x: snake.x, y: snake.y }); | ||
+ | // Сразу после этого удаляем последний элемент из массива змейки, потому что она движется и постоянно особождает клетки после себя | ||
+ | if (snake.cells.length > snake.maxCells) { | ||
+ | snake.cells.pop(); | ||
+ | } | ||
+ | // Рисуем красное яблоко | ||
+ | context.fillStyle = 'red'; | ||
+ | context.fillRect(apple.x, apple.y, grid - 1, grid - 1); | ||
+ | // Одно движение змейки — один новый нарисованный квадратик | ||
+ | |||
+ | // Обрабатываем каждый элемент змейки | ||
+ | snake.cells.forEach(function (cell, index) { | ||
+ | // Чтобы создать эффект клеточек, делаем зелёные квадратики меньше на один пиксель, чтобы вокруг них образовалась чёрная граница | ||
+ | context.fillStyle = 'green'; | ||
+ | context.fillRect(cell.x, cell.y, grid - 1, grid - 1); | ||
+ | |||
+ | // Если змейка добралась до яблока | ||
+ | if (cell.x === apple.x && cell.y === apple.y) { | ||
+ | current += 1; | ||
+ | current1.innerHTML = current; | ||
+ | |||
+ | // увеличиваем длину змейки | ||
+ | snake.maxCells++; | ||
+ | // Рисуем новое яблоко | ||
+ | // На поле умещается 28 ячеек | ||
+ | apple.x = getRandomInt(0, 28) * grid; | ||
+ | apple.y = getRandomInt(0, 28) * grid; | ||
+ | console.log(apple); | ||
+ | } | ||
+ | // Проверяем, не столкнулась ли змея сама с собой | ||
+ | // Для этого перебираем весь массив и смотрим, есть ли у нас в массиве змейки две клетки с одинаковыми координатами | ||
+ | for (var i = index + 1; i < snake.cells.length; i++) { | ||
+ | // Если такие клетки есть — начинаем игру заново | ||
+ | if (cell.x === snake.cells[i].x && cell.y === snake.cells[i].y) { | ||
+ | xCrash = cell.x; //запомним координаты столкновения | ||
+ | yCrash = cell.y; | ||
+ | isCrash = true; | ||
+ | } | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | if (isCrash){ //выделим место столкновения фиолетовым | ||
+ | context.fillStyle = 'violet'; | ||
+ | context.fillRect(xCrash, yCrash, grid - 1, grid - 1); | ||
+ | } | ||
+ | isClicked = false; //обнулим счетчик кликов, чтобы можно было кликать в новом loop | ||
+ | } //the end of loop | ||
+ | |||
+ | |||
+ | |||
+ | // Смотрим, какие нажимаются клавиши, и реагируем на них нужным образом | ||
+ | document.addEventListener('keydown', function (e) { | ||
+ | |||
+ | // Стрелка влево | ||
+ | // Если нажата стрелка влево, и при этом змейка никуда не движется по горизонтали… | ||
+ | if (!isClicked){ | ||
+ | if (e.which === 37 && snake.dx === 0) { | ||
+ | // То даём ей движение по горизонтали, влево, а вертикальное — останавливаем | ||
+ | // Та же самая логика будет и в остальных кнопках | ||
+ | snake.dx = -grid; | ||
+ | snake.dy = 0; | ||
+ | isClicked = true; //больше в этом цикле кликать нельзя | ||
+ | } | ||
+ | // Стрелка вверх | ||
+ | else if (e.which === 38 && snake.dy === 0) { | ||
+ | snake.dy = -grid; | ||
+ | snake.dx = 0; | ||
+ | isClicked = true; | ||
+ | } | ||
+ | // Стрелка вправо | ||
+ | else if (e.which === 39 && snake.dx === 0) { | ||
+ | snake.dx = grid; | ||
+ | snake.dy = 0; | ||
+ | isClicked = true; | ||
+ | } | ||
+ | // Стрелка вниз | ||
+ | else if (e.which === 40 && snake.dy === 0) { | ||
+ | snake.dy = grid; | ||
+ | snake.dx = 0; | ||
+ | isClicked = true; | ||
+ | } | ||
+ | } | ||
+ | }); | ||
+ | requestAnimationFrame(loop); //запускаем бесконечный цикл | ||
+ | |||
+ | </script> | ||
+ | </syntaxhighlight> | ||
+ | </div> |
Текущая версия на 00:19, 6 мая 2021
Работу выполнили студенты гр. 3630103/00003 Корнелюк Алексей, Гришина Юлия.
Код программы[править]
Код программы на языке JavaScript:
1 Описание кода JavaScript:
2
3 <script type="text/javascript">
4
5 var isCrash = false; //если true, произошло столкновение
6 var IsClicked = false; //если true, за одно перемещение змейки нажата какая-то стрелка
7 //иначе, если нажать стрелку несколько раз, может случиться "столкновение" без реального столкновения
8 //связано с функцией, пропускающей несколько кадров (но не кликов) для замедления змейки
9 var canvas = document.getElementById('game');
10 var context = canvas.getContext('2d');
11
12 var current = 3; //текущий счет, стартовый
13
14 function reload () { //перегрузка страницы (кнопка «Play again»)
15 window.location.reload();
16 }
17
18 function again(){ //запускается после Play again, воссоздает начальные условия
19 current = 3;
20 current1.innerHTML = current;
21 snake.x = 150;
22 snake.y = 150;
23 snake.cells = [];
24 snake.maxCells = 3;
25 snake.dx = grid;
26 snake.dy = 0;
27 //ставим яблоко в случайное место
28 apple.x = getRandomInt(0, 28) * grid;
29 apple.y = getRandomInt(0, 28) * grid;
30 }
31
32 // генератор случайных чисел в заданном диапазоне
33 function getRandomInt(min, max) {
34 return Math.floor(Math.random() * (max - min)) + min;
35 }
36
37
38 // размер одной клеточки — 25 пикселей
39 var grid = 25;
40 // переменная, которая отвечает за скорость змейки
41 var count = 0;
42
43 var snake = {
44 // начальные координаты
45 x: 150,
46 y: 150,
47 // скорость змейки — в каждом новом кадре змейка смещается по оси Х или У.
48 //изначально будет двигаться горизонтально, поэтому скорость по игреку равна нулю.
49 dx: grid,
50 dy: 0,
51 // массив с координатами хвоста, изначально пустой
52 cells: [],
53 // стартовая длина змейки — 3 клеточки
54 maxCells: 3
55 };
56
57 var apple = {
58 // начальные координаты яблока
59 x: 300,
60 y: 300
61 }
62 // игровой цикл — основной процесс, внутри которого будет всё происходить
63 function loop() {
64 // функция, которая замедляет скорость игры.
65 // для этого она пропускает (stop-1) кадр, то есть срабатывает каждый кадр с номером stop
66
67 if (!isCrash){ //но только в случае, если нет столкновения, иначе ничего не делать
68 requestAnimationFrame(loop);
69 }
70
71 //далее сам замедляющий механизм
72 if (current <= 15){ // замедляем до 7 кадров, не более
73 stop = 12 - Math.ceil(current / 3);
74 }
75 count+= 1;
76
77 if (count < stop) {
78 return;
79 }
80
81 // обнуляем переменную скорости кадров
82 count = 0;
83 // Очищаем игровое поле
84 context.clearRect(0, 0, canvas.width, canvas.height);
85 // Двигаем змейку с нужной скоростью
86 snake.x += snake.dx;
87 snake.y += snake.dy;
88 // Если змейка достигла края поля по — продолжаем её движение с противоположной стороны
89 if (snake.x < 0) {
90 snake.x = canvas.width - grid;
91 }
92 else if (snake.x >= canvas.width) {
93 snake.x = 0;
94 }
95 if (snake.y < 0) {
96 snake.y = canvas.height - grid;
97 }
98 else if (snake.y >= canvas.height) {
99 snake.y = 0;
100 }
101
102 // Продолжаем двигаться в выбранном направлении. Голова всегда впереди, поэтому добавляем её координаты в начало массива, который отвечает за всю змейку.
103 snake.cells.unshift({ x: snake.x, y: snake.y });
104 // Сразу после этого удаляем последний элемент из массива змейки, потому что она движется и постоянно особождает клетки после себя
105 if (snake.cells.length > snake.maxCells) {
106 snake.cells.pop();
107 }
108 // Рисуем красное яблоко
109 context.fillStyle = 'red';
110 context.fillRect(apple.x, apple.y, grid - 1, grid - 1);
111 // Одно движение змейки — один новый нарисованный квадратик
112
113 // Обрабатываем каждый элемент змейки
114 snake.cells.forEach(function (cell, index) {
115 // Чтобы создать эффект клеточек, делаем зелёные квадратики меньше на один пиксель, чтобы вокруг них образовалась чёрная граница
116 context.fillStyle = 'green';
117 context.fillRect(cell.x, cell.y, grid - 1, grid - 1);
118
119 // Если змейка добралась до яблока
120 if (cell.x === apple.x && cell.y === apple.y) {
121 current += 1;
122 current1.innerHTML = current;
123
124 // увеличиваем длину змейки
125 snake.maxCells++;
126 // Рисуем новое яблоко
127 // На поле умещается 28 ячеек
128 apple.x = getRandomInt(0, 28) * grid;
129 apple.y = getRandomInt(0, 28) * grid;
130 console.log(apple);
131 }
132 // Проверяем, не столкнулась ли змея сама с собой
133 // Для этого перебираем весь массив и смотрим, есть ли у нас в массиве змейки две клетки с одинаковыми координатами
134 for (var i = index + 1; i < snake.cells.length; i++) {
135 // Если такие клетки есть — начинаем игру заново
136 if (cell.x === snake.cells[i].x && cell.y === snake.cells[i].y) {
137 xCrash = cell.x; //запомним координаты столкновения
138 yCrash = cell.y;
139 isCrash = true;
140 }
141 }
142 });
143
144 if (isCrash){ //выделим место столкновения фиолетовым
145 context.fillStyle = 'violet';
146 context.fillRect(xCrash, yCrash, grid - 1, grid - 1);
147 }
148 isClicked = false; //обнулим счетчик кликов, чтобы можно было кликать в новом loop
149 } //the end of loop
150
151
152
153 // Смотрим, какие нажимаются клавиши, и реагируем на них нужным образом
154 document.addEventListener('keydown', function (e) {
155
156 // Стрелка влево
157 // Если нажата стрелка влево, и при этом змейка никуда не движется по горизонтали…
158 if (!isClicked){
159 if (e.which === 37 && snake.dx === 0) {
160 // То даём ей движение по горизонтали, влево, а вертикальное — останавливаем
161 // Та же самая логика будет и в остальных кнопках
162 snake.dx = -grid;
163 snake.dy = 0;
164 isClicked = true; //больше в этом цикле кликать нельзя
165 }
166 // Стрелка вверх
167 else if (e.which === 38 && snake.dy === 0) {
168 snake.dy = -grid;
169 snake.dx = 0;
170 isClicked = true;
171 }
172 // Стрелка вправо
173 else if (e.which === 39 && snake.dx === 0) {
174 snake.dx = grid;
175 snake.dy = 0;
176 isClicked = true;
177 }
178 // Стрелка вниз
179 else if (e.which === 40 && snake.dy === 0) {
180 snake.dy = grid;
181 snake.dx = 0;
182 isClicked = true;
183 }
184 }
185 });
186 requestAnimationFrame(loop); //запускаем бесконечный цикл
187
188 </script>