Как начать игру змеи с событием нажатия клавиши? - PullRequest
1 голос
/ 10 января 2020

Я создал простую игру Snake, используя HTML 5 Canvas и JavaScript. Я почти закончил небольшой проект, однако у меня есть одна проблема, которую я не могу решить. При загрузке игра змейка автоматически запускается, что обычно приводит к «окончанию игры». Я хотел бы, чтобы игрок сначала мог нажать направление, в котором он хочет, до go, а затем игра начнется. Я пытался всеми возможными способами сделать это, в основном используя «keydown» или других подобных слушателей событий. Неважно, куда я положил код, похоже, ничего не работает. Любые идеи? Огромное спасибо всем, кто потратил время из своего дня, чтобы помочь мне, это очень ценится. Ниже я оставлю код проекта для тех, кто хочет помочь.

Сайт игры Snake: Игра Snake

HTML / CSS:

window.onload = function () {
    var cvs = document.getElementById("canvas");
    var ctx = cvs.getContext("2d");

    var cvsW = cvs.width;
    var cvsH = cvs.height;

    var snakeW = 20;
    var snakeH = 20;

    let score = 0;

    var direction = "right";

    this.document.addEventListener("keydown", getDirection);

    function getDirection(e) {
        if (e.keyCode == 37 && direction != "right") {
            direction = "left";
        } else if (e.keyCode == 38 && direction != "down") {
            direction = "up";
        } else if (e.keyCode == 39 && direction != "left") {
            direction = "right";
        } else if (e.keyCode == 40 && direction != "up") {
            direction = "down";
        }
    }

    function drawSnake(x, y) {
        ctx.fillStyle = "#507786";
        ctx.fillRect(x * snakeW, y * snakeH, snakeW, snakeH);

        ctx.fillStyle = "#507786";
        ctx.strokeRect(x * snakeW, y * snakeH, snakeW, snakeH);
    }

    drawSnake(4, 5);

    var len = 4;
    var snake = [];

    for (var i = len - 1; i >= 0; i--) {
        snake.push({
            x: i,
            y: 0
        });
    }

   food = {
        x: Math.floor(Math.random() * (cvsW / snakeW - 1) + 1),
        y: Math.floor(Math.random() * (cvsH / snakeH - 1) + 1)
    }

    function drawFood(x, y) {
        ctx.fillStyle = "black";
        ctx.fillRect(x * snakeW, y * snakeH, snakeW, snakeH);

        ctx.fillStyle = "#507786";
        ctx.strokeRect(x * snakeW, y * snakeH, snakeW, snakeH);
    }

    function checkCollision(x,y,array) {
        for (var i = 0; i < array.length; i++) {
            if (x == array[i].x && y == array[i].y) {
                return true;
            }
        }
        return false;
    }


    function draw() {
        ctx.clearRect(0, 0, cvsW, cvsH);
        for (var i = 0; i < snake.length; i++) {
            var x = snake[i].x;
            var y = snake[i].y;
            drawSnake(x, y);
        }

        drawFood(food.x, food.y);

        var snakeX = snake[0].x;
        var snakeY = snake[0].y;

        if (direction == "left") snakeX--;
        else if (direction == "up") snakeY--;
        else if (direction == "right") snakeX++;
        else if (direction == "down") snakeY++;

        if (snakeX < 0 || snakeY < 0 || snakeX >= cvsW / snakeW || snakeY >= cvsH / snakeH
            || checkCollision(snakeX,snakeY,snake)) {
            snake = null;    
            document.getElementById("gameover").innerHTML = "Game Over";
            setInterval(function(){
                location.reload();
            }, 3000);
        }

        if (snakeX == food.x && snakeY == food.y) {
            food = {
                x : Math.floor(Math.random() * (cvsW / snakeW -1) + 1),
                y : Math.floor(Math.random() * (cvsH / snakeH -1) + 1)
            }
            var newHead = {
                x : snakeX,
                y : snakeY
            };
            score += 1
            document.getElementById("gameScore").innerHTML = score;
        } else {
            snake.pop();
            var newHead = {
                x : snakeX,
                y : snakeY
            };
        }

        snake.unshift(newHead);
    }

    setInterval(draw, 60);

}
<html>
<meta charset="UTF-8">
<title>
    Snake Game
</title>
<link href="https://fonts.googleapis.com/css?family=Sniglet&display=swap" rel="stylesheet">
<style>
    * {
        padding: 0px;
        margin: 0px;
    }

    #canvas {
        background-color: #8BAC0F;
        -webkit-box-shadow: 10px 10px 5px 0px rgba(0, 0, 0, 0.75);
        -moz-box-shadow: 10px 10px 5px 0px rgba(0, 0, 0, 0.75);
        box-shadow: 10px 10px 5px 0px rgba(0, 0, 0, 0.75);
    }

    #snakeGroup {
        text-align: center;
    }

    #snakeTitle {
        font-family: 'Sniglet', cursive;
        font-size: 80px;
        margin-top: 40px;
        margin-bottom: 20px;
    }

    #snakePara {
        font-family: 'Sniglet', cursive;
        font-size: 20px;
        margin-bottom: 20px;
    }

    #gameover {
        font-family: 'Sniglet', cursive;
        font-size: 50px;
        margin-bottom: 15px;
    }

    #footerText {
        font-family: 'Sniglet', cursive;
        font-size: 35px;
        margin-top: 25px;
    }
</style>

<body onkeypress="window.onload">
    <div id="snakeGroup">
        <h1 id="snakeTitle">Snake ?</h1>
        <p id="snakePara">Press the arrow keys ⬅️⬆️⬇️➡️ to move the snake.<br> Eat the food to score points. If the
            snake touches the walls
            or itself, its game over.<br> The game will automatically restart after 3 seconds. Happy Gaming!</p>
        <h2 id="gameover">Score: <span id="gameScore"></span></h2>
        <canvas id="canvas" width="500px" height="500px"></canvas>
        <h3 id="footerText">Made with ❤️ by David Winters</h3>
    </div>

    <script src="snake.js"></script>
</body>

</html>

Ответы [ 2 ]

0 голосов
/ 10 января 2020

Если вы не начинаете направление с правой стороны, вы можете внутренне обернуть функцию рисования с проверкой, чтобы увидеть, установлено ли направление.

...
    var direction = "";
...
...
    function draw() {
      if(direction != ""){
        ...
      }
    }
...
0 голосов
/ 10 января 2020

Он запускается автоматически, потому что вы вызываете drawSnake(4, 5) позже по коду и вы уже задали направление при инициализации на ‘right’

. Вы можете исправить это, назначив переменную типа hasStarted для ложь при инициализации. И затем проверка в обработчике onKeydown, является ли hasStarted истинным или ложным. Если значение равно false (игра еще не началась), для hasStarted устанавливается значение true, а затем следует вызывать setInterval(draw, 60).

var hasStarted = false;
var direction = “”;
this.document.addEventListener("keydown", getDirection);

function getDirection(e) {
    if (!hasStarted) {
        hasStarted = true
        switch e.keyCode {
            case 37:
                direction = "left";
                break;
            case 38:
                direction = "up";
                break;
            case 39:
                direction = "right";
                break;
            case 40:
                direction = "down";
                break;
            default:
                direction = "right";
                break;
        }
        setInterval(draw, 60);
    } else {
        if (e.keyCode == 37 && direction != "right") {
            direction = "left";
        } else if (e.keyCode == 38 && direction != "down") {
            direction = "up";
        } else if (e.keyCode == 39 && direction != "left") {
            direction = "right";
        } else if (e.keyCode == 40 && direction != "up") {
            direction = "down";
        }
    }
}

Edit # 1 (слава Маттиасу): Вы ' Придется также удалить вызов setInterval в последней строке кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...