拜托,我正在学习如何制作蛇游戏的教程,我了解了代码的所有内容,直到蛇必须移动的地方。我似乎没有得到蛇如何移动的逻辑。代码段如下所示:
. . . //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}
,{{1} }。现在,当{x:3,y:0}
之后蛇是如何向前移动的,因为在调用d = "right"
之后蛇的最后一个单元格的x属性/坐标比调用方法之前的原始值小1,并且再次,两个单元格现在重叠,因为snake_array中的两个对象现在具有相同的坐标(paint()
)
答案 0 :(得分:0)
相关代码启动如下:
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}
,{ {1}}。这是因为{x:0,y:0}
从i
开始,length-1
设置为高于for循环的5。这看起来像:
length
然后,在绘画功能中它抓住尾巴位置,因为它打算将尾巴移动到头部即将到达的位置(通过这样做,它不需要移动任何其他的细胞直到下一次涂抹,因为蛇永远不会改变,因为每个循环的蛇从不会移动超过一个细胞。)
[T][x][x][x][H][ ]
[ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ]
蛇的尾部总是此方案下数组中的最后一个元素,并且头部始终是第一个。所以,snake_array [snake_array.length]总是尾巴,而snake_array [0]始终是头部。
记住 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++;
,{x:4,y:0}
,{x:3,y:0}
,{x:2:,y:0}
,{x:1,y:0}
,并假设我们的默认动作是正确的,我们可以计算{{1} }。 nx和ny现在代表的是一个不属于蛇的细胞,而是蛇想进入的细胞。因此代码对该单元格进行一些边界和碰撞检查,以查看它是否与任何墙壁或其他蛇段相交,如果是,则重新启动游戏。
它还检查食物碰撞并处理它(而不是移动尾巴,它只是在细胞位置创建一个新头并产生另一块食物。)
但是,假设这个单元格(nx,ny)位置没有与任何东西发生碰撞,它会运行以下代码:
{x:0,y:0}
从snake_array中删除尾部,将其位置设置为我们之前计算的单元格的位置(nx,ny),然后将其移动到尾部&#39;进入数组的第一个位置(根据我们之前的惯例,它始终是头部):
{nx:5,ny:0}
所以最终会这样:
var tail = snake_array.pop();
tail.x = nx; tail.y = ny;
但实际上,数组仍然是[H] [x] [x] [x] [T]的形式,因为我们决定了snake_array [0]的第一个元素位置中的任何东西都是头部,而且任何东西都在snake_array [snare_array.length]的最后一个元素位置是尾部。所以它确实如此:
snake_array.unshift(tail);
然后整个过程可以一遍又一遍地重复,直到你赢或输!