在我的蛇游戏中停止setTimeout循环?

时间:2017-02-02 21:26:08

标签: javascript jquery

我创造了一个蛇游戏,当蛇击中墙壁或自身时,它仍然不会停止移动。我想出如果我使用clearTimeout(),它会有所帮助。但事实并非如此。 有没有办法阻止循环?还是另一个问题?

jQuery(document).ready(function($) {
    init();
});

var move;
function init() {
    board.initBoard();
    drawSnake();
    food.createFood();
}

function play() {
    $('.newGame').css('visibility', 'hidden');
    $('.playgame').css('visibility', 'hidden');
    moveSnake();
    getSnakeDir();
}

function gameover() {
    clearTimeout(move);
    $('.newGame').css('visibility', 'visible');
}

function playGame() {
    $('#gameboard').empty();
    $('.newGame').hide();
    init();
    play();
}

var board = {
    DIM: 20,
    initBoard: function() {
        for (var i = 0; i < board.DIM; i++) {
            var row = $('<div class="row-' + i + '"></div>');
            
            for (var j = 0; j < board.DIM; j++) {
                var col = ('<div class="col-' + j + '-' + i + '"></div>');
                $(row).append(col);
            }
            $("#gameboard").append(row);
        }
    }
}

var snake = {
    position: ['10-10', '10-11', '10-12'],
    direction: 'r',
    speed: 200,
};

function drawSnake() {
    $('.col-10-10').addClass('snake');
    $('.col-11-10').addClass('snake');
}

function getSnakeDir() {
    $(document).keydown(function(event) {
        //event.preventDefault();
        if (event.which == 38) {
            snake.direction = 'u';
        } else if (event.which == 39) {
            snake.direction = 'r';
        } else if (event.which == 40) {
            snake.direction = 'd';
        } else if (event.which == 37) {
            snake.direction = 'l';
        }
    });
}

function moveSnake() {
    var tail = snake.position.pop();
    $('.col-' + tail).removeClass('snake');

    var coords = snake.position[0].split('-');
    var x = parseInt(coords[0]);
    var y = parseInt(coords[1]);

    if (snake.direction == 'r') {
        x = x + 1;
    } else if (snake.direction == 'd') {
        y = y + 1;
    } else if (snake.direction == 'l') {
        x = x - 1;
    } else if (snake.direction == 'u') {
        y = y - 1;
    }
    
    var currentcoords = x + '-' + y;
    snake.position.unshift(currentcoords);

    $('.col-' + currentcoords).addClass('snake');

    //when snake eats food
    if (currentcoords == food.coords) {
        console.log('true');
        $('.col-' + food.coords).removeClass('food');
        snake.position.push(tail);
        food.createFood();
    }

    //game over
    if (x < 0 || y < 0 || x > board.DIM || y > board.DIM) {
        gameover();
    
    }

    //if snake touch itself
    if (hitItself(snake.position) == true) {
        gameover();
    }
    
    move=setTimeout(moveSnake, 200);
}

var food = {
    coords: "",

    createFood: function() {
        var x = Math.floor(Math.random() * (board.DIM-1)) + 1;
        var y = Math.floor(Math.random() * (board.DIM-1)) + 1;
        var fruitCoords = x + '-' + y;
        $('.col-' + fruitCoords).addClass('food');
        food.coords = fruitCoords;
    },
}

function hitItself(array) {
    var valuesSoFar = Object.create(null);
    for (var i = 0; i < array.length; ++i) {
        var value = array[i];
        if (value in valuesSoFar) {
            return true;
        }
        valuesSoFar[value] = true;
    }
    return false;
}
.buttonnewgame {
     position: relative;
}

.newGame {
    position: absolute;
    top: 45%;
    left: 25%;
    padding: 15px;
    font-size: 1em;
    font-family: arial;
    visibility: hidden;
}

.gameContainer{
    width: 100%;
}

#gameboard {
    background-color:#eee;
    padding:3px;
}

.playgame {
    position: absolute;
    top: 45%;
    left: 20%;
    padding: 15px;
    font-size: 1em;
    font-family: arial;    
}

/* styling the board */
div[class^='row'] {
    height: 15px;
    text-align: center;
}

div[class*='col']{
    display: inline-block;
    border: 1px solid grey;
    width: 15px;
    height: 15px;
}

/*display the snake*/
.snake {

    background-color: blue;
    z-index: 99;
}

.food {
    background: red;
    z-index: 99;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="game">
    <div class="buttonnewgame">
        <input type="button" name="new game" value="new game" class="newGame" onclick="playGame()" />
        <button class="playgame" onclick="play()">Play Game</button>
        <div class="gameContainer">
            <div id="gameboard">
                <!-- snake game in here -->
            </div>
        </div>
    </div>
</div>

2 个答案:

答案 0 :(得分:1)

您可以尝试不在setTimeout功能发起新的moveSnake来电,而是使用。{/ p>

function play() {
    $('.newGame').css('visibility', 'hidden');
    $('.playgame').css('visibility', 'hidden');
    move = setInterval(moveSnake, 200);
    getSnakeDir();

}

并删除

move = setTimeout(moveSnake, 200)

来自moveSnake函数并执行

function gameover() {
    clearInterval(move);
    $('.newGame').css('visibility', 'visible');
}

答案 1 :(得分:1)

有一些问题,但这是“工作版本”和“#39; (还有更多的错误)。

1)我将drawSnake重命名为createSnake。当你打电话给init()时,你并没有完全重新初始化蛇。蛇的位置没有在之前的drawSnake方法中重置,所以看起来游戏不可玩。

之后还有2个错误。

2)你打电话给gameOver之后你还得回来,或者游戏永远不会结束吗?在gameover中清除超时后,您会立即在moveSnake()的最后一行设置另一个超时,因为游戏结束后您没有返回。这导致了奇怪的结果,使得游戏似乎没有反应。

3)您使用visibility nonevisible$.hide()的组合。 $.hide()使用display: none,因此当您尝试使用visibility样式更改再次显示时,它仍为display: none,因此新游戏按钮将停止显示。

我对任何游戏编码器的建议是学习如何分离处理游戏如何工作的代码(游戏逻辑,时钟滴答,游戏状态初始化等)以及如何显示(html)和css)。在干净编写的系统之后对游戏逻辑进行建模易于阅读和调试。当显示代码与游戏逻辑混合时,代码变得更难理解和修改。从理论上讲,我们的游戏应该完美无缺地呈现。然后我们可以编写一个渲染器来生成HTML画布,html DOM,命令行中的文本或OpenGL。

这是一个我从未完成的旧项目,应该说明模型和视图之间的分离。

http://tando.us/ganix/ganix.htm

&#13;
&#13;
jQuery(document).ready(function($) {
    init();
});

var move;
function init() {
    board.initBoard();
    createSnake();
    food.createFood();
}

function play() {
    $('.newGame').hide();
    $('.playgame').hide();
    moveSnake();
    getSnakeDir();
}

function gameover() {
    clearTimeout(move);
    $('.newGame').show();
}

function playGame() {
    $('#gameboard').empty();
    $('.newGame').hide();
    init();
    play();
}

var board = {
    DIM: 20,
    initBoard: function() {
        for (var i = 0; i < board.DIM; i++) {
            var row = $('<div class="row-' + i + '"></div>');
            
            for (var j = 0; j < board.DIM; j++) {
                var col = ('<div class="col-' + j + '-' + i + '"></div>');
                $(row).append(col);
            }
            $("#gameboard").append(row);
        }
    }
}

var snake = {
    position: ['10-10', '10-11', '10-12'],
    direction: 'r',
    speed: 200,
};

function createSnake() {
    $('.col-10-10').addClass('snake');
    $('.col-11-10').addClass('snake');
    snake.position = ['10-10', '10-11', '10-12'];
}

function getSnakeDir() {
    $(document).keydown(function(event) {
        //event.preventDefault();
        if (event.which == 38) {
            snake.direction = 'u';
        } else if (event.which == 39) {
            snake.direction = 'r';
        } else if (event.which == 40) {
            snake.direction = 'd';
        } else if (event.which == 37) {
            snake.direction = 'l';
        }
    });
}

function moveSnake() {
    var tail = snake.position.pop();
    $('.col-' + tail).removeClass('snake');

    var coords = snake.position[0].split('-');
    var x = parseInt(coords[0]);
    var y = parseInt(coords[1]);

    if (snake.direction == 'r') {
        x = x + 1;
    } else if (snake.direction == 'd') {
        y = y + 1;
    } else if (snake.direction == 'l') {
        x = x - 1;
    } else if (snake.direction == 'u') {
        y = y - 1;
    }
    
    var currentcoords = x + '-' + y;
    snake.position.unshift(currentcoords);

    $('.col-' + currentcoords).addClass('snake');

    //when snake eats food
    if (currentcoords == food.coords) {
        console.log('true');
        $('.col-' + food.coords).removeClass('food');
        snake.position.push(tail);
        food.createFood();
    }

    //game over
    if (x < 0 || y < 0 || x > board.DIM || y > board.DIM) {
        gameover();
        return;
    
    }

    //if snake touch itself
    if (hitItself(snake.position) == true) {
        gameover();
        return;
    }
    
    move=setTimeout(moveSnake, 200);
}

var food = {
    coords: "",

    createFood: function() {
        var x = Math.floor(Math.random() * (board.DIM-1)) + 1;
        var y = Math.floor(Math.random() * (board.DIM-1)) + 1;
        var fruitCoords = x + '-' + y;
        $('.col-' + fruitCoords).addClass('food');
        food.coords = fruitCoords;
    },
}

function hitItself(array) {
    var valuesSoFar = Object.create(null);
    for (var i = 0; i < array.length; ++i) {
        var value = array[i];
        if (value in valuesSoFar) {
            return true;
        }
        valuesSoFar[value] = true;
    }
    return false;
}
&#13;
.buttonnewgame {
     position: relative;
}

.newGame {
    position: absolute;
    top: 45%;
    left: 25%;
    padding: 15px;
    font-size: 1em;
    font-family: arial;
}

.gameContainer{
    width: 100%;
}

#gameboard {
    background-color:#eee;
    padding:3px;
}

.playgame {
    position: absolute;
    top: 45%;
    left: 20%;
    padding: 15px;
    font-size: 1em;
    font-family: arial;    
}

/* styling the board */
div[class^='row'] {
    height: 15px;
    text-align: center;
}

div[class*='col']{
    display: inline-block;
    border: 1px solid grey;
    width: 15px;
    height: 15px;
}

/*display the snake*/
.snake {

    background-color: blue;
    z-index: 99;
}

.food {
    background: red;
    z-index: 99;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="game">
    <div class="buttonnewgame">
        <input type="button" name="new game" value="new game" class="newGame" style="display:none;" onclick="playGame()" />
        <button class="playgame" onclick="play()">Play Game</button>
        <div class="gameContainer">
            <div id="gameboard">
                <!-- snake game in here -->
            </div>
        </div>
    </div>
&#13;
&#13;
&#13;