Изменение поля в игре
Всем привет. Нужна помощь. При написании игры "ЖИЗНЬ" столкнулся с проблемой, при выставлении нужного нам размера игры в поле ввода "ширина и высота", меняется размер. Сейчас все построено на том, что у поля постоянный размер(т.е. если например выставить размер игры 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, время: 06:09. |