爪哑脚本 |P5.JS 图书馆 - 贪吃蛇游戏 (X) 未定义



我正在编码/遵循贪吃蛇游戏编码教程,似乎已经到了发现讲师没有遇到的错误的地步,我似乎不明白问题的根源。

我什至评论了每行描述每行的功能,也许可以帮助我找出问题,但我已经空白了。

明确指出了与问题的界限。

来自 Chrome 控制台的完整错误:

捕获的类型错误:无法读取未定义的属性"x"-
在 Snake.show (snake:95(--at
draw (snake:37(--at p5.redraw (p5
.js:17153(--
at p5。(第5.js:12358页(

具体问题行:

rect(this.tail[i].x, this.tail[i].y, scl, scl(; 在最后画尾巴。

当我遇到边界墙或通过朝相反的方向撞到自己时,我最初以 3+ 长度的尾巴进入,我得到这个错误。 有人可以解释导致此错误的原因吗?这一定与死亡方面有关。

完整代码:

<!DOCTYPE html>
<html>
<head>
<title>Snake Game</title>
<script src="http://sethjfreeman.com/resources/jquery-3.1.1.js"></script>
<script src="http://sethjfreeman.com/resources/P5/p5.js"></script>
<link href="http://sethjfreeman.com/projects/snake.css" rel="stylesheet" type="text/css">
</head>
<body>
<script>  <!-- Uses p5.js Javascript Library -->
var s;  // Snake Character.
var scl = 20;   // Size Of Everything.
var food;   // Food Items. Makes Em Grow When Eatin.
function setup() {
createCanvas($(window).width() - 10, $(window).height() - 10);  // Creates De Canvas For Everything To Be In.
s = new Snake();  // Creates A New Snake | Calls Snake Function To Create A Snake |.
frameRate(10);  // Sloooowwwssss Down The Game To Actully Be Able To Control The Snake.
pickLocation(); // Calls Pick Location To Pick A Location For The First Food Item To Be Placed.
}
function pickLocation() {  // A Function To Control Where The Food Goes
var cols = floor(width / scl);  // Creates An Imaginary Vertical Grid Every 20 Pixels. Floor Is Being Used To Prevent A Column From Being Placed At E.G: 40.6 Pixels.
var rows = floor(height / scl);  // Creates An Imaginary Horizontal Gird Every 20 Pixels. Floor Is Being Used To Prevent A Column From Being Placed At E.G: 40.6 Pixels.
food = createVector(floor(random(cols)), floor(random(rows)));  // Assigns Food To Being At The Random Location.
food.mult(scl);  // Makes Sure The Food Vector Is Set In The 20 Pixels Guide Lines. Not The 20.5 Pixel Guide Lines.
}
function draw() {  // Controls Everything That Is Being Drawn To The Canvas.
background(51);  // Sets Background To Be A Grayscale Value. 
if(s.eat(food)) {  // Checks If Food Was Eatin, If True Picks A New Location For A Food Peice.
pickLocation();  // Calls Pick Locatoin Function.
}
s.death();  // Calls Death Function.
s.update();  // Calls Update Function.
s.show();  // Calls Show Function.
fill(255, 0, 100);  // Sets Food's Background Color.
rect(food.x, food.y, scl, scl);  // Creates A New Food Item.
}
function Snake() {  // Controls Everything To Do With De Snake Character.
this.x = 0;  // Holds The X Pos Of Player.
this.y = 0;  // Holds The Y Pos Of The Player.
this.xspeed = 1;  // Moves Player (X) Speed.
this.yspeed = 0;  // Moves Player (X) Speed.
this.total = 0;  // Holds The Amount Of Squares On Snake.
this.tail = [];  // History For Where Each Part Of The Body Needs To Go.
this.dir = function(x, y) {  // Controls The Direction Of The Snake.
this.xspeed = x;  // Recives The Intput From keyPressed.
this.yspeed = y;  // Recives The Intput From keyPressed.
}
this.eat = function(pos) {  // Controls What Happens When A Food Item Was Eatin.
var d = dist(this.x, this.y, pos.x, pos.y);  // Holds The Distance Between Two Points, In This Case, Between The Snake & The Food Item.
if(d < 1) {  // If The Distance Is Less Than 1 Pixel From Food Item Add 1 To Total. 
this.total++;
return true;
} else {  // Else Go To Sleep.
return false;
}
}
this.death = function() {  // Controls When The Player Dies.
for(var i = 0; i < this.tail.length; i++) {  // Loops Through Snake Length. Loop Used For Checking If Snake Runs Into Self.
var pos = this.tail[i];  // Checks Position Of Each Square Of Tail
var d = dist(this.x, this.y, pos.x, pos.y);  // Holds The Distance Between Two Points, In This Case, Between The Snake Head & The Particular Spot On The Tail Thats Being Hit.
if(d < 1) {  // If The Pixel Between The Distance, Restart The Player.
total = 0;  // Resets Total.
this.tail = [];  // Resets Tail.
}
}
}
this.update =  function() {  // Updates Everything. Simple Right?
if(this.total === this.tail.length) {  
for(var i = 0; i < this.tail.length - 1; i++) {  //  Loops Through Whole Snake Besides Head.
this.tail[i] = this.tail[i + 1];  // Shifts Each Body Square Location By 1.
}
}
this.tail[this.total - 1] = createVector(this.x, this.y);
this.x = this.x + this.xspeed * scl;  // The X Cords Of Snake Changes Depending On X Speed * The Scale Of The Snake
this.y = this.y + this.yspeed * scl;  // The Y Cords Of Snake Changes Depending On Y Speed * The Scale Of The Snake
this.x = constrain(this.x, 0, width - scl);  // Constrains The Snake Between The Left Border And Right Border Of The Sceen
this.y = constrain(this.y, 0, height - scl);  // Constrains The Snake Between The Top Border And Bottom Border Of The Sceen
}
/*
_____  _____   ____  ____  _      ______ __  __ 
|  __ |  __  / __ |  _ | |    |  ____|  /  |
| |__) | |__) | |  | | |_) | |    | |__  |   / |
|  ___/|  _  /| |  | |  _ <| |    |  __| | |/| |
| |    | |  | |__| | |_) | |____| |____| |  | |
|_|    |_|  _\____/|____/|______|______|_|  |_|
*/
this.show = function() {
fill(255);  // Draw The Tail White.
for(var i = 0; i < this.tail.length; i++) {  // Draw The Tail.
rect(this.tail[i].x, this.tail[i].y, scl, scl);  // Draw The Tail At The End.
}
rect(this.x, this.y, scl, scl);
}
}
function keyPressed() {  // Checks Which Keys Were Pressed.
if(keyCode === UP_ARROW) {  // If Up Arrow Was Pressed Move Snake Upwards.
s.dir(0, -1);  // Because Direction Starts From Left & Top, -1 = Subtract From Top Pos. +1 = Add From Top Pos.
} else if(keyCode === DOWN_ARROW) {  // If Down Arrow Was Pressed Move Snake Downwards.
s.dir(0, 1);  // Because Direction Starts From Left & Top, -1 = Subtract From Top Pos. +1 = Add From Top Pos.
} else if(keyCode === RIGHT_ARROW) {  // If Right Arrow Was Pressed Move Snake Right.
s.dir(1, 0);  // Because Direction Starts From Left & Top, -1 = Subtract From Top Left. +1 = Add From Top Left.
} else if(keyCode === LEFT_ARROW) {  // If Left Arrow Was Pressed Move Snake Left.
s.dir(-1, 0);  // Because Direction Starts From Left & Top, -1 = Subtract From Top Left. +1 = Add From Top Left.
}
}
</script>
</body>
</html>

你将不得不调试你的程序。(该教程适用于处理,但基本思想是相同的。

你知道你的问题出在这条线上:

rect(this.tail[i].x, this.tail[i].y, scl, scl);

你知道你的错误是:Uncaught TypeError: Cannot read property 'x' of undefined

这告诉你this.tail[i]是未定义的。这通常意味着您正在尝试访问this.tail数组没有的索引(例如尝试访问仅包含 10 个项目的数组的索引 100(。

但是只看你的代码,你只是循环到this.tail.length,所以它不是那么简单。所以现在你必须调试你的代码来找出一些事情:

  • this.tail.length的价值是什么?
  • i的价值是什么?
  • 开始循环之前,每个this.tail索引处的索引是什么?

然后,您将不得不进一步调试以准确确定何时更改this.tail。您是否尝试过使用调试器逐步执行代码,或者至少使用一张纸和一支铅笔跟踪代码?

你需要经历这个过程,直到你确切地了解发生了什么。如果您可以将其缩小到几行行为不符合您的预期,那么请发布MCVE,我们将从那里开始。祝你好运。

最新更新