A rouge-like rpg, heavily inspired on the binding of isaac. Running on a FRDM-K64F Mbed board. C++.

Dependencies:   mbed MotionSensor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Player.cpp Source File

Player.cpp

00001 #include "Player.h"
00002 #include "math.h"
00003 
00004 // Constructor
00005 Player::Player(float pos_x, float pos_y)
00006 {
00007     _hp = 3;
00008     _attack = 1;
00009     _face = 2;
00010     
00011     _hitbox.width = 6;
00012     _hitbox.height = 5;
00013     
00014     _position.x = pos_x;
00015     _position.y = pos_y;
00016     
00017     _sprite_size.width = 6;
00018     _sprite_size.height = 12;
00019     _sprite_size.offset_x = 0;
00020     _sprite_size.offset_y = -7;
00021     
00022     _frame.count = 0;
00023     _frame.number = 0;
00024     _frame.max = 4;
00025     
00026     for (int i = 0; i < bullets_max; i++) {
00027         valid_bullets[i] = false;
00028     }
00029     
00030     _invulnerability_counter = INVULNERABILITY_PERIOD;
00031 
00032     // Upgradable status
00033     _fire_rate_delay = 30;
00034     _fire_rate_counter = _fire_rate_delay;
00035     _velocity = 0.7;
00036     _bullet_speed = 1;
00037 }
00038 
00039 Player::~Player()
00040 {
00041     delete_bullets();
00042 }
00043 
00044 // Accessors
00045 int Player::get_bullet_speed()
00046 {
00047     return _bullet_speed;
00048 }
00049 int Player::get_hearts_width()
00050 {
00051     return 9;
00052 }
00053 int Player::get_hearts_height()
00054 {
00055     return 9;
00056 }
00057 char * Player::get_hearts_sprite()
00058 {
00059     return (char *) sprite_heart;
00060 }
00061 
00062 // Functions
00063 void Player::move(float mapped_x, float mapped_y, char * map, bool * doorways)  // Update all bullet movement and player movement, also takes care of animation
00064 {
00065     move_player(mapped_x, mapped_y, map, doorways);
00066     move_bullets();
00067     increment_frames(mapped_x, mapped_y);   // Sets the face of the person, and increment frame count
00068     _invulnerability_counter++;  // for damage checking
00069 }
00070 
00071 void Player::move_player(float mapped_x, float mapped_y, char * map, bool * doorways)   // Moves the player unless if the player walks onto a wall
00072 {
00073     update_prev_pos();
00074     _position.y -= _velocity*mapped_y;
00075     _position.x += _velocity*mapped_x;
00076     
00077     undo_move_x(entity_to_map_collision_test(_position.x, _prev_pos.y, map, doorways));
00078     undo_move_y(entity_to_map_collision_test(_prev_pos.x, _position.y, map, doorways));
00079 }
00080 
00081 void Player::move_bullets() // For each bullet, move them
00082 {
00083     for (int i = 0; i < bullets_max; i++) {
00084         if (valid_bullets[i]) {
00085             bullets_array[i]->move(get_bullet_speed(), 0, 0, (bool *) 0);
00086         }
00087     }
00088 }
00089 
00090 void Player::increment_frames(float mapped_x, float mapped_y)
00091 {
00092     if (abs(mapped_x) + abs(mapped_y) > 0.1f) { // If player is moving
00093         if (mapped_y < 0 && abs(mapped_y) > abs(mapped_x)) {
00094             _face = 2;
00095         } else if (mapped_y > 0 && abs(mapped_y) > abs(mapped_x)) {
00096             _face = 0;
00097         } else if (mapped_x > 0 && abs(mapped_x) > abs(mapped_y)) {
00098             _face = 1;
00099         } else if (mapped_x < 0 && abs(mapped_x) > abs(mapped_y)) {
00100             _face = 3;
00101         }
00102         if (_frame.number < _frame.max) { // Animate frames by incrementing and reseting frames
00103             _frame.count++;
00104         } else {
00105             _frame.count = 0;
00106         }
00107     } else {
00108         _frame.count = 0;    // If the player is not moving, don't animate
00109     }
00110     _frame.number = (_frame.count/8) % _frame.max; // Frame number is used in chosing sprite-frame for animation; the constant 8 is the number of frames per sprite-frame
00111 }
00112 
00113 void Player::take_damage(int damage)    // Takes damage unless if player just got damaged within invulnerability period
00114 {
00115     if (damage < 0){
00116         _hp -= damage;
00117     }
00118     else if (_invulnerability_counter >= INVULNERABILITY_PERIOD) {
00119         _hp -= damage;
00120         _invulnerability_counter = 0;
00121     }
00122     if (_hp > 5) {   // Max HP is a constant 5, this might be an upgradable status later
00123         _hp = 5;
00124     }
00125 }
00126 
00127 bool Player::delete_out_of_bounds_bullets(char * map, bool * doorways)  // Attempts to delete bullets that are out of bounds or colliding with the wall, returns true if any bullets are deleted
00128 {
00129     bool result = false;
00130     for (int i = 0; i < bullets_max; i++) {
00131         if((valid_bullets[i]) && (bullets_array[i]->out_of_bounds_check(map, doorways))) {
00132             valid_bullets[i] = false;
00133             delete bullets_array[i];
00134             result = true;
00135         }
00136     }
00137     return result;
00138 }
00139 
00140 void Player::draw(N5110 &lcd)
00141 {
00142     draw_player(lcd);
00143 }
00144 
00145 void Player::draw_player(N5110 &lcd)
00146 {
00147     lcd.drawSpriteTransparent(_position.x+_sprite_size.offset_x,
00148                               _position.y+_sprite_size.offset_y,
00149                               _sprite_size.height,
00150                               _sprite_size.width,
00151                               get_frame());
00152 }
00153 
00154 void Player::draw_bullets(N5110 &lcd, int j)
00155 {
00156     for (int i = 0; i < bullets_max; i++) {
00157         if ((valid_bullets[i]) && (bullets_array[i]->get_pos_y() == j)) {
00158             bullets_array[i]->draw(lcd);
00159         }
00160     }
00161 }
00162 
00163 void Player::delete_bullets()   // Delete all bullets, normally used in unloading
00164 {
00165     for (int i = 0; i < bullets_max; i++) {
00166         if (valid_bullets[i]) {
00167             delete bullets_array[i];
00168             valid_bullets[i] = false;
00169         }
00170     }
00171 }
00172 
00173 char * Player::get_frame()  // Returns the current frame's sprite pointer
00174 {
00175     if ((_invulnerability_counter < INVULNERABILITY_PERIOD) && (_invulnerability_counter % 10 <= 4)) {
00176         return (char*) sprite_transparent_player;
00177     }
00178     return (char *) sprite_player[_face][_frame.number];
00179 }
00180 
00181 void Player::buttons(bool button_A, bool button_B, bool button_Y, bool button_X)    // Summons new bullets and overloads the player face when buttons are pressed
00182 {
00183     _fire_rate_counter++;
00184     if (button_Y) {
00185         _face = 0;
00186     } else if (button_B) {
00187         _face = 1;
00188     } else if (button_A) {
00189         _face = 2;
00190     } else if (button_X) {
00191         _face = 3;
00192     }
00193     if (button_Y || button_B || button_A || button_X) {
00194         for (int i = 0; i < bullets_max; i++) {
00195             if (!valid_bullets[i] && (_fire_rate_counter >= _fire_rate_delay)) {  // waits until _fire_rate_delay is done before creating a bullet in an invalid slot of bullet_array
00196                 bullets_array[i] = new Bullets(_position.x+2, _position.y+2, _face);
00197                 valid_bullets[i] = true;
00198                 _fire_rate_counter = 0;
00199                 break;
00200             }
00201         }
00202     }
00203 }