1 #include "cosmic_protector.hpp"
2 
3 const float Player::MAX_SPEED = 10.0f;
4 const float Player::MIN_SPEED = -10.0f;
5 const float Player::ACCEL = 0.006f;
6 const float Player::DECCEL = 0.001f;
7 
logic(int step)8 bool Player::logic(int step)
9 {
10    if (!isDestructable && invincibleCount > 0) {
11       invincibleCount -= step;
12       if (invincibleCount <= 0) {
13          isDestructable = true;
14          if (lives <= 0)
15             return false;
16       }
17    }
18 
19    if (lives <= 0)
20       return true;
21 
22    ResourceManager& rm = ResourceManager::getInstance();
23    Input *input = (Input *)rm.getData(RES_INPUT);
24 
25    if (input->lr() < 0.0f) {
26       angle -= 0.005f * step;
27    }
28    else if (input->lr() > 0.0f) {
29       angle += 0.005f * step;
30    }
31 
32    if (input->ud() < 0.0f) {
33       dx += ACCEL * step * cos(angle);
34       if (dx > MAX_SPEED)
35          dx = MAX_SPEED;
36       else if (dx < MIN_SPEED)
37          dx = MIN_SPEED;
38       dy += ACCEL * step * sin(angle);
39       if (dy > MAX_SPEED)
40          dy = MAX_SPEED;
41       else if (dy < MIN_SPEED)
42          dy = MIN_SPEED;
43       draw_trail = true;
44    }
45    else if (input->ud() > 0.0f) {
46       if (dx > 0)
47          dx -= ACCEL * step;
48       else if (dx < 0)
49          dx += ACCEL * step;
50       if (dx > -0.1f && dx < 0.1f)
51          dx = 0;
52       if (dy > 0)
53          dy -= ACCEL * step;
54       else if (dy < 0)
55          dy += ACCEL * step;
56       if (dy > -0.1f && dy < 0.1f)
57          dy = 0;
58       draw_trail = false;
59    }
60    else {
61       if (dx > 0)
62          dx -= DECCEL * step;
63       else if (dx < 0)
64          dx += DECCEL * step;
65       if (dx > -0.1f && dx < 0.1f)
66          dx = 0;
67       if (dy > 0)
68          dy -= DECCEL * step;
69       else if (dy < 0)
70          dy += DECCEL * step;
71       if (dy > -0.1f && dy < 0.1f)
72          dy = 0;
73       draw_trail = false;
74    }
75 
76    int shotRate;
77    switch (weapon) {
78       case WEAPON_SMALL:
79          shotRate = 300;
80          break;
81       case WEAPON_LARGE:
82          shotRate = 250;
83          break;
84       default:
85          shotRate = INT_MAX;
86          break;
87    }
88 
89    int now = (int) (al_get_time() * 1000.0);
90    if ((lastShot+shotRate) < now && input->b1()) {
91       lastShot = now;
92       float realAngle = angle;
93       float bx = x + radius * cos(realAngle);
94       float by = y + radius * sin(realAngle);
95       Bullet *b = 0;
96       int resourceID = RES_FIRESMALL;
97       switch (weapon) {
98          case WEAPON_SMALL:
99             b = new SmallBullet(bx, by, angle, this);
100             resourceID = RES_FIRESMALL;
101             break;
102          case WEAPON_LARGE:
103             b = new LargeBullet(bx, by, angle, this);
104             resourceID = RES_FIRELARGE;
105             break;
106       }
107       if (b) {
108          my_play_sample(resourceID);
109          new_entities.push_back(b);
110       }
111    }
112 
113    if (input->cheat()) {
114       al_rest(0.250);
115       std::list<Entity *>::iterator it;
116       for (it = entities.begin(); it != entities.end(); it++) {
117          Entity *e = *it;
118          delete e;
119       }
120       entities.clear();
121    }
122 
123    Entity::wrap();
124 
125    if (!Entity::logic(step))
126       return false;
127 
128    return true;
129 }
130 
render_extra(void)131 void Player::render_extra(void)
132 {
133    ResourceManager& rm = ResourceManager::getInstance();
134 
135    if (lives <= 0) {
136       int w = al_get_bitmap_width(highscoreBitmap);
137       int h = al_get_bitmap_height(highscoreBitmap);
138       al_draw_bitmap(highscoreBitmap, (BB_W-w)/2, (BB_H-h)/2, 0);
139       return;
140    }
141 
142    ALLEGRO_STATE st;
143    al_store_state(&st, ALLEGRO_STATE_BLENDER);
144    al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE);
145    al_draw_bitmap(icon, 1, 2, 0);
146    al_restore_state(&st);
147    ALLEGRO_FONT *small_font = (ALLEGRO_FONT *)rm.getData(RES_SMALLFONT);
148    al_draw_textf(small_font, al_map_rgb(255, 255, 255), 20, 2, 0, "x%d", lives);
149    al_draw_textf(small_font, al_map_rgb(255, 255, 255), 2, 18, 0, "%d", score);
150 }
151 
render(int offx,int offy,ALLEGRO_COLOR tint)152 void Player::render(int offx, int offy, ALLEGRO_COLOR tint)
153 {
154    if (lives <= 0)
155       return;
156 
157    int rx = (int)(offx + x), ry = (int)(offy + y);
158 
159    if (!isDestructable) {
160       al_draw_tinted_rotated_bitmap(trans_bitmap, tint,
161          draw_radius, draw_radius, rx, ry,
162          angle+(ALLEGRO_PI/2.0f), 0);
163    }
164    else {
165       al_draw_tinted_rotated_bitmap(bitmap,
166          tint, draw_radius, draw_radius, rx, ry,
167          angle+(ALLEGRO_PI/2.0f), 0);
168    }
169    if (draw_trail) {
170       int tw = al_get_bitmap_width(trail_bitmap);
171       int th = al_get_bitmap_height(trail_bitmap);
172       float ca = (ALLEGRO_PI*2)+angle;
173       float a = ca + ((210.0f / 180.0f) * ALLEGRO_PI);
174       float tx = rx + 42.0f * cos(a);
175       float ty = ry + 42.0f * sin(a);
176       al_draw_tinted_rotated_bitmap(trail_bitmap, tint, tw, th/2,
177          tx, ty, a, 0);
178       a = ca + ((150.0f / 180.0f) * ALLEGRO_PI);
179       tx = rx + 42.0f * cos(a);
180       ty = ry + 42.0f * sin(a);
181       al_draw_tinted_rotated_bitmap(trail_bitmap, tint, tw, th/2,
182          tx, ty, a, 0);
183    }
184 }
185 
render(int offx,int offy)186 void Player::render(int offx, int offy)
187 {
188    render(offx, offy, al_map_rgb(255, 255, 255));
189 }
190 
hit(int damage)191 bool Player::hit(int damage)
192 {
193    Entity::hit(damage);
194    die();
195    return true;
196 }
197 
Player()198 Player::Player() :
199    weapon(WEAPON_SMALL),
200    lastShot(0),
201    score(0),
202    bitmap(0),
203    trans_bitmap(0),
204    trail_bitmap(0),
205    icon(0),
206    highscoreBitmap(0)
207 {
208 }
209 
~Player()210 Player::~Player()
211 {
212 }
213 
destroy(void)214 void Player::destroy(void)
215 {
216    al_destroy_bitmap(bitmap);
217    al_destroy_bitmap(trans_bitmap);
218    al_destroy_bitmap(trail_bitmap);
219    al_destroy_bitmap(icon);
220    al_destroy_bitmap(highscoreBitmap);
221    bitmap = 0;
222    trans_bitmap = 0;
223    trail_bitmap = 0;
224    icon = 0;
225    highscoreBitmap = 0;
226 }
227 
load(void)228 bool Player::load(void)
229 {
230    ALLEGRO_STATE state;
231    al_store_state(&state, ALLEGRO_STATE_TARGET_BITMAP | ALLEGRO_STATE_BLENDER);
232 
233    bitmap = al_load_bitmap(getResource("gfx/ship.png"));
234    if (!bitmap) {
235       debug_message("Error loading %s\n", getResource("gfx/ship.png"));
236       return false;
237    }
238 
239    trans_bitmap = al_create_bitmap(al_get_bitmap_width(bitmap),
240       al_get_bitmap_height(bitmap));
241    if (!trans_bitmap) {
242       debug_message("Error loading %s\n", getResource("gfx/ship_trans.png"));
243       al_destroy_bitmap(bitmap);
244       return false;
245    }
246 
247    /* Make a translucent copy of the ship */
248    al_set_target_bitmap(trans_bitmap);
249    al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
250    al_draw_tinted_bitmap(bitmap, al_map_rgba(255, 255, 255, 160),
251       0, 0, 0);
252    al_restore_state(&state);
253 
254    trail_bitmap = al_load_bitmap(getResource("gfx/trail.png"));
255    if (!trail_bitmap) {
256       debug_message("Error loading %s\n", getResource("gfx/trail.png"));
257       al_destroy_bitmap(bitmap);
258       al_destroy_bitmap(trans_bitmap);
259       return false;
260    }
261 
262    icon = al_load_bitmap(getResource("gfx/ship_icon.tga"));
263    if (!icon) {
264       debug_message("Error loading %s\n", getResource("gfx/ship_icon.tga"));
265       al_destroy_bitmap(bitmap);
266       al_destroy_bitmap(trans_bitmap);
267       al_destroy_bitmap(trail_bitmap);
268       return false;
269    }
270 
271    highscoreBitmap = al_create_bitmap(300, 200);
272    al_set_target_bitmap(highscoreBitmap);
273    al_clear_to_color(al_map_rgba(0, 0, 0, 0));
274 
275    al_restore_state(&state);
276 
277    draw_radius = al_get_bitmap_width(bitmap)/2;
278    radius = draw_radius / 2;
279 
280    newGame();
281    reset();
282 
283    return true;
284 }
285 
get(void)286 void* Player::get(void)
287 {
288    return this;
289 }
290 
newGame(void)291 void Player::newGame(void)
292 {
293    lives = 5;
294    hp = 1;
295    score = 0;
296    isDestructable = true;
297 }
298 
reset(void)299 void Player::reset(void)
300 {
301    x = BB_W/2;
302    y = BB_H/2;
303    dx = 0;
304    dy = 0;
305    angle = -ALLEGRO_PI/2;
306    draw_trail = false;
307    weapon = WEAPON_SMALL;
308 }
309 
die(void)310 void Player::die(void)
311 {
312    shake();
313    reset();
314 
315    lives--;
316    if (lives <= 0) {
317       // game over
318       isDestructable = false;
319       invincibleCount = 8000;
320       ALLEGRO_BITMAP *old_target = al_get_target_bitmap();
321       al_set_target_bitmap(highscoreBitmap);
322       int w = al_get_bitmap_width(highscoreBitmap);
323       int h = al_get_bitmap_height(highscoreBitmap);
324       ResourceManager& rm = ResourceManager::getInstance();
325       ALLEGRO_FONT *large_font = (ALLEGRO_FONT *)rm.getData(RES_LARGEFONT);
326       ALLEGRO_FONT *small_font = (ALLEGRO_FONT *)rm.getData(RES_SMALLFONT);
327       al_draw_textf(large_font, al_map_rgb(255, 255, 255), w/2, h/2-16, ALLEGRO_ALIGN_CENTRE, "GAME OVER");
328       al_draw_textf(small_font, al_map_rgb(255, 255, 255), w/2, h/2+16, ALLEGRO_ALIGN_CENTRE, "%d Points", score);
329       al_set_target_bitmap(old_target);
330    }
331    else {
332       hp = 1;
333       isDestructable = false;
334       invincibleCount = 3000;
335    }
336 }
337 
givePowerUp(int type)338 void Player::givePowerUp(int type)
339 {
340    switch (type) {
341       case POWERUP_LIFE:
342          lives++;
343          break;
344       case POWERUP_WEAPON:
345          weapon = WEAPON_LARGE;
346          break;
347    }
348 }
349 
addScore(int points)350 void Player::addScore(int points)
351 {
352    score += points;
353 }
354 
getScore(void)355 int Player::getScore(void)
356 {
357    return score;
358 }
359 
getAngle(void)360 float Player::getAngle(void)
361 {
362    return angle;
363 }
364 
getSpeed(float * dx,float * dy)365 void Player::getSpeed(float *dx, float *dy)
366 {
367    *dx = this->dx;
368    *dy = this->dy;
369 }
370