Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
00001 /* 00002 ELEC2645 Embedded Systems Project 00003 School of Electronic & Electrical Engineering 00004 University of Leeds 00005 Name: James Nathan Cummins 00006 Username: el17jnc 00007 Student ID Number: 201096364 00008 Date: 22/03/19 00009 */ 00010 00011 #include "Gamepad.h" 00012 #include "mbed.h" 00013 #include "N5110.h" 00014 #include "BrickBreakerEngine.h" 00015 #include "ClassicEngine.h" 00016 #include "OptionsEngine.h" 00017 #include "SDFileSystem.h" 00018 00019 #ifdef WITH_TESTS 00020 #include "tests.h" 00021 #endif 00022 00023 #define RADIUS 3 00024 00025 00026 //Objects 00027 Gamepad gamepad; 00028 N5110 lcd(PTC9,PTC0,PTC7,PTD2,PTD1,PTC11); 00029 ClassicEngine classic; 00030 BrickBreakerEngine brick; 00031 OptionsEngine opt; 00032 Map map; 00033 AnalogIn randnoise(PTB0); 00034 FXOS8700CQ accelerometer(I2C_SDA,I2C_SCL); 00035 Ball ball; 00036 Pause pause; 00037 SDFileSystem sd(PTE3,PTE1,PTE2,PTE4,"sd"); 00038 00039 /** Enum for start menu options*/ 00040 enum StartOption{ 00041 CLASSIC, 00042 BRICKBREAKER, 00043 OPTIONS 00044 }; 00045 00046 /**Start selection struct*/ 00047 struct StartSelection{ 00048 int output; /**<Integer output for line to print arrows to*/ 00049 StartOption next_state[3]; /**<Array of enums for possible next start option*/ 00050 }; 00051 00052 //Methods 00053 void startscreen(); 00054 StartOption menu(); 00055 void init(); 00056 void print_start_menu(int output); 00057 void classic_mode(); 00058 void brickbreaker_mode(); 00059 void options_menu(); 00060 00061 00062 ////////////////Main Function///////////////// 00063 00064 int fps = 16; //declared globally so it doesn't have to be passed to 00065 //the different game mode functions 00066 int main(){ 00067 init(); //first initialise all objects 00068 00069 #ifdef WITH_TESTS //run tests to check code is correct 00070 int test_failures = no_of_tests_failed(); 00071 if(test_failures > 0) return test_failures; //main function returns no of failures 00072 #endif 00073 00074 startscreen(); //then display the introductory screen 00075 while(1){ //keep game running until power is removed 00076 StartOption choice_selected = menu(); //get which mode user wants from the start menu 00077 if(choice_selected == CLASSIC){ classic_mode();} //jump to a game mode once 00078 if(choice_selected == BRICKBREAKER){ brickbreaker_mode();} //its respective enum is received 00079 if(choice_selected == OPTIONS){ options_menu();} //from the start menu 00080 } 00081 } 00082 00083 00084 00085 //////////////Start up functions/////////////////// 00086 00087 void init(){ //initialise all objects in the game 00088 gamepad.init(); 00089 lcd.init(); //some objects are initialised again elsewhere 00090 lcd.setContrast(0.55); //e.g. to reset a game mode when restart is pressed 00091 classic.init(ball, map); 00092 brick.init(RADIUS, ball); 00093 opt.init(); 00094 map.init(); 00095 pause.init(); 00096 accelerometer.init(); 00097 sd.disk_initialize(); 00098 wait(1); 00099 } 00100 00101 void startscreen() { 00102 lcd.clear(); 00103 char gamename[] = {'L', 'A', 'B', 'Y', 'R', 'I', 'N', 'T', 'H', ' ', ' ', '\0'}; //char array containing the game title 00104 int i = 0; 00105 for(int a = 0; a < 35; a++){ //from first letter position to end of the screen at 2 pixel intervals 00106 lcd.clear(); 00107 lcd.drawCircle(24+2*a, 21, 3, FILL_BLACK); //move the ball 2 pixels at a time 00108 for (i = 0; i < a/3; i++) { 00109 lcd.printChar(gamename[i], 15+i*6, 2); //print the next letter in game title once the ball has moved past 00110 lcd.refresh(); //display all contents on LCD display 00111 } 00112 wait_ms(50); 00113 } 00114 lcd.printString("Press start", 9, 4); //instruct user how to advance 00115 lcd.printString("to play >", 15, 5); 00116 lcd.refresh(); 00117 bool advance = false; 00118 while (!advance){ //check for user advancing 00119 if (gamepad.check_event(gamepad.START_PRESSED)){ 00120 lcd.clear(); //if user presses start, clear screen 00121 lcd.refresh(); //before advancing to start menu 00122 advance = true; 00123 } 00124 else { advance = false; } 00125 } 00126 } 00127 00128 StartOption menu(){ 00129 StartSelection fsm[3] = { //state machine to power start menu 00130 {0,{OPTIONS,BRICKBREAKER,CLASSIC}}, //next_state[0] always holds the option above the current one 00131 {2,{CLASSIC,OPTIONS,BRICKBREAKER}}, //next_state[1] always holds the option below the current one 00132 {4,{BRICKBREAKER,CLASSIC,OPTIONS}} //next_state[2] always holds the current option 00133 }; 00134 StartOption state = CLASSIC; //start with the arrow on the top option 00135 int next = 2; //next_state = 2 so that by default it doesn't change arrow position 00136 while(!(gamepad.check_event(gamepad.A_PRESSED))){ //select choice with A 00137 state = fsm[state].next_state[next]; 00138 lcd.clear(); 00139 if(gamepad.get_direction() == N){ next = 0;} //move arrow up 00140 else if(gamepad.get_direction() == S){ next = 1;} //move arrow down 00141 else {next = 2;} //keep arrow in same position 00142 print_start_menu(fsm[state].output); //print on LCD display 00143 lcd.refresh(); 00144 wait(0.25); //longer wait than 1/fps to reduce the impact of button bounce 00145 } 00146 lcd.clear(); 00147 lcd.refresh(); //clear display before moving on to a game mode 00148 return state; //tell main which game mode to run 00149 } 00150 00151 void print_start_menu(int output){ 00152 lcd.printString(">", 0, output); 00153 lcd.printString("Classic", 36, 0); 00154 lcd.printString("BrickBreak", 18, 2); 00155 lcd.printString("Options", 36, 4); 00156 lcd.printString("(A = Select)", 12, 5); 00157 } 00158 00159 //////////////////Game Mode Functions//////////////////////////////// 00160 00161 void classic_mode(){ 00162 classic.init(ball, map); 00163 pause.classic_help(gamepad, lcd); //display how to play instructions before start of game 00164 bool collision = false; //used to determine whether to keep iterating or not 00165 while(!(collision)){ 00166 classic.classic_update(ball, accelerometer, map); //methods to update the game 00167 lcd.clear(); //and render it as the user plays 00168 classic.classic_draw(lcd, map, ball); 00169 lcd.refresh(); 00170 wait(1/fps); 00171 if(gamepad.check_event(gamepad.BACK_PRESSED)){ //check for use of the pause menu 00172 PauseOption choice = pause.pause_menu(gamepad, lcd, fps); //retrieve user's input 00173 if(choice == RESUME){} //the different options must be processed 00174 if(choice == RESTART){ classic.init(ball, map); } //in main.cpp as they have different 00175 if(choice == QUIT){ break; } //return types so can't be passed into main 00176 if(choice == HELP){ pause.classic_help(gamepad, lcd); } //by one public method in pause.h 00177 } 00178 if(classic.finished()){ //check if the game has been completed 00179 classic.mode_complete(lcd, gamepad, fps); //display time taken and break from game mode 00180 break; 00181 } 00182 if(map.check_wall_collision(gamepad, ball)){ //end the game if collision with wall 00183 collision = classic.mode_failed(lcd, gamepad, ball, map); //gives the option to restart the game (and stay in while loop) or quit 00184 if(!(collision)){ classic.init(ball, map); } 00185 } 00186 } 00187 } 00188 00189 void brickbreaker_mode(){ 00190 pause.brickbreaker_help(gamepad, lcd); //display instructions before start of game 00191 for(int i = 0; i < 45*fps; i++){ 00192 if(i == 1){ brick.set_score(0); } //reset score when game restarts 00193 ball.read_input(accelerometer); //methods to continue updating and rendering the game 00194 ball.update(); 00195 /*Vector2D position = _ball.get_position(); 00196 printf("ball_x = %f | ball_y = %f\n", position.x, position.y); //note: running with tests causes the game to run slow and take ~2min30s*/ 00197 brick.check_square_collision(randnoise, ball); 00198 lcd.clear(); 00199 brick.brickbreaker_draw(lcd, ball); 00200 lcd.refresh(); 00201 wait_ms(1000/fps); 00202 if(gamepad.check_event(gamepad.BACK_PRESSED)){ //check for use of the pause menu 00203 PauseOption choice = pause.pause_menu(gamepad, lcd, fps); //Get the user's selection 00204 i = pause.brickbreaker_action(choice, gamepad, lcd, i, fps); //returns which frame to jump to 00205 } 00206 brick.time_warning(gamepad, i, fps); //Use LEDs to display how much time is left 00207 } 00208 brick.end(gamepad, lcd); //display the 'time up' screen with the user score 00209 brick.write_high_scores(); //update high scores accordingly 00210 } 00211 00212 void options_menu(){ 00213 Option choice = BRIGHTNESS; //variable to store the selected option initialised to the top item in list 00214 while(!(gamepad.check_event(gamepad.A_PRESSED))){ 00215 lcd.clear(); //keep rendering and updating the position of the 00216 opt.display_options(lcd); //menu arrows until a choice is made 00217 choice = opt.option_selection(gamepad, lcd); 00218 lcd.refresh(); 00219 wait(0.2); 00220 } 00221 if(choice == BRIGHTNESS){ opt.change_brightness(gamepad, lcd); } //each menu option called by its 00222 if(choice == BALL_SPEED){ opt.change_ball_speed(gamepad, lcd, ball); } //respective enum and a method in 00223 if(choice == HIGH_SCORES){ opt.view_high_scores(gamepad, lcd); } //options engine processes the option 00224 } 00225 00226
Generated on Thu Jul 14 2022 00:39:27 by
1.7.2