Hey guys, How many of you have ever played a top down shooter? well I have and I've decided to make one. holds for applause BUT yo tengo uno problemo, I have a problem. I compile and it runs with no errors however my goal is to have my man rotate depending on the position of the cursor. the problem is he doestnt follow it, and only rotates a certain degree at the begining of the program and no more :T heres my source code 
| 1 | #include <allegro.h> |
| 2 | #include <math.h> |
| 3 | #include "PI.h" |
| 4 | int main() |
| 5 | { |
| 6 | int depth, res; |
| 7 | allegro_init(); |
| 8 | depth = desktop_color_depth(); |
| 9 | if (depth == 0) depth = 32; |
| 10 | set_color_depth(depth); |
| 11 | res = set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0); |
| 12 | if (res != 0) |
| 13 | { |
| 14 | allegro_message(allegro_error); |
| 15 | exit(-1); |
| 16 | } |
| 17 | install_timer(); |
| 18 | install_keyboard(); |
| 19 | install_mouse(); |
| 20 | BITMAP *crosshair = load_bitmap("crosshair.bmp",NULL); |
| 21 | BITMAP *ship = load_bitmap("deml.bmp",NULL); |
| 22 | BITMAP *buffer = create_bitmap(640,480); |
| 23 | int cY = -50; |
| 24 | int cX = -150; |
| 25 | int ship_X = 0; |
| 26 | int ship_Y = 0; |
| 27 | double player_angle; |
| 28 | set_mouse_sprite(crosshair); |
| 29 | show_mouse(screen); |
| 30 | player_angle = (atan2(mouse_y - ship_Y, mouse_x - ship_X)*128/PI + 20); |
| 31 | rotate_sprite(screen, ship, 50,100, itofix(player_angle)); |
| 32 | readkey(); |
| 33 | destroy_bitmap(ship); |
| 34 | destroy_bitmap(buffer); |
| 35 | destroy_bitmap(crosshair); |
| 36 | return 0; |
| 37 | } |
| 38 | END_OF_MAIN() |
I can't figure out what's wrong, of course I'm also terrible at allegro, so you guys do the math XD If you guys have any answers lemme know I'm eager to start developing this game
or if anyone knows of a good open-source game in the depot or else where programmed in allegro also let me know so I can take a look and see how the make the guy follow the cursor
Thanks for reading this post, and Thanks even more if you help!
You need to put it in a loop, or it will only execute those instructions once.
Prepare for image tearing when you use this code, as it is repeatedly drawing to the screen.
Thanks
but howcome It only rotates 128 degrees? instead of 256? I tried messing with the code but nothing changes it :T anyone got any ideas?
EDIT: Would using Pivot_sprite() be any better? and I have a question I read up about it in the allegro docs. and it says cY adn cX are where it pivots or something liek that, but when I set it to a random number ie cX = 10 & cY = 12 It wont rotate >.< I've also tried making the nubers larger smaller and the same nothing works coudl anyone trouble shoot me? btw schyf i took your advise to read up in the allegro docs GREAT IDEA
You've declared 'player_angle' as a double type variable, but you pass itofix(player_angle) as the value for the rotation parameter. Use ftofix instead.
same thing happens :T maye if i declared it as a floating point number? No idea what that would produce jsut an idea though
There are a couple things to watch out for there :
1. You're mixing integer literals with double type variables. It may be that the compiler has converted enough of the mixed expressions into double floating type values, but then you have to make sure you know operator precedence, and order of evaluation. It's far simpler to just use double floating point literal constants in your code by appending .0 to the numbers. Similarly, for a single floating point literal constant, add .0f to the integer literals.
2. <cmath> and <math.h> define M_PI for the value of pi as a const float or double with good precision. Favor using M_PI over user defined PI in most cases.
3. The trigonometry functions from <math.h> produce, and accept radian angles, and it makes sense to define some common conversion factors between radians, degrees, and allegro degrees.
// const double rad_to_deg = 180.0/M_PI;// 360.0/(2.0*M_PI); const double deg_to_adeg = 32.0/45.0;// 256.0/360.0; const double rad_to_adeg = 128.0/M_PI; //
4. Watch out for integer divisions, they will truncate the remainder. I don't think there are any in that code, but be aware of the possibility.
Would using Pivot_sprite() be any better?
Not until you find the source of the inaccurate value. What does the definition of your macro/symbol for PI give it for a value, and what type is it?
same thing happens :T maye if i declared it as a floating point number? No idea what that would produce jsut an idea though
It's fine to leave player_angle as a double type variable. If you call ftofix(double), the compiler can implicitly cast the double to a float and call ftofix((float)player_angle).
Post your current version of the whole code again, please. (It's also standard to indent your code X spaces for each block level, and it makes it much nicer to read. 3 spaces is usually good.)
heh, I got most of that such as declaring my floating point numbers and adding .0 onto the end so the computer doesnt give it a random decimal value HOWEVER I'm in eigth grade -.- and I have no Idea about any of the basic concepts of Trigonometry but from what I got AND just a guess is a tangent a decimal value inside of PI because PI is the radius of a circle? or am I totally off? and If im totaly off could you guys show me a site that explains the basics well? because 10th grade is about 2 years away for me and I dont feel like postponing this project for 2 weeks
Thanks Edgar for your help it explained alot
It'll probably explain mor ewhen I know what It means XD (well msot of it) Thanks
such as declaring my floating point numbers and adding .0 onto the end so the computer doesnt give it a random decimal value
It wouldn't be given a random decimal value, it would just be a different kind of literal constant. Take a look at http://web.mit.edu/1.124/LectureNotes/l2.html and scroll down to section 3, "C++ Data Types". The second table in that section lists different types of literal constants. So adding .0 onto the number makes it a double type literal constant.
and I have no Idea about any of the basic concepts of Trigonometry but from what I got AND just a guess is a tangent a decimal value inside of PI because PI is the radius of a circle?
The tangent of a radian angle is the ratio of the y component to the x component.

The arctangent is the inverse of the tangent function.


You can learn more about trigonometry at wikipedia and wikibooks.
Check out
The wikibook on Trigonometry
and
The wikipedia entry on 'Trigonometric Function', specifically
Trigonometric function : Right angled triangle definitions
You could also see if your school will loan or sell you a trigonometry textbook to learn from as well.
K thanks man
the website helped alot so did the data table and I'll ask for aone
Have you managed to get the facing direction tracking towards the mouse working yet?
Post all of your current code, and we can take a second look at how to fix it.
PI is 3.141592653589793238462643383279, not the radius of a circle. Although there is a connection!
| 1 | #include <allegro.h> |
| 2 | #include <math.h> |
| 3 | #include "PI.h" |
| 4 | int main() |
| 5 | { |
| 6 | int depth, res; |
| 7 | allegro_init(); |
| 8 | depth = desktop_color_depth(); |
| 9 | if (depth == 0) depth = 32; |
| 10 | set_color_depth(depth); |
| 11 | res = set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0); |
| 12 | if (res != 0) |
| 13 | { |
| 14 | allegro_message(allegro_error); |
| 15 | exit(-1); |
| 16 | } |
| 17 | install_timer(); |
| 18 | install_keyboard(); |
| 19 | install_mouse(); |
| 20 | BITMAP *crosshair = load_bitmap("crosshair.bmp",NULL); |
| 21 | BITMAP *ship = load_bitmap("deml.bmp",NULL); |
| 22 | BITMAP *buffer = create_bitmap(640,480); |
| 23 | int cY = -50; |
| 24 | int cX = -150; |
| 25 | int ship_X = 0; |
| 26 | int ship_Y = 0; |
| 27 | double player_angle = 256.0; |
| 28 | set_mouse_sprite(crosshair); |
| 29 | show_mouse(screen); |
| 30 | const double rad_to_deg = 180.0/M_PI;// 360.0/(2.0*M_PI); |
| 31 | const double deg_to_adeg = 32.0/45.0;// 256.0/360.0; |
| 32 | const double rad_to_adeg = 128.0/M_PI; |
| 33 | while(!key[KEY_ESC]) |
| 34 | { |
| 35 | clear(screen); |
| 36 | player_angle = (atan2(mouse_y + ship_Y, mouse_x + ship_X)*rad_to_adeg/M_PI + 20.0); |
| 37 | rotate_sprite(screen, ship, 300,300, ftofix(player_angle)); |
| 38 | //blit(buffer,screen,0,0,0,0,640,480); |
| 39 | } |
| 40 | destroy_bitmap(ship); |
| 41 | destroy_bitmap(buffer); |
| 42 | destroy_bitmap(crosshair); |
| 43 | return 0; |
| 44 | } |
| 45 | END_OF_MAIN() |
heh sorry I didnt post it early edgar, I didnt see that part of your reply XD then I read it again around 10 hours later trying to fix it and I saw it
If you do all of your drawing to the buffer, you can eliminate the flickering from drawing multiple overlapping images rapidly onto the screen.
Watch the units on your data - rad_to_adeg already has the type 'allegro degrees per radian' and includes the division by M_PI, so don't do it twice. To go from radians to allegro degrees, just multiply by rad_to_adeg.
c:\mingw\include>grep -r -E -I -n M_PI .*.*
.\ddk/usbscan.h:76:#define MAX_NUM_PIPES 8
.\ddk/usbscan.h:138: OUT USBSCAN_PIPE_INFORMATION PipeInfo[MAX_NUM_PIPES];
.\math.h:58:#define M_PI 3.14159265358979323846
.\math.h:59:#define M_PI_2 1.57079632679489661923
.\math.h:60:#define M_PI_4 0.78539816339744830962
.\sqlext.h:233:#define SQL_FN_NUM_PI 0x00010000L
Heh, I didn't know about M_PI_2 or M_PI_4. I should surf the standard c library headers more often.
So here's what I would use :
| 1 | int dx = 0 , dy = 0; |
| 2 | player_angle = 0.0; |
| 3 | while(!key[KEY_ESC]) { |
| 4 | clear(buffer); |
| 5 | dx = mouse_x - ship_X; |
| 6 | dy = mouse_y - ship_Y; |
| 7 | if ((dx*dx + dy*dy) != 0) { |
| 8 | // You shouldn't call atan2(0,0) - The angle from one point to itself is |
| 9 | // undefined, so only change it when we can get a value for it |
| 10 | player_angle = atan2(dy , dx)*rad_to_adeg;// + 20? What's the offset for? |
| 11 | } |
| 12 | rotate_sprite(buffer , ship , ship_X , ship_Y , ftofix(player_angle)); |
| 13 | blit(buffer,screen,0,0,0,0,640,480); |
| 14 | rest(20); |
| 15 | } |
This exact code works just fine for me, I've tried it.
Add in the rest(X ms) call so you don't burn out your processor for now until you learn about timer routines. Draw to the buffer to prevent flickering. Indent to keep us sane. Study the manuals so you don't need to be corrected so much. Keep working on it. Good luck.
AHAHAHAH YES, thanks edgar and wow.. that really means alot I dont think any one has ever really wished me luck with programming
heh thanks
and yeah ill take your advise and ok.. huff I'll indent XD
From experiance... learning how to make your code read/editable is going to help you more than learning a language or library itself. Because you can take that skill and apply it to any language or library.
ohh yeah, true