• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
kickkick

Target prediction system / Target leading

15 posts in this topic

An excellent AI system should have everything coded in it, including the so called "target leading" (I like to call it the target prediction system). We should come up with an algorithm that has the purpose of calculating the direction in which to shoot a non-infinite-velocity bullet, in order to hit a moving target. As you know, calculating the direction is easy if the bullet has infinite speed: just look directly at the target! However, if bullets have a certain speed, the target has a good chance of moving away after the bullet has been fired. For that, the shooter should shoot AHEAD of his target. I've heard that this topic's been posted more than once in some math or physics forums, but I have't found anything with google searches, just basic ideas on it. Also, a search on GameDev reveals nothing. So I hope that we will finally post a fully working target prediction system. Technically, this means it's more like a math problem than a programming problem, though the algorith optimization is a programming part. If math were so easy, everyone could just solve it by himself. Coming up with a 3D target prediction system is too hard, 1D is just nonsense, so the 2D will do. That is, consider a 2D plane which is viewed from a top camera, and nothing special like air resistance and gravity. First I'm going to ask some of you about your opinion on how to approach this problem, maybe for someone just to post the final result :). We can work together on the algorithm. In the end, if nothing comes out of it, I'm going to post my own system.
0

Share this post


Link to post
Share on other sites
That is a simple process once the TPS has been solved.

If the bullet's speed does not depend on the shooter's speed, then it is the same as if he were not moving.

If the bullet's speed does depend on the shooter's speed, then we just substract the shooter's vector (X-speed, Y-speed) from the target, as if the coordinate system were moving with the shooter.
0

Share this post


Link to post
Share on other sites
It also depends on the Physics system you are using, i.e. many games use a 'fudged' physics system which makes things much harder to reliably predict.
0

Share this post


Link to post
Share on other sites
Hmm.. what do you mean by fudged?
explain it...

Btw, it's not about the system I'll use, we're just making any system that shoots ahead. Preferably it's something as fluid as possible. You should make assumptions youself, such as the current location of the target is always known (otherwise it won't be much of a game engine).
In my system, the shooter, the bullet and the target are all point-like objects for maximum accuracy. You just pass the current data into the main function, and it returns the current targeting location.
0

Share this post


Link to post
Share on other sites
The math is not hard at all, and it's exactly as easy in 3D as it is in 2D. This is the code to do it in 2D (although you can just change the definitions of Vector and Point to be 3D if you want, and it should all work the same):
[code]#include <iostream>
#include <cmath>

struct Vector {
double x,y;

Vector(double x, double y):x(x),y(y){
}

double dot(Vector const &v) const{
return x*v.x+y*v.y;
}
};

Vector operator*(double s, Vector const &v){
return Vector(s*v.x,s*v.y);
}

struct Point {
double x,y;

Point(double x, double y):x(x),y(y){
}

Vector operator-(Point const &p) const{
return Vector(x-p.x,y-p.y);
}

Point operator+(Vector const &v) const{
return Point(x+v.x,y+v.y);
}
};

double largest_root_of_quadratic_equation(double A, double B, double C){
return (B+std::sqrt(B*B-4*A*C))/(2*A);
}

Point intercept(Point const &shooter, double bullet_speed, Point const &target, Vector const &target_velocity){
double a = bullet_speed*bullet_speed - target_velocity.dot(target_velocity);
double b = -2*target_velocity.dot(target-shooter);
double c = -(target-shooter).dot(target-shooter);

return target+largest_root_of_quadratic_equation(a,b,c)*target_velocity;
}

Vector shoot_at(Point const &shooter, Point const &interception, double bullet_speed){
Vector v = interception-shooter;
return bullet_speed/std::sqrt(v.dot(v))*v;
}

int main(){
Point shooter(0,0);
Point target(0,10);
Vector target_velocity(3,0);
double bullet_speed = 5.0;

Point P = intercept(shooter,bullet_speed,target,target_velocity);
Vector V = shoot_at(shooter,P,bullet_speed);

std::cout << "Shoot in direction (" << V.x << ',' << V.y << ") and you'll hit the target at (" << P.x << ',' << P.y << ").\n";
}
[/code]
0

Share this post


Link to post
Share on other sites
Thanks alvaro, the code works fine and is better than my code. My math calculations start like this:
x1 + cosA = x2 + cosB
y1 + sinA = y2 + sinB
This goes into a second degree equation, also aCos() can be + or -. So I need to check 4 values for validity! That's very unoptimal!

Too bad don't have the math knowledge to understand this code :). Specifically, I've got to look up info about dot products. I would appreciate a math explanation or some equation showing what's going on here. A link is enough.

Could you also post the code for 3D?
0

Share this post


Link to post
Share on other sites
My code works as follows (I am afraid you have to understand the dot product to follow it):

Say the target is initially at position A with a velocity vector v and the shooter is at position B and not moving. At time t the target will be at (A+t*v). We'll try to find the time t at which we can hit the target with a projectile. That value of t satisfies that the distance between (A+t*v) and B is t times the projectile's speed, s.

distance(A+t*v,B) = t*s

The distance between two points is the length of the vector between them (A+t*v-B), and the length of a vector is the square root of the dot product of the vector with itself.

sqrt((A+t*v-B).(A+t*v-B)) = t*s

We can square both sides of the equation to make it easier to deal with (although this type of manipulation often introduces new solutions, so be careful...).

(A+t*v-B).(A+t*v-B) = t^2*s^2
(A-B+t*v).(A-B+t*v) = t^2*s^2


The dot product is [url="http://en.wikipedia.org/wiki/Dot_product#Properties"]bilinear[/url], so we can do:
(A-B).(A-B)+t^2*(v.v)+2*t*((A-B).v) = t^2*s^2

(s^2-(v.v))*t^2 - (2*((A-B).v))*t - (A-B).(A-B) = 0

This is now a quadratic equation in t, which has too solutions. [s]The larger solution is the one we are interested in. I think you can look at the smaller solution as the time at which the target could have shot at you if you were to be hit now.[/s] [EDIT: Any positive solution will work. If you simply take the larger solution of the two, you are guaranteed it will be positive as long as the bullet is faster than the target.]

Once we know the value of t, it's easy to compute A+t*v to find out where the target is going to be hit, and we just have to shoot towards that point.

Notice that the procedure I just described doesn't depend on the dimension of the space in which we are moving, so it can be applied to 3D as easily as to 2D. The modifications to my code in order to do that are fairly obvious, and I think you should try to make them yourself. Just change the definitions of Vector and Point (and the basic methods and functions to deal with them) so there is an extra component z, which is treated just like the others. The functions largest_root_of_quadratic_equation, intercept and shoot_at remain exactly as they are.

If you are serious about game development, you should try to get familiar with linear algebra, including low-dimensional vector spaces, matrices as linear mappings, dot product, orthogonal projection and probably quadratic forms, while you are at it.
1

Share this post


Link to post
Share on other sites
alvaro,
what is your reason to have both, point and vector, instead of a single class?
0

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
alvaro,
what is your reason to have both, point and vector, instead of a single class?


I also have both types. The reason being: type safety in mathematical expressions.

In my experience, I was almost(*) always able to distinguish logically wheater a variable is a position or an offset. Logically, you would make all the math computations on vectors (meaning: offsets in space, n-dim distances). Position is meant as a placement unit (**).
You would never:
- add two positions
- normalize position (as opposed to direction vector)
- take dot/cross product of position/position or position/vector
- scale position (unless for graphic purposes, but that should be done by affine matrices anyway)


---------------

(*) the only exception was when I was tweaking projection-matrix, and un-projecting screen-positions - affine w wasn't equal to 0 or 1.

(**) It's similar to what iterators mean in std containers. There's an iterator and a distance unit.
iterator1 - iterator2 = distance.
iterator * 2 // error
iterator1 + (iterator2 - iterator3) * 2 // ok
0

Share this post


Link to post
Share on other sites
I've analyzed the code and the math. One thing I don't understand is why are we interested in the largest quadratic root. The rest I understood. The way I think about vectors has changed (well, I haven't learnt much about them before). I've modified the code to work with 3D enviroment, but I'm not 100% sure it's correct.


#include <iostream>
#include <iomanip>
#include <cmath>
#include <ctime>
using namespace std;

class Vector {
double x, y, z;
public:
Vector();
Vector(double x, double y, double z);

friend ostream &operator<<(ostream &stream, const Vector &v);
friend Vector operator+(const Vector &v1, const Vector &v2);
friend Vector operator-(const Vector &v1, const Vector &v2);
friend Vector operator*(const double &m, const Vector &v);
friend Vector operator*(const Vector &v, const double &m);
friend double operator%(const Vector &v1, const Vector &v2);
};

Vector::Vector()
{
}

Vector::Vector(double x, double y, double z): x(x), y(y), z(z)
{
}

ostream &operator<<(ostream &stream, const Vector &v)
{
stream << '(' << v.x << ',' << v.y << ',' << v.z << ')';
return stream;
}

Vector operator+(const Vector &v1, const Vector &v2)
{
return Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
}

Vector operator-(const Vector &v1, const Vector &v2)
{
return Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
}

Vector operator*(const double &m, const Vector &v)
{
return Vector(m * v.x, m * v.y, m * v.z);
}

Vector operator*(const Vector &v, const double &m)
{
return Vector(m * v.x, m * v.y, m * v.z);
}

double operator%(const Vector &v1, const Vector &v2)
{
return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
}

Vector intercept(const Vector &p_shooter, double bullet_speed, const Vector &p_target, const Vector &v_target)
{
Vector BA = p_target - p_shooter;
double vxv = v_target % v_target;
double b = BA % v_target;
double a = bullet_speed * bullet_speed - vxv;
return p_target + (b + sqrt(b*b + a * (BA%BA))) / a * v_target;
}

Vector shoot_at(const Vector &p_shooter, const Vector &p_interception, double bullet_speed)
{
Vector v = p_interception-p_shooter;
return bullet_speed/sqrt(v%v) * v;
}

int main()
{
unsigned int c, n;
unsigned int EVENT_COUNT;
bool q;

// ask the user
cout << "Enter number of shots to calculate: " << endl;
cin >> EVENT_COUNT;

// allocate the memory
cout << "allocating memory" << endl;
Vector *p_shooter = new(nothrow) Vector[EVENT_COUNT];
Vector *p_target = new(nothrow) Vector[EVENT_COUNT];
double *bullet_speed = new(nothrow) double[EVENT_COUNT];
Vector *v_target = new(nothrow) Vector[EVENT_COUNT];
Vector *p_hit = new(nothrow) Vector[EVENT_COUNT];
Vector *v_shoot = new(nothrow) Vector[EVENT_COUNT];
if(!p_shooter || !p_target || !bullet_speed || !v_target || !p_hit || !v_shoot)
{
cout << "failed!" << endl;
return 1;
}
else cout << "completed" << endl;

// randomize timer
cout << "randomize_timer: 1 second" << endl;
c = clock() + 1000;
while(clock() < c) rand();
cout << "randomize_timer completed\n" << endl;

// simulate EVENT_COUNT shots
cout << "calculating " << EVENT_COUNT << " events" << endl;
c = clock();
for(n = 0; n < EVENT_COUNT; n++)
{
*p_shooter = Vector((rand() % 101) - 50, (rand() % 101) - 50, (rand() % 101) - 50);
*p_target = Vector((rand() % 101) - 50, (rand() % 101) - 50, (rand() % 101) - 50);
*bullet_speed = (rand() % 5) + 10;
*v_target = Vector((rand() % 7) - 3, (rand() % 7) - 3, (rand() % 7) - 3);
*p_hit = intercept(*p_shooter, *bullet_speed, *p_target, *v_target);
*v_shoot = shoot_at(*p_shooter, *p_hit, *bullet_speed);
p_shooter++; p_target++; bullet_speed++; v_target++; p_hit++; v_shoot++;
}
cout << "calculation finished in " << clock() - c << " milliseconds" << endl;

// ask the user
cout << "do u want to see the results? (1/0)" << endl;
cin >> q;
if(!q) return 0;

// display 4xEVENT_COUNT lines of bulk data
cout << "displaying calculations:" << endl;
p_shooter -= EVENT_COUNT; p_target -= EVENT_COUNT; bullet_speed -= EVENT_COUNT; v_target -= EVENT_COUNT; p_hit -= EVENT_COUNT; v_shoot -= EVENT_COUNT;
for(n = 0; n < EVENT_COUNT; n++)
{
cout << clock();
cout << "shooter loc: " << *p_shooter << ", target loc: " << *p_target << '\n';
cout << "bullet's speed: " << *bullet_speed << ", target dir " << *v_target << '\n';
cout << "shoot dir: " << *v_shoot << ", intercept loc: " << *p_hit << '\n' << endl;
p_shooter++; p_target++; bullet_speed++; v_target++; p_hit++; v_shoot++;
}

return 0;
}



The Vector and the Point is now combined, also operator% is used as the dot product. I've made optimizations where I could. The results are quite satisfactory: on my PC one million of these calculations take only one second. Thanks alvaro, your help is greatly appreciated!

There's something I concluded from this. Geometry sucks! :)
0

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
alvaro,
what is your reason to have both, point and vector, instead of a single class?


Deffer's explanation is correct, but I'll add a little bit to it.

A correct mathematical framework for dealing with this type of problems is Affine Geometry. Vectors are things that we can add, substract and scale (multiply by scalars), with these operations satisfying some basic axioms. Affine space is defined as a set of points, together with a vector space and an "action" of the vectors on the points. That "action" is the operation of adding a vector to a point, with the result being another point. Again there are some axioms that have to be satisfied, basically saying that from any point we can get to any other point by adding an appropriate vector, and that from a given point we will get to different points if we add different vectors.

In any case, although you end up representing both vectors and points as triplets of numbers (in the case of dimension 3), they are definitely not the same thing. Where you place the origin in your space is not important, and it shouldn't change the result of any computations. In the case of vectors, though, the vector (0,0,0) is very special in the sense that you can add it to any point and you get back the same point. There is a natural opposite of a vector, but not for a point: the opposite of "going North 10 feet" is "going South 10 feet", but what is the opposite of the spot where my dog is? The list goes on and on. Keeping separate classes for vectors and points prevents you from accidentally performing many of those meaningless computations.

0

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer(*) the only exception was when I was tweaking projection-matrix, and un-projecting screen-positions - affine w wasn't equal to 0 or 1.


Actually, thinking of vectors as points with a last homogeneous coordinate of 0 and thinking of points as points with a last homogenous coordinate of 1 is not exactly correct. When you use homogenous coordinates, two sets of coordinates that are proportional to each other refer to the same point. These are the coordinates used in Projective Geometry, which is very convenient to use if you are going to be dealing with projections. You can look at affine space as a subset of projective space, for instance looking at the points [x,y,z,w] with w=1 (which is to say w!=0, since you can scale the coordinates however you want). In that case, the points [x,y,z,0], which are not affine points, are not exactly vectors either; they are points at infinity, which can be thought of as something like the points where sets of parallel lines meet. For instance, [1,0,0,0] and [2,0,0,0] are the exact same point (they indicate the direction of the x axis), but (1,0,0) and (2,0,0) are not the same vector.

The points with w different from 0 and 1 are just regular points in projective space. If you want to look at them in their more familiar affine version, you need to divide every coordinate by the w coordinate so you get back your common [x,y,z,1] type of points (or [x,y,1] if you are on 2 dimensions at this point, since you said you were projecting).

Ok, that didn't come out very clear. I guess it's too much information to put in so little space or to explain in so little time. I took an entire year of Projective Geometry in college, and at the beginning it wasn't very intuitive, but with time you realize that there is some deep truth behind this way of thinking.

[Edited by - alvaro on July 4, 2006 9:05:07 AM]
0

Share this post


Link to post
Share on other sites
I have to bring this topic back from the dead, because I'm using the equotion from this post and I have a question about it. I was getting constant crashes in my simulation recently and I could narrow the source down to my getInterceptDir-function. Apparently, some of my projectiles are too slow to actually intercept their target. I need to do a check first, I guess. So my question is: how can I tell wether interception is possible or not?
0

Share this post


Link to post
Share on other sites
At some point you are solving a quadratic equation and using sqrt(). If you would be taking the square root of a negative number, no interception is possible. If the solutions of the quadratic equation are both negative, there is no interception.
1

Share this post


Link to post
Share on other sites
[quote name='alvaro' timestamp='1307805832' post='4822104']
At some point you are solving a quadratic equation and using sqrt(). If you would be taking the square root of a negative number, no interception is possible. If the solutions of the quadratic equation are both negative, there is no interception.
[/quote]

So if the expression inside the sqrt() is negative, theres no interception? That's simple enough. Thank you as always. After having finished my diploma thesis a few weeks ago, I also finally got around to implementing your intercept-equations and polynomial-root-finder (the ones you wrote for me about half a year ago or so...). Now interception with accelerating and steering interceptors works as well - and very fast, too. Thanks again!
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0