javascripthtml5-canvassprite-sheet

Sprites won't draw on canvas


Ok, I give up.

I can get shapes to draw on the canvas, but not tiles from my sprite sheet. I've spent all night reading guide after guide. I'm clearly missing something obvious.

All I want is to draw a little square from my sheet onto the canvas. Not even animate anything, just have it show up.

At one point in my rancorous search for the answer, the whole sprite sheet appeared on the page, then I couldn't do anything with it. That happened with:

document.body.appendChild(spritesheet.png);

A lot of good that did me.

Here is my current bane of existence:

const gamecanvas = document.getElementById("gamecanvas");
const ctx = gamecanvas.getContext("2d");

// makes as many lovely green boxes as I wish
ctx.fillStyle = "green";
ctx.fillRect(0, 0, 50, 50);
ctx.fillStyle = "seagreen";
ctx.fillRect(50, 0, 50, 50);

// doesn't do anything and insults my mother
var sprite = new Image();
sprite.src = 'spritesheet.png';
ctx.drawImage(sprite, 0, 0, 50, 50, 0, 150, 50, 50);

Somebody throw me a bone and tell me why nothing shows up.


Solution

  • I have come across similar things while trying to do my own graphics in canvas.

    James is quite right. You need to wait till the image loads to use it. This is how I have implemented the issue in my own code:

    class CanvasImage{
       constructor(imagesrc){
         this.imgsrc=imagesrc;
         this.image=new Image(); //create new image
         this.image.src=imagesrc;
         this.image.crossOrigin="anonymous"; //stop poisoning the waterhole
         this.ready=false;
         const selfimg=this; //create something for the below anonymous function to reference
         this.image.onload=function(){selfimg.ready=true} //when the image loads, draw it.
       }
    

    Basically, this creates an object with a ready value that will show whether something is ready to draw yet or not.

    You can use the .image attribute in your ctx.drawImage calls.

    For me personally, classes are a nice way to bundle repetitive objects together.

    Implement this in your project like this:

    var sprite= new CanvasImage('spritesheet.png') //'new' keyword is needed whenever you create a new object
    
    ...
    
    //put this in your rendering loop function:
    if(sprite.ready){
    ctx.drawImage(sprite.image, 0, 0, 50, 50, 0, 150, 50, 50);
    }
    

    Note that the render will need to loop in order to draw the image once its ready. I'm sure you already know that, and have probably got a render function.

    The other way you can draw it is by changing the class onload to whatever function, such as a draw function.

    Contact me if more clarity is desired.