Using Touched Function

Update: just changed title of discussion to better reflect subject matter…

Hi everyone, hope you’re all well. After my first successful go at a Codea game, I went back to basics and thought I’d practise by coding a simple touchscreen snap game. Turned out to be more confusing than the scrolling shoot-em-up but I finally got the game to work. It’s the settings page that’s going bug crazy! I’ve set up the options to change speed of transition, amount of cards, etc which just about works ok except that the numbers just don’t stop increasing after only one touch (it’s only supposed to go up one touch at a time!) I’m at a total loss as to why it’s doing this, although am pretty certain it’s something to do with the speed at which Codea draws… Anyone else got any ideas?

Here’s the relevant section of code (the whole program is about 200 odd lines):


if state == settings then
        timebetween = timebetween + 1
        sprite("Dropbox:Settings1", WIDTH/2, HEIGHT*0.25, 400)
        pushStyle()
        font("MarkerFelt-Thin")
        fontSize(30)
        fill(41, 36, 36, 255)
        text(winnum, WIDTH/2+120, HEIGHT*0.25)
        popStyle()
        

    
        if CurrentTouch.x >  WIDTH/2-200 and CurrentTouch.y > HEIGHT*0.25-60 then
            if CurrentTouch.x < WIDTH/2+125 and CurrentTouch.y < HEIGHT*0.25+60 then
                if timebetween > 80 then
                    if winnum == 50 then
                        winnum = 5
                        timebetween = 0
                        
                    else winnum = winnum + 5
                        timebetween = 0
                    end  
                
                end 
            end
        end

I presume that this is in draw. If so, it gets run every 60s, and CurrentTouch holds the most recent touch event, regardless of whether or not there has been a recent touch. It’s better to put this logic in the touched function so that it responds to actual touch events.

@ScottDafydd: I’ll second @Andrew_Stacey in this: “Don’t touch CurrentTouch” :stuck_out_tongue:

As a data point, I’ve been teaching Codea to young children (age 7 to 11) for the past year or so. For input I started with “currentTouch” thinking it would be easier than the “touched(t)” handler function, but it turned out to be confusing and when I showed the “touched(t)” alternative they got it fairly quickly and solidly.

@daveedvdv Oooh, that sounds interesting. As a club or as school lessons?

Thanks @Andrew_Stacey @daveedvdv - appreciate you taking the time to answer; yes, this is in draw under the settings game state and is repeated for each of the three settings option. Funnily enough, I’ve tried both touched function and current touch and it happens with both. That said, I used the touched function by storing it in a variable and then using that in the conditional statement so might that have made it operate in the same way perhaps? It’s kind of weird because the game bit is working fine, it’s just the settings page that’s a bit buggy! :slight_smile:

(Incidentally, what is the actual difference between the two functions? Would I be best to use touch.state? Pretend you’re talking to one of your 7-11 year olds if you like!)

@Andrew_stacey: Just my children and their friends. Lua is the new BASIC :wink: My youngest daughter just proudly presented her implementation of a Connect4-like game at her school’s science fair!

@ScottDafydd: What I teach the kids is that draw() should only draw and not process input or update state in any way. This correspond to what various programming models call the “Model-View” or “Model-View-Controller” approach to writing apps (e.g., Apple’s recommendation).

In that world, the update of timebetween right after the if state == settings test is suspect in the sense that it looks like timebetween is a state variable that lives between invocations of draw(), but I might understand better if I saw the whole code or if you could describe what the purpose of time between is (or maybe what a “snap game” is ;-).

@ScottDafydd - as Andrew said above, CurrentTouch holds the most recent state, however long ago it happened (so it can mislead your program into thinking the touch continues), whereas the touched function is only triggered by current touches.

When using touched, you should check the state property, which can be BEGAN, MOVING or ENDED. If you’re just trapping a touch on the screen, then either BEGAN or ENDED will do.

So for example, you can set a flag when you get a BEGAN state, then do your increment in draw and reset the flag to nil. Or do the increment in touched, like so

function touched(t)
    if t.state==BEGAN then
       if CurrentTouch.x >  WIDTH/2-200 and CurrentTouch.y > HEIGHT*0.25-60 and
            CurrentTouch.x < WIDTH/2+125 and CurrentTouch.y < HEIGHT*0.25+60    
            then
                if timebetween > 80 then
                    if winnum == 50 then
                        winnum = 5
                        timebetween = 0
                    else winnum = winnum + 5
                        timebetween = 0
                    end  
                end 
        end
    end
end

@ScottDafydd: I’m not sure whether it’s relevant, but to time things the tween functions can be useful. From memory (away from the iPad at this moment):

function timer_expired()
    -- Called when the time is up
    -- ... update some stet here
end

function touched(t)
    if t.state == ENDED then
        -- ...
        tween.delay(1.2, timer_expired)  -- timer_expired will be called in 1.2 seconds
    end
end

The tween functions are described in the Animation section of the Codea reference, but they’re usually for all kinds of timing purposes in addition to pure animation.

@daveedvdv I’d be interested in hearing what the steps were in getting your daughter and her friends to that stage. My kids are of a similar age and I’d like to get them in to programming, but thus far haven’t hit on the right strategy.

(Maybe a separate thread for this discussion, if you’d be willing and have the time to share.)

@Andrew_Stacey, @daveedvdv - I’d be interested, too, in finding out what teaching strategy works.

I agree with putting it in a new thread.

@Andrew_Stacey , @Ignatz: I’ve written up a longish report in a new thread as requested. See you there!

@daveedvdv - yes, that’s VERY relevant. Thanks! One of the questions I’ve been meaning to ask for the last few days was regarding a more efficient way of handling time-delays between touches and output etc (in fact this is exactly what timebetween was attempting to do). I’m kind of working my way through the major Codea functions and haven’t yet reached tweening. It might just change my life.

(Btw, ‘snap’ is a children’s card game where you shout “snap” when you see a pair. Apologies for the confusion - I thought it was one of those cultural universals like Connect 4!) :slight_smile:

And thanks too @Ignatz - I never thought to put the whole condition in touched. This is something that I’m still a little confused about when coding my own stuff from scratch, and has led me back to your book on more than one occasion!

I’m a bit ill at the moment so will engage with all the code posted when I can concentrate a bit better but thanks again all. As an ex-academic myself, I’m also quite interested in the other discussion taking place…

@ScottDafydd - I wrote something on tweening here

http://coolcodea.wordpress.com/2013/07/18/995-tweens-what-are-they/
http://coolcodea.wordpress.com/2014/01/24/146-playing-with-tween-functions/

@Ignatz - great stuff, appreciate it. Will put it on my reading list for tomorrow.

Ok, so I’ve finally felt well enough to give this some attention and, although it’s just a simple game, I’d really like to get the principals sorted in my own head. The idea of setup-draw-touched mirroring Apple’s principal of model-view-controller makes a lot of sense. In which case, does that mean that best practice is to put all potential touch conditions in the touched function regardless of game state (eg settings, game playing, intro etc)? If so, does that mean I store every touch in a different variable using a different condition and then just use that variable in the draw function if needed? Happy for anyone to weigh in on this one… I’m almost there!

@ScottDafydd the way I do it is create a table in setup called touches, then make a touch state began if statement at the start then insert the touch in to table touches inside that statement, in the middle have something like this:

for k,v in pairs(touches) do
 if v.id == t.id then
  touches[k] = v
  if v.state == ENDED then
   table.remove(touches,k)
  end
 end
end

This will update each touch inside touches with the corresponding touch ID and remove them on touch end.
With this you can do the same loop in draw like so

for k,v in pairs(touches) do
 ellipse(v.x,v.y,vec2(v.deltaX,v.deltaY):len()+20)
end

This will make circles at each touch point that get bigger with faster movement.

If you create a Touch class (a table works too) which holds all the attributes as a touch does (.x, .y, .deltaX, .deltaY, .prevX etc) then you can manipulate these attributes using code as well, for example scaling touches according to zooming and panning requires this.

Also in my app I use a lot of what I take out of touch and use it in the draw function, it is needed in a lot of cases. But you will need all things that require touch no matter what state in a touch function, but if you use a state machine it will only load these individual functions instead of running through them all and trying to pick out touches from multiple states.

Hi @Luatee, thanks so much for this. Very helpful. And apologies for not replying sooner. My health is not great at the moment and I find I need a lot of concentration to read even the simplest code.

Effectively, you’re storing the touches in a table which has been set up in setup and then removing when the touch ended. Think I get it. I take it this still needs linked up somehow with what goes on in the touched function and then any responding action drawn out I the draw function right?

I’m still not clear as to what or how to use the pairs statement. Is there an easy way to understand it that also explains why the letters k and v are always involved? :slight_smile:

@ScottDafydd - The pairs “for” loop simply loops through all the items in a table. Every item is a pair consisting of a key and a value. The key is used to look up the value.

In a sequential table like t[1], t[2] etc, the numbers 1,2,3 are the keys, and you can do a for loop like “for i=1,#t do”

However, if you store named values in your table, as in t={a=3,b=4,…etc}, then the letters a,b etc are the keys. How do you loop through a table with named keys rather than number keys?

The answer is pairs. This method loops through every item in the table - in no particular order! - and gives you two values for each one - surprise, surprise, they are the key and the value - hence the usual choice of k and v.

so “for k,v in pairs(t) do” loops through all items in table t, and gives you the key and value for each, to do with as you wish.

(get well soon!)

@ScottDafydd – more here

http://coolcodea.wordpress.com/2013/04/07/26-tables/

@Ignatz - ahh, I think the fog is lifting. It’s amazing how many times you have to read the same thing again and again in different ways until you get it! So K and V are used for Key and Value. Makes sense. Which I guess is why in ipairs, I and v are used - I meaning integer right? Tables and pairs seem so important I really want to get this cracked… Thanks everyone for helping me!