canvas drawImage doesn't draw images the first time
Asked Answered
Z

1

5

I'm working on a simple JavaScript game using HTML5 canvas. It's a very typical game-loop setup involving:

  • init() function that initializes objects to be used the playfield, randomizing some start x/y positions and similar setup tasks
  • draw() function that draws all the game objects, including some simple canvas shapes and a few images
  • setInterval to call draw every 25 milliseconds

While getting this project started, I had the setInterval call at the end of the init() function, so it'd just start drawing and animating as soon as you loaded the page, and everything worked fine. Now that I'm further along, I'd like to draw a fully populated, static playfield on load and then use a button to kick off the main game loop interval. So I added a single call to draw() at the end of init(), and the issue is that when I do this, all the canvas shapes get drawn properly but none of the images render on the canvas.

They do render if I let draw() run a few times, like...

    var previewDraw = setInterval(draw, 25);
    var stopPreviewDraw = function() { clearInterval(previewDraw) }
    setTimeout(stopPreviewDraw, 100)

...but that seems dumb. Why doesn't a single call to draw() work? I've logged the objects in Chrome's and Firefox's consoles and everything about them looks fine; they already have the appropriate img src paths and start x/y values available to pass to assign to the new Image() that gets created and then called via my canvas.2dcontext.drawImage() method.

I'm testing this in Chrome 6 and Firefox 3.6.10 as I go, and they're both puzzling me with this behavior. No errors or issues show in Chrome's console but if I try calling draw() only once the Firefox throw this:

uncaught exception: [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIDOMCanvasRenderingContext2D.drawImage]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame :: http://localhost/my-game-url/ :: drawItem :: line 317" data: no]

My Google searches for that error suggest a corrupt image, but they all open in Preview and Photoshop without any problems.

Zoba answered 3/10, 2010 at 15:15 Comment(0)
N
8

I assume you are calling init() after the onload event of the window object is fired. The problem is, that does not guarantee to you that the image data is actually available at that point. AFAIR it would fire after the images are fetched from the network but then they still need to be decoded.

Your best bet would be to wait for the images' onload event instead.

Nonrecognition answered 3/10, 2010 at 15:38 Comment(2)
DUH... nope, since this is a practice project and I'm so focused on new stuff I'm learning, I had totally forgotten the obvious (I was just running it inline at the bottom of the page). Since there aren't that many image assets and they're all small, running init() at window.onload handles this just fine. Thanks much, Jakub.Zoba
Eventually I guess I'll replace all of the external images with Data URLs anyway.Zoba

© 2022 - 2024 — McMap. All rights reserved.