Final Submission. I have read and agreed with Statement of Academic Integrity.
Dependencies: mbed
Diff: main.cpp
- Revision:
- 8:dc7b09f23d75
- Parent:
- 7:8e1111ab8a8c
- Child:
- 9:b160a3de0d00
--- a/main.cpp Fri Jun 05 16:32:56 2020 +0000 +++ b/main.cpp Fri Jun 05 18:07:26 2020 +0000 @@ -1,27 +1,46 @@ #include "mbed.h" #include "Gamepad.h" #include "N5110.h" -#include "Levels.h" //Objects Gamepad pad; N5110 lcd; -//initialise global variables to be used throughought the game +//initialise global variables to be used throughout the game +//initial player position in all levels. char player_char = 'x'; int player_xpos = 8; int player_ypos = 45; -int aim_xpos = 0; -int aim_ypos = 0; +int aim_xpos; +int aim_ypos; int portal_1_xpos; int portal_1_ypos; int portal_2_xpos; int portal_2_ypos; + +//initialise x direction movement +int move = 0; +//initialise terminators for menu and game loops. +bool choice = false; +bool endgame = false; + //initialise Game array char array[84][48]; -//Level 1. the +/*the characters in the level array's represent the following: +'0' = air +'1' = right facing wall +'2' = floor +'3' = cieling +'4' = left facing wall +'B' = Button +'S' = Spikes +'P' = portal 1 +'Q' = portal 2 +'x' = player +*/ +// level 1 char _level_1[84][48] = { {'3','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','2'}, {'3','0','0','0','0','0','0','0','0','0','2','3','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2'}, @@ -108,8 +127,8 @@ {'3','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2'}, {'3','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2'}, }; - -char _level_2[84][48] = { + // level 3 +char _level_3[84][48] = { {'3','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','2'}, {'3','0','0','0','2','2','0','0','0','0','0','0','0','2','3','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','3','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2'}, {'3','0','0','0','0','2','0','0','0','0','0','0','0','2','3','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','3','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2'}, @@ -195,8 +214,8 @@ {'3','0','0','0','0','0','0','2','3','0','0','0','0','0','0','0','0','0','0','0','0','2','1','1','1','1','1','1','1','1','2','3','0','0','0','0','0','0','0','D','0','0','0','0','0','0','0','2'}, {'3','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2'}, }; - -char _level_3[84][48] = { + // level 2 +char _level_2[84][48] = { {'3','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','4','2'}, {'3','0','0','0','2','2','0','0','0','0','0','0','0','2','3','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','0','0','0','0','0','2'}, {'3','0','0','0','0','2','0','0','0','0','0','0','0','2','3','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','0','0','0','0','0','2'}, @@ -283,24 +302,11 @@ {'3','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2'}, }; - - - - -int move = 0; -bool endgame = false; -bool choice = false; //Prototypes void pad_init(); void update_display(); -void draw_array(); -void player_object(); -void Copy_array(); -void player_movements(); -void update_array(); void apply_move(); -void add_surface_array(); void add_player_array(); void get_move(int, Gamepad &pad); void print_screen(); @@ -313,17 +319,20 @@ //Main function int main() { - +//initialise the pad pad_init(); + //loop until player has selected an option from the menu while(choice == false) { + //print welcome screen lcd.clear(); lcd.printString("Welcome to",0,0); lcd.printString("2D Portal!",0,1); lcd.printString("A = controls",0,2); lcd.printString("B = Level 1",0,3); lcd.printString("X = Level 2",0,4); - lcd.printString("y = Level 3",0,5); + lcd.printString("Y = Level 3",0,5); update_display(); + //cycle LED's whilst on home screen pad.led(1,1); wait(0.05); pad.leds_off(); @@ -342,6 +351,7 @@ pad.led(6,1); wait(0.05); pad.leds_off(); + // print the controls for 5 seconds, then return to the menu screen. if(pad.A_pressed() == 1){ lcd.clear(); lcd.printString("Joystick =Move",0,0); @@ -355,52 +365,70 @@ wait_ms(5000); choice = false; } + //loads level 1. else if(pad.B_pressed() == 1){ for(int i = 0; i < 84; i ++){ for(int j = 0; j < 48; j ++){ array[i][j] = _level_1[i][j]; choice = true;}}} + //loads level 2 else if(pad.X_pressed() == 1){ for(int i = 0; i < 84; i ++){ for(int j = 0; j < 48; j ++){ array[i][j] = _level_2[i][j]; choice = true;}}} + //loads level 3 else if(pad.Y_pressed() == 1){ for(int i = 0; i < 84; i ++){ for(int j = 0; j < 48; j ++){ array[i][j] = _level_3[i][j]; choice = true;}}} + //refresh lcd to display chosen level when menu loop breaks. lcd.refresh(); - //Cycle through leds whilst on the home screen } - update_display(); - //Loop runs forever + //Loop runs until the player has solved the puzzle and exited the right hand side of the screen. while(endgame == false){ + // converts joystick input into left or right movement. get_move(move, pad); + + // checks to see if the move is valid and handles teleportation logic. collision_detection(move); + // checks to see if the player has jumped, if they have then the players y pos will descrease by 1 if(pad.A_pressed() == 1){ jump(); } + //checks to see if the player has placed portal 1, if they have then the portal will be placed in the array else if(pad.B_pressed() == 1){ place_portal_1(); + //turns on left red led to show portal 1 has been placed. + pad.led(1,1); } - + //checks to see if the player has placed portal 2, if they have then the portal will be placed in the array else if(pad.Y_pressed() == 1){ place_portal_2(); + //turns on right red led to show portal 2 has been placed. + pad.led(4,1); } else + //handles setting the new position of the player in the array and erasing the previous player position from the array. apply_move(); - add_player_array(); + //prints to the lcd print_screen(); + //refreshes the lcd to display the new screen after movement. update_display(); + // the objective of the game is to open the door and walk through it. as the door is on the right hand side of the screen, when the player + // xpos exceeds 82, the puzzle is assumed to be solved as the door has to be opened to progress. if(player_xpos > 82){ endgame = true;} } + //clear the level and print the win screen lcd.clear(); - lcd.printString("puzzle solved",0,0); + lcd.printString("Puzzle solved!",0,0); + lcd.printString("Press reset",0,0); + lcd.printString("To play again",0,0); lcd.refresh(); } - +//initialise the game array with 0's void array_init(){ for(int j = 0; j < 48; j++){ for(int i = 0; i < 84; i++){ @@ -408,16 +436,17 @@ }}} void apply_move(){ - + // removes old player char in the array and increments the value of the player_xpos by the value in move int old_player_xpos = player_xpos; player_xpos += move; array[old_player_xpos][player_ypos] = '0'; - + //checks if the player is in the air, if they are then increase y by 1 until the player is on the floor and remove the old player char from the array int old_player_ypos = player_ypos; if(array[player_xpos][player_ypos+1] == '0'){ player_ypos += 1; array[player_xpos][old_player_ypos] = '0'; } + //checks if the player has landed on spikes and displays the end game screen with instructions for how to restart the game if they have. else if(array[player_xpos][player_ypos+1] == 'S'){ lcd.clear(); lcd.printString("Spike hit!",0,0); @@ -425,11 +454,14 @@ lcd.printString("Try again!",0,2); lcd.refresh(); wait_ms(1000000000); + //places the player char in the array + add_player_array(); } } - +// converts the chars in the array to on or off pixels, dependant on the type of object in the array. i.e walls are a dark pixel and portals are a light pixel +// this helps to distinguis where the portals are. void print_screen(){ for(int j = 0; j < 48; j++){ for(int i = 0; i < 84; i++){ @@ -456,8 +488,9 @@ lcd.setPixel(i,j, true); } }} - + // finds the position pot(2) is aiming at and prints the aim assist line get_portal_angle(); + // prints the player sprite lcd.setPixel(player_xpos,player_ypos-1, true); lcd.setPixel(player_xpos-1,player_ypos-2, true); lcd.setPixel(player_xpos-1,player_ypos-3, true); @@ -471,82 +504,91 @@ -//Prototype functions -void pad_init(){ +//initilise the pad and LCD +void pad_init() +{ lcd.init(); lcd.setContrast(0.45); lcd.clear(); pad.init(); } - +//places the player char in the array void add_player_array() { array[player_xpos][player_ypos] = player_char; } - +// takes the input from the joystick and converts it into left/rigth movments void get_move(int, Gamepad &pad) { char d = pad.get_direction(); if(d == E){ move = 1; - } else if(d == W){ - move = -1; - - + move = -1; } else move = 0; } - +// refreshes the display with the updated game screen void update_display() { lcd.refresh(); //Refreshes the lcd so the pixels appear wait_ms(150); //Frame rate of game } -/////////////////////////////// all of above is the main loop and a little bit of player stuff. - void collision_detection(int) { + //check if the player is moving into any object other than air. if they are then x direction movement = 0 char dir = pad.get_direction(); if(array[player_xpos+1][player_ypos] != '0' && dir == E){ move = 0;} else if(array[player_xpos-1][player_ypos] != '0' && dir == W){ move = 0;} + // checks if the player is directly next to a portal and runs the logic to check where the player should be teleported to. This is dependant on the surfaces the second portal is placed on. if(array[player_xpos+1][player_ypos] == 'P' || array[player_xpos-1][player_ypos] == 'P' || array[player_xpos][player_ypos-1] == 'P' || array[player_xpos][player_ypos+1] == 'P' ){ move = 0; + // removes the old player char from the array array[player_xpos][player_ypos] = '0'; + //logic for entering portal 1 + // if the position horizontally next to portal 2 is a '3' then portal 2 has been placed on a ceiling and the player must be placed below portal 2. if (array[portal_2_xpos-1][portal_2_ypos] == '3'){ player_xpos = portal_2_xpos; player_ypos = portal_2_ypos+2;} + // if the position horizontally next to portal 2 is a '2' then portal 2 has been placed on a floor and the player must be placed above and to the side of portal 2 so they dont fall back in. else if(array[portal_2_xpos-1][portal_2_ypos] == '2'){ player_xpos = portal_2_xpos + 1; player_ypos = portal_2_ypos-1;} + // if the position vertically next to portal 2 is a '1' then portal 2 has been placed on a right facing wall and the player must be placed on the left of portal 2. else if(array[portal_2_xpos][portal_2_ypos - 1] == '1'){ player_xpos = portal_2_xpos - 2; player_ypos = portal_2_ypos;} + // if the position vertically next to portal 2 is a '4' then portal 2 has been placed on a left facing wall and the player must be placed on the right of portal 2. else if(array[portal_2_xpos][portal_2_ypos - 1] == '4'){ player_xpos = portal_2_xpos + 2; player_ypos = portal_2_ypos;} } + // logic for entering portal 2 else if(array[player_xpos+1][player_ypos] == 'Q' || array[player_xpos-1][player_ypos] == 'Q' || array[player_xpos][player_ypos-1] == 'Q' || array[player_xpos][player_ypos+1] == 'Q' ){ move = 0; array[player_xpos][player_ypos] = '0'; + // if the position horizontally next to portal 1 is a '3' then portal 1 has been placed on a ceiling and the player must be placed below portal 1. if (array[portal_1_xpos-1][portal_1_ypos] == '3'){ player_xpos = portal_1_xpos; player_ypos = portal_1_ypos+2;} + // if the position horizontally next to portal 1 is a '2' then portal 1 has been placed on a floor and the player must be placed above and to the side of portal 1 so they dont fall back in. else if(array[portal_1_xpos-1][portal_1_ypos] == '2'){ player_xpos = portal_1_xpos + 1; player_ypos = portal_1_ypos-1;} + // if the position vertically next to portal 1 is a '1' then portal 1 has been placed on a right facing wall and the player must be placed on the left of portal 1. else if(array[portal_1_xpos][portal_1_ypos - 1] == '1'){ player_xpos = portal_1_xpos - 2; player_ypos = portal_1_ypos;} + // if the position vertically next to portal 1 is a '4' then portal 1 has been placed on a left facing wall and the player must be placed on the right of portal 1. else if(array[portal_1_xpos][portal_1_ypos - 1] == '4'){ player_xpos = portal_1_xpos + 2; player_ypos = portal_1_ypos;} @@ -556,17 +598,16 @@ - + //removes the old player char from the array and replaces it with zero erase_old_sprites(player_xpos, player_ypos); + //checks if the player has stepped on the button, if they have then the button and door are replaced by air and the route to the exit is open. if(array[player_xpos][player_ypos+1] == 'B'){ for(int i = 0; i < 84; i++){ for(int j = 0; j < 48; j++){ if(array[i][j] == 'D' || array[i][j] == 'B'){ array[i][j] = '0';}}}} - - else{ move = move;} } - +// removes the old player character from the array. void erase_old_sprites(char,char) { int old_player_xpos = player_xpos; @@ -576,88 +617,116 @@ array[player_xpos][old_player_ypos] = '0'; } - + void jump() -{ +{ //if the space beneath the player = floor, then increase ypos by 1. Apply move causes the player to fall again shortly after on the next loop. if(array[player_xpos][player_ypos+1] == '2'){ int old_player_ypos = player_ypos; player_ypos += -1; + //removes old player char from the array array[player_xpos][old_player_ypos] = '0'; } } - -//////////////////code so far has movement, surface and portal detection and relevant behaviours. // next steps are to turn pot into degrees and make a function which chechks which pixel the pot is pointing at. - +// this function takes the pot(2) input range and converts it into 45 degree segments, after which the aim detector is sent out until it hits another object void get_portal_angle() { + //take pot(2) val as a double to allow for more precise segments. double angle_input = pad.read_pot2(); - float gradient = tan(angle_input*360); + + //position the player is aiming at aim_xpos = player_xpos; aim_ypos = player_ypos; + + // if pot(2) is between 0 and 45 degrees, aim detection is projected at the floor, if(angle_input > 0 && angle_input < 0.125){ + // The aim_ypos will increment until it is next to a surface that isnt the air. while(array[aim_xpos][aim_ypos + 1] == '0'){ aim_ypos = player_ypos + 1; } + // increment once more to place portal in the surface aim_ypos = player_ypos + 1; + } - } + // if pot(2) is between 45 and 90 degrees, aim detection is diagonally down left else if(angle_input > 0.125 && angle_input < 0.25){ while(array[aim_xpos -1 ][aim_ypos + 1] == '0'){ + // performs relevant increments and decrements for downward diagonal left movement. aim_xpos += - 1; aim_ypos += 1; } + // performs increments and decrements once more to place portal in the surface aim_xpos += - 1; aim_ypos += 1; } + // if pot(2) is between 90 and 135 degrees, aim detection is projected towards the left else if(angle_input > 0.25 && angle_input < 0.375){ while(array[aim_xpos -1 ][aim_ypos] == '0'){ + // The aim_xpos will decrement until it is next to a surface that isnt the air. aim_xpos += - 1; } + // decrement once more to place portal in the surface aim_xpos += - 1; } + // if pot(2) is between 135 and 180 degrees, aim detection is diagonally up left else if(angle_input > 0.375 && angle_input < 0.5){ while(array[aim_xpos -1 ][aim_ypos-1] == '0'){ + // performs relevant decrements for upward diagonal left movement. aim_xpos += - 1; aim_ypos += - 1; } + // performs decrements once more to place portal in the surface aim_xpos += - 1; aim_ypos += -1; } + // if pot(2) is between 180 and 225 degrees, aim detection is upwards else if(angle_input > 0.5 && angle_input < 0.625){ while(array[aim_xpos][aim_ypos-1] == '0'){ + // The aim_ypos will decrement until it is next to a surface that isnt the air. aim_ypos += - 1; } + // decrement once more to place portal in the surface aim_ypos += -1; } + // if pot(2) is between 225 and 270 degrees, aim detection is diagonally up right else if(angle_input > 0.625 && angle_input < 0.75){ while(array[aim_xpos+1][aim_ypos-1] == '0'){ + // performs relevant increments and decrements for downward diagonal left movement. aim_ypos += - 1; aim_xpos += 1; } + // performs increments and decrements once more to place portal in the surface. aim_ypos += -1; aim_xpos += 1; } + // if pot(2) is between 270 and 315 degrees, aim detection is to the right else if(angle_input > 0.75 && angle_input < 0.875){ while(array[aim_xpos+1][aim_ypos] == '0'){ + // The aim_xpos will increment until it is next to a surface that isnt the air. aim_xpos += 1; } + // The aim_xpos will increment once more to place the portal in the surface. aim_xpos += 1; } + // if pot(2) is between 315 and 360 degrees, aim detection is diagonally down right else if(angle_input > 0.875 && angle_input < 1){ while(array[aim_xpos+1][aim_ypos + 1] == '0'){ + // performs relevant increments for downward diagonal left movement. aim_xpos += 1; aim_ypos += 1; } + // performs increments once more to place portal in the surface aim_xpos += 1; aim_ypos += 1; } + // draw the aim assist dashed line to give a visual representation of where the player is aiming the portal gun + // this code allows for dynamic drawing of the aim assist relevant to the players position and the aim direction given by the potentiometer lcd.drawLine((player_xpos),(player_ypos), aim_xpos,aim_ypos,2); lcd.refresh(); } - +//removed the old portal 1 and places the new one where the aim assist is pointed. void place_portal_1() { int old_p1_xpos = portal_1_xpos; @@ -667,7 +736,7 @@ portal_1_ypos = aim_ypos; array[portal_1_xpos][portal_1_ypos] = 'P';} - +//removed the old portal 2 and places the new one where the aim assist is pointed. void place_portal_2() { int old_p2_xpos = portal_2_xpos;