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