|
Bitmap Rotation |
moon_rabbits
Member #8,469
March 2007
|
Here's the source: tank.cpp 1/********************
2 * Tank Source File *
3 ********************/
4
5#include <math.h>
6#include <allegro.h>
7#include "tank.h"
8
9CTank::CTank()
10/* Sets up tank object */
11{
12 x = (SCREEN_W/2); // init player
13 y = SCREEN_H - (SCREEN_H/6);
14 health = 100;
15 reload = 0;
16 score = 0;
17 speed = TANK_SPEED;
18
19 canx = x + TANK_W/2 - CANNON_W/2;
20 cany = y - CANNON_H + (CANNON_H/4);
21
22 tank = create_bitmap(TANK_W, TANK_H);
23 cannon = create_bitmap(CANNON_W, CANNON_H);
24
25 // draw tank to tank bitmap
26 clear_to_color(tank, makecol(255, 0, 255));
27 rectfill(tank, 10, 0, (TANK_W-10), TANK_H-(TANK_H/4), makecol(45, 200, 60));
28 rect(tank, 10, 0, (TANK_W-10), TANK_H-(TANK_H/4), makecol(60, 230, 70));
29
30 ellipsefill(tank, (TANK_W/2), TANK_H-(TANK_H/4)-1, (TANK_W/2)-1,
31 (TANK_H/4), makecol(160, 160, 160));
32 ellipse(tank, (TANK_W/2), TANK_H-(TANK_H/4)-1, (TANK_W/2)-1,
33 (TANK_H/4), makecol(120, 120, 120));
34
35 // draw cannon to cannon bitmap
36 clear_to_color(cannon, makecol(255, 0, 255));
37 rectfill(cannon, 0, 0, CANNON_W, CANNON_H, makecol(45, 200, 60));
38 rect(cannon, 0, 0, CANNON_W-1, CANNON_H-1, makecol(60, 230, 70));
39}
40//--------------------------------------------
41
42CTank::~CTank()
43/* Deletes tank bmps */
44{
45 destroy_bitmap(tank);
46 destroy_bitmap(cannon);
47}
48//--------------------------------------------
49
50void CTank::MoveTank()
51/* Moves tank */
52{
53
54 if((key[KEY_LEFT]) && (x > 0)){
55 x -= speed;
56 canx -= speed;
57 }
58
59 if((key[KEY_RIGHT]) && ((x+TANK_W) < SCREEN_W)){
60 x += speed;
61 canx += speed;
62 }
63
64 angle = atan((canx-(CANNON_W/2)-mouse_x)/(cany-(CANNON_H/2)-mouse_y))/(3.1415/180);
65
66 return;
67}
68//--------------------------------------------
69
70void CTank::FireBullet()
71{}
72//--------------------------------------------
73
74void CTank::DrawTank(BITMAP *surface)
75{
76 // blit tank to *surface
77 masked_blit(tank, surface, 0, 0, x, y, TANK_W, TANK_H);
78 // blit cannon to *surface
79 rotate_sprite(surface, cannon, int(canx), int(cany), ftofix(-angle));
80 textprintf_ex(screen, font, 0, 10, makecol(255,255,255), 0,
81 "Angle = %f", angle);
82}
83//--------------------------------------------
tank.h 1/********************
2 * Tank Class Header*
3 ********************/
4
5#ifndef _TANK_H
6#define _TANK_H
7
8#define MAX_BULLETS 10
9#define MOVE_LEFT 0
10#define MOVE_RIGHT 1
11
12#define TANK_W 100
13#define TANK_H 35
14
15#define TANK_SPEED 1
16
17#define CANNON_W 15
18#define CANNON_H 30
19
20class CTank
21{
22public:
23 CTank();
24 ~CTank();
25
26 int x, y; // x and y coordinate of the player
27 int health; // health of the player
28 int reload; // reload time of the player
29 int speed;
30
31 float canx;
32 float cany;
33 float angle; // angle of cannon
34
35 int score;
36
37 BITMAP *tank, *cannon; //bitmaps to hold the tank and cannon
38
39 void MoveTank();
40 void FireBullet();
41 void DrawTank(BITMAP *surface);
42};
43
44#endif
main.cpp 1/******************************
2 * Tank Defense v.0.1 *
3 * March 25 2007 *
4 * Kelly Crawford *
5 ******************************/
6
7#include <allegro.h>
8#include <time.h>
9#include "tank.h"
10
11#define WINDOW_W 640
12#define WINDOW_H 480
13
14#define MAX_CLOUDS 14
15#define MIN_CLOUDS 7
16
17int SetUp()
18/* Initializes allegro and screen */
19{
20 allegro_init();
21
22 install_keyboard();
23 install_mouse();
24 install_timer();
25
26 set_color_depth(16);
27
28 if(set_gfx_mode(GFX_AUTODETECT_WINDOWED, WINDOW_W, WINDOW_H, 0, 0) != 0)
29 return 1;
30
31 srand(time(0));
32
33 show_mouse(screen);
34
35 return 0;
36}
37//--------------------------------------------
38
39void cloud_line(BITMAP *bmp, int x, int y, int color)
40/* Function called by DoLine() */
41{
42 putpixel(bmp, x, y, color);
43
44 return;
45}
46//--------------------------------------------
47
48void MakeCloud(BITMAP *bmp)
49/* Draws a cloud to bmp */
50{
51 int height = 1 + (rand()%50); // height of cloud
52 int width = 100 + (rand()%50); // general width of cloud
53
54 int x1 = (-30) + rand()%(SCREEN_W-30);
55 int x2 = x1 + width;
56 int y = 10 + rand()%(SCREEN_H-100); // cloud coordinates
57
58 int col = makecol(255,255,255); // cloud color information
59
60 for(int i = 0; i < height; i++) // loops until entire cloud is drawn
61 {
62 do_line(bmp, x1, y, x2, y, col, *cloud_line); // draw line of cloud
63 y += 1;
64
65 if(i < (height/2)){
66 x1 -= 3 + rand()%5;
67 x2 += 3 + rand()%5;}
68 else{
69 x1 += 3 + rand()%5;
70 x2 -= 3 + rand()%5;}
71 }
72
73 return;
74}
75//--------------------------------------------
76
77BITMAP* GenerateSky(BITMAP *bmp)
78/* Generates a sky on bitmap pointed
79 to by bmp */
80{
81 int r = 140, g = 150, b = 225;
82 int col = makecol(r, g, b);
83
84
85 floodfill(bmp, SCREEN_W/2, SCREEN_H/2, col); // fill screen w/ blue
86
87 int clouds = (rand()%(MAX_CLOUDS-MIN_CLOUDS) + MIN_CLOUDS);
88
89 for(int c = 0; c < clouds; c++)
90 MakeCloud(bmp);
91
92 return bmp;
93}
94//--------------------------------------------
95
96int main()
97{
98 if(SetUp() != 0) return 1; // setup + error checking for allegro
99
100 BITMAP *bg_sky = create_bitmap(SCREEN_W, SCREEN_H); // create sky bitmap
101 BITMAP *buffer = create_bitmap(SCREEN_W, SCREEN_H); // create double buffer
102
103 bg_sky = GenerateSky(bg_sky); // colour sky bitmap
104
105 CTank player;
106
107 while(!key[KEY_ESC]){
108
109 blit(bg_sky, buffer, 0, 0, 0, 0, bg_sky->w, bg_sky->h);
110
111 player.MoveTank();
112 player.DrawTank(buffer);
113
114 blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
115 };
116
117 destroy_bitmap(bg_sky);
118 destroy_bitmap(buffer);
119
120 return(0);
121}END_OF_MAIN()
The problem lies in the tank.cpp file. In the MoveTank() function, there is a call to atan() to determine the angle of the mouse in degrees from the center of a bitmap of a cannon. The cannon rotates to face the mouse, basically. But there are errors, it jumps around sometimes when you pass certain parts, and if you keep the mouse near the top of the window and drag it too far left or right, the cannon stops facing it (it faces too far down). Is there any way I can improve upon the angle calculation? |
Onewing
Member #6,152
August 2005
|
Perhaps try atan2()? ------------ |
moon_rabbits
Member #8,469
March 2007
|
Thank you, but the problem persists. |
ImLeftFooted
Member #3,935
October 2003
|
#ifndef _TANK_H #define _TANK_H This is bad style, never follow an underscore with an upper case letter |
Ceagon Xylas
Member #5,495
February 2005
|
tan-1 takes the paramater y/x. You're calculating x/y.
[edit] |
Onewing
Member #6,152
August 2005
|
Quote: This is bad style, never follow an underscore with an upper case letter
Dustin Dettmer earlier said: Single underscores followed by an uppercase letter are reserved for compiler usage. What compiler? Any compiler? I've been doing this for a long time and it has never been a problem. And if you are planning on telling all who do this to stop, you've got an uphill battle in front of you. As far as I can tell, this is the way it is taught to many. I'm not saying you are wrong, I'm just kind of floored by it. ------------ |
Kitty Cat
Member #2,815
October 2002
|
Quote: What compiler? Any compiler? Yup. Macros and symbols starting with an underscore and capital letter, and starting with two underscores and anything, are reserved for the compiler. You can use them sure.. but then it's your own fault if it happens to conflict with an undocumented portion of the compiler. -- |
Onewing
Member #6,152
August 2005
|
Quote: but then it's your own fault if it happens to conflict with an undocumented portion of the compiler. Is it really all that likely to happen though? I mean, if you do CLASSNAME_H? Well, I guess that's why it's good practice not to do that, just for that unlikely case. That's going to be a hard habit to break. ------------ |
Thomas Fjellstrom
Member #476
June 2000
|
Not to mention any symbol tarting with a single underscore and lower case letter is reserved for system/library internal use . Thats sortof unofficial though. Still a good style guide line. You can always tell when a symbol is out of limits. Quote: That's going to be a hard habit to break. Didn't take me long. I used to use _FILE_H_, I now use File_H_GUARD.. simple switch -- |
|