1
\$\begingroup\$

For a game of table tennis, the goal is that when the player hits the ball, the opponent (the computer) will move to the position where the ball will land in order to hit it back to the player.

Said another way, given a ball in 3D space with an XYZ vector for its velocity, how can I calculate an XYZ velocity vector that will result in the position of the computer player being approximately where the ball will land?

For my coordinate system is, Y is up/down, Z is left and right of the table, and X is forward backward (toward or away from the table)... So, I know I can simply just set the player's z velocity to match the ball's z velocity to match the direction, but I need to know how to find the appropriate X velocity so that the player will move backward / forward depending on how fast the ball is traveling + taking into account the height of the ball + gravity, etc.

UPDATE

Seeing that the initial ball height is different than the table and the floor, I did some research and learned that the quadratic formula was the best way to solve this problem...

serveToTable = (-ball.vel.y + Math.sqrt((ball.vel.y * ball.vel.y) - (4 * (gravity * 0.5) * (tableY - ball.pos.y)))) / gravity;
tableToFloor = (-ball.vel.y + Math.sqrt((ball.vel.y * ball.vel.y) - (4 * (gravity * 0.5) * (floorY - ball.pos.y)))) / gravity;
duration = serveToTable + tableToFloor;
player.pos.x = ball.pos.x + (ball.vel.x * duration);
player.pos.z = ball.pos.z + (ball.vel.z * duration);

This, kind of works.. But it seems the player will go to the ball 2-4 times and then miss the ball. Sometimes by quite a lot.

\$\endgroup\$
  • \$\begingroup\$ If you're satisfied with your quadratic formula solution, post it as an answer. If you want help debugging the miss cases, show us an example where it predicts the wrong landing site (including the values of all inputs) and we may be able to trace those through to where the calculation goes wrong. \$\endgroup\$ – DMGregory Nov 21 '18 at 11:50
1
\$\begingroup\$

The problem here is that you can't really use actual physics to solve the problem, because game engines use "Simulated Physics" and not "Real-Time Physics", e.g. Unity uses PhysX for 3d physics.

Take a look in the Physics vs. PhysX section of the documentation to understand where the problem lies.

So, no matter how accurate your equations are, the physics engine will not respond in accordance with those equations.

IMHO the AI playing table tennis should "cheat" a bit to provide an entertaining experience for the real player. I'm a Unity user, so I'll give an indication of what I'd do (or where I'd start) with Unity.

  • I'd add a vertical plane with a trigger collider on the side of the AI player. This vertical plane should be greater than the width of the table, wide enough and tall enough so as to detect all incoming shots. -This trigger should detect the moment the ball crosses it, when a ball is incoming. One of the techniques you can use to detect if the ball is incoming and not outgoing is to use a boolean, and set it after the ball gets hit by the player, and the reset after the ball is hit by the AI.
  • The AI should always keep a reference to the ball's Transform.position. So, after an incoming ball is detected, the AI can have a response time depending on its "table-tennis" skills/experience, i.e. respond faster if the AI is skilled, or slower if not skilled.
  • The AI may also have certain properties and behaviors relative to how often it just -randomly- misses the ball (the AI can get "tired" or "destructed"), whether to apply spin or not, how hard it hits and where, etc.
  • After some experimentation you'll be able to get the AI to respond as you like it.

Of course the physics engine can still simulate the gravity of the ball etc, but since its not possible to conform to actual real-time physics, it can't be used for detecting the exact/physics-based ball movement, so I provided you with an alternative to use for your game.

\$\endgroup\$
1
\$\begingroup\$

When the ball leaves the user's paddle, copy the ball/game state and run the simulation forwards until you know where the ball will end up, but without updating the visual display of the ball. Then, you can create a spline that describes how the computer's paddle will move to meet the ball, and run the simulation while updating the screen.

This way you're guaranteed to reach the ball because the calculations during the real and fake run are identical, right down to floating point errors.

If you need to let the human win, a basic way would be to give the computer's paddle a maximum speed so that it can't reach the ball in time.

\$\endgroup\$
  • \$\begingroup\$ This solution is pretty reliable, especially in case of complex physics simulation or one which is in active development. But readers should be aware that a mathematical solution is likely far more performant. Whether or not performance actually matters depends on the game and the platform it is targeting. \$\endgroup\$ – Philipp Jan 17 at 14:09
0
\$\begingroup\$

You need to split this into two components: the horizontal component and the vertical component. First you calculate the time it takes for the ball to hit the floor.

Using the law of motion:

t = 2 * v(i) / g

v(i) is the initial vertical velocity. g is the gravity constant.

Now you have the time the ball will travel before reaching the ground. Use the horizontal velocity component to calculate the target position:

pos(tar) = pos(start) + v(horizontal) * t
\$\endgroup\$
  • \$\begingroup\$ I tried your suggestion, but it proved to be highly inaccurate do to the fact that the ball has to bounce on the table and then the floor. I ended up going with the quadratic formula, but it still does not seem to offer complete accuracy. It works some/most of the time... I updated my question to reflect this to see if you or others might have an idea how to improve the accuracy. \$\endgroup\$ – patrick Nov 20 '18 at 7:04

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.