5
\$\begingroup\$

Simply put I'm making a basketball game. I'm using these equations to predict the ball position and it works fine:

x = vx * t
y = vy * t + 0.5 * gravity * t * t

But I can't find a way to draw equal length line stripes on the parabola. At this moment I'm using:

t = t + dt

in which dt is the time elapsed in last frame. It works but the line segments would be longer if velocity is larger. Anybody know a way to draw equal length line stripes like the flying trails in Angry Bird? Thanks very much.

I suppose I should calculate the integral on the curve but I can't get it through...

\$\endgroup\$

2 Answers 2

6
\$\begingroup\$

The derivative of the ball position is:

dx/dt = vx
dy/dt = vy + gravity * t

So the derivative of the parabola arc length s is, using Pythagora’s theorem:

ds/dt = sqrt(vx² + (vy + gravity * t)²)

It is possible to write down the integral of s. However, the resulting formula is so complex that it cannot be inverted (ie. you cannot get back t from a given value of s) without resorting to quite complex numerical programming.

However, as a reasonable approximation you could decide that s is only slightly varying. For an arc length l and a time t the next point should be plotted at time t' such that:

t' = t + l / sqrt(vx² + (vy + gravity * t)²)

I am confident this works pretty well in practice. If this does not give acceptable results, you could choose a smaller value for l (eg. l/8) and only plot one point out of 8.

Here is some code showing how it could be implemented:

void drawPointsAlongParabola(Point origin, float vx, float vy, float gravity,
                             float spacing, float duration)
{
    Point v(vx, vy);
    Point g(0, -gravity);

    for (float t = 0; t < duration; t += spacing / length(v + g * t))
        drawPoint(origin + v * t + 0.5 * g * t * t);
}
\$\endgroup\$
1
  • \$\begingroup\$ Thanks it works perfect! Now I feel so stupid I never thought of this before... \$\endgroup\$
    – jagttt
    Mar 2, 2012 at 8:48
0
\$\begingroup\$

I understand the above answer works fine, but I highly doubt that Angry Birds does anything that clever :P

You should be able to just traverse the line and draw points as you reach each interval.

Something like this (not tested, just off the top of my head):

void drawPointsAtInterval(List<Point> points, float pointSpacing) {
    float distanceAlong = 0;

    for(int pt = 0; pt < points.count() - 1; pt ++) {
        Point a = points[pt];
        Point b = points[pt + 1];
        float lineLength = length(b - a);
        Point direction = (b - a) / lineLength;

        while(distanceAlong < lineLength) {
            Point p = a + (distanceAlong * direction);
            drawPoint(p);
            distanceAlong += pointSpacing;
        }

        distanceAlong -= lineLength;
    }
}
\$\endgroup\$
3
  • \$\begingroup\$ Do you work at Rovio? How can you be so sure? \$\endgroup\$ Mar 3, 2012 at 16:03
  • \$\begingroup\$ @Gustavo: No, but I wrote a flash game with this exact same requirement. My method is what you get when you search for the more general case of drawing dots or strokes along an arbitrary wiggly line. Sam's solution works but strikes me as an overcomplicated approach (sorry Sam). To me this problem is about how to draw the line correctly, not how to adjust my simulation so that the time steps give equal spacing. And if you were performing more complicated arc simulation (box2d bounces?) you might not be able to change the time step. \$\endgroup\$ Mar 3, 2012 at 23:34
  • 2
    \$\begingroup\$ @ChrisBurt-Brown: no offense taken, I understand your point :-) However, I added some code to show that while it requires some thinking beforehands to get the maths right, the actual code is extremely short. Provided, as you indicate, that the problem is really about a parabola and not an arbitrary curve. \$\endgroup\$ Mar 6, 2012 at 9:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .