Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在vanilla JS/canvas snake游戏中,尝试获取阵列的最后一个对象并将其移动到前面以移动蛇_Javascript_Canvas - Fatal编程技术网

Javascript 在vanilla JS/canvas snake游戏中,尝试获取阵列的最后一个对象并将其移动到前面以移动蛇

Javascript 在vanilla JS/canvas snake游戏中,尝试获取阵列的最后一个对象并将其移动到前面以移动蛇,javascript,canvas,Javascript,Canvas,我一直在尝试在没有任何教程的情况下构建一个snake游戏应用程序,并且在逻辑问题上被困了好几天。从代码笔的吼声中,你可以看到我的蛇在移动,但它并不像绳子一样移动,它只是作为一个由“块”或碎片粘在一起的单元移动 我相信你们中的大多数人闭上眼睛都能做这样的事情,但我想知道你们是否能说服我离开窗台。我想知道我是否已经把这些放在了一起,以至于我需要重新思考我是如何建立到这一点的,也许(大部分)重新开始 在第43-47行中,您可以看到我尝试将最后一个数组项“pop()”,然后将其“unshift()”,返

我一直在尝试在没有任何教程的情况下构建一个snake游戏应用程序,并且在逻辑问题上被困了好几天。从代码笔的吼声中,你可以看到我的蛇在移动,但它并不像绳子一样移动,它只是作为一个由“块”或碎片粘在一起的单元移动

我相信你们中的大多数人闭上眼睛都能做这样的事情,但我想知道你们是否能说服我离开窗台。我想知道我是否已经把这些放在了一起,以至于我需要重新思考我是如何建立到这一点的,也许(大部分)重新开始

在第43-47行中,您可以看到我尝试将最后一个数组项“pop()”,然后将其“unshift()”,返回到前面,然后将新数组重新绘制到画布上。我可以在我的“updateSnake()”函数中使用JS和Canvas来实现这一点吗?如果不行,你能把我推到我的逻辑有缺陷的地方吗

谢谢

HTML


蛇类游戏
蛇类游戏
分数
0
CSS

#游戏画布{
保证金:自动;
显示:块;
}
#标题{
文本对齐:居中;
利润率:30px 0 100px 0;
字体大小:35px;
}
#得分{
左边距:60像素;
}
JS

let canvas=document.getElementById(“gameCanvas”);
设ctx=canvas.getContext(“2d”);
让蛇来指引方向;
文档。addEventListener(“向下键”,移动快捷键,错误);
让appleX;
让阿普利;
分数=0;
createApple();
蛇类{
构造函数(){
this.body=[{x:50,y:200},{x:34,y:200},{x:18,y:200}];
这条蛇皮dx=15;
这条蛇的速度=15;
this.color=“绿色”;
这个.snakeSize=15;
}
drawSnake(){
ctx.fillStyle=this.color;
for(设i=0;iappleX&&
snake.body[0].yappleY
) {
ctx.clearRect(appleX,appleY,15,15);
createApple();
分数=分数+1;
document.getElementById(“score”).innerText=score;
生长蛇();
}
}
函数(){
设xLength=snake.body[snake.body.length-1].x-16;
设yLength=snake.body[snake.body.length-1].y;
snake.body.push({x:xLength,y:yLength});
}
函数gameOver(){
如果(
snake.body[0].x>canvas.width-snake.snakeSpeedX||
snake.body[0].x<0
) {
警报(“游戏结束!”);
}否则如果(
snake.body[0].y>canvas.height-snake.snakeSpeedY||
snake.body[0].y<0
) {
警报(“游戏结束!”);
}
}

你的直觉很好。缺少的部分实际上是更新新头部,使其朝您想要的方向移动

updateSnake() {
  const dir = {
    up: {x: 0, y: -this.snakeSize},
    down: {x: 0, y: this.snakeSize},
    left: {x: -this.snakeSize, y: 0},
    right: {x: this.snakeSize, y: 0},
  }[snakeDirection] || {x: 0, y: 0};
  this.body.unshift(this.body.pop());
  this.body[0].x = this.body[1].x + dir.x;
  this.body[0].y = this.body[1].y + dir.y;
  this.drawSnake();
}
条件有点难看,因此对象是消除它的简单方法。如果您(正确地)担心在每一帧分配它,则将其范围限定到类

由于
snakeDirection
在脚本开始时未初始化,因此如果在对象中未找到
snakeDirection
键,我将使用
|{x:0,y:0}
dir
设置为默认值

其他几点建议:

  • snakeDirection
    作为一个全局变量是不必要的,这会破坏封装。将其作为参数传递到
    updateSnake
  • this.drawSnake()
    移出
    updateSnake
    函数——最好将关注点分开,并将这些函数调用移到父函数
  • 类似地,
    animate
    不应调用
    gameOver
    函数。这个函数实际上并没有导致游戏结束,所以它的名字有点误导。它检查边界,这应该是游戏或蛇类的责任。它也会在游戏结束时弹出对话框,但我确信这是一个WIP
  • 考虑使用一致的网格大小,如15或20像素
  • 对按键操作使用
    event.preventDefault()
    ,这样在用户处于协同工作状态时屏幕不会四处移动
    updateSnake() {
      const dir = {
        up: {x: 0, y: -this.snakeSize},
        down: {x: 0, y: this.snakeSize},
        left: {x: -this.snakeSize, y: 0},
        right: {x: this.snakeSize, y: 0},
      }[snakeDirection] || {x: 0, y: 0};
      this.body.unshift(this.body.pop());
      this.body[0].x = this.body[1].x + dir.x;
      this.body[0].y = this.body[1].y + dir.y;
      this.drawSnake();
    }