5
\$\begingroup\$

How would someone implement moving an object from one point in 2D space to another using these formulae to update objects:

m_position.setX/Y( m_position.X/Y() + m_velocity.X/Y() * dt + 0.5 * m_acc * pow(dt,2);
m_velocity.setX/Y(m_velocity.X/Y() + m_acc * dt);

I'm trying to make a pong clone and I'm having some trouble programming the AI paddle to go to the y coordinate where the ball will hit. (the y coord is predicted in a function).

Currently I have it so that it applies an acceleration of 1 until half the distance then an acceleration of -1 after it, but naturally it is overshooting by a lot, then trying to go back, etc.

\$\endgroup\$
  • \$\begingroup\$ You can try Easing the paddle into place. You can also dynamically control the paddle using at PID controller. \$\endgroup\$ – mklingen Mar 25 '15 at 14:52
  • \$\begingroup\$ @mklingen Easing, respectively tweening, could be exactly what I need. I'll take a closer look into them. Thank you! \$\endgroup\$ – Cadhylo Mar 25 '15 at 16:00
  • \$\begingroup\$ Why are you integrating acceleration twice? The numerical integration is fine, but the additional symbolic integration does not hold if m_acc is not constant. Even if acceleration never changed, you will still be doubling it. \$\endgroup\$ – MickLH Jan 22 '16 at 22:03
1
\$\begingroup\$

This is a job for a PID Controller:

Proportional Integral Differential Controller.

Consider this: if you are close to the goal, how hard do you push? It all depends on the velocity. If you are not moving, you push towards the goal. Yet, if you are already speeding towards the goal, you need to push in the opposite direction so you don't overshoot.

The PID controller will take an actual value (current pos) and a desired value (goal pos) and gives you a steer value.

This steer value is used to apply force to the paddle (or in other terms: accelerate/decelerate the paddle.)

This means you need to give your paddle two pieces of state: a position and a velocity.

Each frame you do:

accel = pidcontrol( desiredpos, actualpos, dt );
vel = vel + dt * accel;
pos = pos + dt * vel;

To tune the controller, you need to tune P, I and D constants associated with the controller.

I wrote a Primer on PID Control that explains it in detail, and comes with code too.

\$\endgroup\$
0
\$\begingroup\$

Your velocity is 0 when the ball stops, so the velocity must be 0 at the point where it would "overshoot" (when there's a direction change required in the paddle).

You can set your velocity to 0 and change paddle direction when your paddle has reached the y coordinate of the ball.

\$\endgroup\$
  • \$\begingroup\$ I've unfortunately tried that already and discovered that because of the velocity not being constant and is greater than one unit, the position may increase OVER the actual destination coordinate (e.g.: I want to reach y_dest = 300, my initial position is y_init = 200 and for the sake of the argument let's say the velocity is at a constant 7. If you keep adding 7 to 200, the closest you'll get to 300 is 294. Then if you update the position once more it's going to be 301, overshooting it. \$\endgroup\$ – Cadhylo Mar 25 '15 at 15:57
  • \$\begingroup\$ Can you make it so that on the last iteration of the distance step will be exactly the distance required to reach the correct coordinate? Meaning, if the distance between the desired coordinate is less than the step length (7 in this case), you can compensate accordingly by setting the step length to something lower (6, 5, etc.) or just updating the position to the desired coordinate? \$\endgroup\$ – Joshua Yi Mar 25 '15 at 17:50
  • \$\begingroup\$ Hmm... it could work.. although the pad will come to a sudden stop which wouldn't look so smooth. I'll look into it nonetheless. \$\endgroup\$ – Cadhylo Mar 25 '15 at 17:58
  • \$\begingroup\$ Yeah, I wouldn't expect it to look too smooth. There might be a lot of tweaking involved to make everything look seamless. If you want it to look better, I would imagine you have to change acceleration in response to the distance and it could definitely get complicated if you want things exact. \$\endgroup\$ – Joshua Yi Mar 25 '15 at 18:04
0
\$\begingroup\$

I believe it is as simple as accelerating until you are a square root closer and then decelerating to 0. This is because the final distance is equal to the square of the number you begin to decelerate at. If you begin to slow right after 3 pixels, you will end up at 9 pixels from your starting point. If you stop after 20 pixels, the final result will be 400.

\$\endgroup\$
0
\$\begingroup\$

For this purpose I would use Verlet integration. It's nice and easy to implement algorithm. You can read more about it here.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.