渲染JS画布之前加载图片

问题描述 投票:0回答:1

我正在编写一个简单的游戏来学习 JS,并且在此过程中我正在学习 HTML5,所以我需要在画布上绘制东西。

这是代码:

 let paddle = new Paddle(GAME_WIDTH,GAME_HEIGHT);

 new InputHandler(paddle);

 let lastTime = 0;

 const ball = new Image();
 ball.src = 'assets/ball.png';

 function gameLoop(timeStamp){
   let dt = timeStamp - lastTime;
   lastTime = timeStamp;

   ctx.clearRect(0,0,600,600);
   paddle.update(dt);
   paddle.draw(ctx);

   ball.onload = () => {
    ctx.drawImage(ball,20,20);
  }

  window.requestAnimationFrame(gameLoop);
 }

gameLoop();

截图:无球 before comment

现在我注释掉了

clearRect()

after comment

你好球。

画布底部还有一个桨,似乎不受

clearRect()
方法的影响。它工作得很好。我在这里缺少什么?

javascript html canvas drawimage
1个回答
1
投票

将图像的

onload
处理程序放入游戏循环中没有多大意义。这意味着游戏必须在设置图像的
onload
功能之前开始运行,从而导致非常混乱的情况。

正确的顺序是设置

onload
处理程序,然后设置图像源,然后
await
所有图像
onload
在运行游戏循环之前触发。当您只有一张图像时,直接将主循环设置为
onload
非常容易,但对于具有多个资产的游戏,这很快就会变得尴尬。

以下是如何使用

Promise.all
加载许多游戏资源的最小示例。很可能,您希望将加载的图像解压缩为更具描述性的对象而不是数组,但这只是一个开始。

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

const assets = [
  "http://placekitten.com/120/100",
  "http://placekitten.com/120/120",
  "http://placekitten.com/120/140",
];
const assetsLoaded = assets.map(url =>
  new Promise((resolve, reject) => {
    const img = new Image();
    img.onerror = e => reject(`${url} failed to load`);
    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 * 120, // x
          Math.sin(Date.now() * 0.005) * 20 + 40 // y
        )
      );
    })();
  })
  .catch(err => console.error(err));

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.