Touch and Drag to Move Question [ANSWERED]

A neophyte question… is there a simple way to code the ability to touch and move a graphic object (for example a game piece for a board game)?

I’ve looked through the examples and the shared code of others but can’t seem to find what I’m looking for…

As a start I’d love to have a rect() or ellipse() on the screen know when it is touched and dragged to another location (thus redrawn at the new co-ordinates).

Here’s a simple class that makes a rect you can drag around the screen.

-- DragMe
DragMe = class()

function DragMe:init()
    self.pos = vec2(0,0)
    self.size = 200
end

function DragMe:draw()
    pushStyle()
    
    fill(255,0,0)
    
    rectMode(CENTER)
    rect(self.pos.x, self.pos.y, self.size, self.size)
    
    popStyle()
end

function DragMe:hit(point)
    if point.x > (self.pos.x - self.size/2) and
       point.x < (self.pos.x + self.size/2) and
       point.y > (self.pos.y - self.size/2) and
       point.y < (self.pos.y + self.size/2) then
        return true
    end        
    return false
end

function DragMe:touched(touch)
    if self:hit( vec2(touch.x, touch.y) ) and
       touch.state == MOVING then
        self.pos = self.pos + vec2( touch.deltaX, touch.deltaY )
    end
end

And here’s the Main file:

-- Main
function setup()
    box = DragMe()
end

function draw()
    background(0)        
    box:draw()
end

function touched(touch)
    box:touched(touch)
end

Note that this won’t do touch tracking - that is, if you drag fast enough that your touch jumps out of the rect in one frame, the rect will lose tracking of the touch.

This can be fixed by checking if the touch hit on touch.state == BEGAN, and then tracking the position with the touch regardless until the touch state is ENDED.

Thanks a million Simeon! This is a great help!

I vote that something like this is included in the Codea examples.

Added to wiki https://bitbucket.org/TwoLivesLeft/codea/wiki/UserContrib

Hi,

I’ve found this dragging example and I was able to adapt it to my needs so far.

Now I’d like to “mimic” the behaviour of the iOS icon pages: if I drag an object a little bit and release it, the object comes smoothly back to its original position; if I drag it past a certain distance, then it goes away and another will replace it.

Is there an example of this somewhere?

Thanks,

Pedro

I would look up tween. Just save the x,y of the start position when the object is touched and tween it with the release of the object. You might want to tackle touch first

@pvchagas here is an example

-- DragMe
DragMe = class()
local list = {}
local rnd = function() return math.random(255) end
function DragMe:init(x,y)
    self.x = x or WIDTH/2
    self.y = y or HEIGHT/2
    self.size = 100
    self.c = color(rnd(),rnd(),rnd())
    table.insert(list,self)
end

function DragMe:draw()
    pushStyle()

    fill(self.c)

    rectMode(CENTER)
    rect(self.x, self.y, self.size, self.size)

    popStyle()
end

function DragMe:hit(point)
    if point.x > (self.x - self.size/2) and
       point.x < (self.x + self.size/2) and
       point.y > (self.y - self.size/2) and
       point.y < (self.y + self.size/2) then
        return true
    end        
    return false
end
local d0 = 150
function DragMe:touched(touch)
    if self:hit( touch ) then
        if touch.state == BEGAN then
            self.x0 = self.x
            self.y0 = self.y
            self.go = true
        elseif touch.state == MOVING then
            self.x = self.x+touch.deltaX
            self.y = self.y+touch.deltaY
            local d = vec2(self.x-self.x0,self.y-self.y0):len()
            if  d >= d0 and self.go then
                new = DragMe(self.x0,self.y0)
                self.go = false
                new.size = 0
               tween(0.5,new,{size=100},tween.easing.elasticOut)
            end
        elseif touch.state == ENDED or touch.state == CANCELLED then
            local d = vec2(self.x-self.x0,self.y-self.y0):len()
            if  d < d0 then
                tween(0.5,self,{x=self.x0,y=self.y0},
                tween.easing.elasticOut)
            end
        end
        
    end
end

-- Main
function setup()
    DragMe()
end

function draw()
    background(0)        
    for i,box in pairs(list) do box:draw() end
end

function touched(touch)
    for i,box in pairs(list) do box:touched(touch) end
end

http://www.youtube.com/watch?v=Um67wEzD9mg

@Simeon When I use this method and try to drag a rectangle, I get an output saying [string “DragMe = class()…”]:19: attempt to perform arithmetic on field ‘size’ (a nil value). Any advice?

you pbly wrote a . instead of a :

@Jmv38 I didn’t do that, but I found that I accidentally put “self.pos.size” instead of “self.size” . Thanks anyway!