|
|
| Thrust, ship movement 'Asteroids' style |
|
krazak
Member #9,908
June 2008
|
As part of my efforts to learn C++ I decided to attempt an asteroids clone of sorts. Anyways, here is the code(No doubt it is messy as hell, I figured once I got a working model, I would optimise/put things in structs/comment/etc):
Any help would be most appreciated! This is stopping me from learning further! |
|
StevenVI
Member #562
July 2000
|
The sin and cos functions take arguments in radians. Multiply your angles by 3.141592654/180.0 to convert from degrees to radians. __________________________________________________ |
|
krazak
Member #9,908
June 2008
|
I tried this: With this: rotate_sprite(temp, ship, 0,0,(ship_angle * radtofix_r)); And now the ship simply flies upwards, no matter what the rotation, so something is making ship_angle = 0. :S |
|
SiegeLord
Member #7,827
October 2006
|
Quote: so something is making ship_angle = 0
That something is the code you just posted. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
You should use a separate variable for the ship's angle in radians and another for the ships angle in allegro fixed degrees. This way you can change the ships angle in degrees the way you like it and convert it when you need to. ship_angle = (ship_angle * (M_PI/180.0)); Isn't going to do what you want. It will continually decrease your ships angle because you're altering the variable you're supposed to be storing your degree angle in. Alter your angle in degrees as you like but then convert it when you need to , storing the values in different variables. const float deg_to_rad = M_PI/180.0; const float rad_to_afix_degrees = 128.0/M_PI; const float deg_to_afix = 256.0/360.0; float ship_angle_degrees = 0.0; float ship_angle_rad = ship_angle_degrees*deg_to_rad; float ship_angle_afix = ship_angle_degrees*deg_to_afix; Since you want to limit the ships overall speed , it would be nicer to keep a variable just for that. To prevent changing direction of movement when limiting the speed , find the absolute speed first from your altered x and y velocities , reduce the absolute speed if necessary and then refind your x and y velocities. You might also want to limit the degree angle your ships can travel to between [0.0,360.0) degrees by adding or subtracting 360.0 degrees as necessary. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
krazak
Member #9,908
June 2008
|
Ok I tried to figure it out myself with the excellent advice from you guys, but I'm still at a pass! Now I can't seem to get the ship to accept modifications to its current angle value! float ship_x = 400; float ship_y = 340; float ship_accel = 0.01; float ship_yspeed = 0; float ship_xspeed = 0; const float deg_to_rad = M_PI/180.0; const float rad_to_afix_degrees = 128.0/M_PI; const float deg_to_afix = 256.0/360.0; float ship_angle_degrees = 360.0; float ship_angle_rad = ship_angle_degrees * deg_to_rad; float ship_angle_afix = ship_angle_degrees * deg_to_afix;
//Update ship location ship_y = ship_y + ship_yspeed; ship_x = ship_x - ship_xspeed; if (ship_angle_degrees > 360) ship_angle_degrees = 0; // == Draw objects == draw_sprite(buffer, bg, 0,0); rotate_sprite(temp, ship, 0, 0, ship_angle_afix); draw_trans_sprite(buffer, temp, ship_x,ship_y);
|
|
Jonatan Hedborg
Member #4,886
July 2004
|
Without reading all posts, I thought I should point out that the last argument to rotate_sprite should be a "fixed", not a float. Do an ftofix, and obviously you need to update ship_angle_afix each frame. You may want to take a look at the manual.
|
|
krazak
Member #9,908
June 2008
|
I did notice that it reqested a fixed and was getting a float, the compiler gave me warnings, but as they were just warnings, not errors, I thought it might be capable of taking float as well, I'll try ftofix, though I'm pretty sure I've tried it before, I'm at least certain I tried itofix when I had ship_angle as an integer. EDIT: Just tried it, also put ftofix(ship_x) and same for ship_y in the draw_trans_sprite line, this caused the sprite to not be drawn at all. This is a mindbuggerer this little project is. EDIT EDIT: float ship_angle_afix = ship_angle_degrees * deg_to_afix; |
|
Jonatan Hedborg
Member #4,886
July 2004
|
No. That just initiates the variable to whatever that evaluates to at that point. A variable is just a number, nothing more. Maybe you should brush up on your C/C++ while you are at it And once again, please read the manual.
|
|
krazak
Member #9,908
June 2008
|
I never claimed to be even close to proficient at C, thats why I'm doing this project, and why I'm asking for help! Also I've read the manual for every function used in the posted code. I feel like you just want to shoot me down instead of help me understand whats wrong Are you saying that instead of float ship_angle_afix = 0; void update_anglefix() { ship_angle_afix = ship_angle_degrees * deg_to_afix; } and call it before using ship_angle_afix? That it simply calculates ship_angle_degrees * deg_to_afix when it is declared, and returns that float, instead of returning ship_angle_degrees * deg_to_afix? |
|
supermario
Member #4,862
July 2004
|
There was a pixelate article that was exactly about this subject (learning sin and cos), maybe you could search for it. Though its probably hard to find now. |
|
Vanneto
Member #8,643
May 2007
|
In capitalist America bank robs you. |
|
Schyfis
Member #9,752
May 2008
|
What you're trying to do can be accomplished with something like this:
Mess with the rotation+90 if the ship isn't facing the right way. ________________________________________________________________________________________________________ |
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Quoted from your last post : These two lines are incorrect, you were closer before. As Harry Carey said , the sin and cos functions take a single argument of the angle in radians and return a ratio from -1 to 1. This ratio is what you want to multiply your acceleration by to find it's x and y components so you can add them to your velocity. After you add them , find the combined speed and if it is more than you wish to allow , reduce and re-figure your x and y velocities from it. Also your sin and cos calls were backwards , cos gives you the x value and sin gives you the y value :
I introduced some new variables , 'ship_total_speed' , 'ship_max_speed' , 'ship_bearing_angle_rad' , and 'ship_heading_angle_rad'. Since your ship isn't always moving the same direction that it is facing , it is better to track the two angles separately. Heading is the direction it is moving and bearing is the direction it is facing. Your angle updates need a little work as well. When the user presses the key to adjust the angle , you should recalculate your angles in the other formats as well so that way they are never out of sync. Also , if the angle exceeds 360 degrees , you don't want to set it to 0 but rather subtract 360 degrees as necessary from it so the angle is equivalent. In this case your method may have the same effect since you only modify the degree angle by one at a time but if you ever plan to change the turn rate , you'll want to modify the angle by +- n*360 degrees instead of setting it to a constant value.
One last thing , the only time you need to use ftofix is when a fixed data type is called for. In this case that means in the call to rotate_sprite. // function parameters for rotate_sprite : // void rotate_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle); rotate_sprite(temp , ship , 0 , 0 , ftofix(ship_bearing_angle_afix)); // One last last thing , if any parts of your ship are outside a radius equal to the smaller value of (ship->w/2 , ship->h/2) then when you rotate it onto a bitmap of the same dimensions , part of it may be clipped. This can be worked around by using pivot_sprite onto a temporary bitmap that is square and has dimensions of : // float width = 2.0*(sqrt(((float)ship->w/2.0)*((float)ship->w/2.0) + ((float)ship->h/2.0)*((float)ship->h/2.0)); if ((width - (float)(int)width) != 0.0) { width = (float)( (int)width + 1 ); } const int temp_bmp_width = (int)width; BITMAP* temp = create_bitmap(temp_bmp_width , temp_bmp_width); // I know there's a lot here so if you have questions , feel free to ask. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
James Stanley
Member #7,275
May 2006
|
Quote:
float ship_angle_afix = ship_angle_degrees * deg_to_afix;
#define ship_angle_afix (ship_angle_degrees * deg_to_afix) |
|
Jonatan Hedborg
Member #4,886
July 2004
|
Stanley; Say after me! "I will not teach the newbies horrible programming practices"
|
|
James Stanley
Member #7,275
May 2006
|
Just to clarify, I wouldn't do that myself. |
|
Tobias Dammers
Member #2,604
August 2002
|
...while what you should have done is tell him not to do things like this. Anyway, my piece of advice: In your game logic, use radians as the ONLY format for your angles. Ever. The only situation where you ever touch fixed-point numbers, atofix, and allegro's 256-degrees format is when you absolutely have to. Which is at the very moment when you draw your rotated sprite. A simple conversion function is all you need: int radians_to_allegro_angle(double radians) { return ftofix(radians * 128.0 / M_PI); } // and in your drawing code: rotate_sprite(screen, sprite, (int)ship_x, (int)ship_y, radians_to_allegro_angle(ship_angle)); Everything else you do with angles is done using libm's trig functions, and they all consistently use radians (which, from a programming point of view, is the only choice that really makes sense). On a side note: Chunks of code like this one: float ship_x = 400; float ship_y = 340; float ship_accel = 0.01; float ship_yspeed = 0; float ship_xspeed = 0; ...just cry for a class (or at least a struct if you're in plain C): typedef struct { float x; float y; float angle; float accel; float xspeed; float yspeed; } SHIP; /* x y angle accel xspeed yspeed struct SHIP player_ship = { 400.0f, 340.0f, 0.0f, 0.01f, 0.0f, 0.0f }; Then later on, you access the members like this: player_ship.x += player_ship.xspeed * delta_t;
--- |
|
|