Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

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

Tagged:

Comments

  • dave1707dave1707 Mod
    Posts: 7,528

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

  • dave1707dave1707 Mod
    Posts: 7,528

    @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
    
  • Posts: 25

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

  • IgnatzIgnatz Mod
    Posts: 5,396

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

  • Posts: 25

    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.

  • IgnatzIgnatz Mod
    edited June 2015 Posts: 5,396

    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

  • Posts: 25

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

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

  • IgnatzIgnatz Mod
    edited June 2015 Posts: 5,396

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

  • dave1707dave1707 Mod
    Posts: 7,528

    @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
    
  • dave1707dave1707 Mod
    edited June 2015 Posts: 7,528

    @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
    
  • IgnatzIgnatz Mod
    Posts: 5,396

    well, well, I hadn't tried that.

  • Jmv38Jmv38 Mod
    edited June 2015 Posts: 3,295

    ...

  • Posts: 494

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

  • dave1707dave1707 Mod
    Posts: 7,528

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

  • dave1707dave1707 Mod
    Posts: 7,528

    @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
    
  • IgnatzIgnatz Mod
    Posts: 5,396

    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

  • dave1707dave1707 Mod
    Posts: 7,528

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

  • @Ignatz The iPad Pro

  • SimeonSimeon Admin Mod
    Posts: 4,888

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

  • Jmv38Jmv38 Mod
    Posts: 3,295

    @Simeon does that mean there is no solution? Or the opposite?

  • SimeonSimeon Admin Mod
    Posts: 4,888

    @Jmv38 solution to getting a touch outside the draw function? As @dave1707 showed, you definitely can and print a result to the output window. You can also draw inside the touched function if you want.

Sign In or Register to comment.