简体   繁体   English

Javascript 中的贪吃蛇游戏

[英]Snake Game in Javascript

I'm really new to Javascript, so I decided to create a simple SnakeGame to embed in HTML.我对 Javascript 真的很陌生,所以我决定创建一个简单的 SnakeGame 来嵌入 HTML。 However, my code for changing the snake's direction freezes up after a few turns.然而,我改变蛇方向的代码在几圈后就冻结了。

Note: I'm running this in an HTML Canvas.注意:我在 HTML Canvas 中运行它。

Source:来源:

var Canvas;
var ctx;

var fps = 60;

var x = 0;
var seconds = 0;

var lastLoop;
var thisLoop;
var tempFPS = 0;
var blockList = [];
var DEFAULT_DIRECTION = "Right";

var pendingDirections = [];

function update() {
    x += 1;

    thisLoop = new Date();
    tempFPS = 1000 / (thisLoop - lastLoop);
    lastLoop = thisLoop;
    tempFPS = Math.round(tempFPS*10)/10;

    if (x==10){
        document.getElementById("FPS").innerHTML = ("FPS: " + tempFPS);
    }

    //Rendering
    for (var i = 0; i<blockList.length; i++){
        var block = blockList[i];
        draw(block.x, block.y);
    }

    if (x==5){
        x=0;
        seconds+=1;

        //Updates once per x frames
        moveBlocks();
    }
}

function moveBlocks(){
    if(blockList.length === 0){
        return;
    }


    for (var j = 0; j<pendingDirections.length; j++){
        if (b >= blockList.length -1){
            pendingDirections.shift();

        }else {
            //Iterates through each direction that is pending
            var b = pendingDirections[j].block;
            try{
                blockList[b].direction = pendingDirections[j].direction;
            } catch(err){
                alert(err);
            }
            pendingDirections[j].block++;
        }
    }

    for (var i = 0; i<blockList.length; i++){
        var block = blockList[i];
        clear(block.x, block.y);
        if (block.direction == "Down"){
            block.y += BLOCK_SIZE;
        } else if (block.direction == "Up"){
            block.y -= BLOCK_SIZE;
        } else if (block.direction == "Left"){
            block.x -= BLOCK_SIZE;
        } else if (block.direction == "Right"){
            block.x += BLOCK_SIZE;
        } else {
            alert(block.direction);
        }
        draw(block.x, block.y);
    }
}

function init(){
    lastLoop = new Date();
    window.setInterval(update, 1000/fps);
    Canvas = document.getElementById("Canvas");
    ctx = Canvas.getContext("2d");
}

//The width/height of each block
var BLOCK_SIZE = 30;

//Draws a block
function draw(x, y) {

    ctx.fillStyle = "#000000";
    ctx.fillRect(x,y,BLOCK_SIZE,BLOCK_SIZE);
}

function clear(x,y){
    ctx.fillStyle = "#FFFFFF";
    ctx.fillRect(x,y,BLOCK_SIZE,BLOCK_SIZE);
}

function processInput(key){
    if (key == 110){
        //n (new)
        newBlock(BLOCK_SIZE*4,0);
        newBlock(BLOCK_SIZE*3,0);
        newBlock(BLOCK_SIZE*2,0);
        newBlock(BLOCK_SIZE*1,0);
        newBlock(0,0);

    } else if (key == 119){
        changeDirection("Up");
    } else if (key == 115){
        changeDirection("Down");
    } else if (key == 97){
        changeDirection("Left");
    } else if (key == 100){
        changeDirection("Right");
    } else if (key==122){
        var pDir = "Pending Directions: ";
        for (var i = 0; i<pendingDirections.length; i++){
            pDir += pendingDirections[i].direction + ", ";
        }
        alert(pDir);
    } else if (key == 120){
        var dir = "Directions: ";   
        for (var j = 0; j<blockList.length; j++){
            dir += blockList[j].direction + ", ";
        }
        alert(dir);
    } else {
        alert("KEY: " +key);
    }
}

function changeDirection(d){
    var LD = blockList[0].direction;
    var valid = false;

    if (d == "Up"){
        if(LD != "Down"){
            valid = true;
        }
    } else if (d == "Down"){
        if(LD != "Up"){
            valid = true;
        }
    } else if (d == "Left"){
        if(LD != "Right"){
            valid = true;
        }
    } else if (d == "Right"){
        if(LD != "Left"){
            valid = true;
        }
    }  

    if (d == LD) { valid = false;}

    if (valid){     
        var dir = {'direction' : d, 'block' : 0};
        pendingDirections.unshift(dir);
    }
}
function newBlock(x, y){
    var block = {'x': x, 'y' : y, 'direction' : DEFAULT_DIRECTION};
    //This works: alert(block['x']);
    draw(x,y);
    blockList.push(block);
}

Thanks谢谢

As Evan said, the main issue is how you are handling pending directions.正如埃文所说,主要问题是您如何处理未决指示。

The issue occurs when you turn twice in rapid succession, which causes two pending directions to be added for the same block.当您快速连续转弯两次时会出现此问题,这会导致为同一块添加两个待定方向。 If these aren't handled in the correct order, then the blocks may move in the wrong direction.如果这些没有以正确的顺序处理,那么块可能会朝错误的方向移动。 On every update, only one pending direction for each block is needed, so I redesigned how this is handled to avoid multiple directions on one block during a single update.在每次更新时,每个块只需要一个未决方向,因此我重新设计了如何处理这一点,以避免在一次更新期间在一个块上出现多个方向。

Here is the link to it: http://jsbin.com/EkOSOre/5/edit这是它的链接: http : //jsbin.com/EkOSore/5/edit

Notice, when a change in direction is made, the pending direction on the first block is updated, overwriting any existing pending direction.请注意,当方向发生变化时,第一个块上的挂起方向会更新,覆盖任何现有的挂起方向。

if (valid) {
    blockList[0].pendingDirection = direction;
}

Then, when an update occurs, the list of blocks is looped through, and the pending direction of the next block is set to be the current direction of the current block.然后,当发生更新时,循环遍历块列表,并将下一个块的挂起方向设置为当前块的当前方向。

if(!!nextBlock) {
    nextBlock.pendingDirection = block.direction;
}

If the current block has a pending direction, set the direction to the pending direction.如果当前块有未决方向,则将方向设置为未决方向。

if(block.pendingDirection !== null) {
    block.direction = block.pendingDirection;
}

Then update the block locations like normal.然后像往常一样更新块位置。

You also had various other issues, such as using a variable (b) before it was initialized, and how you caught the null/undefined error (you should just do a check for that situation and handle it appropriately), but this was the main issue with your algorithm.您还有各种其他问题,例如在初始化之前使用变量 (b),以及您如何捕获空/未定义错误(您应该检查这种情况并适当处理),但这是主要的你的算法有问题。

You'll also want to remove the old blocks when the user hits 'n', because the old one is left, increasing the speed and number of total blocks present.当用户点击“n”时,您还需要移除旧块,因为旧块被留下,从而增加了存在的总块的速度和数量。

Good luck with the rest of the game, and good luck learning JavaScript.祝游戏的其余部分好运,也祝你学习 JavaScript 好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM