# How to randomly calculate the necessary velocity changes to reach a x,y,z target?

I am working on creating a mini vector graphics ping pong table, as described in this previous post: Trying to use 3D vectors for a 2D ping pong game

Currently, the stage I am at, I am trying to make it so that when the ball exceeds the X bounds of the table, it will reflect backwards and at a new target: a random x,y,z position on the opponent's side of the table.

Trying to use this post as a starting point: How can I launch a GameObject at a target if I am given everything except for its launch angle? I have attempted to adapt some of that example code in my program, but I am not quite getting the desired results.

** updated code **

update: function(paceFactor) {
this.ball.pos3D.x += this.ball.vel.x * paceFactor;
this.ball.pos3D.y += this.ball.vel.y * paceFactor;
this.ball.pos3D.z += this.ball.vel.z * paceFactor;
this.ball.vel.y += this.gravity * paceFactor;

if (!this.stop && Math.abs(this.ball.pos3D.x) > 15) {
this.stop = true; // for testing to prevent velocity from getting changed due to bad values returned from velocityForNextTarget()
var modifier = this.ball.pos3D.x < 0 ? 1 : -1;
var velocity = this.velocityForNextTarget(modifier);
this.ball.vel.x += velocity.x;
this.ball.vel.y += velocity.y;
this.ball.vel.z += velocity.z;
}

if (this.ball.pos3D.y >= 0) {
this.ball.vel.y *= -1;
this.ball.pos3D.y -= this.ball.pos3D.y;
}

this.convert3Dto2D();
},

velocityForNextTarget: function(modifier) {
var targetX = 5 * modifier;
var targetY = 0;
var targetZ = 0;

var deltaX = this.ball.pos3D.x - targetX;
var deltaY = this.ball.pos3D.y - targetY;
var deltaZ = this.ball.pos3D.z - targetZ;

var sqrMagnitude = (deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ);
var speed = Math.sqrt((this.ball.pos3D.x * this.ball.pos3D.x) + (this.ball.pos3D.y * this.ball.pos3D.y) + (this.ball.pos3D.z * this.ball.pos3D.z));

var gSquared = this.gravity * this.gravity;
var b = speed * speed + (deltaY * this.gravity);
var discriminant = (b * b) - (gSquared * sqrMagnitude);

var discRoot = Math.sqrt(discriminant);

var t = Math.sqrt((b - discRoot) * 2 / gSquared);

return {
x: deltaX / t * t / 2,
y: deltaY / t - this.gravity * t / 2,
z: deltaZ / t * t / 2,
};
},


So what I am trying to do is make it so that when the ball reaches the location of a player, it will target the center of the opponent's side of the table, and the ball will move there, and right now this code is making the ball rapidly jump off the screen as soon as it hits the x bounds, and I am not sure what I am doing wrong with the math in velocityForNextTarget()...

I should also mention that gravity is just a constant that I am only adding to my Y velocity so far. I am not sure if that's "right" ?

1. Your return velocity is not correctly calculated.

In the source:

velocity = delta / T - gravity * T/2.0

return {
x: deltaX / t * t / 2,
y: deltaY / t - this.gravity * t / 2,
z: deltaZ / t * t / 2,
};

Correct translation:
(your gravity's x & z are zero, so those terms vanish: a - 0 * t / 2 = a not a * t / 2)

return {
x: deltaX / t,
y: deltaY / t - this.gravity * t / 2,
z: deltaZ / t,
};

var velocity = this.velocityForNextTarget(modifier);
this.ball.vel.x += velocity.x;
this.ball.vel.y += velocity.y;
this.ball.vel.z += velocity.z;

You want to use the new velocity as-is, not mix it with something else:

var velocity = this.velocityForNextTarget(modifier);
this.ball.vel.x = velocity.x;
this.ball.vel.y = velocity.y;
this.ball.vel.z = velocity.z;
3. Your speed calculation is still not meaningful (it's the ball's distance from the origin, not its speed). Why not just pass the ball speed that you want as an input as it was in the source answer?

velocityForNextTarget: function(modifier, speed) {

Or treat it as a configuration parameter similar to your paceFactor

• I hope I understood all your points correctly. I updated my code above to reflect the changes I made... 1) I added the paceFactor multiplication to "this.ball.vel.y += this.gravity * paceFactor;", 2) changed b to only use deltaY with gravity: "var b = speed * speed + (deltaY * this.gravity);" 3) tried using the speed of the actual current vector instead of the distance... Still something is not quite right though. The ball is going in the wrong direction (to the right and up, when I expect to the left and down). – patrick Mar 11 '18 at 8:13
• And I tried experimenting with flipping the signs of x and y returned from the velocityForNextTarget() function, but that seemed wrong.. it seems like what I am doing for speed is still not quite right.. – patrick Mar 11 '18 at 8:15
• "I thought my ball speed is defined by my ball's x/y/z velocity properties." It is, but you're not using its vel properties, you're using its pos3D properties which represent position. I still would not recommend using the incoming velocity as your speed here though. This bounce represents a player hitting the ball with their paddle, right? So they're going to impart energy to it - this doesn't need to be an energy-preserving reflection. It's probably simpler to model it as a "player return speed" configuration parameter that represents how hard players hit the ball. – DMGregory Mar 11 '18 at 20:54
• Probably because you're not handling the case where discriminant is less than zero. You're probably taking the square root of a negative and getting NaNs in your math. These negative discriminants happen when the target is out of range for the given speed, so if you don't want to handle that case, keep your launch speed high enough that you can reach anywhere on the table. – DMGregory Mar 11 '18 at 21:26
• That's a whole new question worth asking separately. – DMGregory Mar 11 '18 at 22:05