Ben Evans / Mbed 2 deprecated Defender_Game

Dependencies:   mbed

GameEngine/GameEngine.cpp

Committer:
evanso
Date:
2020-05-19
Revision:
44:2d957de3bce3
Parent:
42:3aed75338272
Child:
45:fc3238cd28c6

File content as of revision 44:2d957de3bce3:

#include "GameEngine.h"

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();
    
    // Set seed value 
    srand(pad.read_adc()*64000);
    
    // Assign values to variables
    spawn_alien_rate = 250;
    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();
    g_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 (g_lcd_frame_time_flag) {
            // resets ISR flag 
            g_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 
    create_weapons_bullets();
    create_weapons_smart_bomb();
    spawn_aliens();
    spawn_people();

    //If spaceship is destroyed stop joystick input, dont draw spaceship sprite
    if (!spaceship_destroyed){
        read_joystick_direction();
        spaceship.movement(d_);
        spaceship.draw(lcd);
    }
    
    // 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
    g_lcd_frame_time_flag = 1; 
} 



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

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

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();
    }
    
    //slowley incresing the alien counter as game goes on to make harder
    //int rounded_spawn_rate = floor(spawn_alien_rate);
    if(spawn_alien_counter%750 ==  0){
      //alien_number_counter++;      
    }
    
    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);      
    }
}