Saturday 30 April 2016

Some Vector Math

The problem is to allow the player to work out if if there is a dangerous obstacle (an opposing player) in his path whilst dribbling. This is similar to a "field of view" but just re-sized to what the player considers "too close for comfort." So when an opposing player enters the danger area, the dribbler will try to change direction or get rid of the ball.

Here's the vid:

Teaching myself vector math from the beginning again, there is probably a more elegant way to do this. Anyway, here's what my brain came up with.

Given the position of the player p, his normalized velocity v, an angle specifying how wide the field of view should be and a length specifying the size, we can calculate a triangular field of vision (three points, p1, p2, p3) like this:

p1 = p
p2 = v.rotate(angle/2)  x length
p3 = v.rotate(-angle/2) x length

With different parameters, this can also be used to select possible pass receivers etc.

Example in code:

// calculate the angled vectors
Vector3 side1 = position + velocity.rotated(-25, 0, 0).normalised() * 200;
Vector3 side2 = position + velocity.rotated( 25, 0, 0).normalised() * 200;

// p1 is just the position of the player
p1.x = position.x;
p1.y = position.y;

// p2 is end point of the first side
p2.x = side1.x;
p2.y = side1.y;

// p3 is the end point of the second side
p3.x = side2.x;
p3.y = side2.y;


For the uber curious, here's the rotated() function:

// ----------------------------------------------------
//  rotated
// ----------------------------------------------------
Vector3 Vector3::rotated(double a, double x_origin, double y_origin) {

a = RADIANS(a);

Vector3 rotated = *this;

rotated.x -= x_origin;
rotated.y -= y_origin;

double nx = cos(a) * rotated.x - sin(a) * rotated.y;
double ny = sin(a) * rotated.x + cos(a) * rotated.y;

rotated.x = nx;
rotated.y = ny;

rotated.x += x_origin;
rotated.y += y_origin;

return rotated;
}

No comments:

Post a Comment