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