繁体   English   中英

收到“无法读取未定义的属性 'getFoodX'”错误

[英]getting a “Cannot read property 'getFoodX' of undefined” error

因此,我正在尝试编写一个基本的 Snake 游戏并得到一个未定义的错误,尽管在查看它之后我没有发现我的代码有任何问题。 删除导致 getFood 错误的 if 条件时, this.apple.getFoodX出现相同的错误。

class Game {

    constructor(canvas, extent) {
        this.canvas = canvas;
        this.extent = extent;
        this.cellSize = canvas.width / extent;
        this.context = canvas.getContext('2d'); 
        this.initGame();
        this.gameOver = false;
        setInterval(x => {
            this.loop()
        }, 350);
    }

    drawLine(x1, y1, x2, y2) {
        this.context.beginPath();
        this.context.moveTo(x1, y1);
        this.context.lineTo(x2, y2);
        this.context.stroke();

    }

    drawGrid() {
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
        for (let i = 1; i <= this.extent; i++) {
            this.drawLine(i * this.cellSize, 0, i * this.cellSize, this.canvas.height);
            this.drawLine(0, i * this.cellSize, this.canvas.width, i * this.cellSize);
        }
    }

    newApple() {
        this.apple.create(this.extent);
    }

    getAppleX() {
        return this.apple.getFoodX();
    }
    getAppleY() {
        return this.apple.getFoodY();
    }
    getExtent() {
        return this.extent;
    }
    genFood() {
        this.apple.create(extent);
    }

    loop() {
        if(this.gameOver === false) {
            this.snake.update();
        }
        if(this.gameOver === false) {
            this.drawGrid();
            this.snake.draw();
            this.apple.draw();
        }

    }
    draw() {
        this.drawGrid();
        this.snake.draw();
        this.apple.draw();

    }

    initGame() {
        this.snake = new Snake([{x:7,y:8},{x:8,y:8},{x:9,y:8,}],this.cellSize, this.context, this.extent, 'ArrowRight');
        this.apple = new Apple(5,10,this.cellSize,this.context);
    }
    gameEnds() {
        this.gameOver = true;
    }
}

class Apple{
    constructor(x,y,cellSize,context) {
        this.x = x;
        this.y = y;
        this.cellSize = cellSize;
        this.context = context;
        this.newApple = {x:0,y:0};
    }

    draw() {
        this.context.fillStyle = 'green';
        this.context.fillRect(this.x * this.cellSize, this.y * this.cellSize, this.cellSize, this.cellSize);
    }

    create(extent) {
        this.newApple = {x: Math.floor(Math.random() * extent),y: Math.floor(Math.random() * extent)};
        this.x = this.newApple.x;
        this.y = this.newApple.y;

        for(let i = 0; i < this.snake.snakeArray.length; i++) {
            if (this.newApple.x == this.snake.snakeArray[i].x && this.newApple.y == this.snake.snakeArray[i].y) {
                this.newApple = {x: Math.floor(Math.random() * extent),y: Math.floor(Math.random() * extent)};
                this.x = this.newApple.x;
                this.y = this.newApple.y;
            }
        }
    }
    getFoodX() {
        return this.x;
    }
    getFoodY(){
        return this.y;
    }
}

class Snake {
    constructor(snakeArray, cellSize,context,extent,pressedKey) {
        this.cellSize = cellSize;
        this.context = context;
        this.extent = extent;
        this.pressedKey = pressedKey;
        this.snakeArray = snakeArray;
        //this.snakeArray.push(startingPos);
        this.snakeHead = {x: this.snakeArray[this.snakeArray.length-1].x, y:this.snakeArray[this.snakeArray.length-1].y}; 
        document.addEventListener('keyup', event => {
            this.handleKeyUp(event);
        });
    }

    handleKeyUp(event) {
        if (event.code === 'ArrowUp' || event.code === 'ArrowDown' || event.code === 'ArrowLeft' || event.code === 'ArrowRight') {
            this.pressedKey = event.code;
        }
    }

    update() {
        let newSnakeHead = {x:0,y:0};
        if (this.pressedKey === 'ArrowUp') {
            newSnakeHead = {x: this.snakeHead.x, y: this.snakeHead.y-1};
        } else if (this.pressedKey === 'ArrowRight') {
            newSnakeHead = {x: this.snakeHead.x+1, y: this.snakeHead.y};
        } else if (this.pressedKey === 'ArrowDown') {
            newSnakeHead = {x: this.snakeHead.x, y: this.snakeHead.y+1};
        } else if (this.pressedKey === 'ArrowLeft') {
            newSnakeHead = {x: this.snakeHead.x-1, y: this.snakeHead.y};
        }
        if(newSnakeHead.x === this.game.getFoodX() && newSnakeHead.y === this.game.getFoodY()) {
            this.snakeArray.push(newSnakeHead);
            this.game.genFood(); 
        }
        else {
            this.snakeArray.shift();
            if(this.outOfBounds(newSnakeHead, this.extent) === true || this.snakeHit(newSnakeHead, this.extent) === true) {
                this.game.gameEnds();
            }
            else{
                this.snakeArray.push(newSnakeHead);
            }
            }
    }
    draw() {
        for(let i = 0; i< this.snakeArray.length-1; i++) {
            this.drawSquare(this.snakeArray[i].x, this.snakeArray[i].y, 'red');
        }
        this.drawSquare(this.snakeHead.x,this.snakeHead.y,'yellow');
    }

    outOfBounds(newSnakeHead,extent) {
        if(newSnakeHead.x > extent || newSnakeHead.x < 0 || newSnakeHead.y > extent || newSnakeHead.y < 0 ) {
            this.game.gameEnds();
            return true;
        }
    }

    snakeHit(newSnakeHead) {
            for(let i = 0; i< this.snakeArray.length; i++) {
                if (newSnakeHead.x == this.snakeArray[i].x && newSnakeHead.y == this.snakeArray[i].y) {
                    this.game.gameEnds();
                    return true;
                }
            }
    }

    drawSquare(x,y,color) {
        this.context.fillStyle = color;
        this.context.fillRect(x * this.cellSize, y * this.cellSize, this.cellSize, this.cellSize);
    }
}

const canvas = document.getElementById('myCanvas');
const game = new Game(canvas, '16');

任何帮助表示赞赏!

您正在尝试使用this游戏在 Snake class 中访问game object,但它不是 Snake class 的一部分。 所以我认为,在Snake class 中的update()方法中,以下语句是罪魁祸首:-

if(newSnakeHead.x === this.game.getFoodX() && newSnakeHead.y === this.game.getFoodY()) {
            this.snakeArray.push(newSnakeHead);
            this.game.genFood(); 
        }

您可以在 Snake 构造函数中创建对游戏的引用,例如:-

constructor(snakeArray, cellSize,context,extent,pressedKey,game) {
        this.cellSize = cellSize;
        this.context = context;
        this.extent = extent;
        this.pressedKey = pressedKey;
        this.snakeArray = snakeArray;
        this.game = game;
        //this.snakeArray.push(startingPos);
        this.snakeHead = {x: this.snakeArray[this.snakeArray.length-1].x, y:this.snakeArray[this.snakeArray.length-1].y}; 
        document.addEventListener('keyup', event => {
            this.handleKeyUp(event);
        });
    }

在你的游戏 class 中:-

initGame() {
        this.snake = new Snake([{x:7,y:8},{x:8,y:8},{x:9,y:8,}],this.cellSize, this.context, this.extent, 'ArrowRight',this);
        this.apple = new Apple(5,10,this.cellSize,this.context);
    }

传递额外的this参数。 这将帮助您在Snake class 中设置对game属性的正确引用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM