在渲染JS画布之前加载图像 [英] Loading images before rendering JS canvas

查看:55
本文介绍了在渲染JS画布之前加载图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写其中一种简单的游戏来学习JS,并且在此过程中正在学习HTML5,所以我需要在画布上画图.

I'm writing one of those simple games to learn JS and I'm learning HTML5 in the process so I need to draw things on canvas.

代码如下:

 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();

屏幕截图:无球在发表评论之前

现在我注释掉 clearRect():

评论后

你好球.

画布底部还有一个桨,似乎不受 clearRect()方法的影响.它工作正常.我在这里想念什么?

There's also a paddle at the bottom of the canvas that doesn't seem to be affected by the clearRect() method. It works just fine. What am I missing here?

推荐答案

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

It doesn't make much sense to put the image's onload handler inside the game loop. This means the game has to begin running before the image's onload function is set, leading to a pretty confusing situation.

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

The correct sequence is to set the onload handlers, then the image sources, then await all of the image onloads firing before running the game loop. Setting the main loop to an onload directly is pretty easy when you only have one image, but for a game with multiple assets, this can get awkward quickly.

这是有关如何使用 Promise.all .您很可能希望将加载的图像解压缩为更具描述性的对象,而不是数组,但这只是一个开始.

Here's a minimal example of how you might load many game assets using Promise.all. Very likely, you'll want to unpack the loaded images into more descriptive objects rather than an array, but this is a start.

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 => {
    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))
;

这篇关于在渲染JS画布之前加载图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆