You are not logged in.
I'm writing something resembling a very simple game with SDL. I have the player's sprite at the bottom of the screen and a projectile positioned elsewhere. My question is as follows: how do I set the projectile's x and y velocities so that it heads for the player, based on their relative positions?
The game loop is written such that every frame, each object's x and y positions are incremented by its respective velocities. I've already figured out how to set up movement where the projectile reaches the player in a given number of frames:
/* 90 is the frames per second, so transit time is one second */
projectile.velocity_x = (player.position_x - projectile.position_x) / 90;
projectile.velocity_y = (player.position_y - projectile.position_y) / 90;
However, I'd like the projectile's speed to be the constant here, not the time it takes to reach the player. How would I do this? I can't seem to wrap my head around it.
Last edited by Peasantoid (2009-08-18 21:22:00)
Offline
Wouldn't you just calculate the vector from the projectile's current location to the player? And then send the projectile that way?
((player.position_x - projectile.position_x)^2+(player.position_y - projectile.position_y)^2)^.5 / projectile.velocity = time_to_target
Or some such? It's easier if you have sin cos tan, and their inverses if you need components.
Offline
Sorry, I haven't done any geometry in a crazy long time...
(I have no idea what that code does.)
Last edited by Peasantoid (2009-08-18 03:52:04)
Offline
majiq's code calculates the time to the target using the Pythagorean theorem to get the distance (a^2 + b^2 = c^2, where a and b are the legs and c is the hypotenuse) and the fact that the time is equal to the distance divided by the speed (a.k.a. "magnitude of the velocity").
This is easier in terms of vectors.
Imagine that you have an arrow drawn from your projectile to the player. This is a position vector that gives the position of the player relative to the projectile. It has an x component (dist_x = player.position_x - projectile.position_x) and a y component (dist_y = player.position_y - projectile.position_y). Let's denote the vector as (dist_x, dist_y). The total distance is (dist = (dist_x^2 + dist_y^2)^0.5), using the Pythagorean theorem as mentioned above. The total distance (dist) is the magnitude of the vector, i.e. its size.
Now, to aim the projectile at the player, you need to have a velocity vector (think of an arrow) which points at the player from the projectile and which has a magnitude equal to the constant speed that you want. To create this, you can use a unit vector. A unit vector is just a vector with a magnitude of 1. To create a unit vector, you divide each vector component by its own magnitude.
In this case, you want the velocity vector to point in the same direction as the position vector above, so you need to divide each component of the position vector by (dist) and then multiply them by the projectile's speed (speed), i.e.
projectile.velocity_x = speed * dist_x/dist
projectile.velocity_y = speed * dist_y/dist
The projectile will then be headed directly towards the player with the given speed.
Last edited by Xyne (2009-08-18 05:06:10)
My Arch Linux Stuff • Forum Etiquette • Community Ethos - Arch is not for everyone
Offline
I'm going to try to clarify things a little bit. BUT, if you are trying to write any 3d games, you NEED to know geometry, specifically vector calculus. If you have access to a library or don't mind splashing about £40 quid out, then I recommend engineering mathematics by K. Stroud. It's a good foundation, and he has a followup to it, Advanced Engineering Mathematics.
In 3D space, you use a vector to describe the position of an object relative to the position of another. In this case a vector consists of 3 elements, [X, Y, Z], depending on your coordinate system. A vector contains 2 components, direction and length. That means that not only does it tell you which direction to move in, but it also tells you how far to move.
Positions are usually described relative to the coordinate axes you are using, so an object at [1,1,1] is 1 unit distance in each direction from the centre of the axes. It's actual distance (or the length of the vector) from this point is calculated as sqrt ( 1^2 + 1^2 + 1^2) since 1^2 is 1. This is the sqrt(3).
This is all relative to the axes, but you can determine the relative position of the object from another object in the same space. It's easy, you just subtract each element of the set X, Y and Z from the second object from those of the first.
So if you have an object at [2,2,2] and you want to find it's position relative to the first object at [1,1,1], you subtract [1,1,1] from [2,2,2]. Leaving you with [1,1,1]. It's easy. BUT, this operation is not commutative, ie. the order matters. If you do it the wrong way round you will end up with an incorrect result. This is because a vector is directional.
A unit vector is a vector for which the sum of the individual components is 1, in this case this is precisely what you are looking for, as you may have a projectile whose speed is 5 m/s so you want to be able to add 5 * [X, Y, Z] to it's position. You can't do this with a normal vector, so you have to divide it by it's length. Again you calculate the length of the vector by using length = sqrt( X^2 + Y^2 + Z^2).
So, to sum up. To have your projectile move along a fixed trajectory at a fixed speed, you first need to calculate the unit vector. Once you have that you can add this, or any multiple of this you want, in each time interval.
Offline
Thanks everyone — couldn't be clearer.
(SiC: I was going to ask about 3D vectors, but you beat me to it.)
Last edited by Peasantoid (2009-08-18 21:32:07)
Offline