Javascript | P5.JS图书馆 - 蛇游戏(X)未定义

时间:2017-08-25 22:43:11

标签: javascript p5.js

我正在编写/遵循蛇形游戏编码教程,似乎已经找到了一个我发现教师没有遇到过的错误,我似乎不明白问题的根源。

我甚至评论了每一行描述每行的功能,可能会帮助我找出问题,但我已经空白了。

明确指出了问题的界限。

Chrome控制台完全错误:

  

未捕获的TypeError:无法读取属性' x'未定义的   --at Snake.show(蛇:95)
   - 画画(蛇:37)
  --at p5.redraw(p5.js:17153)
  --at p5。 (p5.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>

1 个答案:

答案 0 :(得分:1)

您将需要debug您的计划。 (该教程适用于Processing,但基本思路是相同的。)

你知道你的问题就在这一行:

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我们将从那里开始。祝你好运。