Subversion Repositories battle

[/] [trunk/] [Battle/] [Player.cpp] - Blame information for rev 173

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 bert
#include "SDL/SDL.h"
2 bert
 
3 108 bert
#include <iostream>
4 bert
 
5 42 bert
#include "Main.h"
6 bert
 
7 108 bert
#include "Projectile.h"
8 bert
#include "Bomb.h"
9 bert
#include "Gameplay.h"
10 bert
#include "Level.h"
11 2 bert
#include "Player.h"
12 bert
 
13 108 bert
#define BULLETS_UNLIMITED -1
14 3 bert
 
15 124 bert
const int Player::CHARACTER_COUNT = 20;
16 108 bert
const Character Player::CHARACTERS[Player::CHARACTER_COUNT] = {
17 bert
        //      Name               Filename            sp wt wp bd
18 bert
        {(char*)"BERT",         (char*)"gfx/bert.bmp",          1, 1, 1, 1},
19 139 bert
        {(char*)"JEROEN",       (char*)"gfx/jeroen.bmp",        1, 1, 2, 0},
20 bert
        {(char*)"STEVEN",       (char*)"gfx/steven.bmp",        0, 2, 0, 2},
21 bert
        {(char*)"TEDJE",        (char*)"gfx/tedje.bmp",         1, 1, 2, 0},
22 bert
        {(char*)"OKKE",         (char*)"gfx/okke.bmp",          2, 0, 2, 0},
23 bert
        {(char*)"JEREMY",       (char*)"gfx/jeremy.bmp",        2, 0, 0, 2},
24 bert
        {(char*)"MARCEL",       (char*)"gfx/marcel.bmp",        2, 0, 1, 1},
25 bert
        {(char*)"JAY",          (char*)"gfx/jay.bmp",           0, 2, 1, 1},
26 108 bert
        {(char*)"DONJA",        (char*)"gfx/donja.bmp",         2, 0, 1, 1},
27 bert
        {(char*)"ROB",          (char*)"gfx/rob.bmp",           0, 2, 0, 2},
28 139 bert
        {(char*)"EVA",          (char*)"gfx/eva.bmp",           0, 2, 1, 1},
29 bert
        {(char*)"TOBIAS",       (char*)"gfx/tobias.bmp",        1, 1, 0, 2},
30 108 bert
        {(char*)"ARJAN",        (char*)"gfx/arjan.bmp",         0, 2, 2, 0},
31 bert
        {(char*)"RUUD",         (char*)"gfx/ruud.bmp",          2, 0, 0, 2},
32 139 bert
        {(char*)"PETER",        (char*)"gfx/peter.bmp",         1, 1, 1, 1},
33 bert
        {(char*)"BERRY",        (char*)"gfx/berry.bmp",         2, 0, 1, 1},
34 bert
        {(char*)"TON",          (char*)"gfx/ton.bmp",           0, 2, 2, 0},
35 155 bert
//      {(char*)"ANTON",        (char*)"gfx/anton.bmp",         1, 1, 0, 2},
36 bert
        {(char*)"GIJS",         (char*)"gfx/gijs.bmp",          1, 1, 0, 2},
37 108 bert
        {(char*)"RUTGER",       (char*)"gfx/rutger.bmp",        2, 0, 2, 0},
38 124 bert
        {(char*)"KIM",          (char*)"gfx/kim.bmp",           1, 1, 1, 1},
39 108 bert
};
40 bert
const int Player::COLORS[4] = {
41 bert
        0xaa0000,
42 bert
        0x0000aa,
43 bert
        0x009900,
44 bert
        0xaa9900,
45 bert
};
46 bert
 
47 bert
const int Player::SPEEDCLASS_COUNT = 3;
48 bert
const SpeedClass Player::SPEEDCLASSES[Player::SPEEDCLASS_COUNT] = {
49 bert
        {30},
50 139 bert
        {35},
51 108 bert
        {40},
52 bert
};
53 bert
const int Player::WEIGHTCLASS_COUNT = 3;
54 bert
const WeightClass Player::WEIGHTCLASSES[Player::WEIGHTCLASS_COUNT] = {
55 139 bert
        {5,   5, 35, 20},
56 bert
        {10, 10, 30, 15},
57 bert
        {15, 15, 25, 10},
58 108 bert
};
59 bert
const int Player::WEAPONCLASS_COUNT = 3;
60 bert
const WeaponClass Player::WEAPONCLASSES[Player::WEAPONCLASS_COUNT] = {
61 bert
        {10, 300, 10},
62 139 bert
        { 9, 325, 10},
63 108 bert
        { 8, 350, 10},
64 bert
};
65 bert
const int Player::BOMBPOWERCLASS_COUNT = 3;
66 bert
const BombPowerClass Player::BOMBPOWERCLASSES[Player::BOMBPOWERCLASS_COUNT] = {
67 bert
        {15},
68 bert
        {20},
69 bert
        {25},
70 bert
};
71 bert
 
72 2 bert
const int Player::jump_height = 144;
73 bert
 
74 108 bert
// Movement constantes
75 bert
#define MAX_MOMENTUM_FALL 100
76 bert
#define MAX_MOMENTUM_JUMP 40
77 bert
#define MAX_MOMENTUM_HORIZ 20
78 bert
#define MAX_MOMENTUM_HORIZ_DUCKJUMP 10
79 bert
#define MAX_MOMENTUM_RUN 40
80 2 bert
 
81 108 bert
#define FRAME_CYCLE_DISTANCE 24
82 13 bert
 
83 108 bert
#define MOMENTUM_INTERV_HORIZ 1
84 bert
#define MOMENTUM_INTERV_VERT 1
85 60 bert
 
86 108 bert
// Base speed
87 bert
#define SPEED_HORIZ 2
88 bert
#define SPEED_VERT 2
89 2 bert
 
90 108 bert
// Freeze time
91 bert
#define PLAYER_FREEZE_FRAMES 30
92 2 bert
 
93 173 bert
// Shield time
94 bert
#define PLAYER_SHIELD_FRAMES 180
95 bert
 
96 108 bert
Player::Player(int character, int number) {
97 bert
        name = CHARACTERS[character].name;
98 110 bert
        this->character = character;
99 108 bert
        this->number = number;
100 8 bert
 
101 108 bert
        speedclass = CHARACTERS[character].speedclass;
102 bert
        weightclass = CHARACTERS[character].weightclass;
103 bert
        weaponclass = CHARACTERS[character].weaponclass;
104 bert
        bombpowerclass = CHARACTERS[character].bombpowerclass;
105 8 bert
 
106 108 bert
        rounds_won = 0;
107 bert
 
108 114 bert
        input = NULL;
109 bert
 
110 108 bert
        reset();
111 bert
 
112 bert
        position = new SDL_Rect();
113 bert
        last_position = new SDL_Rect();
114 bert
 
115 bert
        position->w = PLAYER_W;
116 bert
        position->h = PLAYER_H;
117 bert
 
118 bert
        sprites = Main::graphics->player->at(character);
119 bert
        marker_clip_above = Main::graphics->pmarker_clip_above[(number - 1)];
120 bert
        marker_clip_below = Main::graphics->pmarker_clip_below[(number - 1)];
121 bert
}
122 bert
 
123 bert
Player::~Player() {
124 bert
        delete position;
125 bert
        delete last_position;
126 bert
}
127 bert
 
128 bert
void Player::set_character(int character) {
129 bert
        name = CHARACTERS[character].name;
130 110 bert
        this->character = character;
131 108 bert
 
132 bert
        speedclass = CHARACTERS[character].speedclass;
133 bert
        weightclass = CHARACTERS[character].weightclass;
134 bert
        weaponclass = CHARACTERS[character].weaponclass;
135 bert
        bombpowerclass = CHARACTERS[character].bombpowerclass;
136 bert
 
137 bert
        sprites = Main::graphics->player->at(character);
138 bert
}
139 bert
 
140 bert
void Player::reset() {
141 bert
        momentumx = 0;
142 bert
        momentumy = 0;
143 bert
 
144 bert
        current_sprite = SPR_R;
145 bert
        distance_walked = 0;
146 bert
 
147 bert
        is_running = false;
148 bert
        is_duck = false;
149 bert
        is_duck_forced = false;
150 bert
        duck_force_start = 0;
151 bert
 
152 bert
        is_jumping = false;
153 bert
        is_falling = false;
154 bert
 
155 114 bert
        if(input != NULL)
156 bert
                input->reset();
157 108 bert
 
158 3 bert
        is_hit = false;
159 bert
        hit_start = 0;
160 bert
        hit_delay = 30;
161 bert
        hit_flicker_frame = 0;
162 bert
 
163 108 bert
        is_dead = false;
164 bert
        dead_start = 0;
165 bert
 
166 72 bert
        is_frozen = false;
167 bert
        freeze_start = 0;
168 bert
 
169 171 bert
        is_shielded = false;
170 bert
        shield_start = 0;
171 bert
        shield_frame = 0;
172 bert
 
173 108 bert
        bounce_direction_x = 0;
174 bert
        bounce_direction_y = 0;
175 bert
 
176 3 bert
        shoot_start = 0;
177 bert
        shoot_delay = 10;
178 bert
 
179 68 bert
        bomb_start = 0;
180 bert
        bomb_delay = 30;
181 bert
 
182 18 bert
        bullets = 10;
183 27 bert
        bombs = 3;
184 45 bert
        doubledamagebullets = 0;
185 47 bert
        instantkillbullets = 0;
186 18 bert
 
187 108 bert
        score = 0;
188 3 bert
        hitpoints = 100;
189 bert
 
190 108 bert
        bullets_fired = 0;
191 bert
        bullets_hit = 0;
192 bert
        bombs_fired = 0;
193 bert
        bombs_hit = 0;
194 bert
        headstomps = 0;
195 bert
 
196 2 bert
        cycle_direction = CYCLE_UP;
197 bert
}
198 bert
 
199 108 bert
void Player::draw(SDL_Surface * screen, bool marker) {
200 2 bert
        SDL_Rect rect;
201 173 bert
        SDL_Surface * sprites;
202 2 bert
 
203 bert
        rect.x = position->x;
204 bert
        rect.y = position->y;
205 bert
 
206 173 bert
        sprites = this->sprites;
207 bert
 
208 136 bert
        // Dead players are not visible
209 108 bert
        if(is_dead && Gameplay::frame - dead_start > 120) {
210 bert
                return;
211 bert
        }
212 bert
 
213 3 bert
        // Check if player is hit and cycle between a show and a hide of the player to create
214 bert
        // a flicker effect
215 bert
        if(is_hit) {
216 bert
                hit_flicker_frame = (hit_flicker_frame + 1) % 10;
217 bert
                if(hit_flicker_frame < 5)
218 bert
                        return;
219 bert
        }
220 bert
 
221 173 bert
        if(is_shielded) {
222 bert
                if((shield_start + PLAYER_SHIELD_FRAMES) - Gameplay::frame > 60) {
223 bert
                        sprites = Main::graphics->shield;
224 bert
                } else {
225 bert
                        shield_frame = (shield_frame + 1) % 10;
226 bert
                        if(shield_frame >= 5)
227 bert
                                sprites = Main::graphics->shield;
228 bert
                }
229 bert
        }
230 171 bert
 
231 108 bert
        SDL_BlitSurface(sprites, Main::graphics->player_clip[current_sprite], screen, &rect);
232 2 bert
 
233 bert
        // If the player is going out the side of the screen, we want it to
234 bert
        // appear on the other side.
235 3 bert
        if(position->x >= WINDOW_WIDTH - PLAYER_W) {
236 bert
                rect.x = position->x - WINDOW_WIDTH;
237 2 bert
                rect.y = position->y;
238 171 bert
 
239 108 bert
                SDL_BlitSurface(sprites, Main::graphics->player_clip[current_sprite], screen, &rect);
240 2 bert
        }
241 bert
        if(position->x <= 0) {
242 3 bert
                rect.x = position->x + WINDOW_WIDTH;
243 2 bert
                rect.y = position->y;
244 171 bert
 
245 108 bert
                SDL_BlitSurface(sprites, Main::graphics->player_clip[current_sprite], screen, &rect);
246 2 bert
        }
247 37 bert
 
248 72 bert
        // Show marker if the player is above the screen
249 37 bert
        if(position->y + position->h <= 0) {
250 108 bert
                rect.x = position->x + ((PLAYER_W - marker_clip_below->w) / 2);
251 37 bert
                rect.y = 0;
252 108 bert
                SDL_BlitSurface(Main::graphics->pmarker, marker_clip_below, screen, &rect);
253 37 bert
        }
254 108 bert
 
255 bert
        // Show marker above the player
256 bert
        if(marker) {
257 bert
                rect.x = position->x + ((PLAYER_W - marker_clip_above->w) / 2);
258 bert
                rect.y = position->y - marker_clip_above->h - 4;
259 bert
                SDL_BlitSurface(Main::graphics->pmarker, marker_clip_above, screen, &rect);
260 bert
        }
261 2 bert
}
262 bert
 
263 32 bert
SDL_Rect * Player::get_rect() {
264 bert
        SDL_Rect * rect;
265 bert
        rect = new SDL_Rect();
266 bert
        rect->x = position->x;
267 bert
        rect->y = position->y;
268 bert
        rect->w = PLAYER_W;
269 bert
        rect->h = PLAYER_H;
270 bert
        if(is_duck) {
271 bert
                rect->y = rect->y + (PLAYER_H - PLAYER_DUCK_H);
272 bert
                rect->h = PLAYER_DUCK_H;
273 bert
        }
274 bert
        return rect;
275 bert
}
276 bert
 
277 108 bert
void Player::move(Level * level) {
278 bert
        int speedx, speedy;
279 bert
        int maxx;
280 bert
        int momentumx_old;
281 2 bert
        SDL_Rect rect;
282 bert
 
283 108 bert
        if(is_dead)
284 bert
                return;
285 2 bert
 
286 108 bert
        last_position->x = position->x;
287 bert
        last_position->y = position->y;
288 bert
        last_position->w = position->w;
289 bert
        last_position->h = position->h;
290 bert
        if(is_duck) {
291 bert
                last_position->y = last_position->y + (PLAYER_H - PLAYER_DUCK_H);
292 bert
                last_position->h = PLAYER_DUCK_H;
293 2 bert
        }
294 108 bert
 
295 bert
        speedx = 0;
296 bert
        speedy = 0;
297 bert
 
298 bert
        if(is_hit) {
299 bert
                // The player has been hit long enough
300 bert
                if(Gameplay::frame > hit_start + hit_delay) {
301 bert
                        is_hit = false;
302 bert
                }
303 bert
        }
304 2 bert
 
305 108 bert
        if(is_frozen) {
306 bert
                if(Gameplay::frame > freeze_start + PLAYER_FREEZE_FRAMES) {
307 bert
                        is_frozen = false;
308 bert
                }
309 bert
        }
310 2 bert
 
311 171 bert
        if(is_shielded) {
312 173 bert
                if(Gameplay::frame > shield_start + PLAYER_SHIELD_FRAMES) {
313 171 bert
                        is_shielded = false;
314 bert
                }
315 173 bert
                if(Gameplay::frame == (shield_start + PLAYER_SHIELD_FRAMES - 60)) {
316 bert
                        Main::audio->play(SND_SHIELD, position->x + (position->w / 2));
317 bert
                }
318 171 bert
        }
319 bert
 
320 108 bert
        speedx = SPEED_HORIZ;
321 37 bert
 
322 108 bert
        momentumx_old = momentumx;
323 bert
 
324 bert
        // Are we running?
325 114 bert
        if(input->is_pressed(A_RUN)) {
326 108 bert
                is_running = true;
327 bert
                //maxx = MAX_MOMENTUM_RUN;
328 bert
                maxx = SPEEDCLASSES[speedclass].run_speed;
329 bert
        } else {
330 bert
                is_running = false;
331 bert
                maxx = MAX_MOMENTUM_HORIZ;
332 bert
        }
333 bert
 
334 bert
        // Are we ducking?
335 114 bert
        if(input->is_pressed(A_DOWN)) {
336 108 bert
                is_duck = true;
337 bert
        }
338 bert
        else {
339 bert
                is_duck = false;
340 bert
        }
341 bert
 
342 bert
        // Are we forced to being ducked?
343 bert
        if(is_duck_forced) {
344 bert
                if(Gameplay::frame - duck_force_start > DUCK_FORCE_FRAMES) {
345 bert
                        is_duck_forced = false;
346 bert
                } else {
347 bert
                        is_duck = true;
348 bert
                }
349 bert
        }
350 37 bert
 
351 108 bert
        // Force the player to duck when bumping the head
352 bert
        if(!is_duck && level->is_intersecting(position)) {
353 bert
                is_duck = true;
354 bert
        }
355 2 bert
 
356 108 bert
        if(is_duck) {
357 bert
                if(is_jumping || is_falling) {
358 bert
                        // The player can move when jumping and ducking at the same time
359 bert
                        maxx = MAX_MOMENTUM_HORIZ_DUCKJUMP;
360 bert
                } else {
361 bert
                        // The player cannot move when ducking and standing on the ground
362 bert
                        maxx = 0;
363 bert
                }
364 bert
        }
365 bert
 
366 144 bert
        if(!is_frozen && input->is_pressed(A_LEFT)) {
367 108 bert
                // Move more to the left
368 bert
                if(momentumx > 0) momentumx -= MOMENTUM_INTERV_HORIZ;
369 bert
                if(momentumx >= -maxx) momentumx -= MOMENTUM_INTERV_HORIZ;
370 bert
                else momentumx += MOMENTUM_INTERV_HORIZ;
371 bert
        }
372 144 bert
        if(!is_frozen && input->is_pressed(A_RIGHT)) {
373 108 bert
                // Move more to the right
374 bert
                if(momentumx < 0) momentumx += MOMENTUM_INTERV_HORIZ;
375 bert
                if(momentumx <= maxx) momentumx += MOMENTUM_INTERV_HORIZ;
376 bert
                else momentumx -= MOMENTUM_INTERV_HORIZ;
377 bert
        }
378 144 bert
        if(is_frozen || (!input->is_pressed(A_LEFT) && !input->is_pressed(A_RIGHT))) {
379 108 bert
                // Slide until we're standing still
380 bert
                if(momentumx < 0) momentumx += MOMENTUM_INTERV_HORIZ;
381 bert
                if(momentumx > 0) momentumx -= MOMENTUM_INTERV_HORIZ;
382 bert
        }
383 bert
 
384 bert
        // Move the player horizontally
385 bert
        speedx = (int)((double)speedx * ((double)momentumx / 10));
386 bert
        position->x += speedx;
387 bert
 
388 bert
        // Which sprite do we want to show?
389 bert
        if(momentumx == 0) {
390 bert
                // Standing still
391 114 bert
                if(!input->is_pressed(A_LEFT) && !input->is_pressed(A_RIGHT)) {
392 108 bert
                        if(current_sprite >= SPR_L && current_sprite <= SPR_L_DUCK) {
393 bert
                                if(is_duck) {
394 bert
                                        set_sprite(SPR_L_DUCK);
395 bert
                                } else if(is_jumping || is_falling) {
396 bert
                                        set_sprite(SPR_L_JUMP);
397 bert
                                } else {
398 bert
                                        set_sprite(SPR_L);
399 bert
                                }
400 bert
                        }
401 bert
                        if(current_sprite >= SPR_R && current_sprite <= SPR_R_DUCK) {
402 bert
                                if(is_duck) {
403 bert
                                        set_sprite(SPR_R_DUCK);
404 bert
                                } else if(is_jumping || is_falling) {
405 bert
                                        set_sprite(SPR_R_JUMP);
406 bert
                                } else {
407 bert
                                        set_sprite(SPR_R);
408 bert
                                }
409 bert
                        }
410 bert
                }
411 bert
                else {
412 114 bert
                        if(input->is_pressed(A_LEFT) && !input->is_pressed(A_RIGHT)) {
413 108 bert
                                if(is_duck)
414 bert
                                        set_sprite(SPR_L_DUCK);
415 bert
                                else
416 bert
                                        set_sprite(SPR_L_WALK1);
417 bert
                        }
418 114 bert
                        if(!input->is_pressed(A_LEFT) && input->is_pressed(A_RIGHT)) {
419 108 bert
                                if(is_duck)
420 bert
                                        set_sprite(SPR_R_DUCK);
421 bert
                                else
422 bert
                                        set_sprite(SPR_R_WALK1);
423 bert
                        }
424 bert
                }
425 bert
                distance_walked = 0;
426 bert
        }
427 bert
        if(momentumx < 0) {
428 bert
                // Moving left
429 bert
                if(is_duck) {
430 bert
                        set_sprite(SPR_L_DUCK);
431 bert
                } else if((is_jumping || is_falling) && !is_duck) {
432 bert
                        set_sprite(SPR_L_JUMP);
433 bert
                } else {
434 bert
                        if(is_running) {
435 bert
                                if(current_sprite < SPR_L_RUN1 || current_sprite > SPR_L_RUN3) {
436 bert
                                        set_sprite(SPR_L_RUN1);
437 bert
                                }
438 bert
                        } else {
439 bert
                                if(current_sprite < SPR_L_WALK1 || current_sprite > SPR_L_WALK3) {
440 bert
                                        set_sprite(SPR_L_WALK1);
441 bert
                                }
442 bert
                        }
443 114 bert
                        if(input->is_pressed(A_RIGHT)) {
444 108 bert
                                set_sprite(SPR_L_BRAKE);
445 bert
                                distance_walked = 0;
446 bert
                        }
447 bert
                        if(distance_walked < -FRAME_CYCLE_DISTANCE) {
448 bert
                                if(is_running)
449 bert
                                        cycle_sprite(SPR_L_RUN1, SPR_L_RUN3);
450 bert
                                else
451 bert
                                        cycle_sprite(SPR_L_WALK1, SPR_L_WALK3);
452 bert
                                distance_walked = 0;
453 bert
                        }
454 bert
                        distance_walked += speedx;
455 bert
                }
456 bert
        }
457 bert
        else if(momentumx > 0) {
458 bert
                // Moving right
459 bert
                if(is_duck) {
460 bert
                        set_sprite(SPR_R_DUCK);
461 bert
                } else if(is_jumping || is_falling) {
462 bert
                        set_sprite(SPR_R_JUMP);
463 bert
                } else {
464 bert
                        if(is_running) {
465 bert
                                if(current_sprite < SPR_R_RUN1 || current_sprite > SPR_R_RUN3) {
466 bert
                                        set_sprite(SPR_R_RUN1);
467 bert
                                }
468 bert
                        } else {
469 bert
                                if(current_sprite < SPR_R_WALK1 || current_sprite > SPR_R_WALK3) {
470 bert
                                        set_sprite(SPR_R_WALK1);
471 bert
                                }
472 bert
                        }
473 114 bert
                        if(input->is_pressed(A_LEFT)) {
474 108 bert
                                set_sprite(SPR_R_BRAKE);
475 bert
                                distance_walked = 0;
476 bert
                        }
477 bert
                        if(distance_walked > FRAME_CYCLE_DISTANCE) {
478 bert
                                if(is_running)
479 bert
                                        cycle_sprite(SPR_R_RUN1, SPR_R_RUN3);
480 bert
                                else
481 bert
                                        cycle_sprite(SPR_R_WALK1, SPR_R_WALK3);
482 bert
                                distance_walked = 0;
483 bert
                        }
484 bert
                        distance_walked += speedx;
485 bert
                }
486 bert
        }
487 bert
 
488 bert
        rect.x = position->x;
489 bert
        rect.y = position->y;
490 bert
        rect.w = position->w;
491 bert
        rect.h = position->h;
492 bert
        if(is_duck) {
493 bert
                // If the player is ducking, the top should be lower
494 bert
                rect.y = position->y + (PLAYER_H - PLAYER_DUCK_H);
495 bert
                rect.h = PLAYER_DUCK_H;
496 bert
        }
497 2 bert
 
498 108 bert
        if(level->is_intersecting(&rect)) {
499 bert
                // Stop if colliding with the level
500 bert
                position->x -= speedx;
501 bert
                momentumx = 0;
502 bert
        }
503 bert
 
504 bert
        // Move through the sides
505 bert
        // If we went too far to the right, appear at the far left (and vica versa)
506 bert
        if(position->x >= WINDOW_WIDTH)
507 bert
                position->x -= WINDOW_WIDTH;
508 bert
        if(position->x < 0)
509 bert
                position->x += WINDOW_WIDTH;
510 bert
 
511 bert
 
512 bert
        // Jumping
513 bert
514 114 bert
        if(input->is_pressed(A_JUMP) && !is_falling && !is_jumping && !is_frozen) {
515 108 bert
                // Start the jump
516 bert
                momentumy = MAX_MOMENTUM_JUMP;
517 bert
                is_jumping = true;
518 bert
 
519 126 bert
                Main::instance->audio->play(SND_JUMP, position->x);
520 108 bert
        }
521 114 bert
        if(!input->is_pressed(A_JUMP) && is_jumping) {
522 108 bert
                // The up key is released, so fall faster
523 bert
                is_jumping = false;
524 bert
                is_falling = true;
525 bert
        }
526 144 bert
        if(is_falling || is_jumping) {
527 108 bert
                speedy = SPEED_VERT;
528 bert
                // Increase downward momentum (= decrease upward momentum)
529 bert
                if(momentumy > -MAX_MOMENTUM_FALL) {
530 bert
                        momentumy -= MOMENTUM_INTERV_VERT;
531 bert
                // Falling is faster than jumping (also.. we start to fall faster when the
532 bert
                // up key is not held down)
533 bert
                        if(is_falling)
534 144 bert
                                momentumy  -= MOMENTUM_INTERV_VERT;
535 108 bert
                }
536 bert
        }
537 bert
 
538 bert
        speedy = (int)((double)speedy * ((double)momentumy / 10));
539 bert
 
540 bert
        // Move the player vertically
541 bert
        position->y -= speedy;
542 bert
 
543 bert
        rect.x = position->x;
544 bert
        rect.y = position->y;
545 bert
        rect.w = position->w;
546 bert
        rect.h = position->h;
547 bert
        if(is_duck) {
548 bert
                // If the player is ducking, the top should be lower
549 bert
                rect.y = position->y + (PLAYER_H - PLAYER_DUCK_H);
550 bert
                rect.h = PLAYER_DUCK_H;
551 bert
        }
552 bert
 
553 bert
        // Did we hit something?
554 bert
        if(level->is_intersecting(&rect)) {
555 bert
                if(speedy > 0) {
556 bert
                        level->bounce_tile(&rect);
557 bert
                }
558 bert
 
559 bert
                // Put the player back into the previous position
560 bert
                position->y += speedy;
561 bert
 
562 bert
                if(speedy > 0) {
563 bert
                        // Bounce off the top (bump head)
564 bert
                        is_jumping = false;
565 bert
                        is_falling = true;
566 bert
                        momentumy = 0;
567 bert
                } else {
568 bert
                        // Stop at the bottom
569 bert
                        is_jumping = false;
570 bert
                        is_falling = false;
571 bert
                        momentumy = 0;
572 bert
                }
573 bert
        }
574 bert
 
575 bert
        if(!is_jumping && !is_falling && !level->is_on_bottom(position)) {
576 bert
                // start falling when there is no bottom
577 bert
                is_falling = true;
578 bert
        }
579 bert
 
580 bert
        // Die when we fall out of the level
581 bert
        if(position->y + position->h > (14 * TILE_H)) {
582 bert
                hitpoints = 0;
583 bert
        }
584 2 bert
}
585 bert
 
586 108 bert
void Player::bounce(Player * other) {
587 bert
        SDL_Rect * rect, * source;
588 bert
 
589 bert
        rect = last_position;
590 bert
        source = other->last_position;
591 bert
 
592 bert
        int l, r, t, b;
593 bert
        int ls, rs, ts, bs;
594 bert
        bool is_above, is_below;
595 bert
        bool is_left, is_right;
596 bert
 
597 bert
        l = rect->x;
598 bert
        t = rect->y;
599 bert
        r = rect->x + rect->w;
600 bert
        b = rect->y + rect->h;
601 bert
 
602 bert
        ls = source->x;
603 bert
        ts = source->y;
604 bert
        rs = source->x + source->w;
605 bert
        bs = source->y + source->h;
606 bert
 
607 bert
        if(l - ls > (WINDOW_WIDTH / 2)) {
608 bert
                ls += WINDOW_WIDTH;
609 bert
                rs += WINDOW_WIDTH;
610 2 bert
        }
611 108 bert
        if(ls - l > (WINDOW_WIDTH / 2)) {
612 bert
                l += WINDOW_WIDTH;
613 bert
                r += WINDOW_WIDTH;
614 bert
        }
615 37 bert
 
616 108 bert
        is_above = (b <= ts);
617 bert
        is_below = (t >= bs);
618 bert
        is_left = (r <= ls);
619 bert
        is_right = (l >= rs);
620 bert
 
621 bert
        if(!is_above && !is_below && !is_left && !is_right) {
622 bert
                if(bounce_direction_y == -1) is_above = true;
623 bert
                if(bounce_direction_y == 1) is_below = true;
624 bert
                if(bounce_direction_x == -1) is_left = true;
625 bert
                if(bounce_direction_x == 1) is_right = true;
626 bert
        }
627 bert
 
628 bert
        // Players hit each others top
629 bert
        if(is_above) {
630 bert
                bounce_direction_y = -1;
631 114 bert
                if(input->is_pressed(A_JUMP)) {
632 126 bert
                        Main::audio->play(SND_JUMP, position->x);
633 108 bert
                        momentumy = MAX_MOMENTUM_JUMP;
634 bert
                        is_falling = false;
635 bert
                        is_jumping = true;
636 bert
                } else {
637 bert
                        momentumy = 30;
638 bert
                }
639 bert
        }
640 bert
        if(is_below) {
641 bert
                bounce_direction_y = 1;
642 bert
                is_duck_forced = true;
643 bert
                duck_force_start = Gameplay::frame;
644 137 bert
                momentumy = -10;
645 171 bert
                if(damage(WEIGHTCLASSES[other->weightclass].headjump_damage)) {
646 108 bert
                        other->headstomps++;
647 bert
                }
648 bert
        }
649 bert
        if(!is_above && !is_below) {
650 bert
                bounce_direction_y = 0;
651 bert
        }
652 bert
 
653 bert
        newmomentumx = momentumx;
654 bert
        // Players hit each others side
655 bert
        if(is_left || is_right) {
656 bert
                newmomentumx = other->momentumx;
657 bert
 
658 bert
                if(is_left) {
659 bert
                        bounce_direction_x = -1;
660 bert
                        newmomentumx -= WEIGHTCLASSES[other->weightclass].push_force - WEIGHTCLASSES[weightclass].push_force + 10;
661 bert
                }
662 bert
                if(is_right) {
663 bert
                        bounce_direction_x = 1;
664 bert
                        newmomentumx += WEIGHTCLASSES[other->weightclass].push_force - WEIGHTCLASSES[weightclass].push_force + 10;
665 bert
                }
666 bert
        } else {
667 bert
                bounce_direction_x = 0;
668 bert
        }
669 2 bert
}
670 bert
 
671 108 bert
void Player::bounce_up(SDL_Rect * source) {
672 bert
        is_falling = true;
673 bert
        is_frozen = true;
674 bert
        freeze_start = Gameplay::frame;
675 bert
        momentumy = WEIGHTCLASSES[weightclass].bounce_momentum_x;
676 bert
        if(position->x < source->x) {
677 bert
                momentumx -= WEIGHTCLASSES[weightclass].bounce_momentum_y;
678 bert
        }
679 bert
        if(position->x > source->x) {
680 bert
                momentumx += WEIGHTCLASSES[weightclass].bounce_momentum_y;
681 bert
        }
682 bert
        if(momentumx > MAX_MOMENTUM_HORIZ)
683 bert
                momentumx = MAX_MOMENTUM_HORIZ;
684 bert
        if(momentumx < -MAX_MOMENTUM_HORIZ)
685 bert
                momentumx = -MAX_MOMENTUM_HORIZ;
686 2 bert
}
687 bert
 
688 171 bert
bool Player::damage(int damage) {
689 bert
        if(is_shielded)
690 bert
                return true;
691 bert
 
692 bert
        if(is_dead || is_hit)
693 bert
                return false;
694 bert
 
695 bert
        is_hit = true;
696 bert
        hit_start = Gameplay::frame;
697 bert
 
698 bert
        hitpoints -= damage;
699 bert
 
700 bert
        if(hitpoints < 0)
701 bert
                hitpoints = 0;
702 bert
 
703 bert
        return true;
704 bert
}
705 bert
 
706 108 bert
void Player::process() {
707 bert
        if(is_dead)
708 bert
                return;
709 bert
 
710 114 bert
        if(input->is_pressed(A_SHOOT)) {
711 108 bert
                if(Gameplay::frame > shoot_start + WEAPONCLASSES[weaponclass].rate &&
712 bert
                        (((bullets == BULLETS_UNLIMITED) ||  bullets > 0) ||
713 bert
                        ((doubledamagebullets == BULLETS_UNLIMITED) ||  doubledamagebullets > 0) ||
714 bert
                        ((instantkillbullets == BULLETS_UNLIMITED) ||  instantkillbullets > 0))) {
715 bert
                        shoot_start = Gameplay::frame;
716 bert
                        Projectile * pr;
717 bert
                        SDL_Rect * clip_weapon;
718 bert
                        bool doubledamage;
719 bert
                        bool instantkill;
720 bert
 
721 bert
                        doubledamage = doubledamagebullets > 0;
722 bert
                        instantkill = instantkillbullets > 0;
723 bert
 
724 bert
                        clip_weapon = new SDL_Rect();
725 bert
                        if(instantkill)
726 bert
                                clip_weapon->x = 16;
727 bert
                        else if(doubledamage)
728 bert
                                clip_weapon->x = 8;
729 bert
                        else
730 bert
                                clip_weapon->x = 0;
731 bert
                        clip_weapon->y = 0;
732 bert
                        clip_weapon->w = 8;
733 bert
                        clip_weapon->h = 8;
734 bert
 
735 bert
                        pr = new Projectile(Main::graphics->weapons, clip_weapon);
736 bert
                        pr->owner = this;
737 bert
                        if(instantkill)
738 bert
                                pr->damage = 100;
739 bert
                        else if(doubledamage)
740 bert
                                pr->damage = WEAPONCLASSES[weaponclass].damage * 2;
741 bert
                        else
742 bert
                                pr->damage = WEAPONCLASSES[weaponclass].damage;
743 bert
 
744 bert
                        if(current_sprite >= SPR_L && current_sprite <= SPR_L_DUCK) {
745 bert
                                pr->speedx = -10;
746 bert
                                pr->position->x = position->x - pr->position->w - 1;
747 bert
                        } else {
748 bert
                                pr->speedx = 10;
749 bert
                                pr->position->x = position->x + position->w + 1;
750 bert
                        }
751 bert
                        if(is_duck)
752 bert
                                pr->position->y = position->y + 28;
753 bert
                        else
754 bert
                                pr->position->y = position->y + 8;
755 bert
                        Gameplay::instance->add_object(pr);
756 bert
 
757 bert
                        pr->max_distance = WEAPONCLASSES[weaponclass].distance;
758 bert
 
759 bert
                        if(instantkill)
760 bert
                                instantkillbullets--;
761 bert
                        else if(doubledamage)
762 bert
                                doubledamagebullets--;
763 bert
//                      else if(ruleset.doubledamagebullets != BULLETS_UNLIMITED)
764 bert
//                              bullets--;
765 bert
766 bert
                        bullets_fired++;
767 bert
 
768 126 bert
                        Main::instance->audio->play(SND_SHOOT, pr->position->x);
769 108 bert
                }
770 bert
        }
771 114 bert
        if(input->is_pressed(A_BOMB)) {
772 108 bert
                if(Gameplay::frame > bomb_start + bomb_delay && (bombs > 0 || bombs == -1)) {
773 bert
                        bomb_start = Gameplay::frame;
774 bert
                        Bomb * b;
775 bert
 
776 bert
                        b = new Bomb(Main::graphics->bombs);
777 bert
                        b->damage = BOMBPOWERCLASSES[bombpowerclass].damage;
778 bert
                        b->time = 60;
779 bert
                        b->frame_start = Gameplay::frame;
780 bert
                        b->frame_change_start = Gameplay::frame;
781 bert
                        b->frame_change_count = 12;
782 bert
                        b->owner = this;
783 bert
                        b->position->x = position->x + (position->w - b->position->w) / 2;
784 bert
                        b->position->y = position->y + (position->h - b->position->h);
785 bert
                        Gameplay::instance->add_object(b);
786 bert
 
787 bert
                        if(bombs != -1)
788 bert
                                bombs -= 1;
789 bert
 
790 bert
                        bombs_fired++;
791 bert
 
792 126 bert
                        Main::instance->audio->play(SND_SHOOT, b->position->x);
793 108 bert
                }
794 bert
        }
795 bert
}
796 bert
 
797 2 bert
void Player::set_sprite(int sprite) {
798 bert
        current_sprite = sprite;
799 bert
}
800 bert
 
801 bert
void Player::cycle_sprite(int first, int last) {
802 bert
        if(current_sprite < first || current_sprite > last) {
803 bert
                current_sprite = first;
804 bert
                return;
805 bert
        }
806 bert
        if(current_sprite == last)
807 bert
                current_sprite = first;
808 bert
        else
809 bert
                current_sprite++;
810 bert
}
811 bert
 
812 bert
void Player::cycle_sprite_updown(int first, int last) {
813 bert
        if(current_sprite < first || current_sprite > last) {
814 bert
                cycle_direction = CYCLE_UP;
815 bert
                current_sprite = first;
816 bert
                return;
817 bert
        }
818 bert
 
819 bert
        if(cycle_direction == CYCLE_UP && current_sprite == last) {
820 bert
                        cycle_direction = CYCLE_DN;
821 bert
        }
822 bert
        if(cycle_direction == CYCLE_DN && current_sprite == first) {
823 bert
                        cycle_direction = CYCLE_UP;
824 bert
        }
825 bert
 
826 bert
        if(cycle_direction == CYCLE_UP) current_sprite++;
827 bert
        if(cycle_direction == CYCLE_DN) current_sprite--;
828 3 bert
}