未使用 drawImage() 加载 HTML5 画布图像

时间:2021-03-26 12:00:12

标签: javascript html html5-canvas game-development

我正在学习 freeCodeCamp 的关于飞翔小鸟游戏的教程 https://www.youtube.com/watch?v=pufKO5EG8nc

但我通过课堂来了解更多相关信息。

问题是,图像无法加载,而在视频中加载正常。

我在谷歌上搜索并了解了 onload 事件,并在那里实现了它,但仍然没有任何问题,控制台中也没有错误消息。

即使没有 onload 事件,为什么视频的图像会加载,而我的却没有? >:(

我的 HTML 代码:

<canvas id="canvas" width="512" height="512">
</canvas>

我的 JS 代码:

const canvas = document.querySelector("#canvas");
class Game {
    constructor(c) {
        this.c = c; //canvas
        this.ctx = c.getContext("2d"); // context
        this.sprites = 5;
        this.loadedSprites = 0;

        this.player = new Image(); // define images
        this.bg = new Image();
        this.fg = new Image();
        this.north = new Image();
        this.south = new Image();

        this.pX = 10; // player starting location
        this.pY = 150;

        // set sprite locations and load.
        this.player.src = "images/crab.png";
        this.player.onload = this.draw;
        this.bg.src = "images/bg.png";
        this.bg.onload = this.draw;
        this.fg.src = "images/fg.png";
        this.fg.onload = this.draw;
        this.north.src = "images/obstacle.png";
        this.gap = 80;
        this.constant = this.north.height + this.gap;
        this.north.onload = this.draw;
        this.south.src = "images/obstacle.png";
        this.south.onload = this.draw;
    }

    //draw images
    draw() {
        this.loadedSprites += 1;
        if (this.loadedSprites >= this.sprites) {
            this.ctx.drawImage(this.bg, 0, 0);
            this.ctx.drawImage(this.north, 100, 0);
            this.ctx.drawImage(this.south, 0, 0 + this.constant);
            this.ctx.drawImage(this.fg, 0, this.c.height - this.fg.height);
            this.ctx.drawImage(this.player, this.pX, this.pY);
        }
    }
}
let game = new Game(canvas);

1 个答案:

答案 0 :(得分:0)

您的问题与范围有关——它指的是变量、对象和函数的可访问性——以及this关键字的含义取决于实际范围.

为了更好地理解,让我们看一下下面的例子:

class Game {
  constructor() {
    console.log("Game constructor:", this);
    this.player = new Image();
    this.player.onload = this.draw;
    this.player.src = "https://picsum.photos/200/300";
  }

  draw() {
    console.log("draw:", this);
  }
}
let game = new Game();

如果您点击“运行代码片段”,您应该会在控制台中看到以下输出:


Game constructor: {}
draw: <img src="https://picsum.photos/200/300"></img>

如您所见,对 draw() 内的 this 的调用不再指同一事物。在第一种情况下,它是 Game 的对象实例(用大括号表示),在第二种情况下,它是 HTMLImageElement 的实例。

所以你的代码失败了,因为:

this.loadedSprites += 1;
if (this.loadedSprites >= this.sprites) {

不要引用 Game 类的私有变量 loadedSpritessprites - 事实上它根本不引用任何东西,因为它只是在 draw 函数的范围内未定义,因此 {{1} } 永远不会增加。

一种解决方法是使用新属性将 Game 类的上下文传递给每个 Image 实例,例如loadedSprites

.reference

并在 draw() 中使用它,例如:

this.player = new Image();
this.player.reference = this;
this.player.onload = this.draw;

以下是基于您的代码的完整示例:

draw() {
     this.reference.loadedSprites += 1;
}
const canvas = document.querySelector("#canvas");
class Game {
  constructor(c) {
    this.c = c; //canvas
    this.ctx = c.getContext("2d"); // context
    this.sprites = 5;
    this.loadedSprites = 0;

    this.player = new Image(); // define images
    this.player.reference = this;
    this.bg = new Image();
    this.bg.reference = this;
    this.fg = new Image();
    this.fg.reference = this;
    this.north = new Image();
    this.north.reference = this;
    this.south = new Image();
    this.south.reference = this;

    this.pX = 10; // player starting location
    this.pY = 150;

    // set sprite locations and load.

    this.player.onload = this.draw;
    this.player.src = "https://picsum.photos/id/237/20/20";

    this.bg.onload = this.draw;
    this.bg.src = "https://picsum.photos/id/22/20/20";

    this.fg.onload = this.draw;
    this.fg.src = "https://picsum.photos/id/30/20/20";

    this.gap = 80;
    this.constant = this.north.height + this.gap;

    this.north.onload = this.draw;
    this.north.src = "https://picsum.photos/id/37/20/20";

    this.south.onload = this.draw;
    this.south.src = "https://picsum.photos/id/137/20/20";
  }

  //draw images
  draw() {
    let ref = this.reference;
    ref.loadedSprites += 1;
    if (ref.loadedSprites >= ref.sprites) {
      ref.ctx.drawImage(ref.bg, 0, 0);
      ref.ctx.drawImage(ref.north, 100, 0);
      ref.ctx.drawImage(ref.south, 0, 0 + ref.constant);
      ref.ctx.drawImage(ref.fg, 0, ref.c.height - ref.fg.height);
      ref.ctx.drawImage(ref.player, ref.pX, ref.pY);
    }
  }
}
let game = new Game(canvas);

相关问题