Ben Evans / Mbed 2 deprecated Defender_Game

Dependencies:   mbed

GameEngine/GameEngine.cpp

Committer:
evanso
Date:
2020-05-19
Revision:
49:ed569eceeaa4
Parent:
47:49fa1adc10b4
Child:
51:35cb8e604b72

File content as of revision 49:ed569eceeaa4:

#include "GameEngine.h"
  
/** Define acelleromter object */
FXOS8700CQ accelerometer(I2C_SDA,I2C_SCL);

/** Define SD card object */
SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd");

GameEngine::GameEngine() {
    //attach ticker to isr 
    ticker.attach(callback(this, &GameEngine::lcd_frame_time_isr), 0.04 );
}
 
GameEngine::~GameEngine() {
    
}

void GameEngine::init() {
    // Initalise objects
    pad.init();
    lcd.init();
    spaceship.init();
    map.init(pad);
    menu.init();
    accelerometer.init();
    
    // Set seed value 
    srand(pad.read_adc()*64000);
    
    // Assign values to variables
    spawn_time_multipler_ = 1;
    alien_number_counter_ = 3;
    spawn_alien_counter_ = 0;
    spaceship_lives_ = 3;
    spaceship_destroyed_ = false;
    reset_map_counter_ = 0;
    smart_bomb_counter_ = 4;
    create_people();
    points_ = 0;
    smart_bomb_timer_ =  0;
    bullet_timer_ = 0;
    current_menu_part_= menu.get_current_menu_part();
    lcd_frame_time_flag_ = 0;
}

// Menu Control-----------------------------------------------------------------

void GameEngine::game_select_part(){
    switch (current_menu_part_) {
    case main_menu: run_menu(); break;
    case play: run_play(); break;
    case settings: run_settings(); break;
    case saved_games: run_saved_games(); break;
    }
}

void GameEngine::run_menu(){
    lcd.setContrast(pad.read_pot1());          
    lcd.clear();
    
    // Scrolls, draws and selcts menu parts
    read_joystick_direction();
    menu.menu_scroll(pad, d_);
    menu.draw_part(lcd);  
    menu.select_part(lcd, pad);
    
    current_menu_part_ = menu.get_current_menu_part();
    
    lcd.refresh(); 
}

void GameEngine::run_play(){
    while (1) {             
     // Checks flag and prints spaceship on lcd then resets flag
        if (lcd_frame_time_flag_) {
            // resets ISR flag 
            lcd_frame_time_flag_ = 0; 
            
            gameplay_loop(); 
            
            // break out of game loop when lives = 0
            if(!spaceship_lives_){
                break;
                
            } 
        }
        
        // MCU put to sleep between each frame to save power 
        sleep();    
    }
    lcd.clear();
    lcd.printString("Game Over",15,3);
    lcd.refresh();
    wait(3);
    current_menu_part_ = main_menu;
}

void GameEngine::gameplay_loop() {

    // clear screen and set contrast
    lcd.setContrast(pad.read_pot1());          
    lcd.clear();
    
    // creat objects 
    spawn_aliens();
    spawn_people();

    //If spaceship is destroyed stop joystick input, dont draw spaceship sprite
    if (!spaceship_destroyed_){
        //read_joystick_direction();
        read_accelerometer_direction();
        spaceship.movement(d_);
        spaceship.draw(lcd);
        create_weapons_bullets();
        create_weapons_smart_bomb();
    }
    
    // Draws objects
    map.draw_map(lcd, d_);
    draw_aliens();
    draw_bullets();
    draw_explosions();
    draw_people(); 
    hud.draw_HUD(lcd, spaceship_lives_, points_, smart_bomb_counter_);
    spaceship_lives_leds();
    
    reset_map_timer();
    
    // refresh's screen
    lcd.refresh(); 
}

void GameEngine::run_settings(){
    
}

void GameEngine::run_saved_games(){
    
}

void GameEngine::lcd_frame_time_isr(){
    // set ISR flag
    lcd_frame_time_flag_ = 1; 
} 



//Spaceship control ------------------------------------------------------------

void GameEngine::read_joystick_direction(){
    d_ = pad.get_direction();
}

void GameEngine::read_accelerometer_direction(){  
    float roll = accelerometer.get_roll_angle();
    float pitch = accelerometer.get_pitch_angle();
    // printf("Pitch = %f  Roll = %f\n", pitch, roll);  
     
    //north
    if(pitch >= -35){
        if(roll >= 10){
            d_ = NE;
        }else if (roll <= -10){
            d_ = NW;
        }else {
            d_ = N;
        }
    //south
    }else if(pitch <= -55){
        if (roll >= 10){
            d_ = SE;
        }else if(roll <= -10){
            d_ = SW;
        }else {
            d_ = S; 
        }
    // East/west
    }else {
        if (roll >= 10){
            d_ = E;
        }else if(roll <= -10){
            d_ = W;
        }else{
            d_ = CENTRE;
        }
    }      
}

void GameEngine::spaceship_lives_leds(){
    pad.leds_off(); 
    
    //top two red leds on if 1 lives left
    if(spaceship_lives_ >= 1){
        pad.led(1,1); 
        pad.led(4,1);
    }
    
    //middle two orange leds also on if 2 lives left
    if(spaceship_lives_ >= 2){
        pad.led(2,1);
        pad.led(5,1);
    }
    
    //bottom two red leds also on if 3 lives left
    if(spaceship_lives_ == 3){
        pad.led(3,1);
        pad.led(6,1);
    }
}



//Weapon control ---------------------------------------------------------------

void GameEngine::create_weapons_bullets(){
// controlls speed that bullet can be fired
if(bullet_timer_ <=0){
    if (pad.A_pressed()){
    // Bullet object
    Weapons new_bullet;
        
    new_bullet.init(spaceship.get_pos(), 
    spaceship.get_spaceship_sprite_direction(), true);
        
    // Stores bullet object in vector 
    bullet_vector.push_back(new_bullet);
    } 
    bullet_timer_ =  5;   
}
bullet_timer_--;   
}

void GameEngine::create_weapons_smart_bomb(){
// timer to stop smart bomb button be accidently pressed twice
if(smart_bomb_timer_ <=0){    
    if (pad.B_pressed() && smart_bomb_counter_ > 0){
        weapons.smart_bomb(lcd);
        smart_bomb_counter_--;
            
        //Deletes alien object if on screen
        for (int i = (alien_vector.size() -1) ; i >= 0 ; i--){
            Vector2D alien_pos = alien_vector[i].get_pos(); 
            
            // Creats explosion if alien was on the screen    
            if(alien_pos.x <= 84 && alien_pos.x >= -6){
                create_explosion(alien_pos); 
                
                //delete person object if was being abducted by destroyed alien
                if(alien_vector[i].get_collision_people_element() > -1){
                    people_vector.erase(people_vector.begin() + 
                    alien_vector[i].get_collision_people_element()); 
                } 
                
                alien_vector.erase(alien_vector.begin()+ i);
                points_ ++;  
            }
        }
    smart_bomb_timer_ =  30;   
    } 
} 
smart_bomb_timer_--;
}

void GameEngine::draw_bullets(){
    // interates over bullet vectors, moves and draws bullet objects
    
    // Alien bullets
    for (int i = 0; i < alien_bullet_vector.size(); i++){
        alien_bullet_vector[i].draw_alien_bullet(lcd, d_);
        
        // deletes alien bullet object after bullet has moved set distance   
        if(alien_bullet_vector[i].get_bullet_delete_counter() >> 5){
             alien_bullet_vector.erase(alien_bullet_vector.begin()+ i);
        }
        
        // Deletes bullet and shpaceship if collision detected
        if (spaceship.check_collision(alien_bullet_vector[i]) && 
        !spaceship_destroyed_ ){
            create_explosion(spaceship.get_pos());
            
            spaceship_destroyed_ = true;
            alien_bullet_vector.erase(alien_bullet_vector.begin()+ i);     
        }
    }
    
    // Spaceship bullets 
    for (int i = 0; i < bullet_vector.size(); i++){
        bullet_vector[i].draw_bullet(lcd);
         
        // deletes bullet object after bullet has moved set distance   
        if(bullet_vector[i].get_bullet_delete_counter() >> 5){
             bullet_vector.erase(bullet_vector.begin()+ i);
        }
    }
}



//Alien Control ----------------------------------------------------------------

void GameEngine::spawn_aliens(){
    if(alien_vector.size() <= alien_number_counter_){
        create_alien();
    }
    
    //printf( " alien_number_counter_ = %d\n",alien_number_counter_);
    
    //slowley incresing the alien counter as game goes on to make harder
    if(spawn_alien_counter_%(500*spawn_time_multipler_) ==  0){
        alien_number_counter_++;
        spawn_time_multipler_++;      
    }
    
    spawn_alien_counter_++;
}

void GameEngine::create_alien(){
    int position_x_start = 0;
    
    // Alien object
    Alien new_alien;
    
    //spawns aliens between x > 84 and x <0
    if(rand() % 2){
        position_x_start = rand() % 84 + 84;
    }else{
        position_x_start =rand() % 83 - 84;
    } 
    new_alien.init(pad, position_x_start, (rand() % 33 + 9));
    
    // Stores alien object in vector 
    alien_vector.push_back(new_alien);
}

void GameEngine::check_alien_people_collision(int i){
    // only a collision if all three of theses conditions are met:
    // check all these codition for every alien to every person
    // 1)person hasn't already had a collision
    // 2)There is an acutaual collision of people and alien
    for (int x = 0; x < people_vector.size(); x++){
        if (!people_vector[x].get_alien_collision_flag() &&
            people_vector[x].check_alien_collision(alien_vector[i])){  
            alien_vector[i].set_collision_people_element(x); 
        }
    }
    
    //draws collision if detected
    if(alien_vector[i].get_collision_people_element() > -1){
        alien_vector[i].draw_alien(lcd,spaceship.get_pos(),d_, 
        map.get_length_map(), map.get_position_x_map(),true);
    }else{
        alien_vector[i].draw_alien(lcd,spaceship.get_pos(),d_, 
        map.get_length_map(), map.get_position_x_map(),false);
    }    
}

void GameEngine::alliens_fire_bullets(int i){
    if (alien_vector[i].get_alien_fire_counter()%60 == 0){
        Weapons alien_bullet;
            
        // fires bullet towards direction of spaceship
        bool alien_bullet_direction = false;
        Vector2D spaceship_pos = spaceship.get_pos();
        Vector2D alien_pos = alien_vector[i].get_pos();
        if(spaceship_pos.x > alien_pos.x){
            alien_bullet_direction = true;
        }
            
        alien_bullet.init(alien_vector[i].get_pos(), 
        alien_bullet_direction , false);
        
        // Stores bullet object in vector 
        alien_bullet_vector.push_back(alien_bullet); 
    }   
}

void GameEngine::delete_aliens(int i){
    for (int x = 0; x < bullet_vector.size(); x++){
        if (alien_vector[i].check_collision(bullet_vector[x])){
            create_explosion(alien_vector[i].get_pos());
                
            //delete person object if was carried by destroyed alien
            if(alien_vector[i].get_collision_people_element() > -1){
                people_vector.erase(people_vector.begin() + 
                alien_vector[i].get_collision_people_element()); 
            }
            
            bullet_vector.erase(bullet_vector.begin()+ x);    
            alien_vector.erase(alien_vector.begin()+ i);  
            points_ ++;   
        }
    }   
}

void GameEngine::draw_aliens(){
    // interates over alien vector and draws each new_alien object 
    for (int i = 0; i < alien_vector.size(); i++){
        
        check_alien_people_collision(i);
        
        // deleted spaceship if alien ship touches spaceship
        if (spaceship.check_alien_collision(alien_vector[i]) && 
        !spaceship_destroyed_){
            create_explosion(spaceship.get_pos());
            spaceship_destroyed_ = true;  
        }
        
        alliens_fire_bullets(i);
        
        delete_aliens(i);
    }
}



//Explotion Control ------------------------------------------------------------   

void GameEngine::create_explosion(Vector2D destroyed_position){
    // explosion object
    Explosion new_explosion;
    
    new_explosion.init(destroyed_position);
    
    // Stores explosion object in vector 
    explosion_vector.push_back(new_explosion);
}

void GameEngine::draw_explosions(){
    // interates over expoltion vector and draws each explosion object then 
    // deleted object after set size
    for (int i = 0; i < explosion_vector.size(); i++){
        explosion_vector[i].draw_explosion(lcd);
        
        // delete explosion after reaches set size
        if(explosion_vector[i].get_explosion_radius() == 8){
             explosion_vector.erase(explosion_vector.begin()+ i);    
        }
    }
}



//People Control ---------------------------------------------------------------

void GameEngine::spawn_people(){
    // Keeps number of people objects constant as people objecs are erased
    if(people_vector.size() <= 5){
        create_people();
    }
}

void GameEngine::create_people(){
    // People object
    People people;
    
    people.init(pad, (rand() % 168 - 84));
    
    // Stores alien object in vector 
    people_vector.push_back(people);
}

void GameEngine::draw_people(){
    for (int i = 0; i < people_vector.size(); i++){
        people_vector[i].draw_people(lcd, d_, 
        map.get_length_map(), map.get_position_x_map());  
        
        //errase person if at top of screen as captured by alien and alien is 
        //set to track mode
        Vector2D people_pos =  people_vector[i].get_pos();
        
        for (int x = 0; x < alien_vector.size(); x++){
        Vector2D alien_pos = alien_vector[x].get_pos();
            if(people_pos.y < 30 && alien_pos.y < 9){
                    
                //set alien who abducted person to track mode
                if(alien_vector[x].get_collision_people_element() == i){
                   alien_vector[x].set_track_flag(true);
                    people_vector.erase(people_vector.begin()+ i); 
                }  
               
            }  
           
        }
    }
}



//Map Control-------------------------------------------------------------------

void GameEngine::reset_map_timer(){
if(spaceship_destroyed_){
    reset_map_counter_++; 
    
    // stops map movement
    d_ = CENTRE;
    
    // reset map after set time
    if(reset_map_counter_ == 50){
        reset_map();
    }
}   
}
   
void GameEngine::reset_map(){
    // Reassign values to variables
    spaceship.init();
    spaceship_lives_--;
    spaceship_destroyed_ = false;
    reset_map_counter_ = 0;
    
    // erase aliens so redrawn in random positions when respawning spaceship
    for (int i = (alien_vector.size() - 1); i >= 0 ; i--){
        alien_vector.erase(alien_vector.begin()+ i);  
    }
    
    // erase all people so redrawn at bottom of map
    for (int i = (people_vector.size() - 1); i >= 0 ; i--){
         people_vector.erase(people_vector.begin()+ i);      
    }
    
    // erase all alien bullets
    for (int i = (alien_bullet_vector.size() - 1); i >= 0 ; i--){
         alien_bullet_vector.erase(alien_bullet_vector.begin()+ i);      
    }
}