ELEC2645 (2018/19) / Mbed 2 deprecated el17szs

Dependencies:   mbed

Cricket/Cricket.cpp

Committer:
shahidsajid
Date:
2019-05-09
Revision:
35:dc957021982c
Parent:
34:d9099874bbc3

File content as of revision 35:dc957021982c:

#include "Cricket.h"

#define BALL_LIIMT 10

//Constructor for the Cricket Object
Cricket::Cricket()
{

}
//Deconstructor for the Cricket Object
Cricket::~Cricket()
{

}
/*Initialises the Ball Object
  Initialises all the game objects
  sets the cricekt game variabes to intitial values
*/
void Cricket::init(int ball_size,int bat_width,int bat_height)
{
   _ux.init();
   _bat.init(bat_width,bat_height);
   _ball.init(ball_size);
   _scoreboard.init();
   _new_round=1;
   direction_set=0;
   _new_game=1;
   _fielders_count=0;
   _init_field_counter=0;
   init_positions();  //sets the positions for ball to be hit
   _set_hit=0;
   _set_loft=0;
   _position_no=-1;
   _check_bowled=0;
   _ball_limit=BALL_LIIMT;
   _check_hit=0;
   _loft_check=0;
   _check_update=-1;
}

//Resets the game variables for each round
void Cricket::round_reset(){
   _ball.reset();
   _bat.reset();
   _new_round=0;
   direction_set=0;
   _fielders_count=0;
   _loft_check=0;
   _check_hit=0;
   _set_hit=0;
   _set_loft=
   _init_field_counter=0;
   init_positions();
   _position_no=-1;
   _check_bowled=0;
   _check_update=-1;
}
//resets the ux method and the game variables for start of new game.
void Cricket::game_reset(){
    //pad.leds_off();
    _ux.reset();
    round_reset();
    _new_game=1;
    _scoreboard.reset(); //sets score to 0
    _ball.reset_ball_count(); //sets ball count to 0
}

//Calls the first menu when game is booted up

void Cricket::intro(N5110 &lcd){
    _ux.first_menu(lcd);
}
/* Method checks the state of the game (start of new game or round) 
   and calls play_game() accordingly. */
void Cricket::game(N5110 &lcd,Gamepad &pad){
     if (_new_game==1){  //_new_game acts as a flag to start a new game
         _scoreboard.generate_target();
         _ux.second_menu(lcd);  //calls the second menu giving user option to start game or read options 
         _new_game=0;
     }
     if (_new_round==1){
        if (game_status(lcd)==false){ //game_status returns false if the game is over
            game_reset(); //resets the game
        }
        else{  
          pad.leds_off();
          round_reset();  //resets the round variables
          set_field(lcd); //randomly sets a new field for each round
          _ball.increment_ball_count(); 
          play_game(lcd,pad); 
          _new_round=0;
        }
    }
    else{
        play_game(lcd,pad);
    }
}
/*Method to check current status of the game
  returns false is game is over and true if not */
bool Cricket::game_status(N5110 &lcd){
    if (_scoreboard.compare_target()==true){   //checks if the player has reached the target score
             //printf("TARGET BLOCK"); //used for debugging
             _ux.victory_menu(lcd);
             game_reset();
             return false;
        }
        //checks if player has balls played has reached the limit
        else if(check_ball_count(lcd)==true){
           _ux.game_over_menu(lcd,1);
           game_reset();
           return false;
        }
        else{
            return true;
        }
}
/*Boolean function that checks if the current ball count has reached ball limit
 returns true if ball limit has been reached */
bool Cricket::check_ball_count(N5110 &lcd){
    int count=_ball.get_ball_count(); //gets ball_count from ball object
    if (count==_ball_limit){
        _new_round=1;
        _ball.reset_ball_count();
        _new_game=1;
        return true;
    }
    else{
        return false;
    }
}
/*Method that checks if the target score has been accomplished
  and if true prints the Game Won screen */
void Cricket::check_victory(N5110 &lcd){
    bool _victory_check=_scoreboard.compare_target();
        if (_victory_check==true){
            _ux.victory_menu(lcd);
            _new_game=1;
            _ball.reset_ball_count();
        }
}

/*Initialises te positions for the ball to be hit
  The ball can be hit in 7 positions in the game 
  according to the joystick orientation */
void Cricket::init_positions(){
    set_init_positions(42,15,N,1);
    set_init_positions(84,30,E,2);
    set_init_positions(0,30,W,3);
    set_init_positions(2,44,SW,4);
    set_init_positions(0,2,NW,5);
    set_init_positions(65,2,NE,6);
    set_init_positions(60,44,SE,7);
}
/*Method to set the ball hit positions*/
void Cricket::set_init_positions(int x,int y, Direction direction,int no){
    positions[_init_field_counter].x=x;
    positions[_init_field_counter].y=y;
    positions[_init_field_counter].dir=direction;
    positions[_init_field_counter].no=no;
    _init_field_counter++;
}
/*Method takes user input and sets the flags for the game accordingly */
void Cricket::play_game(N5110 &lcd,Gamepad &pad){
    _check_hit=_bat.get_hit_ball(_ux); //checks if the ball has been hit
    if (_check_hit==1){
        _set_hit=1;
    }
    _loft_check=_bat.get_loft_ball(_ux); //checks if the ball hit is lofted
    if (_loft_check==1){
        _set_loft=1;
    }
    Direction dir=pad.get_direction(); //sets ball direction 
    if (_check_bowled!=1){ //checks if the ball has been bowled
        _check_bowled=_ball.ball_start(pad);
    }
    else{
        update_game(_set_hit, _set_loft, dir,pad,lcd); //updates the game
    }
}
void Cricket::update_game(int checkHit,int _loft_check, Direction dir,Gamepad &pad,N5110 &lcd){
  set_ball_direction(dir); //sets the direction for ball to be hit
  int fielder_check=check_fielder(ball_direction); //checks if there is a fielder in direction of ball
  
  if (checkHit!=1){ //checks if ball has been hit
      batsman_out(2,pad,lcd); //if false, batsman is out and game over
  }    
  if(direction_set==1 && checkHit==1){ //if direction is set and ball is hit game continues
  // checks if there is a fielder present in the direction of ball hit
  if (fielder_check!=-1){ 
     int _check_update=_ball.update_ball(field[fielder_check].x,field[fielder_check].y); //checks for position of ball
     
     //printf("Location x %i y %i\n",field[fielder_check].x,field[fielder_check].y);
     
     if (_loft_check==1){ //checks if hit is lofted
         if (_check_update==1) 
           batsman_out(3,pad,lcd); //lofted hit to a fielder is out and game over
     }
     //if batsman is not out, scoreboard is updating according to the runs scored
     else
         update_scoreboard(_check_update,field[fielder_check].position+1,pad);
        /*position+1 is used for runs argument  because a fielder inside the circle has position 0 and prodices 1 run
          whereas a fielder outside the circle has position number 1 and produces 2 runs. */
  }
  //If there is no fielder present
  if (fielder_check==-1){
        _check_update=_ball.update_ball(positions[_position_no].x,positions[_position_no].y);
        //printf("location x %i y %i\n  update %i\n",positions[_position_no].x,positions[_position_no].y,_check_update);
        if (_loft_check==1)
         update_scoreboard(_check_update,6,pad); //lofted shot in the gap is 6 runs
        else
            update_scoreboard(_check_update,4,pad); //normal shot in the gap is 4 runs
    }
}
}

/* Method to update the score of the game
   Takes runs and check_update as arguments */
void Cricket::update_scoreboard(int check_update, int runs,Gamepad &pad){
    //runs can only be updated after the ball has reached the destination co-ordinates
    if (check_update==1){ 
       /* if ball is hit straight there are no runs given
          This was done because hitting straight would form an easy way
          of scoring runs every round and would not make the game challenging */
        if (ball_direction==N){
            _scoreboard.update_score(0);
            pad.led(3,1.0);
            wait(0.5);
            _new_round=1;
        }
        else{
            _scoreboard.update_score(runs);
            pad.led(3,1.0);  //LED flashes to inform user that runs has been updated and get ready for new round
            wait(0.5);
            _new_round=1;
        }
    }
    pad.leds_off();
}
/*Method when batsman is out and game is over
  Method resets game and prints a screen to the LCD to inform user that game is over
*/
void Cricket::batsman_out(int option,Gamepad &pad, N5110 &lcd){
    _scoreboard.reset();
    pad.led(1,1.0); //red LED indicates that the game is over
    pad.tone(750.0,0.5); //tone indicates that game is over
    _ball.reset_ball_count();
    _ux.game_over_menu(lcd,option);
    game_reset();
    _new_game=1;
    wait(2);
    pad.leds_off();
}
//Draws all the components of the Cricket to the LCD
void Cricket::draw(N5110 &lcd){
    lcd.drawCircle((WIDTH/2),HEIGHT/2,23,FILL_TRANSPARENT);
    lcd.drawRect(37,11,12,30,FILL_TRANSPARENT);
    //calls draw method of game objects
    _ball.draw(lcd);
    draw_field(lcd);
    _bat.draw(lcd);
    _scoreboard.draw(lcd);
}
//Method to set the ball direction
void Cricket::set_ball_direction(Direction dir){
    if (direction_set!=1){
        for (int i=0;i<_init_field_counter+1;i++){
            if(dir==positions[i].dir){
                ball_direction=dir;
                printf(" BALL DIRECTION %i x %i y %i \n",positions[i].no,positions[i].x,positions[i].y);
                _position_no=i; //index of direction in array is stoed in the variable
                direction_set=1; //toggles direction_set flag
                break;
            }
        }
    }
}
/*Method that checks if a fielder is present in the direction of the ball*/
int Cricket::check_fielder(Direction dir){
    if (dir==N){
        return -1;
    }
    /*loops through fielder array and checks if fielder is present in the direction*/
    for (int i=0;i<8;i++){
      if(dir == field[i].dir){
         return i;
     }
   }
   //returns -1 if no fielder is present
   return -1;
  }
/*Draws the fielders by printing each fielder in the array to the LCD*/
void Cricket::draw_field(N5110 &lcd){
    lcd.drawCircle(field[0].x,field[0].y,2,FILL_TRANSPARENT);
    lcd.drawCircle(field[1].x,field[1].y,2,FILL_TRANSPARENT);
    lcd.drawCircle(field[2].x,field[2].y,2,FILL_TRANSPARENT);
    lcd.drawCircle(field[3].x,field[3].y,2,FILL_TRANSPARENT);
    lcd.drawCircle(field[4].x,field[4].y,2,FILL_TRANSPARENT);
}
/*Method to set the fielders for the game 
 Loops through a for loop 6 times, generating a random number each time
 and sets a fielder based on the randon number*/
void Cricket::set_field(N5110 &lcd){
    int d=0;
    int pos=0;
    int i=0;
    int continueCount=0;
    srand(time(NULL));
    while (_fielders_count!=5){
        d = 1+ rand() % 6;
        pos=rand()%2;
        for (int j=0;j<10;j++){
           //checks if the number generated has already been used to set a fielder
           if (fieldNumbers[j]==d){
                continueCount=1;
            }
        }
        if (continueCount==1){
            continueCount=0;
            continue;
        }
        //sets fielders based on random number generated
        if (d==1){ //NW
            if (pos==1){
              field[i].dir=NW;
              field[i].x=30;
              field[i].y=9;
              field[i].position=1;
              fieldNumbers[i]=d;
              i++;
              _fielders_count++;
            }
            else{
              field[i].dir=NW;
              field[i].x=25;
              field[i].y=2;
              field[i].position=0;
              fieldNumbers[i]=d;
              i++;
              _fielders_count++;
            }
        }

        if (d==2){ //NE
            if (pos==1){
            field[i].dir=NE;
            field[i].x=55;
            field[i].y=9;
            field[i].position=1;
            fieldNumbers[i]=d;
              i++;
              _fielders_count++;
            }
            else{
            field[i].dir=NE;
                field[i].x=65;
                 field[i].y=2;
                 field[i].position=0;
                 fieldNumbers[i]=d;
                  i++;
                  _fielders_count++;
            }
        }
        if (d==3){ //SW
            if (pos==1){
                field[i].dir=SW;
                field[i].x=33;
                field[i].y=40;
                field[i].position=1;
                fieldNumbers[i]=d;
                i++;
                _fielders_count++;
            }

            else{
              field[i].dir=SW;
              field[i].x=25;
              field[i].y=44;
              field[i].position=0;
              fieldNumbers[i]=d;
              i++;
              _fielders_count++;
            }
        }
        if (d==4){ //SE
            if (pos==1){
              field[i].dir=SE;
              field[i].x=55;
              field[i].y=40;
              field[i].position=1;
              fieldNumbers[i]=d;
              i++;
              _fielders_count++;
            }
            else{
              field[i].dir=SE;
              field[i].x=65;
              field[i].y=44;
              field[i].position=0;
              fieldNumbers[i]=d;
              i++;
              _fielders_count++;
            }
        }

        if (d==5){ //W
            if (pos==1){
              field[i].dir=W;
              field[i].x=3;
              field[i].y=30;
              field[i].position=1;
              fieldNumbers[i]=d;
              i++;
              _fielders_count++;
            }
            else{
              field[i].dir=W;
              field[i].x=25;
              field[i].y=30;
              field[i].position=0;
              fieldNumbers[i]=d;
              i++;
              _fielders_count++;
            }
        }
        if (d==6){ //W
            if (pos==1){
                field[i].dir=E;
                field[i].x=80;
                field[i].y=30;
                field[i].position=1;
                fieldNumbers[i]=d;
                i++;
                _fielders_count++;
            }
            else{
                 field[i].dir=E;
                field[i].x=60;
                field[i].y=30;
                field[i].position=0;
                fieldNumbers[i]=d;
                i++;
                _fielders_count++;
            }
        }
  }
}