Problem when dragging an object

I have a player and I want to drag it with “touch moved”:

function movePlayer( event ) &nbsp; &nbsp; local currentX&nbsp; &nbsp; &nbsp; local currentY&nbsp; &nbsp; &nbsp; if (event.phase == "began") then &nbsp; &nbsp; display.getCurrentStage( ):setFocus( event.target ) &nbsp; &nbsp; currentX = event.target.x &nbsp; &nbsp; currentY = event.target.y &nbsp; &nbsp; --print("CurrentX: "..currentX) \<-- prints the right value &nbsp; &nbsp; elseif (event.phase == "moved") then &nbsp; &nbsp; player.x = (event.x - event.xStart) + currentX \<-- ERROR &nbsp; &nbsp; player.y = (event.y - event.yStart) + currentY &nbsp; &nbsp; elseif (event.phase == "ended") then &nbsp; &nbsp; end &nbsp; &nbsp; return true &nbsp; &nbsp; end

But i get this error:

Attempt to perform arithmetic on local 'currentX' (a nil value)

The problem is scope.  By the time that second bit of code has executed, the original currentX doesn’t exist.

Let me explain if I can, then provide a better way.

  1. You touch the object and ‘movePlayer’ is called.

  2. The function creates a local called currentX

  3. Because the phase is “began”, you enter the first part of your if-statement and assign a value to currentX

  4. The function exits, currentX falls out of scope and is automatically destroyed.

Your touch continues… with moved, moved, moved, … and eventually an ended phase.

  1. On each new event, the function is called again and another NEW instance of currentX is created.  So, the value you thought you were storing is GONE.

The better way to do this is:

function movePlayer( event ) local target = event.target local phase = event.phase if ( phase == "began" ) then display.getCurrentStage( ):setFocus( target ) target.currentX = target.x target.currentY = target.y elseif ( phase == "moved" ) then player.x = (event.x - event.xStart) + target.currentX player.y = (event.y - event.yStart) + target.currentY elseif ( phase == "ended" ) then end return true end

Right, which means that there must always be a reference to the “player” before the checking of the “phase” in order to get it’s x and y values inside it.

Thanks.

  1. No.  I’m not sure what you’re saying.   This isn’t about the order of execution, but scoping rules in Lua and how listeners are called.

  2. No need to quote my entire post, just reply back and if you need to reference a specific line of code, simply paste it to a code block.  Quoting response makes the post hard to read later when others have the same question.

To be more clear (perhaps), in my answer I stored the data you wanted to keep in as fields on the target.  I created new variables attached to the target and stored information in them.

That way the data wouldn’t be lost from call to call.

The way I understand it is as follows:

In the first method :

1- I defined a variable “currentX”

2- In the “began” phase I gave “currentX” a value which  only gets executed once.

3- In the “moved” phase I tried to call “currentX”, but it didn’t work because the function was called a second time in order to execute the “moved” phase, and in this time the code inside “began” never happened, therefore, “currentX” doesn’t have a value.

So in order to overcome this problem (as I understand it):

1- We need to have a reference to the object itself  “target” before we start to check  which phase it is.

2- So when we are inside the “moved” phase we can access “target”'s properties(x,y) and they will have a value to return.

Pretty close.  What I’m saying is in “began” I stored the ‘starting <x,y>’ values in fields on the target so later I can access them.  

The target is the player right?  If, “Yes”, then I stored x and y starting in two named fields ‘currentX’ and ‘currentY’.  These fields are attached to the player.  A reference to player is passed in the event because the player is the target you touched.

The entire ‘event’ is a table and transient in nature.  On each ‘touch event’ Corona creates a table and stuffs it with values related to that touch, then passes that table to the listener.  So each phase of the touch gets a new table with values like these in it:

  • time
  • target - Same as player I think (based on what I’ve seen of your code).
  • phase
  • startX
  • … etc.

Thanks, I appreciate that you spare the  time & effort to help others.

The problem is scope.  By the time that second bit of code has executed, the original currentX doesn’t exist.

Let me explain if I can, then provide a better way.

  1. You touch the object and ‘movePlayer’ is called.

  2. The function creates a local called currentX

  3. Because the phase is “began”, you enter the first part of your if-statement and assign a value to currentX

  4. The function exits, currentX falls out of scope and is automatically destroyed.

Your touch continues… with moved, moved, moved, … and eventually an ended phase.

  1. On each new event, the function is called again and another NEW instance of currentX is created.  So, the value you thought you were storing is GONE.

The better way to do this is:

function movePlayer( event ) local target = event.target local phase = event.phase if ( phase == "began" ) then display.getCurrentStage( ):setFocus( target ) target.currentX = target.x target.currentY = target.y elseif ( phase == "moved" ) then player.x = (event.x - event.xStart) + target.currentX player.y = (event.y - event.yStart) + target.currentY elseif ( phase == "ended" ) then end return true end

Right, which means that there must always be a reference to the “player” before the checking of the “phase” in order to get it’s x and y values inside it.

Thanks.

  1. No.  I’m not sure what you’re saying.   This isn’t about the order of execution, but scoping rules in Lua and how listeners are called.

  2. No need to quote my entire post, just reply back and if you need to reference a specific line of code, simply paste it to a code block.  Quoting response makes the post hard to read later when others have the same question.

To be more clear (perhaps), in my answer I stored the data you wanted to keep in as fields on the target.  I created new variables attached to the target and stored information in them.

That way the data wouldn’t be lost from call to call.

The way I understand it is as follows:

In the first method :

1- I defined a variable “currentX”

2- In the “began” phase I gave “currentX” a value which  only gets executed once.

3- In the “moved” phase I tried to call “currentX”, but it didn’t work because the function was called a second time in order to execute the “moved” phase, and in this time the code inside “began” never happened, therefore, “currentX” doesn’t have a value.

So in order to overcome this problem (as I understand it):

1- We need to have a reference to the object itself  “target” before we start to check  which phase it is.

2- So when we are inside the “moved” phase we can access “target”'s properties(x,y) and they will have a value to return.

Pretty close.  What I’m saying is in “began” I stored the ‘starting <x,y>’ values in fields on the target so later I can access them.  

The target is the player right?  If, “Yes”, then I stored x and y starting in two named fields ‘currentX’ and ‘currentY’.  These fields are attached to the player.  A reference to player is passed in the event because the player is the target you touched.

The entire ‘event’ is a table and transient in nature.  On each ‘touch event’ Corona creates a table and stuffs it with values related to that touch, then passes that table to the listener.  So each phase of the touch gets a new table with values like these in it:

  • time
  • target - Same as player I think (based on what I’ve seen of your code).
  • phase
  • startX
  • … etc.

Thanks, I appreciate that you spare the  time & effort to help others.