【问题标题】:setInterval time increases on every click每次点击时 setInterval 时间都会增加
【发布时间】:2019-05-12 09:29:51
【问题描述】:

我用 HTML5 和 Javascript 创建了一个简单的蛇游戏。我添加了一个按钮来开始/暂停游戏。但问题是,每当我通过单击按钮暂停并开始游戏时,蛇的速度都会增加。我是 JavaScript 新手。所以我不知道 setinterval 函数是如何工作的。代码如下:

snake.html

<!DOCTYPE html>
<html>
<head>
    <title>Snake game</title>
    <style type="text/css">
        #snakeBoard {
            background-color: black;
        }
        #score {
            text-align: left;
            font-size: 40px;
            font-family: 'Arial', 'Helvetica', sans-serif;
      }
    </style>
</head>
<body>
    <div id="score">0</div>
    <canvas id="snakeBoard" width="250" height="250"></canvas>
    <script type="text/javascript" src="snake.js"></script>
    <div><button type="submit" id="play" onclick="javascript:game();">Play</button></div>

</body>
</html>

snake.js

var play = document.getElementById("play");
var isPaused = false;
function game() {
        setInterval(draw,200);
        isPaused = !isPaused;
    }

    var canvas = document.getElementById("snakeBoard");
    var cxt = canvas.getContext("2d");

    var canvasW = canvas.width;
    var canvasH = canvas.height;

    var snakeW = 10;
    var snakeH = 10;

    var score = 0;

    // deafult direction
    var direction = "right";


    //to color snake
    function drawSnake (x, y) {
        cxt.fillStyle = "#FFF";
        cxt.fillRect(x*snakeW,y*snakeH,snakeW,snakeH);

        cxt.strokeStyle = "#000";
        cxt.strokeRect(x*snakeW,y*snakeH,snakeW,snakeH);
    }

    //drawSnake(4,4);

    //create snake as array. By default contains four cells
    var len = 4;
    var snake = [];

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

    //create food   
        food = {
            x: Math.round(Math.random()*(canvasW/snakeW-2)+1),
            y: Math.round(Math.random()*(canvasH/snakeH-2)+1)
        };


    function createFood (x,y) {

        for (var i=0; i<snake.length; i++) {
            if (x==snake[i].x && y==snake[i].y) {
                food = {
                    x: Math.round(Math.random()*(canvasW/snakeW-2)+1),
                    y: Math.round(Math.random()*(canvasH/snakeH-2)+1)
                };
                createFood(food.x, food.y);
            }

        }

        cxt.fillStyle = "red";
        cxt.fillRect(x*snakeW,y*snakeH,snakeW,snakeH);

        cxt.strokeStyle = "#000";
        cxt.strokeRect(x*snakeW,y*snakeH,snakeW,snakeH);
    }

    //add user inputs
    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";
        }
    }

    // check when the snake hits itself
    function checkSelfHit(x,y,snakeArray) {
        // for(var i=0; i<snakeArray.length-2; i++) {
        //  if(snakeArray[snakeArray.length-1].x==snakeArray[i].x && snakeArray[snakeArray.length-1].y==snakeArray[i].y) {
        //      return true;
        //  }
        //  return false;
        // }
        for (var i=0; i<snakeArray.length; i++) {
            if(x==snakeArray[i].x && y==snakeArray[i].y) {
                return true;
            }

        }
        return false;

    }

     // function drawScore(score) {
        // cxt.fillStyle = "blue";
        // cxt.fillText("Score: ",10,50);
     // }

    function draw() {

        if (isPaused) {
            return;
        }

        cxt.clearRect(0,0,canvasW,canvasH);
        for(var i=0; i<snake.length; i++) {
            var x = snake[i].x;
            var y = snake[i].y;
            drawSnake(x,y);
        }


        createFood(food.x, food.y);


        // snake head
        let snakeX = snake[0].x;
        let snakeY = snake[0].y;


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

        // if the snake hits the wall....... and for self hit checkSelfHit(snakeX,snakeY,snake)
        if (snakeX < 0 || snakeY < 0 || snakeX >= canvasW/snakeW || snakeY >= canvasH/snakeH || checkSelfHit(snakeX,snakeY,snake)) {
            return;
        }


        if (snakeX == food.x && snakeY == food.y) {
            let newHead = {x: snakeX, y: snakeY};
            snake.unshift(newHead);
            score++;
            food = {
                x: Math.round(Math.random()*(canvasW/snakeW-2)+1),
                y: Math.round(Math.random()*(canvasH/snakeH-2)+1)
            }


        }
        else {
            // remove tail
            snake.pop();
            let newHead = {x: snakeX, y: snakeY};
            snake.unshift(newHead);
        }


        document.getElementById('score').innerHTML = score;

    }

这也是我的第一个游戏项目和第一个 javascript 项目。因此,感谢代码中的任何其他输入或错误。 注意:请忽略js文件中的一些cmets。那是我的错误。供我参考。

【问题讨论】:

  • 每次您执行setInterval 时,您都在创建一个新的间隔计时器。您必须保存函数的返回值并在开始新计时器之前取消旧计时器。见this
  • 查看 clearInterval 和 setTimeout

标签: javascript setinterval clearinterval


【解决方案1】:

正如@fredrik 已经说过的,您每次执行game 都会创建一个新间隔 .

一种方法是通过将间隔保存在变量中并在创建新变量之前将其清除来控制间隔:

var play = document.getElementById("play");
var isPaused = false;
var ticker = null;
function game() {
    if (ticker) {
        clearInterval(ticker);
        ticker = null;
    } else {
        ticker = setInterval(draw,200);
    }
    // isPaused = !isPaused; No need for this anymore
}

// ....

另一种方法是让isPaused 完成所有工作,例如:

var play = document.getElementById("play");
var isPaused = true; // should be paused before clicking “play” in this case
var ticker = setInterval(draw,200);
function game() {
    isPaused = !isPaused;
}

// ....

【讨论】:

  • 谢谢。这解决了我的问题。我还有一个问题。与问题无关,但与同一游戏有关。我的游戏功能在第二次点击时执行,但不是在第一次点击时执行。问题出在哪里?
  • 与上面相同的代码。我刚刚添加了变量ticker。甚至在我添加变量之前,第二次单击后的执行问题就存在了,即问题出在我上面粘贴的代码上。
  • 我明白了。这是因为该功能将在第一次单击时暂停。我错误地初始化了 isPaused。
  • 给你... ?
  • 当变量增加到某个值以上时,您能建议一种方法来增加 setInterval 的计时器吗?
猜你喜欢
  • 2023-03-29
  • 2015-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-24
  • 1970-01-01
相关资源
最近更新 更多