Problem removing an enterframe event listener

Hello everybody.

My name is Andreu, I am new to Corona and this is my first post. I am trying to develop my first game in Corona and I have a small problem.

I need to be able to attach ropes to platforms. At the moment, platforms are rectangles and the rope is a distance joint.

The rope is created inside the function CreateRope which is called by a touch event listener assigned to the platform.

One end of the rope is attached to the point of first contact in the platform and the other end is where the touch is taking place at any moment. My problem is when creating the guide line for the rope, for which I have modified the example of the cue line for the simple pool demo game included in the Corona SDK.

In my program the function CreateRope is in another file in order to modularize the code and because it has more functionalities.

The problem I have is with the function drawLine. This function is called every frame from an enterframe event listener initiated in the began phase of the touch event and ended by removing the event listener in the end or cancelled phase of the same touch event. At this point the guide line is also removed.

If I put the drawLine function inside the ‘if “began” == phase’ chunk of code it works properly. However, when I put the drawLine function outside of this chunk of code and inside the CreateRope function (as is shown in the pasted code) the guide line continues to be drawn when the touch event is finished and is never removed. In fact, the enterframe event listener is not removed, because it seems that I have no acces to it from where I remove the enterframe event listener. Also, I am sure that I only create one enterframe event listener because I print whenever one is created.

I don’t understand why this happens and it’s strange to me, though I am sure it’s a basic mistake. I don’t know why I can’t put the function drawLine inside the function CreateRope and not in the “if began” portion of this same function. I want to have it outside in order to make other variables local (xtouch, ytouch, myLine, anchorplatform).

I’d be very grateful if anyone can help me.

Thanks in advance.

Here is the troublesome code:

[code]
local physics = require(“physics”)
–physics.setDrawMode( “hybrid” )
physics.start()

display.setStatusBar( display.HiddenStatusBar )

– ground
local ground = display.newRect( 0,0, 900, 160 )
ground.x = display.contentWidth / 2; ground.y = display.contentHeight - ground.height / 2
physics.addBody( ground, “static”, { friction=0.6 } )

– platform
local platform = display.newRect( 0,0, 200, 80 )
platform:setFillColor(0,255,0)
platform.x = 320; platform.y = 200
platform.rotation=-20
physics.addBody( platform, “dynamic”, { density=1, friction=0.7, bounce=0.1 } )
local function CreateRope( event )

local platform = event.target
local phase = event.phase

xtouch = event.x
ytouch = event.y

local function drawLine()

if ( myLine ) then
myLine.parent:remove( myLine ) – erase previous line, if any
end

myLine = display.newLine( anchorplatform.x, anchorplatform.y, xtouch, ytouch )
myLine:setColor( 255, 255, 255, 50 )
myLine.width = 8

return

end

if “began” == phase then

myLine=nil

display.getCurrentStage():setFocus( platform )
platform.isFocus = true

– 1st anchor point of the rope: where the event starts in the platform
anchorplatform=display.newCircle( event.xStart, event.yStart, 2 )
anchorplatform:setFillColor(0,0,255)
physics.addBody(anchorplatform)
physics.newJoint( “weld”, platform, anchorplatform, event.xStart, event.yStart )

– Add the enterframe event listener
platform.drawLine = Runtime:addEventListener(“enterFrame”, drawLine)
print(“add”)

elseif platform.isFocus then

xtouch = event.x
ytouch = event.y

if “moved” == phase then

elseif “ended” == phase or “cancelled” == phase then

– 2nd anchor point of the rope: where the touch event ends
local anchor = display.newCircle( event.x, event.y, 2 )
anchor:setFillColor(255,0,0)
physics.addBody( anchor, “kinematic”, { density = 0.1, friction = 0.3, bounce = 0.2, radius = 1 } )
local rope = physics.newJoint( “distance”, platform, anchor, anchorplatform.x, anchorplatform.y, event.x, event.y )

– Remove the enterframe event listener
Runtime:removeEventListener(“enterFrame”, drawLine)
print(“remove”)

myLine.parent:remove( myLine )
myLine=nil

display.getCurrentStage():setFocus( nil )
platform.isFocus = false

end
end

return true

end

platform:addEventListener( “touch”, CreateRope )
[/code] [import]uid: 152893 topic_id: 29372 reply_id: 329372[/import]

Hi there,
Welcome to Corona!

At first glance, I would say this:

Line 56, you don’t need to assign the Runtime listener to the reference “platform.drawLine”. Runtime listeners all reside in the same “space” and don’t need reference or holder variables.

I’d pull the entire drawLine function out of that main function (un-nest it) and place it directly above. And somewhere above that, create a local reference variable like “currentRope” which will become your constantly-changing rope image/line. Use this for ALL of your rope references instead of the global “myLine”. To reference the anchor in the un-nested function, you could assign it (anchorplatform, the object) to a subvariable like “currentRope.anchorPoint”.

Let me know how this goes, and I should be able to help you through the rest!

Brent
[import]uid: 9747 topic_id: 29372 reply_id: 118122[/import]

Thank you very much Brent, your solution worked all right and seems a better design.

The problem in Line 56 assigning reference to the listener was a desperate attempt to make it work but as you said it was useless.

However, I still don’t know why the drawLine function works fine inside the “if began == phase” (i.e. after line 48) but it doesn’t work in line 28 because in both cases it is inside the function CreateRope. In fact, the drawLine works fine in both places, but if I put it in line 28 I can’t remove the enterframe event listener and the guide line for creating the rope remains on screen after the touch event.

And now it’s even more mysterious to me, because the program behaves in the same way whether the function drawLine is outside the CreateRope function or inside the if began==phase of the function CreateRope but differently if the function drawLine is inside the CreateRope function but outside its “if” branching.

Regards,
Andreu.

[import]uid: 152893 topic_id: 29372 reply_id: 118210[/import]

Hi Andreu,

Very good questions. I understand that the answer “it works” often isn’t enough; personally, I like to know why it works.

That being said, this issue could be caused by many things. Most likely it’s a minor scope/referencing issue.

Upon further inspection, it could be that you have created 2 variables names “platform”, but they reside in different scopes… one resides outside the function, the other is created as a new object within the function as the event.target. From a referencing standpoint, Lua might be confused by which one you’re trying to call (it should be calling the “most local” one, which would be the one created inside the function). Try making them distinct names (in fact, I would suggest you never repeat variable names unless you’re explicitly using one for a temporary sub-routine and then nil’ing it immediately afterward).

Remember that event.target also works with both phases, began and ended. A beginning touch on an object will return that object as the target, but if your touch moves outside that object and you release (‘ended’ phase), it won’t return an event target because your touch isn’t over that object anymore. I’m not sure if this is how your app is doing it, but keep that in mind. If you want to ensure that you are locking one object as the “active” one, it’s best once again to create some holding or reference variable above and assigning the object to that variable. That should prevent any confusion in the referencing of it.

Try these things out and see if it helps. I’m not sure these are the answers, but it might do the trick.

Best regards,
Brent
[import]uid: 9747 topic_id: 29372 reply_id: 118211[/import]

I was thinking it was a scope/referencing issue, though I didn’t know why and how to solve it.

I’ll try your solutions and I’ll let you know the results.

Thanks again, Brent. [import]uid: 152893 topic_id: 29372 reply_id: 118222[/import]