Tutorial: How to Drag Objects

Share on Facebook0Share on Google+0Tweet about this on TwitterShare on LinkedIn0

Dragging Objects in CoronaDragging objects is something that’s common across many games and apps, but unfortunately, how to do it isn’t readily apparent. Today, I’m going to show you exactly how basic dragging is accomplished—and it’s easier than you think.

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.

Share on Facebook0Share on Google+0Tweet about this on TwitterShare on LinkedIn0

This entry has 46 replies

  1. Mo says:

    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.



  2. great!

  3. Abstract Edge says:

    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"
    self.x = event.x
    self.y = event.y

    return true


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

  4. PiotrT says:

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

  5. dm says:

    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

    — event handled
    return true

    • Visualomics says:

      Thanks! That fixed the issue !

  6. Jonathan Beebe says:

    @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!

  7. Jonathan Beebe says:

    @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.

  8. Sven.Lua says:

    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.

  9. David says:

    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?


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

    return true

    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!) .


  11. Jonathan Beebe says:

    @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.

  12. 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.


  13. Jonathan Thomas says:

    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.

  14. Jonathan Thomas says:

    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.

  15. Jonathan Beebe says:

    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 🙂

  16. Dan Ringrose says:

    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!

    • Jim says:

      I asked a similar question today. Were you able to resolve the array issue yet?

  17. Guh Clemente says:

    very good. Thanks!

  18. Chris Williams says:

    I am trying to follow this tutorial. I keep getting error messages saying, ” attempt to index global ‘self’ .

    Any ideas?

    • Joe says:

      To fix this, you must add in right next to ‘event’, add ‘self, ‘ then when you call it, before it put myObject.touch = myObject:touch(or what ever you named your function) Then, when you call it, instead of calling the function, replace it with myObject

  19. Jim says:

    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] )

    — 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

    return true

  20. Malik Gray says:

    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?

  21. Anton says:

    When When I drag an object and it passes through the wall.

  22. jakobdt says:

    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.

  23. Waseem says:

    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
    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
    display.getCurrentStage():setFocus(nil )
    self.isFocus = false
    elseif event.phase == “cancelled” then
    display.getCurrentStage():setFocus(nil )
    self.isFocus = false
    –event handled
    return true

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

  24. kumar ks says:

    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 .

  25. kumar ks says:

    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.

    • bava says:

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

  26. bava says:

    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)

    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

  27. Steven says:

    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?)

  28. Asad Sheikh says:

    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 🙂

  29. Seers says:

    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
    return true

  30. Alan says:

    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

  31. Amir says:

    IS there an actual “Drag” event listener. Something when you move contacts on the phone that moves objects up and down depending how fast you drag them.

  32. Amir says:

    Is there an actual “drag” event. So you can create something like moving the contacts list on the phone with variable speed.

  33. Mads says:

    hi, im new to programing. is there anyway to disable the Y-axis so that the object only moves in one direction?

    • Rob Miracle says:

      Yes, in the drag code, simply don’t set the .y value.

  34. Lam says:

    Hi guys, I learned about Corona in a 5-day class, so I don’t know about a lot of stuff. How can you drag a character, but have it stay on the bottom of the screen (like the Atari Breakout platform used to bounce the ball)? Please help. Thx!

    • Rob Miracle says:

      In the drag code, simply don’t change the .y value.

  35. rob says:

    Hello, i am using the following code to drag my object. But when i release the object after dragging and then click on it again it jumps away from the cursor!

    Hope someone can help! Thankyou

    function welcome:touch(event)
    if event.phase == “began” then

    — began focus

    display.getCurrentStage():setFocus (self, event.id)


    elseif self.isFocus then
    if event.phase ==”moved” then


    — drag object

    self.x = event.x – event.xStart + self.markX
    self.y = event.y – event.xStart + self.markY

    elseif event.phase == “ended” or event.phase == “cancelled” then
    — end focus

    display.getCurrentStage():setFocus( self, nil)
    self.isFocus = false


    return true

    welcome:addEventListener (“touch”, welcome)

    • Rob Miracle says:

      Can you please ask this in the forums?


Leave a reply

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">