vectors in sprite-based space games
I''m only a sophmore in high school, so i havent had much math, though i can understand higher maths if needed. I''m trying to figure out how to control the vector and rotation of a spaceship sprite. I''d like to have two keys for left and right rotation, one for acceleration. if the player wants to stop the space ship, they would simply turn it around and accelerate in the opposite direction. I have 36 sprites, starting with a sprite at 0 degrees (straight) going right in increments of 10 til it spins all the way around. i dont know how to figure out which way i''m pointing by the keyboard input, and then i dont know how to apply acceleration along that direction. can someone please help me with the math and programming concepts involved?
I think there is a game for macintosh called Escape Velocity that is similar to what i want, though i haven''t played it in years. I am using the Win32 with the GDI, as i had a really hard time with directx and i dont think my game is large enough of a project to need its added speed, etc. i will learn it someday, and maybe if i use enough abstraction in this project i can apply it here later.
thanks
Brian
Brian J
ok...i''ll solve your acceleration problem first, then i''ll get to problem of "which sprite to render"...
we keep a number called angle, this is a floating point number in degrees. since you want to keep 36 different positions, you will increment it by 10 degrees when left key is pressed and decrement by 10 degrees when right key is pressed.
Now, we convert this angle into a vector using:
v=(cos(angle*PI/180),sin(angle*PI/180));
this will give you the unit direction of motion. Simplest way to move (not accelerate, i''ll get to that soon) is to multiply your speed to v (to get vector d=(speed*cos(angle*PI/180),speed*sin(angle*PI/180)). Now add this vector to your current position, and the object shall move correctly.
Now, to actually accelerate, you need to keep a velocity vector. Each time a key is pressed, you add d to velocity vector instead of directly to position, and then add velocity vector to position. Then you have to reduce speed (using friction). But that doesnt apply in space...so i''ll leave that for now. Rather, use a maximum speed beyond which acceleration is not allowed. This is done by computing
velocity (dotproduct) velocity=velocity.x*velocity.x + velocity.y*velocity.y+velocity.z*velocity.z
this is square of the length of the velocity vector (i.e. square of your speed)...if this is greater than some maximum, you donot add the acceleration vector.
You probably also need a means to decelerate (say down key on keyboard)... rather than adding acceleration, subtract it and the same maximum applies (the length of a vector is unsigned).
Ok, bored yet? there''s just a tiny bit more to come...
Now that we have an angle stored, we can use it to determine which image to use...just take image[(int)(angle/10)] and it''ll do it.
One last thing...to control your drawing (in order to not draw too much and save frame rate), use a Quad Tree... it''ll be hard to explain everything at once, but may be you can find some tutorials on that..
we keep a number called angle, this is a floating point number in degrees. since you want to keep 36 different positions, you will increment it by 10 degrees when left key is pressed and decrement by 10 degrees when right key is pressed.
Now, we convert this angle into a vector using:
v=(cos(angle*PI/180),sin(angle*PI/180));
this will give you the unit direction of motion. Simplest way to move (not accelerate, i''ll get to that soon) is to multiply your speed to v (to get vector d=(speed*cos(angle*PI/180),speed*sin(angle*PI/180)). Now add this vector to your current position, and the object shall move correctly.
Now, to actually accelerate, you need to keep a velocity vector. Each time a key is pressed, you add d to velocity vector instead of directly to position, and then add velocity vector to position. Then you have to reduce speed (using friction). But that doesnt apply in space...so i''ll leave that for now. Rather, use a maximum speed beyond which acceleration is not allowed. This is done by computing
velocity (dotproduct) velocity=velocity.x*velocity.x + velocity.y*velocity.y+velocity.z*velocity.z
this is square of the length of the velocity vector (i.e. square of your speed)...if this is greater than some maximum, you donot add the acceleration vector.
You probably also need a means to decelerate (say down key on keyboard)... rather than adding acceleration, subtract it and the same maximum applies (the length of a vector is unsigned).
Ok, bored yet? there''s just a tiny bit more to come...
Now that we have an angle stored, we can use it to determine which image to use...just take image[(int)(angle/10)] and it''ll do it.
One last thing...to control your drawing (in order to not draw too much and save frame rate), use a Quad Tree... it''ll be hard to explain everything at once, but may be you can find some tutorials on that..
Well, i''ll reapeat what he said. But summarize it and make it more practical to be sure you do it right.
the data needed for the ship:
x
y
angle
speed_x
speed_y
and a constant ''MaxSpeed''
When pressing ''left'' or ''right'':
just add or substract a certain value from angle, and rearange if needed sa that the value is between 0 and 359.
When you press ''up'' then:
angleInRadians = angle*PI/180
new_speed_x = speed_x + A*cos(angleInRadians)
new_speed_y = speed_y + A*sin(angleInRadians)
//(where A is a constant arbitrary value for acceleration)
After this, check if the new velocity isn''t too fast.
if (new_speed_x² + new_speed_y² <= MaxSpeed)
{
speed_x = new_speed_x
speed_y = new_speed_y
}
else
{
// too fast*
}
*here, there are 2 possibilities:
1) the unaccurate and simple:
Just don''t modify the speed values.
2) the accurate and more complicated:
Or modify it respecting the max. speed like this:
speed_x = new_speed_x / (new_speed_x² + new_speed_y²)^(1/2) * MaxSpeed
speed_y = new_speed_y / (new_speed_x² + new_speed_y²)^(1/2) * MaxSpeed
Each time you want to calculate the new position of the ship, just add the velocity to it''s coordinates.
x = x + speed_x
x = y + speed_y
Note: it''s sometimes a good choice to choose decimal format for x & y and then round it to an int when drawing. (A matter of accuracy)
cheers
the data needed for the ship:
x
y
angle
speed_x
speed_y
and a constant ''MaxSpeed''
When pressing ''left'' or ''right'':
just add or substract a certain value from angle, and rearange if needed sa that the value is between 0 and 359.
When you press ''up'' then:
angleInRadians = angle*PI/180
new_speed_x = speed_x + A*cos(angleInRadians)
new_speed_y = speed_y + A*sin(angleInRadians)
//(where A is a constant arbitrary value for acceleration)
After this, check if the new velocity isn''t too fast.
if (new_speed_x² + new_speed_y² <= MaxSpeed)
{
speed_x = new_speed_x
speed_y = new_speed_y
}
else
{
// too fast*
}
*here, there are 2 possibilities:
1) the unaccurate and simple:
Just don''t modify the speed values.
2) the accurate and more complicated:
Or modify it respecting the max. speed like this:
speed_x = new_speed_x / (new_speed_x² + new_speed_y²)^(1/2) * MaxSpeed
speed_y = new_speed_y / (new_speed_x² + new_speed_y²)^(1/2) * MaxSpeed
Each time you want to calculate the new position of the ship, just add the velocity to it''s coordinates.
x = x + speed_x
x = y + speed_y
Note: it''s sometimes a good choice to choose decimal format for x & y and then round it to an int when drawing. (A matter of accuracy)
cheers
thanks that answered a ton of my questions! i have been wondering for a couple of months how to round numbers...i cant believe using and (int) typecast never occured to me. and no math doesnt bore me as long as i understand it! in my case, my understanding is sort of limited when it comes to trig, etc.
Here are a few things i dont understand. i looked up what a dot product was but i dont understand how it applies to this. i dont understand the stuff about squaring the speed. why is this important? couldn''t i just do like the absolute value or something?
also about the deceleration. part of my concept is that there is no deceleration, but you can accelerate in any direction. since you can accelerate in the opposite way, you can decelerate this way. I want to do this so you can travel in one direction and still shoot in any other direction. so what you described to me will work fine without a deceleration feature. thanks alot, both posts have been infinitely helpful.
oh yeah i didn''t understand the second method:
speed_x = new_speed_x / (new_speed_x² + new_speed_y²)^(1/2) * MaxSpeed
speed_y = new_speed_y / (new_speed_x² + new_speed_y²)^(1/2) * MaxSpeed
if this is too complicated to explain, dont sweat it. I think that i can just not add to the vector if it will exceed the speed.
Here are a few things i dont understand. i looked up what a dot product was but i dont understand how it applies to this. i dont understand the stuff about squaring the speed. why is this important? couldn''t i just do like the absolute value or something?
also about the deceleration. part of my concept is that there is no deceleration, but you can accelerate in any direction. since you can accelerate in the opposite way, you can decelerate this way. I want to do this so you can travel in one direction and still shoot in any other direction. so what you described to me will work fine without a deceleration feature. thanks alot, both posts have been infinitely helpful.
oh yeah i didn''t understand the second method:
speed_x = new_speed_x / (new_speed_x² + new_speed_y²)^(1/2) * MaxSpeed
speed_y = new_speed_y / (new_speed_x² + new_speed_y²)^(1/2) * MaxSpeed
if this is too complicated to explain, dont sweat it. I think that i can just not add to the vector if it will exceed the speed.
Brian J
quote:
Here are a few things i dont understand. i looked up what a dot product was but i dont understand how it applies to this.
The dot product is a mathamatical operation performed on two vectors. x1x2+y1y2+z1z2 (of course, if you''re working in 2D, you can consider z1 and z2 0, in which case they can be ignored). However, it''s used in many different ways depending on what your vectors represent. For example, if one of your vectors represents a plane normal and the other one represents a point, it just so happens that the dot product returns the distance from that point to the plane. If your vectors are both normalized, then it just so happens that the value returned is the cosine of the angle between then. Yet in this case, we are simply using the dot product for the raw math it performs, without any other types of interpretation.
quote:
i dont understand the stuff about squaring the speed. why is this important? couldn''t i just do like the absolute value or something?
Pythagorean Theorum - a2 + b2 = c2
If a and b are our x and y velocities, we can sum their squares and get c2, which is the square of the actual speed. However, in order to get the actual speed itself, we need to perform a square root. Here''s the big kahuna. Square roots are slow and expensive and should be avoided when not needed. In this case, all we care about is the relationship between the x, y, and the speed, which is exactly what the Pythagorean Theorum provides. If we store our max speed in it''s squared form (so instead of 20, we store 400), then the relationship holds true and works well. That part wasn''t explained very well so I thought I should help out

quote:
oh yeah i didn''t understand the second method:
speed_x = new_speed_x / (new_speed_x² + new_speed_y²)^(1/2) * MaxSpeed
speed_y = new_speed_y / (new_speed_x² + new_speed_y²)^(1/2) * MaxSpeed
I was first confused as to what this did, but then realized that I was just doing the wrong order of operations. If there aren''t any parenthesis and the operators have equal precedence, then you do it from left to right in order.
Remember how I said that the pythagorean theorum can be used to find the actual speed of the ship? Well, (new_speed_x² + new_speed_y²)^(1/2) represents that speed. So when we do new_speed_x / (new_speed_x² + new_speed_y²)^(1/2), we are finding the ratio between the x speed and the ships absolute speed. Since the x speed can never be larger the the ships absolute speed (Pythagorean Theorum can prove that too), the result of that operation is always within the interval [-1, 1]. When we multiply that by MaxSpeed, we get a number that is between -MaxSpeed and MaxSpeed. The whole operation basically scales your speeds so that the ship can easily reach the whole range of its maximum speeds. However I do believe there is a mistake is what he posted. He should have done (MaxSpeed)^(1/2) as well, since we are working with actual speeds, and not just the relationships anymore.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement