Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Rotating a sprite depending on the position of the mouse

This thread is locked; no one can reply to it. rss feed Print
Rotating a sprite depending on the position of the mouse
Allegro newbie
Member #10,212
September 2008

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 :P

1#include <allegro.h>
2#include <math.h>
3#include "PI.h"
4int main()
5{
6int depth, res;
7allegro_init();
8depth = desktop_color_depth();
9if (depth == 0) depth = 32;
10set_color_depth(depth);
11res = set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0);
12if (res != 0)
13{
14allegro_message(allegro_error);
15exit(-1);
16}
17install_timer();
18install_keyboard();
19install_mouse();
20BITMAP *crosshair = load_bitmap("crosshair.bmp",NULL);
21BITMAP *ship = load_bitmap("deml.bmp",NULL);
22BITMAP *buffer = create_bitmap(640,480);
23int cY = -50;
24int cX = -150;
25int ship_X = 0;
26int ship_Y = 0;
27double player_angle;
28set_mouse_sprite(crosshair);
29show_mouse(screen);
30player_angle = (atan2(mouse_y - ship_Y, mouse_x - ship_X)*128/PI + 20);
31rotate_sprite(screen, ship, 50,100, itofix(player_angle));
32readkey();
33destroy_bitmap(ship);
34destroy_bitmap(buffer);
35destroy_bitmap(crosshair);
36return 0;
37}
38END_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!

someone972
Member #7,719
August 2006
avatar

You need to put it in a loop, or it will only execute those instructions once.

while(!key[KEY_ESC])
{
    clear(screen);
    player_angle = (atan2(mouse_y - ship_Y, mouse_x - ship_X)*128/PI + 20);
    rotate_sprite(screen, ship, 50,100, itofix(player_angle));
}

Prepare for image tearing when you use this code, as it is repeatedly drawing to the screen.

______________________________________
As long as it remains classified how long it took me to make I'll be deemed a computer game genius. - William Labbett
Theory is when you know something, but it doesn't work. Practice is when something works, but you don't know why. Programmers combine theory and practice: Nothing works and they don't know why. -Unknown
I have recklessly set in motion a chain of events with the potential to so-drastically change the path of my life that I can only find it to be beautifully frightening.

Allegro newbie
Member #10,212
September 2008

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

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Allegro newbie
Member #10,212
September 2008

same thing happens :T maye if i declared it as a floating point number? No idea what that would produce jsut an idea though

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Quote:

//
player_angle = (atan2(mouse_y - ship_Y, mouse_x - ship_X)*128/PI + 20);
    rotate_sprite(screen, ship, 50,100, itofix(player_angle));
//

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.

Quote:

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?

Quote:

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.)

Allegro newbie
Member #10,212
September 2008

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 :)

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Quote:

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.

Quote:

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.
<math>\tan{\theta} = \frac{y}{x}</math>

The arctangent is the inverse of the tangent function.
<math>\arctan{(\tan{\theta})} = \arctan{\frac{y}{x}}</math>

<math>\theta = \arctan{\frac{y}{x}}</math>

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.

Allegro newbie
Member #10,212
September 2008

K thanks man :) the website helped alot so did the data table and I'll ask for aone :)

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

jason perkins
Member #10,586
January 2009

PI is 3.141592653589793238462643383279, not the radius of a circle. Although there is a connection!

Allegro newbie
Member #10,212
September 2008

1#include <allegro.h>
2#include <math.h>
3#include "PI.h"
4int main()
5{
6int depth, res;
7allegro_init();
8depth = desktop_color_depth();
9if (depth == 0) depth = 32;
10set_color_depth(depth);
11res = set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0);
12if (res != 0)
13{
14allegro_message(allegro_error);
15exit(-1);
16}
17install_timer();
18install_keyboard();
19install_mouse();
20BITMAP *crosshair = load_bitmap("crosshair.bmp",NULL);
21BITMAP *ship = load_bitmap("deml.bmp",NULL);
22BITMAP *buffer = create_bitmap(640,480);
23int cY = -50;
24int cX = -150;
25int ship_X = 0;
26int ship_Y = 0;
27double player_angle = 256.0;
28set_mouse_sprite(crosshair);
29show_mouse(screen);
30const double rad_to_deg = 180.0/M_PI;// 360.0/(2.0*M_PI);
31const double deg_to_adeg = 32.0/45.0;// 256.0/360.0;
32const 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 }
40destroy_bitmap(ship);
41destroy_bitmap(buffer);
42destroy_bitmap(crosshair);
43return 0;
44}
45END_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

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Quote:

//
 while(!key[KEY_ESC])
 {
    clear(screen);
    player_angle = (atan2(mouse_y + ship_Y, mouse_x + ship_X)*rad_to_adeg/M_PI + 20.0);
    rotate_sprite(screen, ship, 300,300, ftofix(player_angle)); 
    //blit(buffer,screen,0,0,0,0,640,480);
 }
//

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.

grep said:

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. ;)

Allegro newbie
Member #10,212
September 2008

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

jason perkins
Member #10,586
January 2009

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.

Allegro newbie
Member #10,212
September 2008

ohh yeah, true

Go to: