Search Unity

Zig-zag gesture

Discussion in 'Scripting' started by Arashikage, Dec 8, 2013.

  1. Arashikage

    Arashikage

    Joined:
    Dec 8, 2013
    Posts:
    14
    I've been searching the internet for weeks and I haven't found an answer to this problem. I'm working on a gesture-based mobile game and I'm trying to implement a zig-zag gesture. The other controls are just taps and swipes and they're working fine, but I can't figure out how to use multiple coordinates. I think I know how it should work, but I don't know how to program it.

    In my head, the way I see it is this:
    Touch the screen and point 1 is registered. Swipe right and when you change direction point 2 is registered at the point where the direction changed. When you change direction again point 3 is registered and then when your gesture ends point 4 is registered.
    Point 2 and 3 get compared to see if the X direction was reversed, point 3 and 4 get compared to see if the X direction was reversed again, and point 1 and 4 get compared to see if the Y direction stays the same. If all the conditions are met, then an action gets executed.

    My question is how do I store/register multiple points/direction changes in a gesture? A swipe (point A and point B) is simple enough, but I can't figure out how to add point C and point D.
    I've found a couple of gesture recognizers, but they use a lot of code and/or multiple files because they're testing for a wide range of gestures. I'm hoping there's a simpler way, something along the lines of testing for a swipe gesture but with a few more checks for the extra coordinates/directions.


    I think I have to use something like if touch.deltaPosition changes magnitude, then test something, and when it changes magnitude again, do another test... I just don't have enough programming knowledge to put it into usable code.
     
    Last edited: Dec 8, 2013
  2. Arashikage

    Arashikage

    Joined:
    Dec 8, 2013
    Posts:
    14
    I tried this:

    Code (csharp):
    1. function Update ()
    2. {
    3.  
    4.     if (Input.touchCount > 0  TouchPhase.Began)
    5.     {
    6.         var gestureStart : Vector2 = Input.GetTouch(0).position;
    7.         if (Input.touchCount > 0  TouchPhase.Moved  Input.GetTouch(0).deltaPosition.x > gestureStart.x)
    8.         {
    9.             var gestureDelta2 : Vector2 = Input.GetTouch(0).deltaPosition;
    10.             if (Input.touchCount > 0  TouchPhase.Moved  Input.GetTouch(0).deltaPosition.x < gestureDelta2.x)
    11.             {
    12.                 var gestureDelta3 : Vector2 = Input.GetTouch(0).deltaPosition;
    13.                 if (Input.touchCount > 0  TouchPhase.Moved  Input.GetTouch(0).deltaPosition.x > gestureDelta3.x)
    14.                 {
    15.                     var gestureDelta4 : Vector2 = Input.GetTouch(0).deltaPosition;
    16.                     if (Input.GetTouch(0).phase == TouchPhase.Ended)
    17.                     {
    18.                         transform.Translate (0,5,0);  //just to see if it does anything
    19.                     }
    20.                 }
    21.             }
    22.         }
    23.     }
    24.  
    25. }
    No errors, but it doesn't do anything.
     
  3. Arbelzapf

    Arbelzapf

    Joined:
    Sep 30, 2013
    Posts:
    58
  4. Arashikage

    Arashikage

    Joined:
    Dec 8, 2013
    Posts:
    14

    I found the older version of the dollar recognizer, but the problem with that (and the other recognizers I've found) is that they have way more gestures than I need, and the code seems to be pretty complicated so I don't know how to pick out the parts I need and apply it what I'm trying to do.

    A swipe gesture is very simple, so I figured a zigzag should just be 3 connected swipes. If the first part of the swipe is going in the positive X direction, then you check if the second swipe is going in the negative X direction and if the third swipe is positive X again, then it's a zigzag and 'do something'.
    Am I wrong in thinking that it should be so easy?
    I just can't figure out how to implement it. How do I store or track multiple points on a single gesture path? Many of the examples I've found talk about that, but none of them actually mention how to do it.
     
  5. Arbelzapf

    Arbelzapf

    Joined:
    Sep 30, 2013
    Posts:
    58

    I only had a quick glance at that recognizer, but I do plan to implement it in my own input wrapper at some point.
    As far as I can see, the code only consists of the algorithm to match a set of predefined points, which are stored as a "Gesture" class that is created using an array of points and a name. So stripping out unneeded gestures should be as easy as removing those predefined Gesture objects.





    You could store the last frame's deltaPosition and compare it to the current. Then, if the angle of this deltaPosition changed more than a specific threshold, you create a new point at the current location.

    Then, if the touch action ends, you could have a look at all the points you created and then figure out if the desired zigzag shape was drawn, probably by again comparing the angles of the resulting lines.

    I know this is is again much talk and no implementation, but let's just say this: If you got to this point, you might at well switch to using the recognizer.

    You will probably spend quite some time with this, just to come up with a program that only knows how to recognize zig-zags. Sure it wouldn't be hard to extend to more shapes, but using a library that will recognize any shape you throw at it will probably save you lots of headaches. And the code fits on a sheet of paper, so it's not that complicated either




    Remember that all this code runs in a single point in time.

    You are checking for TouchPhase.Ended in the same branch that checked for TouchPhase.Began at the very same moment. This cannot work. gestureStart, gestureDelta2, gestureDelta3 and gestureDelta4 will all have the exact same value since the touch position could not possibly have changed between those lines of code.
    Each of these steps should be done separately and one after another, probably using boolean flags (like gesture2Finished = true; ) to control the flow.