1

I am making a very simple game engine, and I'm working on a function to make sprites and draw them onto the canvas, but it seems to not draw. The image loads and it shows up in the chrome sources, but does not want to draw.


Here is the error:

Neutrino.js:44 Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)' at Image.Sprite.img.onload

And here is my code:

var canvas = document.createElement("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
var c = canvas.getContext("2d");

var Sprite = function(src,x,y,w,h,ctx) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.src = src;
    this.img = new Image(this.w,this.h);
    this.img.onload = function() {
        ctx.drawImage(this.img,this.x,this.y);   
    };
    this.img.src = this.src;
    return this;    
}

var puppy = new Sprite("puppy.jpg",100,100,100,100,c);

"puppy.jpg" is in the current web directory also.

neutrino
  • 11
  • 2
  • 3
    What does this have to do with python? – JacobIRR Jul 27 '18 at 20:57
  • Use an arrow function instead of `function`: `this.img.onload = () => { ctx.drawImage(this.img,this.x,this.y); };`. Your `this` context is wrong, see [How does the this keyword work](https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – ASDFGerte Jul 27 '18 at 20:59
  • Possible duplicate of [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – ASDFGerte Jul 27 '18 at 21:01

1 Answers1

0

Your onload callback uses the this keyword, which is not the same object as the this in the outer scope (How does the "this" keyword work?). You should fix the problem by either making a copy of the outer this and using the copy inside the callback:

var _this = this;
this.img.onload = function() {
    ctx.drawImage(_this.img, _this.x, _this.y);   
};

Or you can replace the callback function with a lambda, which treats the this keyword differently. I should remember that only modern browsers support lambdas at this point (https://caniuse.com/#feat=arrow-functions), so the first solution above maybe a better solution depending on the audience you want to reach. Here is the lambda version:

this.img.onload = () => ctx.drawImage(this.img, this.x, this.y);
HugoTeixeira
  • 3,879
  • 2
  • 18
  • 28