## Verify that a touch/drag was along a path

Nibbie
Posts: 3
Joined: 2009.05
Post: #1
Does anyone have a good idea, or at least can point me in the right direction, of being able to verify that a player's drag was along a specified path?

For example, let's say you have a simple square, just 4 lines, 4 points. I'd like the player to have to trace the square, and stay on the paths that make up the square. Also, I don't want the player to be able to go back over the path they just traced upon.

Any ideas or suggestions? I'm comfortable with tracking user touches and drags and such, but unclear as to how to force the player, or at detect rather, if they drew a path correctly without a ton of code.

Kind regards,

Bangtickboom
Member
Posts: 353
Joined: 2002.04
Post: #2
I would have a look what Googling "gesture recognition" gives you.
Member
Posts: 161
Joined: 2005.07
Post: #3
Initial setup:
- define a square as four paths
- define each path as a series of evenly-spaced points (I'd recommend 10-20 pixels apart, but make sure every point is the exact same distance away from each other), with booleans for whether the path is completely drawn, whether the user is currently drawing that path, and whether the path is being drawn backwards (from the last point to the first point), then have an int to keep track of how many points in the path have been drawn so far, and an int that says how many points are in the path
- each point is just an (x, y) coordinate.

Starting a path:
- when the user touches the screen, loop through all the paths, make sure the "completely drawn" flag is false, then see if the touch point is within a certain distance of one of the end points of the current path. If so, set the "is drawing" flag to true and the "points drawn" int to 1. If they touched the last point in the path, set the "drawn backwards" flag to true.

(note: it's likely that more than one path will have the "is drawing" flag set to true in the above step. If they touch the bottom-left corner of a square, we don't yet know if they're going to draw the left edge or the bottom edge.)

Continuing a path:
- loop through all the paths. If the "is drawing" flag is true for the current path, figure out which point is next in the path like so:
a. if the path is being drawn forward, the next point is just the "points drawn" value.
b. if the path is being drawn backwards, the next point is (size of the path - "points drawn" - 1).
- see if the current touch point is within a certain distance of the next point in the path (maybe 20 pixels? You'll probably need to tweak these values a bit...). If it is, increment the number of points that have been drawn for that path.
- if they succeeded in drawing the next point, and if the number of drawn points for the path is around 4 or 5 points, set the "is drawing" flag for all the other paths to false. (We need to track a few points so we know which path they're trying to draw. Once we know, we can stop tracking the other paths.)
- if the current touch point is further than a certain distance from the next point (something larger, like 30-35 pixel), then the user failed at drawing that path. Set the "is drawing" flag to false for every path and give some visual and audial feedback to let them know they failed (jitter the screen, buzzing sound, etc.)
- finally, if the number of points drawn is equal to the size of the path, set the "completely drawn" flag for the path to true!

Drawing the path to the screen:
- if the "completely drawn" flag is set, just loop through the points and draw them as a sequence of lines.
- if the "is drawing" flag is set, and if the number of points drawn is 4 or 5 (make sure to use the same number as above, where I also said 4 or 5!), then loop through the points that have been drawn so far and draw them as a sequence of lines.

Should work okay after you tweak the values until it feels right.

EDIT: By the way, I should specify that I'm thinking of this one DS game where you had to connect the dots to draw shapes. The difference between that and a gesture is (1) gestures are timed-based, while you can take as long as you want to draw the path in the game, (2) gestures can be really sloppy and still work, while this needs to be drawn very carefully and precisely, and (3) gestures need to be drawn all at once, while this one can be drawn as individual paths if you want.
Moderator
Posts: 455
Joined: 2002.09
Post: #4
I think you can do it with some simple vector math.

Let's start with the simple case, a single line segment with a start and end point. I think you just need two tests - distance from line, and direction. Distance from line is the test to prevent them from drifting too far away from the line. It simply requires you to compute the distance from their current position to the nearest point on the line segment. If more than D units away from the path, they fail.

The direction test is, are they heading in the direction of the line segment. Compute their vector of movement (current position - previous position). Take the dot product of that vector with the path segment's vector. If I remember my geometry correctly, this dot product is the cosine of the angle between the two vectors. Just check that they haven't deviated from the path segment's direction by more than N degrees, where N is an angle (45 degrees) that you come up with through trial and error, and depending on how hard you want the game to be.

Multiple segments require a little more work. When the player is within D units of both the end of the first segment and the start of the next segment, it is not clear which line segment they are tracking. They might even be transitioning from the first to the second, following a path that's more like the average of the two vectors.

If the angle between the two vectors is small then there's no problem. The problem is if your path has abrupt turns, like the square example. The first thing I'd try there is that if the test against the first segment fails, and they are close enough to the start point of the 2nd segment, start testing them against the 2nd segment. I suspect this approach is too simplistic because users may transition smoothly between the two vectors, tracing a tight curve with their finger, and if they don't transition abruptly enough they might fail the test. You could also simply drop the direction test when they are close to one of these points. Eventually they will move far enough away from the first segment and clearly be following the 2nd segment.

Note that a lot hinges on the D & N parameters you choose, and whether your path segments have abrupt turns. Switchbacks (i.e. angle between two path segments greater than 90 degrees) could be a particular difficulty.

(You may also find you have to average their recent movement vectors, or ignore isolated direction failures. I don't know how noisy the touch position data you'll get is.)

Measure twice, cut once, curse three or four times.