清除和元素渲染的问题

发布于 2025-02-12 10:05:00 字数 2541 浏览 2 评论 0原文

这个问题似乎很简单,但是我不明白我的错误是什么。

我在画布上绘制图像,一切都很好,但是当我添加清晰的效果时,这些元素将完全从画布中移除而不恢复它们。尽管清理周期应该在渲染之前发生

什么我的错误?一切似乎都很简单,但是我一直坚持使用很长的

应用程序主游戏类

游戏类 - 负责渲染画布并清理

IT播放器 - 负责玩家行为动画的逻辑

- 请求AnimatimationFrame。此功能,传递给它的功能

        class App {
    
        constructor() {
    
            this.player = new Player("Player 1", 0, 102);
            this.game = new Game();
    
            this.game.CreateCanvas();
    
            window.addEventListener('keyup', () => this.player.UpKey());
            window.addEventListener('keydown', (event)=> this.player.HandlerKeyPress(event));
    
            new Animation(this.Display.bind(this));
    
        }
    
        Display() {
    
            this.game.ClearCanvas();
            this.SetLevel();
    
        }
    
        SetLevel() {
    
            this.game.LoadSprite(assets.mario, [...player_assets.mario.small.standing_right,  ...this.player.GetPosition(), 16, 16]);
            this.StaticObject();
    
        }
    
        StaticObject () {
    
            for(let i = 0; i < 32; i++){
    
                this.game.LoadSprite(assets.block, [...lvl_1.block.ground.size,  i* 16, 134, 16,16]);
                this.game.LoadSprite(assets.block, [...lvl_1.block.ground.size,  i* 16, 118, 16,16]);
            
            }
    
        }
    
    }
    
    new App();
    
    export default class Game {
    
        CreateCanvas () {
    
            this.canvas = document.createElement("canvas");
    
            this.ctx = this.canvas.getContext("2d");
    
            document.body.appendChild(this.canvas);
    
        }
    
        ClearCanvas() {
    
            this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    
        }
    
        SetBackgroundColor (color) {
    
            this.ctx.fillStyle = color;
            this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
    
        }
    
        LoadSprite (src, position) {
            
            const _image = new Image();
    
            _image.src = src;
    
            _image.onload = () => {
    
                this.ctx.drawImage(_image, ...position, true);
    
            }
    
        }
    
    }

export default class LoopAnimation {

    constructor(display) {

        this.display = display;

        this.Animation = this.Animation.bind(this);

        this.Animation();

    }

    Animation() {

        requestAnimationFrame(this.Animation);

        this.display();

    }

}

the question may seem simple, but I can not understand what is my mistake.

I draw images on my canvas, everything is fine, but at the moment when I add clearRect, the elements are completely removed from the canvas without restoring them. Although the cleanup cycle should happen before the rendering

what's my mistake? everything seems to be simple, but I'm stuck with it for a very long time

App main game class

Game class - responsible for rendering to the canvas and clearing it

player - responsible for the logic of the player's behavior

animation - requestanimationframe is called in this function, on the function passed to it

        class App {
    
        constructor() {
    
            this.player = new Player("Player 1", 0, 102);
            this.game = new Game();
    
            this.game.CreateCanvas();
    
            window.addEventListener('keyup', () => this.player.UpKey());
            window.addEventListener('keydown', (event)=> this.player.HandlerKeyPress(event));
    
            new Animation(this.Display.bind(this));
    
        }
    
        Display() {
    
            this.game.ClearCanvas();
            this.SetLevel();
    
        }
    
        SetLevel() {
    
            this.game.LoadSprite(assets.mario, [...player_assets.mario.small.standing_right,  ...this.player.GetPosition(), 16, 16]);
            this.StaticObject();
    
        }
    
        StaticObject () {
    
            for(let i = 0; i < 32; i++){
    
                this.game.LoadSprite(assets.block, [...lvl_1.block.ground.size,  i* 16, 134, 16,16]);
                this.game.LoadSprite(assets.block, [...lvl_1.block.ground.size,  i* 16, 118, 16,16]);
            
            }
    
        }
    
    }
    
    new App();
    
    export default class Game {
    
        CreateCanvas () {
    
            this.canvas = document.createElement("canvas");
    
            this.ctx = this.canvas.getContext("2d");
    
            document.body.appendChild(this.canvas);
    
        }
    
        ClearCanvas() {
    
            this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    
        }
    
        SetBackgroundColor (color) {
    
            this.ctx.fillStyle = color;
            this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
    
        }
    
        LoadSprite (src, position) {
            
            const _image = new Image();
    
            _image.src = src;
    
            _image.onload = () => {
    
                this.ctx.drawImage(_image, ...position, true);
    
            }
    
        }
    
    }

export default class LoopAnimation {

    constructor(display) {

        this.display = display;

        this.Animation = this.Animation.bind(this);

        this.Animation();

    }

    Animation() {

        requestAnimationFrame(this.Animation);

        this.display();

    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

独闯女儿国 2025-02-19 10:05:00

我的怀疑是与缓存和事件的on载没有射击有关。 image.onload事件和浏览器cache
建议在src之前设置onload属性。

var img = new Image();
img.onload = function () {
   alert("image is loaded");
}
img.src = "img.jpg";

如果要重复使用已加载的图像,请将它们存储在数组中。然后从那里重复使用图像。例如,请参见:

const canvas = document.createElement("canvas");
document.body.appendChild(canvas);
canvas.width = 450;
canvas.height = 250;
const ctx = canvas.getContext("2d");

const assets = [
  "https://picsum.photos/id/237/150",
  "https://picsum.photos/id/235/150",
  "https://picsum.photos/id/232/150",
];
const assetsLoaded = assets.map(url =>
  new Promise(resolve => {
    const img = new Image();
    img.onload = e => resolve(img);
    img.src = url;
  })
);

Promise
  .all(assetsLoaded)
  .then(images => {
    (function gameLoop() {
      requestAnimationFrame(gameLoop);
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      images.forEach((e, i) =>
        ctx.drawImage(
          e, 
          i * 150 + Math.cos(Date.now() * 0.003 + i) * 20, // x
          Math.sin(Date.now() * 0.005 + i) * 50 + 50 // y
        )
      );
    })();
  })
  .catch(err => console.error(err))
;

// from https://stackoverflow.com/a/61337279/3807365

特别是针对您的问题,您可以声明全局对象var cache = {}其键是要加载的图像的SRC。因此,例如:

var cache = {};

LoadSprite(src, position) {
  if (cache[src]) {
    this.ctx.drawImage(cache[src], ...position, true);
    return;
  }

  const _image = new Image();
  _image.src = src;
  _image.onload = () => {
    cache[src] = _image;
    this.ctx.drawImage(_image, ...position, true);
  }
}

My suspicion is it's related to cache and event onload not firing. image.onload event and browser cache
suggests to set the onload property before the src.

var img = new Image();
img.onload = function () {
   alert("image is loaded");
}
img.src = "img.jpg";

If you want to reuse loaded images, then store them in an array. Then reuse the image from there. See for example:

const canvas = document.createElement("canvas");
document.body.appendChild(canvas);
canvas.width = 450;
canvas.height = 250;
const ctx = canvas.getContext("2d");

const assets = [
  "https://picsum.photos/id/237/150",
  "https://picsum.photos/id/235/150",
  "https://picsum.photos/id/232/150",
];
const assetsLoaded = assets.map(url =>
  new Promise(resolve => {
    const img = new Image();
    img.onload = e => resolve(img);
    img.src = url;
  })
);

Promise
  .all(assetsLoaded)
  .then(images => {
    (function gameLoop() {
      requestAnimationFrame(gameLoop);
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      images.forEach((e, i) =>
        ctx.drawImage(
          e, 
          i * 150 + Math.cos(Date.now() * 0.003 + i) * 20, // x
          Math.sin(Date.now() * 0.005 + i) * 50 + 50 // y
        )
      );
    })();
  })
  .catch(err => console.error(err))
;

// from https://stackoverflow.com/a/61337279/3807365

Specifically for your question, you can declare a global object var cache={} where its keys are the src of images to load. so, for example:

var cache = {};

LoadSprite(src, position) {
  if (cache[src]) {
    this.ctx.drawImage(cache[src], ...position, true);
    return;
  }

  const _image = new Image();
  _image.src = src;
  _image.onload = () => {
    cache[src] = _image;
    this.ctx.drawImage(_image, ...position, true);
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文