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
- Committer:
- JamesCummins
- Date:
- 2019-05-09
- Revision:
- 40:a1cdb6ab08af
- Parent:
- 39:dfc489594f11
File content as of revision 40:a1cdb6ab08af:
/* ELEC2645 Embedded Systems Project School of Electronic & Electrical Engineering University of Leeds Name: James Nathan Cummins Username: el17jnc Student ID Number: 201096364 Date: 22/03/19 */ #include "Gamepad.h" #include "mbed.h" #include "N5110.h" #include "BrickBreakerEngine.h" #include "ClassicEngine.h" #include "OptionsEngine.h" #include "SDFileSystem.h" #ifdef WITH_TESTS #include "tests.h" #endif #define RADIUS 3 //Objects Gamepad gamepad; N5110 lcd(PTC9,PTC0,PTC7,PTD2,PTD1,PTC11); ClassicEngine classic; BrickBreakerEngine brick; OptionsEngine opt; Map map; AnalogIn randnoise(PTB0); FXOS8700CQ accelerometer(I2C_SDA,I2C_SCL); Ball ball; Pause pause; SDFileSystem sd(PTE3,PTE1,PTE2,PTE4,"sd"); /** Enum for start menu options*/ enum StartOption{ CLASSIC, BRICKBREAKER, OPTIONS }; /**Start selection struct*/ struct StartSelection{ int output; /**<Integer output for line to print arrows to*/ StartOption next_state[3]; /**<Array of enums for possible next start option*/ }; //Methods void startscreen(); StartOption menu(); void init(); void print_start_menu(int output); void classic_mode(); void brickbreaker_mode(); void options_menu(); ////////////////Main Function///////////////// int fps = 16; //declared globally so it doesn't have to be passed to //the different game mode functions int main(){ init(); //first initialise all objects #ifdef WITH_TESTS //run tests to check code is correct int test_failures = no_of_tests_failed(); if(test_failures > 0) return test_failures; //main function returns no of failures #endif startscreen(); //then display the introductory screen while(1){ //keep game running until power is removed StartOption choice_selected = menu(); //get which mode user wants from the start menu if(choice_selected == CLASSIC){ classic_mode();} //jump to a game mode once if(choice_selected == BRICKBREAKER){ brickbreaker_mode();} //its respective enum is received if(choice_selected == OPTIONS){ options_menu();} //from the start menu } } //////////////Start up functions/////////////////// void init(){ //initialise all objects in the game gamepad.init(); lcd.init(); //some objects are initialised again elsewhere lcd.setContrast(0.55); //e.g. to reset a game mode when restart is pressed classic.init(ball, map); brick.init(RADIUS, ball); opt.init(); map.init(); pause.init(); accelerometer.init(); sd.disk_initialize(); wait(1); } void startscreen() { lcd.clear(); char gamename[] = {'L', 'A', 'B', 'Y', 'R', 'I', 'N', 'T', 'H', ' ', ' ', '\0'}; //char array containing the game title int i = 0; for(int a = 0; a < 35; a++){ //from first letter position to end of the screen at 2 pixel intervals lcd.clear(); lcd.drawCircle(24+2*a, 21, 3, FILL_BLACK); //move the ball 2 pixels at a time for (i = 0; i < a/3; i++) { lcd.printChar(gamename[i], 15+i*6, 2); //print the next letter in game title once the ball has moved past lcd.refresh(); //display all contents on LCD display } wait_ms(50); } lcd.printString("Press start", 9, 4); //instruct user how to advance lcd.printString("to play >", 15, 5); lcd.refresh(); bool advance = false; while (!advance){ //check for user advancing if (gamepad.check_event(gamepad.START_PRESSED)){ lcd.clear(); //if user presses start, clear screen lcd.refresh(); //before advancing to start menu advance = true; } else { advance = false; } } } StartOption menu(){ StartSelection fsm[3] = { //state machine to power start menu {0,{OPTIONS,BRICKBREAKER,CLASSIC}}, //next_state[0] always holds the option above the current one {2,{CLASSIC,OPTIONS,BRICKBREAKER}}, //next_state[1] always holds the option below the current one {4,{BRICKBREAKER,CLASSIC,OPTIONS}} //next_state[2] always holds the current option }; StartOption state = CLASSIC; //start with the arrow on the top option int next = 2; //next_state = 2 so that by default it doesn't change arrow position while(!(gamepad.check_event(gamepad.A_PRESSED))){ //select choice with A state = fsm[state].next_state[next]; lcd.clear(); if(gamepad.get_direction() == N){ next = 0;} //move arrow up else if(gamepad.get_direction() == S){ next = 1;} //move arrow down else {next = 2;} //keep arrow in same position print_start_menu(fsm[state].output); //print on LCD display lcd.refresh(); wait(0.25); //longer wait than 1/fps to reduce the impact of button bounce } lcd.clear(); lcd.refresh(); //clear display before moving on to a game mode return state; //tell main which game mode to run } void print_start_menu(int output){ lcd.printString(">", 0, output); lcd.printString("Classic", 36, 0); lcd.printString("BrickBreak", 18, 2); lcd.printString("Options", 36, 4); lcd.printString("(A = Select)", 12, 5); } //////////////////Game Mode Functions//////////////////////////////// void classic_mode(){ classic.init(ball, map); pause.classic_help(gamepad, lcd); //display how to play instructions before start of game bool collision = false; //used to determine whether to keep iterating or not while(!(collision)){ classic.classic_update(ball, accelerometer, map); //methods to update the game lcd.clear(); //and render it as the user plays classic.classic_draw(lcd, map, ball); lcd.refresh(); wait(1/fps); if(gamepad.check_event(gamepad.BACK_PRESSED)){ //check for use of the pause menu PauseOption choice = pause.pause_menu(gamepad, lcd, fps); //retrieve user's input if(choice == RESUME){} //the different options must be processed if(choice == RESTART){ classic.init(ball, map); } //in main.cpp as they have different if(choice == QUIT){ break; } //return types so can't be passed into main if(choice == HELP){ pause.classic_help(gamepad, lcd); } //by one public method in pause.h } if(classic.finished()){ //check if the game has been completed classic.mode_complete(lcd, gamepad, fps); //display time taken and break from game mode break; } if(map.check_wall_collision(gamepad, ball)){ //end the game if collision with wall collision = classic.mode_failed(lcd, gamepad, ball, map); //gives the option to restart the game (and stay in while loop) or quit if(!(collision)){ classic.init(ball, map); } } } } void brickbreaker_mode(){ pause.brickbreaker_help(gamepad, lcd); //display instructions before start of game for(int i = 0; i < 45*fps; i++){ if(i == 1){ brick.set_score(0); } //reset score when game restarts ball.read_input(accelerometer); //methods to continue updating and rendering the game ball.update(); /*Vector2D position = _ball.get_position(); 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*/ brick.check_square_collision(randnoise, ball); lcd.clear(); brick.brickbreaker_draw(lcd, ball); lcd.refresh(); wait_ms(1000/fps); if(gamepad.check_event(gamepad.BACK_PRESSED)){ //check for use of the pause menu PauseOption choice = pause.pause_menu(gamepad, lcd, fps); //Get the user's selection i = pause.brickbreaker_action(choice, gamepad, lcd, i, fps); //returns which frame to jump to } brick.time_warning(gamepad, i, fps); //Use LEDs to display how much time is left } brick.end(gamepad, lcd); //display the 'time up' screen with the user score brick.write_high_scores(); //update high scores accordingly } void options_menu(){ Option choice = BRIGHTNESS; //variable to store the selected option initialised to the top item in list while(!(gamepad.check_event(gamepad.A_PRESSED))){ lcd.clear(); //keep rendering and updating the position of the opt.display_options(lcd); //menu arrows until a choice is made choice = opt.option_selection(gamepad, lcd); lcd.refresh(); wait(0.2); } if(choice == BRIGHTNESS){ opt.change_brightness(gamepad, lcd); } //each menu option called by its if(choice == BALL_SPEED){ opt.change_ball_speed(gamepad, lcd, ball); } //respective enum and a method in if(choice == HIGH_SCORES){ opt.view_high_scores(gamepad, lcd); } //options engine processes the option }