Quick Links: Gideros Home | Download Gideros | Developer Guide
onEnterFrame removal troublesome.
  • Hey guys,

    I'm stumped on this right now; Trying to reset my level but my update function continues and errors out some Bump stuff. So I figure I need to remove the event listener on reset, but it doesn't work. Here's some code:
    function GameScene:addEventListeners()
    self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
    end
     
    function GameScene:removeListeners(s)
    print(s)
    print(self)
    print(GameScene)
     
    s:removeEventListener(Event.ENTER_FRAME, s.onEnterFrame, s)
    end


    In my NPC class's update loop (triggered from GameScene:onEnterFrame on a GAME_STARTED bool):
    if LIVES > 1 then
    GameScene:removeListeners(GameScene)
    else
    ...


    I'm not great around the whole event listening concept to be honest.

    But basically the new level loads an then swiftly crashes when GAME_STARTED is set to true and it will try to finish the previous round's update loop...
  • pie +1 -1 (+1 / -0 )
    Member Accepted Answer
    Maybe i am wrong, but it seems to me that in the second snippet you are using a global class as a parameter (and as base class) for your function.
    I am Sorry I am on mobile right now so it's hard to write it out... :)
    I think that in your NPC function you need to call the gamescene with its instance name (not the class name).
    if you're using scene manager it may be scenemanager.scene1
    Edit: another option could be to ask the NPC instance to get its parent (which somewhere in the hierarchy of sprites is the scene) using self:getParent() - where self, if placed inside the NPC base class refers to the instance of NPC class which is executing the code.

    Likes: Astirian

  • antixantix +1 -1 (+1 / -0 )
    Member
    @pie is correct, your'e doing it wrong :D

    When you create your game scene you must be calling GameScene.new() so you would need to use that instance when removing listeners, like this..
    GAME_SCENE = GameScene.new()
     
    GAME_SCENE:removeListeners()

    Which would work without errors I think.

    Are you using SceneManager in your project?

    Likes: Astirian

    Check out my DevBlog, my GitHub, and my games Falling Animals | Breaky Wall | Exetor
  • jdbcjdbc +1 -1
    Member
    Try this:
    GameScene = Core.class(Sprite)
     
    -- Create game scene
    function GameScene:init()
    ...
    self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame,self)
    end
     
    function GameScene:onEnterFrame()
    -- Update your player, ...
    end
     
    function GameScene:removeListeners()
    self:removeEventListener(Event.ENTER_FRAME, self.onEnterFrame,self)
    ...
    end


    Call removeListeners when you are going to change the current scene. For example:
    -- Player is dead
    self:removeEventListeners()
     
    -- Change scene now using SceneManager.


    I have also published the full source code of my game Square Dots published in Android and iOS but GPL 3 license for education purposes. You can learn from it, this is the way I have built most of my games.

    https://github.com/jdbcdev/Dots

  • jdbcjdbc +1 -1
    Member

    I guess your problem is you need to understand class (use . as separator) and objects methods (use : as separator) in Object Oriented Programming. For instance:

    GameScene.staticFunction1() is a class function. You have to call in this way:
    GameScene.staticFunction1()


    Below function does not need to create a object of GameScene, you can use it anywhere in your Gideros project.

    Besides GameScene:removeListener() is a function of one instance of the GameScene. You must use
    self:removeListener()


  • antix said:

    @pie is correct, your'e doing it wrong :D

    When you create your game scene you must be calling GameScene.new() so you would need to use that instance when removing listeners, like this..

    GAME_SCENE = GameScene.new()
     
    GAME_SCENE:removeListeners()

    Which would work without errors I think.

    Are you using SceneManager in your project?


    Ahh... Yes I am. Let me see if I understand this.

    I'm instantiating scenes like this in main.lua:
    	scenes = {"logo", "menu", "game", "score"}
     
    sceneManager = SceneManager.new({
    ["logo"] = LogoScene,
    ["menu"] = MenuScene,
    ["game"] = GameScene,
    ["score"] = ScoreScene
    })
     
    stage:addChild(sceneManager)

    So when do this from NPC.lua's update function:
    	o = self:getParent()
    o2 = o:getParent()
    o3 = o2:getParent()
    o4 = scenes[3]
    o5 = game
     
    print(o)
    print(o2)
    print(o3)
    print(o4)
    print(o5)
     
    GameScene:removeListeners(o4)


    Which calls this in GameScene.lua:
    function GameScene:removeListeners(s)
    print(s)
    print(self)
    print(GameScene)
     
    print(self.onEnterFrame)
     
    s:removeEventListener(Event.ENTER_FRAME, s.onEnterFrame, s)
    end


    I'm past the _userdata error but now s is nil I think, and I'm not sure why as s is the instantiated scene right?

    The memory addresses (or pointers?) for the variables above are interesting (obviously they change on every run but you get the idea :) )

    o = 0x115cf748
    o2 = 0x115bc090
    o3 = 0x1159f1d0
    o4 = game
    o5 = nil

    self and GameScene are 0x115c52e8 (which I assume is the base class directly?)

    I'm guessing that passing in 'game' is not correct?

    Interestingly trying GAME = sceneManager.game is nil...
  • antixantix +1 -1 (+1 / -0 )
    Member Accepted Answer
    To access one class from another I just use global variables. Even though many people frown on this it isn't as bad as it might seem. In my game class for instance...
    function Game:init()
    GAME = self -- makes this instance available to ALL other things
    end

    So that line of code makes that instance of the game class available to ALL instances of ALL other classes in your project.
    function npc:update()
    local game = GAME -- not strictly required but good if multiple calls will be used
    game:removeListeners(o4)
    end

    That is guaranteed to work :)

    Let us know how you get on ;)

    Might I ask why every npc instance has it's own EnterFrame event?

    Likes: Astirian

    Check out my DevBlog, my GitHub, and my games Falling Animals | Breaky Wall | Exetor
  • @antix Thanks I'll give that a crack when I get home from work.

    To answer your question, I don't have an onEnterFrame function in the NPC class, but my game scene's onEnterFrame calls the NPC's update function.

    So basically, here we're saying to the NPC instance (on the update run where it tries to reset the round):
      local game = GAME -- not strictly required but good if multiple calls will be used
    game:removeListeners(o4)


    locally use game (which points to the GAME instance form init) and send it a reference to o4, which itself is a direct reference to the instance created when I initially create my sceneManager array in main? (I.e. scenes[3])
  • antixantix +1 -1 (+1 / -0 )
    Member
    Yep that's correct.

    So I still don't quite get your code though. This line..
    s:removeEventListener(Event.ENTER_FRAME, s.onEnterFrame, s)

    seems to read that the object s has an ENTER_FRAME event listener attached to it.

    Likes: Astirian

    Check out my DevBlog, my GitHub, and my games Falling Animals | Breaky Wall | Exetor
  • jdbcjdbc +1 -1 (+1 / -0 )
    Member
    Astirian said:

    @antix Thanks I'll give that a crack when I get home from work.

    To answer your question, I don't have an onEnterFrame function in the NPC class, but my game scene's onEnterFrame calls the NPC's update function.

    So basically, here we're saying to the NPC instance (on the update run where it tries to reset the round):

      local game = GAME -- not strictly required but good if multiple calls will be used
    game:removeListeners(o4)


    locally use game (which points to the GAME instance form init) and send it a reference to o4, which itself is a direct reference to the instance created when I initially create my sceneManager array in main? (I.e. scenes[3])


    Just use my code above, easier and using only local variables in every scene. I have done all my games using these code and I have several ones.

    In the main.lua the following code to create scenes using SceneManager:
    scenes = {"menu", "game"}
     
    sceneManager = SceneManager.new({
    ["menu"] = MenuScene,
    ["game"] = GameScene,
    })
     
    stage:addChild(sceneManager)
     
    local currentScene = scenes[1]
     
    local timer = Timer.new(1000, 1)
    timer:addEventListener(Event.TIMER,
    function()
    ...
    sceneManager:changeScene(currentScene)
    end)
    timer:start()


    Only use global variables with constants or global objects.

    Likes: Astirian

  • AstirianAstirian +1 -1 (+1 / -0 )
    Member
    Thanks guys, got it working. :)

    Likes: antix

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Login with Facebook Sign In with OpenID

In this Discussion

Top Posters