1

I'm trying to use coffeescript with box2dweb to create a simple game. Setting up the physics works fine and updates fine but when it comes to trying to call my own functions in the update loop I get this error 'undefined is not a function (evaluating this.batman())' (batman being the function name). I'm compiling to javascript before running it. This is my first time using coffeescript so I may be doing something stupid.

Here's my code:

root = exports ? this
root.world = null

class Game
    class Game
    canvasHeight: 450
    canvasWidth: 800
    canvas: null
    drawingContext: null

    constructor: ->
        @createCanvas()
        @resizeCanvas()
        @createDrawingContext()
        @initPhysics()

    createCanvas: ->
        @canvas = document.createElement 'canvas'
        document.body.appendChild @canvas

    resizeCanvas: ->
        @canvas.height = @canvasHeight
        @canvas.width = @canvasWidth

    createDrawingContext: ->
        @drawingContext = @canvas.getContext '2d'

    initPhysics: ->
        #physics setup removed for brevity

        window.setInterval(@update, 1000 / 60)


    batman: ->
        alert "whatever"

    update: ->
        root.world.Step(1 / 60,  10, 10)
        root.world.DrawDebugData()
        root.world.ClearForces()
        @batman()


    window.Game = Game
Evan Davis
  • 35,493
  • 6
  • 50
  • 57
  • It seems like your indentation is wrong. Everything inside the class should be indented. – elclanrs Jul 17 '13 at 01:25
  • You can't just call the `Batman`, you need to instantiate `BatSignal` first, then use `BatSignal.Call(Batman)`. –  Jul 17 '13 at 01:59

1 Answers1

1

In initPhysics, you need to bind @update to this:

window.setInterval(@update.bind(this), 1000 / 60)

because otherwise the this context is lost when update is called.

go-oleg
  • 19,272
  • 3
  • 43
  • 44
  • You'd need to save `this` outside of setInterval; otherwise your code compiles to `this.update.bind(this)` which is redundant. – Evan Davis Jul 17 '13 at 01:37
  • 1
    @Mathletics: The difference between `this.update` and `this.update.bind(this)` is that the former refers to a function (not bound to anything) whereas the latter refers to a function bound to `this`. The `this` in `bind(this)` is evaluated at the time that `window.setInterval` is called at which point it has the correct value (the Game instance) which is what we want. Heres a [fiddle](http://jsfiddle.net/BEAnv/) demonstrating something similar but in JavaScript. – go-oleg Jul 17 '13 at 01:46
  • `this.update` has `window` as its context, but I understand what you're trying to say. Your fiddle certainly proves it, though I have to say WTF to JavaScript for parsing `this.update.bind(this)` as `window.update.bind(Game)`. That's certainly a new one for me. – Evan Davis Jul 17 '13 at 12:06
  • Thanks a lot, that fixed it (and solved a few other mysteries too), although it still doesn't make a lot of sense to me. – user2589494 Jul 17 '13 at 12:44