Posted on by

Here’s the logic behind it:

At the start of a user’s touch (also known as the “began” phase of a touch event), you must store the current location of the object. Then, during the “move” phase of the event, you subtract the start location of the event (event.xStart, event.yStart) from the event’s current location (event.x, event.y) and also add the stored location of the object. Finally, you change the object’s location to the newly calculated one and that’s what moves the object with the user’s finger.

Sounds like a mouthful right? Here’s the code:

And that’s it! That’s all there is to dragging objects in Corona. And although this tutorial was a little on the short side, its usefulness is infinite—I find myself using the same code I shared here across many different projects.

Feel free to ask any questions you have in the comments section, or start a new thread in the forums and post a link to it.


Posted by . Thanks for reading...

37 Responses to “Tutorial: How to Drag Objects”

  1. Mo

    Another “killer” tutorial!

    Thanks a lot Jon. I put in on memory bank for time when I will need to use it…which maybe pretty soon.

    Thanks.

    Mo

    Reply
  2. Abstract Edge

    I have seen this method lot of times, but if I really just want to drag an object then why do I need to store the x and y position in the variables in the began phase and then again in the moved phase substract do all this things?

    Why cant I do directly like the following code? Is there anything wrong with the following code? Plz. advice.

    -- create object
    local myObject = display.newRect( 0, 0, 100, 100 )
    myObject:setFillColor( 255 )

    -- touch listener function
    function myObject:touch( event )

    if event.phase == "moved"
    then
    self.x = event.x
    self.y = event.y
    end

    return true

    end

    -- make 'myObject' listen for touch events
    myObject:addEventListener( "touch", myObject )

    Reply
  3. PiotrT

    Jonathan what about dragging and physics. How to drag an object and keep His physics properties , for example in labyrinth of walls. gameUI ?

    Reply
  4. dm

    Better capture the focus during the “began” phase. Otherwise you lose the object during fast dragging.

    function myObject:touch( event )
    if event.phase == “began” then
    — begin focus
    display.getCurrentStage():setFocus( self, event.id )
    self.isFocus = true

    self.markX = self.x
    self.markY = self.y

    elseif self.isFocus then
    if event.phase == “moved” then
    — drag touch object
    self.x = event.x – event.xStart + self.markX
    self.y = event.y – event.yStart + self.markY

    elseif event.phase == “ended” or event.phase == “cancelled” then
    — end focus
    display.getCurrentStage():setFocus( self, nil )
    self.isFocus = false
    end
    end

    — event handled
    return true
    end

    Reply
  5. Jonathan Beebe

    @PiotrT: Here’s a previous tutorial about dragging physics, exactly what you’re looking for: http://blog.anscamobile.com/2010/11/tutorial-dragging-physics/

    @dm: I agree, you should definitely set focus on objects in their touch listeners, so great point! However, I just wanted to explain and show the basic logic related to dragging specifically in this tutorial—to prevent any confusion or misunderstanding as to what’s relevant to dragging, and what’s not.

    Thanks for the comments thus far guys—keep them coming!

    Reply
  6. Jonathan Beebe

    @Abstract Edge: The reason I stored the object’s x/y coordinates at the start of the touch, and then add them on every move phase, is because where the user touched the object may not be where the it’s reference point is, causing the image to jump into place as soon as you move it.

    When you modify an object’s x/y coordinates, it positions the reference point of the object to those coordinates. By adding it’s stored location, you’re really just adding an offset so that the object will appear to move from where it was at, to where you dragged it.

    I encourage you to try omitting the storing of the object’s coordinates (and adding during the move event) and see what happens. Sometimes that’s the best way to learn and understand new things.

    Reply
  7. Sven.Lua

    Keep up the good work Jon,
    but I think in your writing are 2 mistakes:
    – “That’s all there is to dragging objects in Corona” – I think there’s a lot more needed
    – “its usefulness is infinite” – I think it’s limited to special cases, for non physics maybe it’s perfect

    In a physics controlled bodies this kind of dragging will not work as one would await. I think you will create strange unwanted forces.

    I think your later comment “I just wanted to explain and show the basic logic” is missed in the article.

    Reply
  8. David

    How is this different than the gameUI.dragBody (event, prop)? I’m guessing this technique above would not require the gameUI module and same memory space?

    -David

    Reply
  9. Nicholas Golden

    I have a question, and it’s more of a basic lua/corona question.

    return true
    end

    What does return true do? The problem I have is I find a lot of tutorials, and they all assume that I’ve done some programming but doesn’t explain these little things.

    What are the advantages to return true, vs not using it at all (i’m not that great at programming yet, go easy on me!) .

    ng

    Reply
  10. Jonathan Beebe

    @ng: When it comes to touch events, return true let’s the event know that a touch was “intended” and prevents touches from going THROUGH that object, potentially to another object behind it with a touch listener. If you don’t return anything, it’ll return nil by default, and with touch listeners, that means the touch will go through.

    With other functions, return true does whatever you programmed it to do. You can make a function return any variable (to include functions and tables). Since the concept of a touch listener function is built into the Corona core, returning true to specify whether a touch was successful/intended is how they were programmed.

    Reply
  11. Ed Wainwright

    Thank You John.

    Your tutorial was concise and to the point.

    I am looking to add some pop with a flick added to the move, however, I think that might be something for a future tutorial.

    Ed

    Reply
  12. Jonathan Thomas

    This tutorial is so close! I am trying to figure out how to create an event where this draggable object has a final destination where I want it to stop once I drag it within a certain proximity of the final spot. Like for puzzle pieces???? Please help. I hope it’s not too difficult for a newbie coder like myself.

    Reply
  13. Jonathan Thomas

    Thank you so much! I’ve only been coding for a month now! You seem to have done it all man! WHERE DID YOU START? Any specific Lua programming book? Just dissecting sample code (like I’m doing)? I want to fasttrack my learning, but not miss any fundamental basics. Too much of this is still jargon to me, but I’m very technical minded so I’m determined to stick it out.

    I will develop a puzzle app (as my 1st app) yet this year.

    Reply
  14. Jonathan Beebe

    I started by looking at the beginner docs, then studied the SampleCode (especially Samurai Kitchen!), built my first app, and then built more apps and kept improving as I went. In between, I learned more about Lua and continued to gain more experience by putting what I learned into practice … all that in just a few months time, and I’m no genius. With Corona, that’s all it takes.

    You’ll have it all down in no time flat :-)

    Reply
  15. Dan Ringrose

    This is awesome – Thank you Jonathan. I have two things I’m struggling with:
    a) how to extend listening for a touch on a single object (this example) to listening for touches to an array of objects on the screen. For now I’m not concerned with physics for the objects, just allowing the user to drag any of them to a desired position. Do I need write a loop that creates an event listener for each object in the array? Naive question, I know.

    b) how to incorporate additional function into the listener, so that when an object is touched (tapped) a counter gets incremented for that object, rather than dragging the object around. Do I just put this in the “began” phase of the touch event?

    I’m new at all this, but slowly getting up to speed. Once I figure out the essential mechanics I can then move on to building an app around them! Thanks!

    Reply
  16. Jim

    Two questions:
    First, I am looping through an array img[i] to load eight PNG images that I want to be able to move around the screen. How would I code the event listener when there are indices for each image, and would I do it inside of the loop or outside of the loop.

    Next, how would I write the function(s) to move the images? Would I write one function overall, or eight individual functions, one for each image?

    Here is where I finally got stuck:

    for y = 0, 2 do
    for x = 0, 2 do
    z = z + 1
    if z == 9 then break end
    img[z] = display.newImage(0 .. z .. “.PNG”,0,0,true)
    img[z].x = x * 100 + 65
    img[z].y = y * 100 + 105
    img[z]:addEventListener( “touch”, img[z] )
    end
    end

    — touch listener function
    function img:touch( event )
    if event.phase == “began” then

    self.markX = self.x — store x location of object
    self.markY = self.y — store y location of object

    elseif event.phase == “moved” then

    local x = (event.x – event.xStart) + self.markX
    local y = (event.y – event.yStart) + self.markY

    self.x, self.y = x, y — move object based on calculations above
    end

    return true
    end

    Reply
  17. Malik Gray

    I actually tried to use this code in a brand new blank main.lua file and it wouldn’t work at all. I could see the white rectangle but clicking on it and dragging it didn’t do anything. Any ideas why?

    Reply
  18. jakobdt

    I want to be able to drag an object in the y-axis direction only or the x-axis direction only depending on which way I move my finger on the screen. I have come so far that I can see that the code should just change the y-coordinate or the x-coordinate depending on which situation it is. However, I need to somehow detect whether the user is dragging alongside the y-axis or the x-axis to determine whether to use the code that changes the y-coordinate or the code that changes the x-coordinate.

    Reply
  19. Waseem

    I am trying to use the same code to swap two objects but getting an error that self.x is a nil value. Help please !

    local jewel_id={}

    function jewel_id: touch( event )
    print(“EVENT CALLED”)
    if event.phase == “began” then
    –begin focus
    display.getCurrentStage():setFocus( event.target )
    self.isFocus = true
    print(“SELF.X::”,self.x)
    print(“SELF.Y::”,self.y)
    self.markX = self.x
    self.markY = self.y

    elseif self.isFocus then
    if event.phase == “moved” then
    self.x = event.x – event.xStart + self.markX
    self.y = event.y – event.yStart + self.markY

    elseif event.phase == “ended” then
    self.x=self.markX
    self.y=self.markY
    display.getCurrentStage():setFocus(nil )
    self.isFocus = false
    elseif event.phase == “cancelled” then
    display.getCurrentStage():setFocus(nil )
    self.isFocus = false
    end
    end
    –event handled
    return true
    end

    jewel_id[(x1*y1)+(y1-1)]:addEventListener( “touch”, jewel_id)

    Reply
  20. kumar ks

    hi ,

    The code is working and tutorial is awesome, but when i place the object some where else other than the target position , the object moves to the original position in a flash , but i need to have smooth movement to its original position , is there any way . Pls tell me soon .

    Reply
  21. kumar ks

    I am dragging the object , but when i leave the object other than the specified target , its just disappearing . But what i need is , it should smoothly go back to its original position . How to do this , give me some examples.

    Reply
    • bava

      use this line of code in your event.ended phase :
      transition.to( myObject, { time=500, alpha=1, x=(180), y=(272) } )

      Reply
  22. bava

    Hai All.,
    I am really very new to corona(lua)
    please any one help!

    The question is :

    First I stored 10 images in array(i.e., table) from 1-10 as key values and I create a random number using math.random function between 0-9.,
    and i need to access the image that is stored in array by the value created by random function, and need to assign the touch and move(drag and drop) function for the particular image file alone., other images also needs touch(i.e, drag alone)

    Ex:
    if the random fn creates no as “5” i need to drag and drop the image 5.png that is stored in array index as 5 .,other images except 5.png should not able to drop., (i.e., they are allowed to move in screen but not to drop able in screen)

    Thanks a lot

    Reply
  23. Steven

    Hey would it be possible to explain with a diagram (or similar visual aid) what exactly each of those variables is storing? for example what exactly is markX (I know that it is the stored points of the original, or something similar, but in relation to the data of the other variables where is it?)

    Reply
  24. Asad Sheikh

    I want to restrict my Draggable display object to be dragged only on x -axis ? How can i restict it from moving on y-axis ??? can u please help :)

    Reply
  25. Seers

    In my opinion, just use a simple code below to accomplish the same result without going through overhead calculations.
    I use this code in my games to drag the objects.

    function player:touch( event )
    if (event.phase==”moved”) then
    self.x = event.x
    end
    return true
    end

    Reply
  26. Alan

    For those of you who need to drag an object that is within a display group that has been scaled, here is the code that will correctly move the dragable object inside that display group (only difference is in the “moved” phase so that is what I’m posting):

    if event.phase == “moved” then
    — drag touch object
    local reverseScaleFactorX = myDisplayGroup.width / myDisplayGroup..contentWidth
    local reverseScaleFactorY = myDisplayGroup.height / myDisplayGroup.contentHeight

    local distanceMovedScaledX = (event.x – event.xStart) * reverseScaleFactorX
    local distanceMovedScaledY = (event.y – event.yStart) * reverseScaleFactorY

    self.x = distanceMovedScaledX + self.markX
    self.y = distanceMovedScaledY + self.markY

    Reply

Leave a Reply

  • (Will Not Be Published)