Codea waiting for touch event

Hello Folks,

So, basically I’m trying to get my program to wait for a user interaction OUTSIDE THE DRAW() FUNCTION.
So far I’ve tried repeat loops, while loops, the CurrentTouch var, the function touched(t), I’ve even tried using coroutines in order to set a specific position upon the next user interaction.

What should explain my case best is:

while not touched do
    if not (CurrentTouch.state == ENDED) then
        touched = true
        pos = vec2(CurrentTouch.x, CurrentTouch.y)
    end
end

This was also one if my (unsuccessful) tries.
Can anyone help me with that?

Thanks,
McSebi

@TheMcSebi If you want to wait for user interaction, the touched() function is the best. But I don’t understand what you’re trying to accomplish. You’re question and example don’t help me very much.

@TheMcSebi How close is this to what you want. When you touch the screen the code will execute. When you lift your finger, some of the code won’t execute. If this isn’t what you’re after, can you explain more.

displayMode(FULLSCREEN)

function setup()
    x,y=WIDTH/2,200   
    counter=0
    fontSize(30)
end

function draw()   
    background(0)
    if not touch then
        fill(255)
        text("waiting for someone to touch the screen",WIDTH/2,HEIGHT/2)
        text(counter,WIDTH/2,HEIGHT/2-100)
        sprite("Planet Cute:Character Horn Girl",x,y)
        sprite("Planet Cute:Character Boy",WIDTH-x,HEIGHT-y)
        return
    end
    text("someone touched the screen",WIDTH/2,HEIGHT/2)
    text("so the rest of function draw will run",WIDTH/2,HEIGHT/2-50)
    x=(x+5)%WIDTH
    y=(y+5)%HEIGHT
    sprite("Planet Cute:Character Horn Girl",x,y)
    sprite("Planet Cute:Character Boy",WIDTH-x,HEIGHT-y)
    counter=counter+1
    text(counter,WIDTH/2,HEIGHT/2-100)
end

function touched(t)
    if t.state==BEGAN then
        touch=true
    end
    if t.state==ENDED then
        touch=false
    end
end

@dave1707
I’ve tried to accomplish this without using the draw function in any way.
For example if I press a button which executes a function (let’s say setPosition()) This function then requires a screen touch to continue.

function setup()
    somePositionThing = vec2(0, 0)
    parameter.action("set some position stuff", "setPosition")
end

function setPosition()
    local pos = "the next touch on screen, but idle as long as the screen hasn't been touched"
    somePositionThing = pos
end

Maybe this example makes it more clear, thanks for your help :slight_smile:
It’s not a huge problem if this isn’t possible, I’m just trying to keep my code as clean as possible. If there is no way to achieve this in LUA, I’m simply gonna use the draw loop with a little helper function.

that is what the touched function is for. Why not use that?

This didn’t work because i guess the touched function only gets refreshed after the draw function has successfully ended. Or something like that. The viewer freezes every time this function gets called because apparently it never reaches the position where it sets ‘touched’ to true.

function theButton()
    while not touched do
        for k,touch in pairs(touches) do
            while not (touch.state == ENDED) do
                myPos = vec2(touch.x, touch.y)
                touched = true
            end
        end
    end
end

function touched(touch)
    if not touches then touches = {} end
    if touch.state == ENDED then
        touches[touch.id] = nil
    else
        touches[touch.id] = touch
    end
end

That I initialized the touches table within the first screen touch is NOT the problem, because until it reaches the ‘for in pairs’-loop there will always be at least a few screen touches.

all Lua code must finish before draw or touched will run.

  1. take out the while loop

  2. create a variable to tell you when a touch occurs, eg IsTouched

  3. in the touched function, set IsTouched=true

  4. in draw, call TheButton if IsTouched=true

simple as that

Well, I know it can be simple as that, but my intention was to achieve all that without writing anything inside the draw function. Since that doesn’t seem to be possible I guess I have to create a hook then… Thank you anyway :slight_smile:

If I find a fancy way using coroutines I’m going to post it here for educational purpose. :slight_smile:

@TheMcSebi - I really can’t see why you don’t want to put anything in draw. Although it’s called draw, it is really an “update everything” function, which suits your purpose. So you could write a very compact draw function

function draw()
    RunChecks() --do checks for touched, other housekeeping
    DrawScreen() --draw on screen, based on state of program
end

The fundamental difference in Codea is that it is a movie, ticking by at 60 frames a second. It’s not a normal program where you can pause execution while waiting for a touch. In Codea, you must keep the draw function ticking along, and do checks inside it if you want.

Using coroutines or hooks or other fancy techniques is a distortion of Codea’s design, and completely unnecessary. Codea users have written many hundreds of different and often complex programs without any need for this. If you want to do it for fun, so be it, but it’s likely to just create unnecessary complexity.

@TheMcSebi Here’s a program that doesn’t use draw() or anything else besides the touched() function. If you don’t use the draw() function, you can’t show anything on the screen. As you can see here, the only thing you can do is print something in the output window. If printing information is all you want to do based on where someone touches the screen, then this will work. In one of your posts above you say “If I press a button which executes a function”, guess what, you can’t display a button without using draw().

function touched(t)
    if t.state==BEGAN then
        output.clear()
        print("began")
        if t.y>HEIGHT/2 then
            print("you touched above the middle")
        else
            print("you touched below the middle")
        end
    end
    if t.state==MOVING then
        print("moving")
    end
    if t.state==ENDED then
        print("end")
    end
end

@Ignatz I have to disagree on one of your statements above ‘all Lua code must finish before draw or touched will run’. If you put a very large ‘for’ loop in draw that takes several seconds to complete, the touched function will still execute. For instance, if you put a counter in the touched function that increments every time the screen is touched, you can touch the screen and it will recognize how many times you touched the screen even though the ‘for’ loop is still running. Here’s an example. You can adjust the for loop size.

function setup()
    cnt=0
end

function draw()
    print("start")
    for z=1,50000000 do
        a=math.sqrt(z)
    end
    print("end")
end

function touched(t)
    if t.state==BEGAN then
        cnt=cnt+1
        print(cnt)
    end

end

well, well, I hadn’t tried that.

@dave1707 I’ve noticed it myself too, that Codea’s draw() and touched() loops seem to be asynchronous. Good catch!

@se24vad Even though the touched function knows about touches during a long loop, it still doesn’t allow you to do anything with the information until the loop is finished. That tells me that Codea isn’t the one seeing the touch. I think it’s the operating system that’s getting the touch information, then when Codea finishes the loop, the touched function executes and gets the information and processes it. So I don’t think there’s any asynchronous code. Everything just waits it’s turn.

@se24vad This verifies my thoughts above, about the operating system recognizing the touches and then when the for loop and draw is finished, the touched() function gets its turn and gets the information. I added a time when draw start and ends and when the touch gets processed. If you run this and tap the screen several times while the for loop is running, the time reported by the screen touches happens after the draw end time, even though the touches actually happened before draw ended.

function setup()
    cnt=0
end

function draw()
    print("start",os.clock())
    for z=1,50000000 do
        a=math.sqrt(z)
    end
    print("end",os.clock())
end

function touched(t)
    if t.state==BEGAN then
        cnt=cnt+1
        print(cnt,os.clock())
    end
end

Hey, maybe that’s how quantum mechanics works - there is a draw loop and a touch event - so the whole universe is a Codea program, running on a rather large iPad! :-j

We’re just a large video game and the battery’s going to go dead and end the game.

@Ignatz The iPad Pro

@dave1707 Good detective work. This happens because the runtime executes independently of the touch handling.

So whenever you touch the screen a block of code is pushed onto the runtime queue, and it will get around to executing it when it’s free.