6

I am tearing my hair out trying to figure out what seems to be a very easy problem. I know a lot of this stuff has been talked about tangentially, so apologies if this treads on well-covered ground, but I can't find anything specific to my solution (believe me, I've looked).

Basically I want to drag an object/sprite along a pre-defined, curved path (not just move it, but DRAG IT). Think of the iPhone's "Slide to unlock" thing, but instead of just dragging the slider left-to-right, make the path an arc or a wavy line.

My basic thinking was:

  • define a bezier path, set the object at the start point.
  • if the object is touched, check for hit detection on the bezier path in touchesMoved (or some similar function). if touches stay on the path, advance the sprite along the path until the path ends (in which case, task is finished) or the user's finger goes off the path (in which case, the object should go back to the beginning).

None of this is trivial (at least, that's how it seems). For example:

  • Doing hit detection on a Bezier path is a royal pain since you actually need to do it on the stroked portion, not the fill portion. And even then, I can't seem to find a way to do it on a path of any width -- only on the 1-point-wide path of the Bezier.
  • Moving an object partially along a path doesn't even seem possible: all of the animation methods move the sprite along the ENTIRE path. Also, doing this requires you to find the point on the path closest to the user's touch, which, if you've ever looked this up involves astoundingly complicated math.
  • I've thought of using rigid bodies to occupy all of the space EXCEPT the path, so the object can only move in the path. However, this requires the definition of curved rigid bodies some of which must be concave. Dead end.

Am I making this too hard? It doesn't seem that complicated. I don't need a whole solution, just a new way to think about this and kick in the right direction. Any help would be really appreciated.

  • 1
    I know this was asked a long time ago but i'm running into something very similar right now and was wondering if you had figured this out and might be able to help direct me down the correct path. – gikygik Apr 29 '15 at 16:31

2 Answers2

2

How about this?

  • Consider the X Axis of your bezier path.
  • Each time the user taps or interacts with the screen just look at the x portion of the touch
  • Map that X Coordinate with your path and move the object to the right position.
arclight
  • 5,299
  • 1
  • 22
  • 26
  • Would this solution work if the curve crosses the same point on the X axis more than once? For example, what if the curve is simply the letter "S". The same X point can occur multiple times for different Y points on the curve... – johnnysports May 24 '11 at 20:40
  • 1
    No it wouldn't. What you can do is use the Y Axis to decide which point in the curve you should adjust to – arclight May 24 '11 at 20:48
0

Yes, you are making this too hard.

Take the simplification suggested above (or along a circle, line, etc) if it works for, or if you really want to do it against a bézier curve, consider the following:

  1. Look at the definition of the bézier curve
  2. What you're looking for is to define a new object position P' from a current position P and a change in touch position D.
  3. If you rephrase the original P(x,y) in terms of t (bézier curves are parametric), then the problem becomes finding how much t offset to add based on D.
  4. Something involving the differential of the bezier fn at P might be a good way to do that. Ie, how much t would have been added had the curve just been a straight line coming from point P along the curve.

EDIT: Transition between segments: If each segment has t in [0,1), then you can detect t >= 1 and move on to the next segment, setting P to the end of the previous segment, and evaluating the movement again in relation to that point. There might have to be some heuristics involved if you have a lot of small points, etc.

Andrew Pouliot
  • 5,423
  • 1
  • 30
  • 34
  • Andrew, thanks for your response. Please bear with me because I'm really trying to understand this but it's still eluding me. I think yours and arclight's solutions might not work for more complicated paths. I believe (correct me if I'm wrong) that your solution will work if my curve is a single bezier curve. However, if I construct a path that consists of multiple segments, some straight, some quad curves, some arcs (which the SDK allows), I need to figure out what segment I'm on, and then calculate the new position. Do you see what I'm saying? – johnnysports May 24 '11 at 19:53
  • See above for a possible way to handle this. – Andrew Pouliot May 25 '11 at 08:00
  • I know this was all asked a long time ago but i'm trying to do something similar now and was wondering maybe you could answer this. I'm wanting to drag along a ellipses which I drew using a beizerpath. Is there a way to get all the points in the ellipse so I can do what you recommended above? – gikygik Apr 29 '15 at 16:37
  • @gikygik There an an infinite number of points on the ellipse, by definition, so your question doesn't make sense to me. The ellipse case is much easier than the bezier curve case, though, so you can just take the parametric definition of an ellipse and find it's derivative (look at any vector calculus textbook here). It doesn't matter how you drew the ellipse—it's still an ellipse. – Andrew Pouliot May 04 '15 at 01:31