Angle Shooting

Started by
11 comments, last by os3330 16 years ago
I'm trying to figure out how to shoot based on the character's angle. Every time a player or enemy shoots, a bullet is created right in front of them and then moves off on its own. Right now, I'm only checking for 0 and 180 (up and down). And the code on that is pretty long (one for X and Y). Is there a mathematical function to do this easily?
Advertisement
look into using sin and cos
Trig isn't my specialty, but I'll take a shot.

I got this (the Bullet class takes care of positioning):
offset.x = ( character->get_x_pos() ) - static_cast<Sint16>( ( offset.w / 2 ) * sin( angle ) );offset.y = ( character->get_y_pos() ) - static_cast<Sint16>( ( offset.h / 2 ) * cos( angle ) );
It's a bit off (at 315 degrees, it shows up lower than the firing point). I have to incorporate this into the shooting function.
Now I have to calculate the bullet's trajectory based on angle. I plan to go by 45 degree increments.

Here's the code. Correct me if anything is wrong.
// Sets the X and Y velocity based on angle.void set_velocity( int newVel ){	// If the angle is a multiple of 180, the Y velocity is zeroed.	if ( angle % 180 == 0 ) {		yVel = 0;		xVel = newVel;	}	// If the angle is only a multiple of 90, the X velocity is zeroed.	else if ( angle % 90 == 0 ) {		xVel = 0;		yVel = newVel;	}	// If it's any other angle, set both velocities.	else {		xVel = newVel;		yVel = newVel;	}}
Look into vector math. What you're doing can be simplified a lot. Besides, your code is only correct for 0/90/180/270-degree angles. You really should investigate vector math as it can save you a lot of time and hassle later on.

Anyway:
void set_velocity(int newVel){	float factor = newVel / sqrt(xVel * xVel + yVel * yVel);	xVel *= factor;	yVel *= factor;}
What happens here is that you divide your x and y components by the current velocity (the length of this vector) and you then multiply it by the new velocity. In other words, you first set the length of your velocity to one - it keeps it's angle but not it's length - and then it's as easy as multiplying both by the new velocity - so the length will be newVel, because 1 * newVel is newVel.
Create-ivity - a game development blog Mouseover for more information.
Ah, vector math. Unfortunately, my velocity has to be in whole number integers (because a velocity of one means one pixel per frame).

So if I had xVel = 2 and yVel = 3, using your formula would yield a factor of 6. Thus, the newVel parameter has to be bigger than or equal 12 to make any real difference.

Is there a way to move every few or so frames so I can get a more accurate velocity calculation?
why does it have to be an integer? If it's for rendering then you can round the floats to an integer if that's necessary.

http://en.wikipedia.org/wiki/Unit_circle

See the vector produced from an angle. (cos(angle), sin(angle)) that's a unit vector. To get velocity for a bullet you can multiply it by a scalar like:
(cos(angle) * speed, sin(angle) * speed)

Depending on how you set things up if the y is reversed then:
(cos(angle), -sin(angle))
and
(cos(angle) * speed, -sin(angle) * speed)
Quote:Unfortunately, my velocity has to be in whole number integers (because a velocity of one means one pixel per frame).

No it doesn't. The screen is not the game world, the screen is a view of the game world; there's nothing wrong with your object being at (0.6, 1.4) and your display showing it at (1, 1) ... although with most graphics libraries you could draw it at (0.6, 1.4) anyway.

I can only second the 'look at vector maths'. Object motion, particularly if you start modifying velocities in flight (gravity, homing missiles, air resistance, force fields etc etc), is extremely well described by simple vector operations.
And of course I can use vector math to determine the distance of the player through the enemy and shoot a bullet there.

It's a shame that SDL_Rect doesn't take decimals.
Okay, I've encountered another problem. Using my new velocity function, the objects jerk around or don't move at all. Nothing else has changed except the velocity functions.

Here's the code that changes the velocity:
// Sets the X and Y velocity based on angle. //void Character::set_x_vel( float newVel ){	// Calculates the unit vector. //	// Checks if lower denominator is zero.	float normal = sqrt( pow( xVel, 2 ) + pow( yVel, 2 ) );		if ( normal == 0 ) {		xVel = static_cast<float>( newVel * cos( to_radians( angle ) ) );	}	else {		float factor = newVel / normal;		xVel *= static_cast<float>( factor * cos( to_radians( angle ) ) );	}}void Character::set_y_vel( float newVel ){	// Calculates the unit vector. //	// Checks if lower denominator is zero.	float normal = sqrt( pow( xVel, 2 ) + pow( yVel, 2 ) );		if ( normal == 0 ) {		yVel = static_cast<float>( newVel * sin( to_radians( angle ) ) );	}	else {		float factor = newVel / normal;		yVel *= static_cast<float>( factor * sin( to_radians( angle ) ) );	}}
Is there anything wrong with my calculation of the unit vector?

This topic is closed to new replies.

Advertisement