Touch and drag

I am brand new to Codea and halfway through my tutorials and they are enlightening and I can’t wait to get stuck in, but just wanted to enquire whether it is possible to touch and drag objects from one point to another and if so, is there existing code or tutorials based on this specifically?

thanks

You could make the X and Y of a sprite touch.x and touch.y
Example:

function draw()
sprite("SpaceCute:Background",touch.x,touch.y)

Quick example using a class (so you can make multiple instances)

--# Main
function setup()
    exobj = Object(WIDTH/2, HEIGHT/2)
end

function draw()
    background(40, 40, 50)
    
    exobj:draw()
end

function touched(touch)
    exobj:touched(touch)
end


--# Object
Object = class()

function Object:init(x,y)
    self.pos = vec2(x, y)
    self.selected = false
    
    self.size = 100
end

function Object:draw()
    rectMode(CENTER)
    fill(255, 141, 0, 255)
    
    rect(self.pos.x, self.pos.y, self.size, self.size)
end

function Object:touched(touch)
    if touch.state == BEGAN then
        -- If you touch the object, select it
        if touch.x > self.pos.x - self.size/2 and touch.x < self.pos.x + self.size/2 and
        touch.y > self.pos.y - self.size/2 and touch.y < self.pos.y + self.size/2 then
            self.selected = true
        end
        
        -- Center on touch
        if self.selected then
            self.pos = vec2(touch.x, touch.y)
        end
    elseif touch.state == MOVING then
        -- If the object is selected, follow the touch
        if self.selected then
            self.pos = vec2(touch.x, touch.y)
        end
    elseif touch.state == ENDED then
        -- When you let go, deselect the object
        self.selected = false
    end
            
end

@jamesfootlight Here’s another example. Just select a character and drag it around.


displayMode(FULLSCREEN)

function setup()
    selected=0
    ex=390    -- ellipse x
    ey=410    -- ellipse y
    ea=200    -- ellipse a radius
    eb=100    -- ellipse y radius
    rx=70
    ry=120
    rw=630
    rh=580
    tab={}
    for z=1,5 do    -- create 5 objects
        table.insert(tab,vec2(math.random(70,700),math.random(120,700)))
    end
    tab1={}    -- table of sprites
    table.insert(tab1,readImage("Planet Cute:Character Boy"))
    table.insert(tab1,readImage("Planet Cute:Character Horn Girl"))
    table.insert(tab1,readImage("Planet Cute:Character Cat Girl"))
    table.insert(tab1,readImage("Planet Cute:Character Pink Girl"))
    table.insert(tab1,readImage("Planet Cute:Character Princess Girl"))
end

function draw()
    background(40, 40, 50)
    noFill()
    stroke(255)
    strokeWidth(2)
    rect(rx,ry,rw,rh)
    ellipse(ex,ey,ea*2,eb*2)    -- draw ellipse
    for a,b in pairs(tab) do    -- draw each objects   
        if checkEllipse(b.x,b.y) then
            sprite("Planet Cute:Heart",b.x,b.y)
        else
            sprite(tab1[a],b.x,b.y)
        end
   end
end

function checkRect(x,y)
    if x>rx and x<rx+rw and y>ry and y<ry+rh then
        return true
    end
    return false    
end

function checkEllipse(x,y)
    -- determine if touched value is inside ellipse
    if (x-ex)^2/ea^2+(y-ey)^2/eb^2 <= 1 then 
        return true       
    end  
    return false
end

function touched(t)
    if t.state==BEGAN then    -- check which object is selected
        v1=vec2(t.x,t.y)
        for a,b in pairs(tab) do
            if v1:dist(vec2(b.x,b.y))<50 then
                selected=a
                break
            end
        end
    end
    if t.state==MOVING and selected>0 then    -- move selected object
        if checkRect(t.x,t.y) then
            tab[selected].x=t.x
            tab[selected].y=t.y
        end
    end
    if t.state==ENDED then    -- done moving
        selected=0
    end
end

You guys are amazing, it works like a dream. Following this up, does anyone know if it’s possible for an image to react at different points on the screen? Eg if there were 4 quadrants on a page and if u moved an object into this quadrant or area could a command come up on the screen or the movable object change opacity ?

@jamesfootlight Yes. You would just have to compare the x,y value of what you’re moving. If it’s in a special area, then you do something special.

@jamesfootlight I changed my above code. See if that’s what you’re thinking of. Move the character into the rectangle.

@jamesfootlight - this formula will tell you which quadrant you are in, numbered 1 to 4 ( I’ll leave it to you to work out which is which)

q = math.floor(x*2/WIDTH)*2+math.floor(y*2/HEIGHT) +1

Excellent, thanks. If I wanted 5 different objects that all had seperate images, would i reference them in the function draw() section? ie sprite1 etc?

yes, but if you don’t know this, then I suggest you may be getting a bit ahead of yourself.

I suggest you stick with the tutorials until you have the basics of putting stuff on the screen, so you don’t ask unnecessarily basic questions. It’s not that we mind helping, but we prefer to fix problems than provide personal tuition :wink:

Of course, thanks, I completely appreciatte that. I will keep on working on my code and learn some more! thanks

So, i’m almost there with my objects on my new background, however, i need them to react within an ellipse area in the centre of my screen, i have adapted the code below to try to get them to react to an ellipse area but to no avail, i keep getting an error message ‘then’ expected near’,', can anyone help?

displayMode(FULLSCREEN)

function setup()
    tab={}
    for z=1,5 do    -- create 5 objects
        table.insert(tab,vec2(math.random(WIDTH),math.random(HEIGHT)))
    end
end

function draw()
    background(40, 40, 50)
    ellipse(390,410,0,0)
    for a,b in pairs(tab) do    -- draw each objects
        if b.x<390,410 and b.y<390,410 then
            sprite("Planet Cute:Character Princess Girl",b.x,b.y)
        else
            sprite("Planet Cute:Character Boy",b.x,b.y)
        end
    end
end

function touched(t)
    if t.state==BEGAN then    -- check which object is selected
        v1=vec2(t.x,t.y)
        for a,b in pairs(tab) do
            if v1:dist(vec2(b.x,b.y))<50 then
                selected=a
                break
            end
        end
    end
    if t.state==MOVING and selected>0 then    -- move selected object
        tab[selected].x=t.x
        tab[selected].y=t.y
    end
    if t.state==ENDED then    -- done moving
        selected=0
    end
end

@jamesfootlight - first, put three ~ at the top and bottom of your code to format it nicely. (I fixed it for you).

The problem is probably with

If b.x<390,410

What is the comma and the 410 doing there? They will cause an error (and so will the y value later on that line).

Other than that, your code looks pretty good.

Thanks, the problem i have is I need the sprites to change when they enter/leave the ellipse and they are currently only changing in the bottom left of the screen.
and the 390,410 (I originally had if b.x<ellipse and b.y<ellipse then

but this caused an error

@jamesfootlight I changed my code above to handle an ellipse.

ignatz thanks again,and dave1707 I’m sending you digital hugs!

my interactive risk map is now really taking shape thanks to all your help, I now need to ensure my objects cannot be moved out of a rectangle (70,120,630,580) that sits just outside the ellipse, would I first of all code the rectangle in function set up():
rx=70
ry=120
rw=630
rh=580

then in function draw():

rect(rx,ry,rw,rh)
fill (0,0,0,0)

then do function checkSprite ()
if b.x,b.y-sprite<rw or b.x,b.y+sprite >rw then stop
if b.x,b.y-sprite<rh or b.x,b.y+sprite >rh then stop

My ipad just ran out of juice so unable to check till later, but is this the right direction?

thanks guys!

@jamesfootlight Here’s a routine you could use. Just call checkRect with the x,y values of the sprites. If you get stuck, see my code above. I added it there.


function checkRect(x,y)
    if x>rx and x<rx+rw and y>ry and y<ry+rh then
        return true
    end
    return false    
end

@jamesfootlight. you are in the community. (CC)??

in the community there are many examples that you can download and you can provide enough support.

Also u can see the Wikis created by @ignatz

Thanks Luismi, in the below code, how would i attribute each image in the table to change into an individual image, rather than each one changing into the heart?

ie each image changes into a different image when entering the ellipse?

function setup()
    selected=0
    ex=390    -- ellipse x
    ey=410    -- ellipse y
    ea=200    -- ellipse a radius
    eb=100    -- ellipse y radius
    rx=70
    ry=120
    rw=630
    rh=580
    tab={}
    for z=1,5 do    -- create 5 objects
        table.insert(tab,vec2(math.random(70,700),math.random(120,700)))
    end
    tab1={}    -- table of sprites
    table.insert(tab1,readImage("Planet Cute:Character Boy"))
    table.insert(tab1,readImage("Planet Cute:Character Horn Girl"))
    table.insert(tab1,readImage("Planet Cute:Character Cat Girl"))
    table.insert(tab1,readImage("Planet Cute:Character Pink Girl"))
    table.insert(tab1,readImage("Planet Cute:Character Princess Girl"))
end

function draw()
    background(40, 40, 50)
    noFill()
    stroke(255)
    strokeWidth(2)
    rect(rx,ry,rw,rh)
    ellipse(ex,ey,ea*2,eb*2)    -- draw ellipse
    for a,b in pairs(tab) do    -- draw each objects   
        if checkEllipse(b.x,b.y) then
            sprite("Planet Cute:Heart",b.x,b.y)
        else
            sprite(tab1[a],b.x,b.y)
        end
   end
end

function checkRect(x,y)
    if x>rx and x<rx+rw and y>ry and y<ry+rh then
        return true
    end
    return false    
end

function checkEllipse(x,y)
    -- determine if touched value is inside ellipse
    if (x-ex)^2/ea^2+(y-ey)^2/eb^2 <= 1 then 
        return true       
    end  
    return false
end

function touched(t)
    if t.state==BEGAN then    -- check which object is selected
        v1=vec2(t.x,t.y)
        for a,b in pairs(tab) do
            if v1:dist(vec2(b.x,b.y))<50 then
                selected=a
                break
            end
        end
    end
    if t.state==MOVING and selected>0 then    -- move selected object
        if checkRect(t.x,t.y) then
            tab[selected].x=t.x
            tab[selected].y=t.y
        end
    end
    if t.state==ENDED then    -- done moving
        selected=0
    end
end