Howdy, Stranger!

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

Using Touched Function

edited February 2014 in Bugs Posts: 50

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

Comments

  • Posts: 2,161

    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" :P

    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.

  • Posts: 2,161

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

  • edited February 2014 Posts: 50

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

    (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 ;-) 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 ;-).

  • IgnatzIgnatz Mod
    edited February 2014 Posts: 5,396

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

  • edited February 2014 Posts: 2,161

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

  • IgnatzIgnatz Mod
    Posts: 5,396

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

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

  • @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!

  • edited February 2014 Posts: 1,595

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

  • edited February 2014 Posts: 50

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

  • IgnatzIgnatz Mod
    edited February 2014 Posts: 5,396

    @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!)

  • @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!

  • IgnatzIgnatz Mod
    Posts: 5,396

    @ScottDafydd - tables in Lua are amazing. So simple but so powerful. Yes, very important and well worth the effort to learn about them.

    (And I know the feeling of reading the same thing over and over until you suddenly get it. It's like looking at one of those ambiguous pictures which can be seen in two ways, and only being able to see one of them until your brain suddenly clicks).

Sign In or Register to comment.