【问题标题】:Snake movement in snake game蛇游戏中的蛇运动
【发布时间】:2015-11-07 10:12:29
【问题描述】:

拜托,我正在学习如何制作蛇游戏的教程,我了解了有关代码的所有内容,直到蛇必须移动的地方。我只是似乎不明白蛇是如何移动的逻辑。代码sn-p如下所示:

. . . //the code block to setup the canvas and other basic stuff for the game
//creating the snake
var snake_array;  //an array of cells to make up the snake
function create_snake(){
    var length = 5;   //length of the snake
    snake_array = [] //starting with an empty array
    for (var i = 0; i < length; i++) {
        //this will create a horizontal snake starting from top left
        snake_array.push({x:i,y:0});
    }
}

create_snake() // invoking the method

//painting the snake
function paint(){

    . . . // code block to clear the trail of the snake on the canvas before the snake moves

    var nx = snake_array[0].x;
    var ny = snake_array[0].y;
    if(d == "right") nx++;    //d is a variable updated by the keydown event listener code(not shown here) 
    else if(d == "left") nx--;
    if(d == "up") ny--;
    if(d == "down") ny++;

    var tail = snake_array.pop(); // pops out the last cell
    tail.x = nx;
    tail.y = ny;
    snake_array.unshift(tail)

    . . . // code block to paint the snake cells

    }
}

paint() // invoking the method

我的问题是:我上面概述的部分代码如何完成推进蛇的工作,因为当我尝试使用浏览器控制台跟踪代码时,在调用 create_snake() 之后,我有一个包含五个对象的数组(代表蛇细胞)具有以下属性和值:{x:0,y:0},{x:1,y:0},{x:2,y:0},{x:3,y:0},{x:4,y:0}。调用paint方法后,我仍然有一个包含五个对象的数组,但具有以下属性和值:{x:1,y:0},{x:0,y:0},{x:1,y:0},{x:2,y:0},{x:3,y:0}。现在当d = "right"snake 调用paint() 后snake 的最后一个单元格的x 属性/坐标比调用该方法之前的原始值小1 时,snake 将如何向前移动,并且再次,两个单元格现在重叠因为snake_array 中的两个对象现在具有相同的坐标({x:1,y:0})

【问题讨论】:

    标签: javascript logic game-physics


    【解决方案1】:

    相关代码是这样启动的:

    var snake_array;
    function create_snake(){
        var length = 5;
        snake_array = [];
        for(var i = length-1; i>=0; i--){
            snake_array.push({x: i, y:0});
        }
    }
    

    关于这段代码需要注意的重要一点是它向后生成蛇,所以它看起来像这样:{x:4,y:0}{x:3,y:0}{x:2:,y:0}{x:1,y:0}{x:0,y:0}。这是因为i 开始于length-1 并且length 在for 循环上方设置为5。这看起来像:

    [T][x][x][x][H][ ]
    [ ][ ][ ][ ][ ][ ]
    [ ][ ][ ][ ][ ][ ]
    [ ][ ][ ][ ][ ][ ]
    

    然后,在绘制函数中,它会抓取尾部位置,因为它打算将尾部移动到头部即将到达的位置(通过这种方式,它不需要移动任何其他单元格,直到下一个油漆,因为这些永远不会改变,因为蛇每个周期移动的次数不会超过一个单元格。)

        var nx = snake_array[0].x;
        var ny = snake_array[0].y;
        if(d == "right") nx++;
        else if(d == "left") nx--;
        else if(d == "up") ny--;
        else if(d == "down") ny++;
    

    蛇的尾巴总是在这个方案下数组中的最后一个元素,头部总是第一个。所以,snake_array[snake_array.length] 永远是尾巴,snake_array[0] 永远是头。

    记住{x:4,y:0}{x:3,y:0}{x:2:,y:0}{x:1,y:0}{x:0,y:0},假设我们的默认运动是对的,我们可以计算出{nx:5,ny:0}。 nx 和 ny 现在代表一个不属于蛇的细胞,而是蛇想要进入的细胞。因此,代码对该单元格进行了一些边界和碰撞检查,以查看它是否与任何墙或其他蛇段相交,如果相交则重新启动游戏。

    它还检查食物碰撞并处理它(而不是移动尾部,它只是在单元格位置创建一个新头部并生成另一块食物。)

    但是,假设这个单元格 (nx,ny) 的位置没有与任何东西发生碰撞,它会运行以下代码:

        var tail = snake_array.pop();
        tail.x = nx; tail.y = ny;
    

    从snake_array中删除尾部,将其位置设置为我们之前计算的单元格的位置(nx,ny),然后将这个“尾部”移动到数组的第一个位置(始终是头部,按照我们之前的约定):

        snake_array.unshift(tail);
    

    结果是这样的:

    [ ][x][x][x][H][T]
    [ ][ ][ ][ ][ ][ ]
    [ ][ ][ ][ ][ ][ ]
    [ ][ ][ ][ ][ ][ ]
    

    但实际上,数组仍然是 [H][x][x][x][T] 的形式,因为我们决定在 snake_array[0] 的第一个元素位置的任何东西都是头部,而在snake_array[snare_array.length] 的最后一个元素位置是尾部。原来如此:

    [ ][T][x][x][x][H]
    [ ][ ][ ][ ][ ][ ]
    [ ][ ][ ][ ][ ][ ]
    [ ][ ][ ][ ][ ][ ]
    

    然后整个过程可以一遍又一遍地重复,直到你输赢!

    【讨论】:

    • 请您详细说明一下,如果有重叠,那么画布上应该有 3 个蛇形单元格,而不是 4 个,因为两个单元格将绘制在 x,y 的相同位置 -坐标
    • 其实我有点看错代码了,给我一分钟来修正我的答案。
    • 感谢您的回答,它澄清了一些问题,但从您的回答来看,新坐标不应该是{x:5,y:0} but {x:1,y:0},因为从我在问题上方粘贴的代码中,nx = snake_array[0].x0,如果我们假设蛇正朝着正确的方向移动,则代码中的nx++ 运行,nx 变为1。然后我们pop() 蛇的头部并将其返回到数组中,使其坐标等于nxny 的坐标。
    • 是的 - 我编辑了我的答案,因为我读错了(我认为它正在使用数组中最后一项的值。)我认为它可能是一个错误,它是按原样完成的(如果不是,我需要查看更多代码来找出原因。)
    • 好的,非常感谢您的回复。这是教程的链接,也许您可​​以查看它以获得完整的要点,这样它可以帮助您更好地解释它thecodeplayer.com/walkthrough/…谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-30
    相关资源
    最近更新 更多