Изменение поля в игре
Всем привет. Нужна помощь. При написании игры "ЖИЗНЬ" столкнулся с проблемой, при выставлении нужного нам размера игры в поле ввода "ширина и высота", меняется размер. Сейчас все построено на том, что у поля постоянный размер(т.е. если например выставить размер игры 500х500, игра будет работать только в поле 300х300 т.к. это стандартный размер). Как это можно реализовать?
Ссылка на работу игры: https://codepen.io/Siarhei1607/pen/JjWYpqW |
prototip,
забавно ... else { mas2[i][j] == 0; } |
игра жизнь canvas
prototip,
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <style type="text/css"> #canvas { width: 300; height: 300; border: 2px solid black; margin: 40px; } </style> <title>life</title> </head> <body> <canvas id="canvas" width="300" height="300"></canvas> <label for="height">Высота:</label> <input type="text" class="inputText" id="height" value="500"/> <label for="width">Ширина:</label> <input type="text" class="inputText" id="width" value="500"/> <input type="button" value="Создать поле" class="btn red" id="create" /> <p>Таймер: <span id="count">0</span></p> <button id="start">Start</button> <script> let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); let width = document.getElementById("width"); let height = document.getElementById("height"); let mas = []; let count = 0; let timer; canvas.onclick = function(event) { let x = event.offsetX; let y = event.offsetY; x = Math.floor(x / 10); y = Math.floor(y / 10); mas[y][x] = 1; drawField(); }; function resizeCanvas() { canvas.width = width.value; canvas.height = height.value; goLife(); } function goLife() { let width = canvas.width; let height = canvas.height; let n = width / 10; let m = height / 10; for (let i = 0; i < m; i++) { mas[i] = []; for (let j = 0; j < n; j++) { mas[i][j] = 0; } } } goLife(); function drawField() { let width = canvas.width; let height = canvas.height; ctx.clearRect(0, 0, width, height); for (let i = 0; i < height / 10; i++) { for (let j = 0; j < width / 10; j++) { if (mas[i][j] == 1) { ctx.fillRect(j * 10, i * 10, 10, 10); } } } } function startLife() { let mas2 = []; let width = canvas.width; let height = canvas.height; for (let i = 0; i < height / 10; i++) { mas2[i] = []; for (let j = 0; j < width / 10; j++) { let neighbors = [-1, 1].reduce((a, b) => { b = mas[i + b]; if(b === void(0)) return a; let num = b[j]; if(b[j + 1] !== void(0)) num += b[j + 1]; if(b[j - 1] !== void(0)) num += b[j - 1]; return a + num; }, 0); neighbors = [-1, 1].reduce((a, b) => a += mas[i][j + b] !== void(0) && mas[i][j + b], neighbors); if (neighbors == 2 || neighbors == 3) { mas2[i][j] = 1; } else { mas2[i][j] = 0; }; } } mas = mas2; drawField(); count++; document.getElementById('count').innerHTML = count; timer = setTimeout(startLife, 300); } document.getElementById("create").onclick = resizeCanvas; document.getElementById("start").onclick = startLife; </script> </body> </html> |
рони,
не верно, если я сейчас выставлю ширину и высоту игрового поля 500х500, то квадратики в нижней части не будут ставится да и если нажать на кнопку start, игра не запустится |
Цитата:
|
рони,
Большое спасибо) |
prototip,
лучше сократить все вычисления ширины и высоты до одного раза, а не делать это в каждой функции, есть и другие места для оптимизации. |
рони, тут я с вами согласен. Обьясните пожалуйста почему, когда я выношу эти переменные ширины и высоты в глобальную переменную, код перестает работать?
let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); let widthInput = document.getElementById("width"); let heightInput = document.getElementById("height"); let width = canvas.width; let height = canvas.height; let n = width / 10; let m = height / 10; let xRect= 10; let yRect= 10; let mas = []; let count = 0; let timer; canvas.onclick = function (event) { let x = event.offsetX; let y = event.offsetY; x = Math.floor(x / 10); y = Math.floor(y / 10); mas[y][x] = 1; drawField(); }; function resizeCanvas(){ canvas.width = widthInput.value; canvas.height = heightInput.value; goLife(); } function goLife() { for (let i = 0; i < m; i++) { mas[i] = []; for (let j = 0; j < n; j++) { mas[i][j] = 0; } } } goLife(); function drawField(){ ctx.clearRect(0, 0, width, height); for (let i = 0; i < m; i++) { for (let j = 0; j < n / 10; j++) { if (mas[i][j] === 1) { ctx.fillRect(j * xRect, i * yRect, 10, 10); } } } } function startLife() { let mas2 = []; for (let i = 0; i < m; i++) { mas2[i] = []; for (let j = 0; j < n; j++) { let neighbors = [-1, 1].reduce((a, b) => { b = mas[i + b]; if(b === undefined) return a; let num = b[j]; if(b[j + 1] !== undefined) { num += b[j + 1] } if(b[j - 1] !== undefined) { num += b[j - 1] } return a + num; }, 0); neighbors = [-1, 1].reduce((a, b) => a += mas[i][j + b] !== undefined && mas[i][j + b], neighbors); if (neighbors == 2 || neighbors == 3) { mas2[i][j] = 1; } else { mas2[i][j] = 0; }; } } mas = mas2; drawField(); count++; document.getElementById('count').innerHTML = count; timer = setTimeout(startLife, 300); } function pauseLife(){ clearInterval(timer) } function stopLife(){ } document.getElementById("create").onclick = resizeCanvas; document.getElementById("start").onclick = startLife; document.getElementById("pause").onclick = pauseLife; document.getElementById("stop").onclick = stopLife; |
prototip,
объявлять надо глобально, а присваивать значение только в goLife() |
рони,
последний вопрос и я отстану от вас) Подскажите пожалуйста, как сделать, чтобы при нажатии кнопки "Стоп" игра остановилась, таймер сбросился на ноль и я смог заново начать игру |
Цитата:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <style type="text/css"> #canvas { width: 300; height: 300; border: 2px solid black; margin: 40px; } </style> </head> <body> <canvas id="canvas" width="300" height="300"></canvas> <label for="height">Высота:</label> <input type="text" class="inputText" id="height" value="330" /> <label for="width">Ширина:</label> <input type="text" class="inputText" id="width" value="220" /> <input type="button" value="Создать поле" class="btn red" id="create" /> <p>Таймер: <span id="count">0</span></p> <button id="start">Start</button> <button id="pause">Pause</button> <button id="stop">Stop</button> <script> let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); let widthInput = document.getElementById("width"); let heightInput = document.getElementById("height"); let count = document.getElementById('count'); let width, height, n, m; let xRect = 7; let yRect = 19; let mas = []; let timer; canvas.onclick = function(event) { event.stopPropagation(); let x = event.offsetX; let y = event.offsetY; x = Math.floor(x / xRect); y = Math.floor(y / yRect); mas[y][x] = 1; drawField(); }; function resizeCanvas() { canvas.width = widthInput.value = (widthInput.value/xRect|0) * xRect; canvas.height = heightInput.value = (heightInput.value/yRect|0) * yRect; width = canvas.width; height = canvas.height; n = width / xRect; m = height / yRect; goLife(); } function goLife() { for (let i = 0; i < m; i++) { mas[i] = []; for (let j = 0; j < n; j++) { mas[i][j] = 0; } } } resizeCanvas(); function drawField() { ctx.clearRect(0, 0, width, height); for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { if (mas[i][j] === 1) { ctx.fillRect(j * xRect, i * yRect, xRect, yRect); } } } } function startLife() { let mas2 = []; for (let i = 0; i < m; i++) { mas2[i] = []; for (let j = 0; j < n; j++) { let neighbors = [-1, 1].reduce((a, b) => { b = mas[i + b]; if (b === undefined) return a; let num = b[j]; if (b[j + 1] !== undefined) { num += b[j + 1] } if (b[j - 1] !== undefined) { num += b[j - 1] } return a + num; }, 0); neighbors = [-1, 1].reduce((a, b) => a += mas[i][j + b] !== undefined && mas[i][j + b], neighbors); mas2[i][j] = +(neighbors == 2 || neighbors == 3) } } mas = mas2; drawField(); count.innerHTML++; timer = setTimeout(startLife, 300); } function pauseLife() { clearInterval(timer) } function stopLife() { pauseLife(); goLife(); drawField(); count.innerHTML = 0; } document.getElementById("create").onclick = resizeCanvas; document.getElementById("start").onclick = startLife; document.getElementById("pause").onclick = pauseLife; document.getElementById("stop").onclick = stopLife; </script> </body> </html> |
рони,
спасибо |
рони,
prototip, Насколько я помню, логика в этой игре другая. |
|
ekaterina22,
согласен, правила игру другие, спасибо что нашли мне новую работёнку) |
ekaterina22,
Цитата:
mas2[i][j] = +(neighbors == 3 || (mas[i][j] && neighbors == 2)); |
рони,
подскажите пожалуйста, начал тестить игру и если выставить большие размеры поля игры(например 100000х100000) игра падает из-за ошибки по памяти. Поэтому решил показывать предупреждение, что такой размер нельзя создать. Вставил после 55 строки: if(canvas.width >= 1000 || canvas.height >= 1000) { alert("Максимальный размер поля игры 1000") } вылетает предупреждение алерт с моим текстом, и при нажатии кнопки ОК, поле создается. Как сделать, чтобы после нажатия ОК поле не создавалось, а можно было бы вводить заново новый размер. Или есть другой способ как это можно сделать? |
prototip,
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <style type="text/css"> #canvas { width: 300; height: 300; border: 2px solid black; margin: 40px; } </style> </head> <body> <canvas id="canvas" width="300" height="300"></canvas> <label for="height">Высота:</label> <input type="text" class="inputText" id="height" value="147" /> <label for="width">Ширина:</label> <input type="text" class="inputText" id="width" value="147" /> <input type="button" value="Создать поле" class="btn red" id="create" /> <p>Таймер: <span id="count">0</span></p> <button id="start">Start</button> <button id="pause">Pause</button> <button id="stop">Stop</button> <script> let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); let widthInput = document.getElementById("width"); let heightInput = document.getElementById("height"); let count = document.getElementById('count'); let width, height, n, m; let xRect = 10; let yRect = 10; let mas = []; let timer; let maxWidth = 1000; let maxHeight = 1000; canvas.onclick = function(event) { event.stopPropagation(); let x = event.offsetX; let y = event.offsetY; x = Math.floor(x / xRect); y = Math.floor(y / yRect); mas[y][x] = 1; drawField(); }; function resizeCanvas() { width = Math.min(widthInput.value, maxWidth); height = Math.min(heightInput.value, maxHeight); let str = ""; if(width == maxWidth) str += ` Установлена максимальная ширина поля игры ${maxWidth}` if(height == maxHeight) str += ` Установлена максимальная высота поля игры ${maxWidth}` if(str) alert(str); width = Math.trunc(width/xRect) * xRect; height = Math.trunc(height/yRect) * yRect; canvas.width = widthInput.value = width; canvas.height = heightInput.value = height; n = width / xRect; m = height / yRect; goLife(); } function goLife() { for (let i = 0; i < m; i++) { mas[i] = []; for (let j = 0; j < n; j++) { mas[i][j] = 0; } } } resizeCanvas(); function drawField() { ctx.clearRect(0, 0, width, height); for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { if (mas[i][j] === 1) { ctx.fillRect(j * xRect, i * yRect, xRect, yRect); } } } } function startLife() { pauseLife(); let mas2 = []; for (let i = 0; i < m; i++) { mas2[i] = []; for (let j = 0; j < n; j++) { let neighbors = [-1, 1].reduce((a, b) => { b = mas[i + b]; if (b === undefined) return a; let num = b[j]; if (b[j + 1] !== undefined) { num += b[j + 1] } if (b[j - 1] !== undefined) { num += b[j - 1] } return a + num; }, 0); neighbors = [-1, 1].reduce((a, b) => a += mas[i][j + b] !== undefined && mas[i][j + b], neighbors); mas2[i][j] = +(neighbors == 3 || (mas[i][j] && neighbors == 2)); } } mas = mas2; drawField(); count.innerHTML++; timer = setTimeout(startLife, 300); } function pauseLife() { clearInterval(timer) } function stopLife() { pauseLife(); goLife(); drawField(); count.innerHTML = 0; } document.getElementById("create").onclick = resizeCanvas; document.getElementById("start").onclick = startLife; document.getElementById("pause").onclick = pauseLife; document.getElementById("stop").onclick = stopLife; </script> </body> </html> |
рони,
спасибо за помощь |
рони,
подскажите пожалуйста, при многократном нажатии на кнопку start скорость игры увеличивается с каждым нажатием, при этом нужно столько же нажать на кнопку стоп, чтобы остановить игру. Решил этот баг убрать, но итоге решил добавить 3 радиокнопки, которые будут настраивать скорость игры(low, medium, hight), при этом medium скорость будет стоять по умолчанию. как это можно реализовать? <label>Speed:</label> <input type="radio" id="low" /> <label>low </label> <input type="radio" id="medium" checked/> <label>medium </label> <input type="radio" id="hight" /> <label>hight </label> |
Цитата:
|
Цитата:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <style type="text/css"> #canvas { width: 300; height: 300; border: 2px solid black; margin: 40px; } </style> </head> <body> <canvas id="canvas" width="300" height="300"></canvas> <label for="height">Высота:</label> <input type="text" class="inputText" id="height" value="147" /> <label for="width">Ширина:</label> <input type="text" class="inputText" id="width" value="147" /> <input type="button" value="Создать поле" class="btn red" id="create" /> <p>Таймер: <span id="count">0</span></p> <button id="start">Start</button> <button id="pause">Pause</button> <button id="stop">Stop</button> <label>Speed:</label> <label><input type="radio" name="speed" value="800"/>low</label> <label><input type="radio" name="speed" value="300" checked/>medium</label> <label><input type="radio" name="speed" value="100"/>hight</label> <script> let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); let widthInput = document.getElementById("width"); let heightInput = document.getElementById("height"); let count = document.getElementById('count'); let width, height, n, m; let xRect = 10; let yRect = 10; let mas = []; let timer; let maxWidth = 1000; let maxHeight = 1000; canvas.onclick = function(event) { event.stopPropagation(); let x = event.offsetX; let y = event.offsetY; x = Math.floor(x / xRect); y = Math.floor(y / yRect); mas[y][x] = 1; drawField(); }; function resizeCanvas() { width = Math.min(widthInput.value, maxWidth); height = Math.min(heightInput.value, maxHeight); let str = ""; if(width == maxWidth) str += ` Установлена максимальная ширина поля игры ${maxWidth}` if(height == maxHeight) str += ` Установлена максимальная высота поля игры ${maxWidth}` if(str) alert(str); width = Math.trunc(width/xRect) * xRect; height = Math.trunc(height/yRect) * yRect; canvas.width = widthInput.value = width; canvas.height = heightInput.value = height; n = width / xRect; m = height / yRect; goLife(); } function goLife() { for (let i = 0; i < m; i++) { mas[i] = []; for (let j = 0; j < n; j++) { mas[i][j] = 0; } } } resizeCanvas(); function drawField() { ctx.clearRect(0, 0, width, height); for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { if (mas[i][j] === 1) { ctx.fillRect(j * xRect, i * yRect, xRect, yRect); } } } } function startLife() { pauseLife(); let mas2 = []; for (let i = 0; i < m; i++) { mas2[i] = []; for (let j = 0; j < n; j++) { let neighbors = [-1, 1].reduce((a, b) => { b = mas[i + b]; if (b === undefined) return a; let num = b[j]; if (b[j + 1] !== undefined) { num += b[j + 1] } if (b[j - 1] !== undefined) { num += b[j - 1] } return a + num; }, 0); neighbors = [-1, 1].reduce((a, b) => a += mas[i][j + b] !== undefined && mas[i][j + b], neighbors); mas2[i][j] = +(neighbors == 3 || (mas[i][j] && neighbors == 2)); } } mas = mas2; drawField(); count.innerHTML++; const delay = document.querySelector("[name='speed']:checked").value; timer = setTimeout(startLife, delay); } function pauseLife() { clearInterval(timer) } function stopLife() { pauseLife(); goLife(); drawField(); count.innerHTML = 0; } document.getElementById("create").onclick = resizeCanvas; document.getElementById("start").onclick = startLife; document.getElementById("pause").onclick = pauseLife; document.getElementById("stop").onclick = stopLife; </script> </body> </html> |
рони,
Интересное решение, не думал что решается так просто, пробовал сделать через условия, но получалось ерунда. Спасибо:thanks: |
Часовой пояс GMT +3, время: 22:58. |