Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Изменение поля в игре (https://javascript.ru/forum/misc/82489-izmenenie-polya-v-igre.html)

prototip 15.05.2021 12:12

Изменение поля в игре
 
Всем привет. Нужна помощь. При написании игры "ЖИЗНЬ" столкнулся с проблемой, при выставлении нужного нам размера игры в поле ввода "ширина и высота", меняется размер. Сейчас все построено на том, что у поля постоянный размер(т.е. если например выставить размер игры 500х500, игра будет работать только в поле 300х300 т.к. это стандартный размер). Как это можно реализовать?
Ссылка на работу игры:
https://codepen.io/Siarhei1607/pen/JjWYpqW

рони 15.05.2021 13:58

prototip,
забавно ...

else {
mas2[i][j] == 0;
}

рони 15.05.2021 14:07

игра жизнь 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>

prototip 15.05.2021 14:50

рони,
не верно, если я сейчас выставлю ширину и высоту игрового поля 500х500, то квадратики в нижней части не будут ставится да и если нажать на кнопку start, игра не запустится

рони 15.05.2021 15:53

Цитата:

Сообщение от prototip
если я сейчас

исправлено)))

prototip 16.05.2021 09:25

рони,
Большое спасибо)

рони 16.05.2021 09:37

prototip,
лучше сократить все вычисления ширины и высоты до одного раза, а не делать это в каждой функции, есть и другие места для оптимизации.

prototip 16.05.2021 13:49

рони, тут я с вами согласен. Обьясните пожалуйста почему, когда я выношу эти переменные ширины и высоты в глобальную переменную, код перестает работать?
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;

рони 16.05.2021 14:39

prototip,
объявлять надо глобально, а присваивать значение только в goLife()

prototip 16.05.2021 21:23

рони,
последний вопрос и я отстану от вас)
Подскажите пожалуйста, как сделать, чтобы при нажатии кнопки "Стоп" игра остановилась, таймер сбросился на ноль и я смог заново начать игру

рони 16.05.2021 22:04

Цитата:

Сообщение от 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="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 17.05.2021 09:32

рони,
спасибо

ekaterina22 17.05.2021 18:17

рони,
prototip,
Насколько я помню, логика в этой игре другая.

ekaterina22 17.05.2021 18:18

https://ru.wikipedia.org/wiki/%D0%98...ots_conway.png

Вот, нашла.

prototip 17.05.2021 18:29

ekaterina22,
согласен, правила игру другие, спасибо что нашли мне новую работёнку)

рони 17.05.2021 19:28

ekaterina22,
Цитата:

в пустой (мёртвой) клетке, рядом с которой ровно три живые клетки, зарождается жизнь;
если у живой клетки есть две или три живые соседки, то эта клетка продолжает жить; в противном случае, если соседей меньше двух или больше трёх, клетка умирает («от одиночества» или «от перенаселённости»)
строка 105 #11
mas2[i][j] = +(neighbors == 3 || (mas[i][j] && neighbors == 2));

prototip 18.05.2021 10:42

рони,
подскажите пожалуйста, начал тестить игру и если выставить большие размеры поля игры(например 100000х100000) игра падает из-за ошибки по памяти. Поэтому решил показывать предупреждение, что такой размер нельзя создать.
Вставил после 55 строки:
if(canvas.width >= 1000 || canvas.height >= 1000) {
                 alert("Максимальный размер поля игры 1000")
      }

вылетает предупреждение алерт с моим текстом, и при нажатии кнопки ОК, поле создается. Как сделать, чтобы после нажатия ОК поле не создавалось, а можно было бы вводить заново новый размер. Или есть другой способ как это можно сделать?

рони 18.05.2021 11:22

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>

prototip 18.05.2021 12:21

рони,
спасибо за помощь

prototip 18.05.2021 18:49

рони,
подскажите пожалуйста, при многократном нажатии на кнопку start скорость игры увеличивается с каждым нажатием, при этом нужно столько же нажать на кнопку стоп, чтобы остановить игру. Решил этот баг убрать, но итоге решил добавить 3 радиокнопки, которые будут настраивать скорость игры(low, medium, hight), при этом medium скорость будет стоять по умолчанию. как это можно реализовать?
<label>Speed:</label>
    <input type="radio" id="low" /> <label>low&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</label>
    
    <input type="radio" id="medium" checked/>    <label>medium&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</label>
    
    <input type="radio" id="hight" />   <label>hight&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</label>

рони 18.05.2021 19:12

Цитата:

Сообщение от prototip
при многократном нажатии на кнопку start скорость игры увеличивается с каждым нажатием,

исправлено, строка 100, #18.

рони 18.05.2021 19:25

Цитата:

Сообщение от prototip
low, medium, hight

<!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>

prototip 18.05.2021 19:42

рони,
Интересное решение, не думал что решается так просто, пробовал сделать через условия, но получалось ерунда. Спасибо:thanks:


Часовой пояс GMT +3, время: 22:58.