Search code examples
javascriptcoffeescriptcreatejsevent-listener

CreateJS createjs.Ticker.off("tick", element.update) not working


I'm making a shooting game in which I need to update the state of bullets by binding them to the 'tick' event, however when calling the remove method to remove them from the 'tick' event it does not removes it. After creating a new instance this keeps getting updated instead of the one that was binded.

The methods 'add'/'remove' are used to bind/unbind the methods from the 'tick' event

class window.Stage

  stage = undefined
  counter = 0
  fps = 60

  add: (element) =>
    element.id = counter++
    stage.addChildAt(element.view, element.id)
    element.listener = createjs.Ticker.on("tick", element.update)

  remove: (element) =>
    createjs.Ticker.off("tick", element.listener) # Not removing!
    stage.removeChildAt(element.id)

  update: () =>
    stage.update()

This is how I'm calling the remove method in the Game class

  run: () => 

    if @gun? && [email protected]
      @stage.remove(@gun)
      @gun = undefined

    if @player.shooting() && !@gun?     
      @gun = @player.shoot() # Ticker keeps updating new instance
      @stage.add(@gun)

    for bunker in @bunkers
      if @gun? && bunker.gotShot(@gun)
        @gun.alive = false

This is how bullets are created

class window.Player      
  shoot: =>
    new Gun(@name, @x, @y - radius, false)

If there's any tutorial to better undestand how to correctly use listerners a link will be very much appreciated, thanks is advance.


Solution

  • The off() method requires you pass the method closure generated by calling on(), and not the original method that is passed. This is because the on() method generates a closure to maintain scope -- whereas addEventListener will not scope methods for you, requiring you to bind them yourself, or use global or anonymous handlers.

    Make sure to store off the closure, and pass that instead. I am not familiar with the syntax in your example, so here is a vanilla JS example:

    var listener = element.on("tick", handler, this);
    element.off("tick", listener);
    

    Note that the 3rd parameter is the scope the method should be called in, and if you don't pass it, it still generates a closure, and fires it in the element's scope instead of anonymously. There are also some other nice features of the on() approach, such as the "fire once" and event.remove() functionality.

    You can always stick with the addEventListener/removeEventListener methods if you would prefer the same behaviour as DOM level 3 events.