My ELEC2645 project. Nikollao Sulollari. 200804685
Dependencies: N5110 SoftPWM mbed
Fork of Treasure_Hunt by
main.cpp
- Committer:
- Nikollao
- Date:
- 2016-05-04
- Revision:
- 21:6b02ef341358
- Parent:
- 20:59aa6189a47d
File content as of revision 21:6b02ef341358:
/** @file main.cpp @brief Game implementation */ #include "main.h" #include "stdlib.h" int main(void) { lcd.init(); ///initialise LED init_K64F(); ///init K64F init_serial(); ///initiate connection with PC port init_game(); ///initialize game led_output = fsm[fsm_state]; ///set FSM to turn on LEDs calibrateJoystick(); ///calibrate joystick game_ticker.attach(&game_timer_isr,0.2); ///attach ticker for the menu different from the main ticker menu(); game_ticker.detach(); //timer.start(); ticker.attach(&timer_isr,game_speed); ///attach ticker with ISR. Speed is selected by the user reset = level; ///set reset = level to check later if level has increased g_button1_flag = 0; timer.start(); while (1) { if (g_timer_flag) {///if timer flag is UP g_timer_flag = 0; ///reset flag lcd.clear(); if (reset < level) { ///if level has increased g_button1_flag = 0; ///reset weapon button reset = level; ///update reset rectY = 0; ///set enemies to default position circleX = 0; } guidance(); ///get guidance hero(); ///call hero enemies(); ///generate enemies obstacles(); ///generate obstacles //float count_time = timer.read(); if (g_button1_flag) { ///the blue LED indicates if the weapon is ready to use or not blue_led = 0; } else { blue_led = 1; } checkOverlap(); ///check is hero has overlapped with enemies or obstacles updateJoystick(); ///update joystick lcd.refresh(); } sleep();///use sleep and timer triggered interrupt to save power } } //mbed functions void init_serial() { // set to highest baud - ensure terminal software matches pc.baud(115200); } void init_K64F() { // on-board LEDs are active-low, so set pin high to turn them off. r_led = 1; g_led = 1; b_led = 1; blue_led = 1; // since the on-board switches have external pull-ups, we should disable the internal pull-down // resistors that are enabled by default using InterruptIn sw2.mode(PullNone); sw3.mode(PullNone); button.rise(&button_isr); ///assign rise with ISR button1.rise(&button1_isr); button.mode(PullDown); ///use PullDown mode button1.mode(PullDown); } ///ISR functions void timer_isr () { g_timer_flag = 1; } void game_timer_isr() { g_game_timer_flag = 1; } void sw2_isr() { g_sw2_flag = 1; } void sw3_isr() { g_sw3_flag = 1; } void button_isr() { g_button_flag =1; } void button1_isr() { g_button1_flag =1; } void timeout_isr() { if (button) { pc.printf("timeout \n"); } } ///game functions void enemies() { /// generate enemies in the screen depending on the level of difficulty if (level == 0) { ///generate enemies at level 0 enemyRect(); if (g_button1_flag == 0) { enemyCircle(); } } else if (level == 1) {///generate enemies at level 1 enemyRect(); if (g_button1_flag == 0) { enemyCircle(); } } else if (level == 2) {///generate enemies at level 2 enemyRocket(); if (g_button1_flag == 0) { enemyCircle(); } } else if (level == 3) {///generate enemies at level 3 enemyRect(); if (g_button1_flag == 0) { enemyCircle(); } } else if (level == 4) {///generate enemies at level 4 enemyRect(); if (g_button1_flag == 0) { enemyCircle(); } } else if (level == 5) {///generate enemies at level 5 enemyRocket(); if (g_button1_flag == 0) { enemyCircle(); } } else if (level == 6) {///generate enemies at level 6 enemyRocket(); if (g_button1_flag == 0) { enemyCircle(); } } else if (level == 7) {///generate enemies at level 7 enemyRocket(); enemyCircle(); if (g_button1_flag == 1) {///if button1 is pressed don't allow to use at level 7 g_button1_flag = 0; lcd.clear(); lcd.printString("Can't use now!",0,0); lcd.refresh(); wait(1); lcd.clear(); } } } void enemyRect() { ///generate rectangular shape enemy lcd.drawRect(rectX,rectY,5,4,1); rectX = rectX + rand()%4 - 2; rectY++; ///enemy moving towards hero if (rectY > 50) {///set boundaries for enemy position rectY = 0; } if (rectX > 75 || rectX < 25) { rectX = 40+rand()%6 - 3; } } void enemyRocket() { ///generate a "rocket-like" enemy lcd.drawRect(rectX,rectY,2,7,1); lcd.drawCircle(rectX+1,rectY+1,2,1); lcd.drawLine(rectX-2,rectY+2,rectX,rectY-1,1); lcd.drawLine(rectX+2,rectY+2,rectX,rectY-1,1); rectX = rectX + rand()%4 - 2; rectY++; ///enemy moving towards hero if (rectY > 50) {///set boundaries for position of enemy rectY = 0; } if (rectX > 75 || rectX < 10) { rectX = 40+rand()%6 - 3; } } void enemyCircle() { ///generate circle shape enemy lcd.drawCircle(circleX,circleY,4,1); circleY = circleY + rand() %4 - 2; if (circleY <= 10) { ///set the boundaries of the enemy circleY = 20; } if (circleY >= 35) { circleY = 35; } if (circleX > 84) { circleX = 0; } circleX++; ///enemy moving towards hero } void hero() { ///cotrol hero if (joystick.direction == RIGHT) { ///joystick direction points to the right heroX--; } else if (joystick.direction == LEFT) {///joystick direction points to the left heroX++; } else { heroX = heroX; } if (joystick.direction == UP) {///joystick direction points to the top heroY--; } else if (joystick.direction == DOWN) {///joystick direction points down heroY++; } else { heroY = heroY; ///joystick is centred } if (joystick.direction == UP_LEFT) { ///joystick direction points up and left heroY--; heroX++; } else if (joystick.direction == UP_RIGHT) { ///joystick direction points up and right heroY--; heroX--; } else if (joystick.direction == DOWN_RIGHT) {///joystick direction points down and right heroY++; heroX--; } else if (joystick.direction == DOWN_LEFT) {///joystick direction points down and left heroY++; heroX++; } ///set x-axis boundaries so hero does not go out of screen if (heroX > 40) { heroX = -40; } if (heroX < -45) { heroX = 35; } if (heroY < -45) { ///if hero has reached the top of the screen heroY = 0; ///hero goes back to the bottom of the screen g_button1_flag = 0; level++; ///increase level of the game } if (heroY >= 0) {/// hero cannot go to previous level heroY = 0; } ///draw hero lcd.drawLine(40+heroX, 47+heroY, 48+heroX, 43+heroY,1); ///variables heroX and heroY are used to control the direction of the hero lcd.drawLine(40+heroX, 43+heroY,48+heroX, 47+heroY,1); lcd.drawLine(44+heroX, 45+heroY,44+heroX, 41+heroY,1); lcd.drawCircle(44+heroX, 39+heroY,2,0); } void init_game() { ///initialise game srand(time(NULL)); /// generate random numbers rectY = 0; /// init rectX, rectY rectX = rand() %40 + 20; circleY = rand() %20 + 10; /// init circleX, circleY circleX = 0; lcd.setBrightness(0.5); // put LED backlight on 50% lcd.printString("Welcome to",11,1); lcd.printString("Treasure Hunt!",1,3); lcd.refresh(); //timeout.attach(&timeout_isr,3); // sleep(); wait(3); ///small delay prints welcome message lcd.clear(); } void guidance() { if (level < 7) { lcd.drawLine(42,0,40,2,1); lcd.drawLine(42,0,44,2,1); lcd.drawLine(42,0,42,3,1); } /// function acts as guidance towards the treasure else if (level == 7) { lcd.printString("F",42,0); /// print the treasure icon } else if (level == 8) { timer.stop(); ///stop timer timer.reset(); float win_time = timer.read();///value reads the time taken to win the game char win[80]; ///create an array of chars sprintf(win,"Time:%.2f sec",win_time); ///create string ticker.detach(); game_ticker.attach(&game_timer_isr,0.2); lcd.clear(); lcd.printString("Well done!",0,0); lcd.refresh(); wait(2); lcd.clear(); lcd.printString(win,0,0); ///print the time taken to win the game on screen wait(3); lcd.clear(); lcd.printString("Play again!",0,0); ///provide play again option lcd.drawCircle(70,4,2,1); lcd.refresh(); g_button_flag = 0; while(1) { if (g_button1_flag) { ///if button1 is pressed ///reset g_button1_flag = 0; level = 0; lcd.clear(); main(); r_led = 0; lcd.refresh(); } sleep(); } } } void obstacles() { /// place obstacles in the screen /// as level difficulty increases, more obstacles are added if (level == 0) { ///obstacles are located in the ground and they change from one level to another lcd.drawRect(10,15,2,2,1); lcd.drawRect(74,15,2,2,1); } else if (level == 1) { lcd.drawRect(10,15,2,2,1); lcd.drawRect(74,15,2,2,1); lcd.drawRect(10,28,2,2,1); lcd.drawRect(74,28,2,2,1); } else if (level == 2) { lcd.drawCircle(25,25,5,0); lcd.drawCircle(65,25,5,0); lcd.drawCircle(45,11,3,1); lcd.drawCircle(25,25,3,1); lcd.drawCircle(65,25,3,1); lcd.drawRect(80,2,2,42,1); lcd.drawRect(2,2,2,42,1); } else if (level == 3) { lcd.drawRect(5,12,2,2,1); lcd.drawRect(79,12,2,2,1); lcd.drawRect(5,30,2,2,1); lcd.drawRect(79,30,2,2,1); lcd.drawRect(28,12,2,2,1); lcd.drawRect(52,12,2,2,1); lcd.drawRect(28,30,2,2,1); lcd.drawRect(52,30,2,2,1); } else if (level == 4) { lcd.drawRect(5+rand() %4 - 2 ,12+rand() %4 - 2,2,2,1); ///make obstacles moveable by adding a small random variance in position lcd.drawRect(79 + rand() %4 - 2,12 + rand() %4 - 2,2,2,1); lcd.drawRect(5+ rand() %4 - 2,30+rand() %4 - 2 ,2,2,1); lcd.drawRect(79 + rand() %4 - 2,30+rand() %4 - 2,2,2,1); lcd.drawRect(28 + rand() %4 - 2,12+ rand() %4,2,2,1); lcd.drawRect(52+rand() %4 - 2,12 + rand() %4 - 2,2,2,1); lcd.drawRect(28+rand() %4 - 2,30 + rand() %4 - 2,2,2,1); lcd.drawRect(52 + rand() %4 - 2,30+ rand() %4,2,2,1); } if (objectX == 0) { ///check position of obstacle state = 0; ///assign states to the position of the obstacle } else if (objectX == 60) { state = 1; } else { state = state; } if (state == 0) { ///if state is 0 increase position on x-axis objectX++; } else { objectX--; ///else if state is 1 decrease position on x-axis } if (objectX1 == 68) { state1 = 1; } else if (objectX1 == 10) { state1 = 0; } if (state1 == 1) { objectX1--; } else if (state1 == 0) { objectX1++; } objectY = objectY + rand() %4 - 2; ///set poistion of obstacle on y-axis to be valuable ///keep moving object within boundaries if (objectY <= 10) { objectY = 10; } if (objectY >= 37) { objectY = 37; } if ( level == 5) { lcd.drawLine(15,10,15,37,1); lcd.drawLine(71,10,71,37,1); lcd.drawRect(11+objectX,objectY,2,2,1); ///draw obstacle lcd.drawRect(80,10,2,2,1); lcd.drawRect(5,10,2,2,1); lcd.drawRect(80,20,2,2,1); lcd.drawRect(5,20,2,2,1); lcd.drawRect(80,30,2,2,1); lcd.drawRect(5,30,2,2,1); } else if (level == 6) { lcd.drawLine(15,10,15,37,1); ///draw boundaries lcd.drawLine(71,10,71,37,1); lcd.drawRect(11+objectX,objectY,2,2,1); /// draw moving obstacles on screen lcd.drawRect(objectX1,10+objectY,2,2,1); lcd.drawRect(80,10,2,2,1); ///draw stable obstacles lcd.drawRect(5,10,2,2,1); lcd.drawRect(80,20,2,2,1); lcd.drawRect(5,20,2,2,1); lcd.drawRect(80,30,2,2,1); lcd.drawRect(5,30,2,2,1); } else if (level == 7) { lcd.printString("??",65,0); lcd.drawRect(1,23,82,2,1); if (button && heroX <-30) { g_button_flag = 0; heroX = -30; heroY = -30; } pc.printf("x = %d , y = %d \n",heroX,heroY); } } void calibrateJoystick() { // must not move during calibration joystick.x0 = xPot; // initial positions in the range 0.0 to 1.0 (0.5 if centred exactly) joystick.y0 = yPot; } void updateJoystick() { // read current joystick values relative to calibrated values (in range -0.5 to 0.5, 0.0 is centred) joystick.x = xPot - joystick.x0; joystick.y = yPot - joystick.y0; // read button state joystick.button = button; // calculate direction depending on x,y values // tolerance allows a little lee-way in case joystick not exactly in the stated direction if ( fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { joystick.direction = CENTRE; } else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { joystick.direction = UP; } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { joystick.direction = DOWN; } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) { joystick.direction = RIGHT; } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) { joystick.direction = LEFT; } else if (joystick.y > DIRECTION_TOLERANCE && joystick.x < DIRECTION_TOLERANCE) { joystick.direction = UP_LEFT; } else if (joystick.y > DIRECTION_TOLERANCE && joystick.x > DIRECTION_TOLERANCE) { joystick.direction = UP_RIGHT; } else if (joystick.y < DIRECTION_TOLERANCE && joystick.x < DIRECTION_TOLERANCE) { joystick.direction = DOWN_LEFT; } else if (joystick.y < DIRECTION_TOLERANCE && joystick.x > DIRECTION_TOLERANCE) { joystick.direction = DOWN_RIGHT; } } void menu() { while(1) { if (g_game_timer_flag) { g_game_timer_flag = 0; updateJoystick(); lcd.clear(); lcd.printString("Start Game",0,0); ///print the main lcd.printString("Settings",0,2); lcd.printString("Exit",0,4); //lcd.drawCircle(70,4,2,1); lcd.refresh(); switch (joystick.direction) { ///check the direction of joystick case UP: option--; break; case DOWN: option++; break; } if (option < 0) { /// if the last (down) option is set for selection and user presses joystick down, selector moves at the top option = 2; } if (option > 2) { /// if the first (up) option is set for selection and user presses joystick up, selector moves at the bottom option = 0; } if (option == 0) { ///selection in menu depends on the value of int option lcd.drawCircle(70,4,2,1); } else if (option == 1) { lcd.drawCircle(55,20,2,1); } else if (option == 2) { lcd.drawCircle(35,35,2,1); } if(g_button_flag) { /// if button is pressed g_button_flag = 0; ///reset flag if (option == 0) { ///break the while loop, start game break; } else if (option == 1) { ///enter settings menu option = 0; while(1) { if (g_game_timer_flag) { g_game_timer_flag = 0; updateJoystick(); ///update joystick position lcd.clear(); if (normal) { if (sound) { lcd.printString("Game speed",0,0); ///print settings menu lcd.printString("Lcd:Inverse",0,1); lcd.printString("Sound:ON",0,2); lcd.printString("Back",0,4); } else { lcd.printString("Game speed",0,0); ///print settings menu lcd.printString("Lcd:Inverse",0,1); lcd.printString("Sound:OFF",0,2); lcd.printString("Back",0,4); } } else { if (sound) { lcd.printString("Game speed",0,0); ///print settings menu lcd.printString("Lcd:Normal",0,1); lcd.printString("Sound:ON",0,2); lcd.printString("Back",0,4); } else { lcd.printString("Game speed",0,0); ///print settings menu lcd.printString("Lcd:Normal",0,1); lcd.printString("Sound:OFF",0,2); lcd.printString("Back",0,4); } } switch (joystick.direction) { case UP: option--; break; case DOWN: option++; break; case CENTRE: option = option; break; } if (option < 0) { ///if selector is on the top of the screen and UP is pressed, selector goes to the bottom option = 3; } if (option > 3) { ///if selector is on the bottom of the screen and DOWN is pressed, selector goes to the top option = 0; } /// menu selection depends on the position of the Joystick if (option == 0) { lcd.drawCircle(70,4,2,1); } else if (option == 1) { lcd.drawCircle(70,12,2,1); } else if (option == 2) { lcd.drawCircle(70,20,2,1); } else { lcd.drawCircle(35,36,2,1); } if (g_button_flag) { ///if button is pressed g_button_flag = 0; ///reset button if (option == 0) { /// if user selects to modify speed of the game while(1) { ///set speed of the game if (g_game_timer_flag) { g_game_timer_flag = 0; updateJoystick(); lcd.clear(); if (speed == 0) { lcd.printString("Slow<",0,0); ///print game speed menu lcd.printString("Normal",0,1); lcd.printString("Fast",0,2); lcd.printString("Back",0,4); } else if (speed == 1) { lcd.printString("Slow",0,0); //print game speed menu lcd.printString("Normal<",0,1); lcd.printString("Fast",0,2); lcd.printString("Back",0,4); } else if (speed == 2) { lcd.printString("Slow",0,0); //print game speed menu lcd.printString("Normal",0,1); lcd.printString("Fast<",0,2); lcd.printString("Back",0,4); } switch (joystick.direction) { case UP: option--; break; case DOWN: option++; break; case CENTRE: option = option; break; } if (option < 0) { option = 3; } if (option > 3) { option = 0; } if (option == 0) { lcd.drawCircle(70,4,2,1); } else if (option == 1) { lcd.drawCircle(55,12,2,1); } else if (option == 2) { lcd.drawCircle(35,20,2,1); } else { lcd.drawCircle(35,36,2,1); } if (g_button_flag) { g_button_flag = 0; if (option == 0) { game_speed = 0.1; ///slow speed = 0; } else if (option == 1) { game_speed = 0.05; ///normal speed = 1; } else if (option == 2) { game_speed = 0.04; ///fast speed = 2; } else if (option == 3) { break; } } lcd.refresh(); } sleep(); } } else if (option == 1) { /// Lcd inverse mode normal =! normal; if (normal) { lcd.inverseMode(); } else { lcd.normalMode(); } } else if (option == 2) { ///select sound or not sound =! sound; if (sound) { //buzzer.write(0.5); // buzzer.period(1/4000); } else { buzzer.write(0.0); } // buzzer.period(1/400); } else if(option == 3) { ///go back to main menu break; } } lcd.refresh(); } sleep(); } } else if (option == 2) { ///turn off LED lcd.clear(); lcd.turnOff(); while(1) { deepsleep(); } } } lcd.refresh(); } sleep(); } } int intersection(int i, int j) { /// check for overlap between enemies and hero n=0; if (lcd.getPixel(i-1,j-1)!=0) //pixel to the top-left n++; // increase n by 1 if (lcd.getPixel(i-1,j)!=0) //pixel to the left n++; // increase n by 1 if (lcd.getPixel(i-1,j+1)!=0) //pixel to the bottom-left n++; // increase n by 1 if (lcd.getPixel(i,j-1)!=0) // pixel to the top n++; // increase n by 1 if (lcd.getPixel(i,j+1)!=0) //pixel to the bottom n++; // increase n by 1 if (lcd.getPixel(i+1,j-1)!=0) //pixel to the top-right n++; // increase n by 1 if (lcd.getPixel(i+1,j)!=0) // pixel to the right n++; // increase n by 1 if (lcd.getPixel(i+1,j+1)!=0) //pixel to the bottom right n++; // increase n by 1 return n; } void checkOverlap() { for (int i=40+heroX; i<50+heroX; i++) { ///loop follows the hero and checks for overlap around him for (int j=35+heroY; j<48+heroY; j++) { int check = intersection(i,j); ///int gets number of pixels around the hero //lcd.setPixel(i,j); char bit[50]; sprintf(bit,"Pixels: %d",check); for(int i = 40; i < 50; i++) { ///provides safety if hero is in default position he doesn't get killed by enemies for (int j = 35; j < 47; j++) { if (lcd.getPixel(i,j) && check > 6) { ///6 is the offset of the neigbours, as hero has his own neighbours pixels check = 6; } } } if (check > 7) { tries--; //if tries lcd.printString("BANG!",0,0); ///Bang message is displayed when overlap has occured if (sound) { buzzer.write(0.5); //buzzer.pulsewidth(0.9); } else { buzzer.write(0.0); } lcd.refresh(); wait(2); lcd.clear(); if (tries == 2) { g_button1_flag = 0; lcd.printString("Ready.",20,1); lcd.refresh(); wait(0.5); lcd.printString("Ready..",20,1); lcd.refresh(); wait(0.5); lcd.printString("Ready...",20,1); lcd.refresh(); wait(1); lcd.printString("GO!",31,3); lcd.refresh(); wait(1); lcd.clear(); fsm_state = 1; ///2 lives left } else if (tries == 1) { g_button1_flag = 0; lcd.clear(); lcd.printString("Last Chance!",10,2); lcd.refresh(); wait(1); fsm_state = 2; //1 life left } else if (tries == 0) { g_button1_flag = 0; fsm_state = 3; led_output=fsm[fsm_state]; lcd.clear(); lcd.printString("Game Over!",10,2); timer.stop(); timer.reset(); lcd.refresh(); wait(2); ticker.detach(); game_ticker.attach(&game_timer_isr,0.2); ///attach a slower ticker to save power while not playing lcd.clear(); lcd.printString("Play again!",0,0); lcd.drawCircle(70,4,2,1); lcd.refresh(); g_button_flag = 0; while(1) { if (g_button1_flag) { ///if button1 is pressed g_button1_flag = 0; ///reset button1 flag level = 0; ///reset parameters tries = 3; fsm_state = 0; led_output=fsm[fsm_state]; buzzer.write(0.0); lcd.clear(); ///reset values heroX = 0; heroY = 0; rectY = 0; circleX = 0; main(); ///call main } sleep(); } } heroX = 0; heroY = 0; rectY = 0; circleX = 0; led_output=fsm[fsm_state]; buzzer.write(0.0); } } } }