Question

LoCEngine.prototype.runGame = function() {
    // Initiate our game loop
    ctx.clearRect(0, 0, 800, 600);
    this.drawScene(this.curScene);
    if(this.gameRunning) {
            window.setTimeout(Engine.runGame, 1000 / this.framerate);
    }
}

LoCEngine is an experimental engine I've been building to learn the ins and outs of HTML5 Canvas gaming. Been a good time thusfar, until I've hit the gameloop. runGame is called over time, which clears the Canvas and calls the drawScene function.

LoCEngine instance is stored in variable Engine (not sure if using that in setTimeout is best practices...please advise)

It will correctly call this.drawScene for the first frame, but upon the Timeout (30 FPS) it throws an exception saying:

TypeError: this.drawScene is not a function

Not quite sure why...I'm sure it's just something about JS I haven't come across. Thank you in advance.

Was it helpful?

Solution

You need to do it like this to make the method call properly:

LoCEngine.prototype.runGame = function() {
    // Initiate our game loop
    ctx.clearRect(0, 0, 800, 600);
    this.drawScene(this.curScene);
    if(this.gameRunning) {
            window.setTimeout(function() {
                Engine.runGame()
            }, 1000 / this.framerate);
    }
}

When you pass Engine.runGame to setTimeout(), it just passes the method reference itself and the object part of is lost. Thus, when it's called by the internals of setTimeout(), it no longer has the proper object reference in this and it generates the error you see when the code tries to call another method based on this. The work-around is to call it yourself with an anonymous function as I've shown.

It's also possible to use .bind() which essentially does the same thing for you internally. But, .bind() isn't supported in older browsers so I tend to just use the anonymous function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top