Code for 4180 mini project
Dependencies: 4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player
Fork of Pacman by
Diff: main.cpp
- Revision:
- 1:b86030cf57c4
- Parent:
- 0:0a900ff9a788
- Child:
- 2:610d5194c64e
--- a/main.cpp Tue Mar 25 04:36:32 2014 +0000 +++ b/main.cpp Tue Mar 25 18:49:05 2014 +0000 @@ -1,29 +1,35 @@ +/* +So far, this program will run through one level of what will hopefully be a full Pacman game. +As of now, only Pacman will run all the way through, so the thread to start the blue ghost has +been commented out. This program only runs through one level of the game. +*/ + #include "mbed.h" #include "rtos.h" #include "uLCD_4DGL.h" -#define PAC_SIZE 5 -#define STEP_SIZE 8 -#define CLEARANCE 12 +#define PAC_SIZE 5 //The radius of Pacman and the ghost +#define STEP_SIZE 8 //The number of pixels each character moves at once +#define CLEARANCE 12 //The number of pixels each character checks ahead before moving AnalogIn jsx(p19); // The joysticks origin is about 1.6V in both directions -AnalogIn jsy(p20); // For just three states in each direction use thresholds 1.1V and 2V +AnalogIn jsy(p20); // For just three states in each direction, thresholds .33V and 3V were used uLCD_4DGL uLCD(p28, p27, p29); Mutex lcd_mutex; -void checkMOVE(void); +void checkMOVE(void); //This function is defined below. It was written here since other functions return to it that it also calls. -volatile bool win=false; -volatile bool lose=false; -volatile int x = 64; +//several variables are used by multiple threads +volatile bool win=false; //True when pacman has eaten all coins +volatile bool lose=false; //True when the position of the ghost and pacman are the same +volatile int x = 64; //x and y are pacman's position. The starting position is defined here. volatile int y = 88; -//volatile int x = 0; -//volatile int y = 0; -volatile int gx1 = 64; +volatile int gx1 = 64; //Starting position of the blue ghost volatile int gy1 = 40; -volatile int pixel; int i; bool clearRIGHT,clearLEFT,clearUP,clearDOWN,bgcr,bgcl,bgcu,bgcd; + +//An array containing the locations of the 81 coins pacman must eat int coins[81][2] = { {40,88},{48,88},{56,88},{72,88},{80,88},{88,88}, {40,40},{48,40},{56,40},{64,40},{72,40},{80,40},{88,40}, @@ -45,19 +51,21 @@ {72,24},{72,32} }; +//This function is used in the ghost thread to replace coins as it passes over them void replaceCOINS(void) { for(int n=0; n<81; n++) { - lcd_mutex.lock(); + lcd_mutex.lock(); //The coins array is used by both threads if(gx1 == coins[n][0] && gy1 == coins[n][1]) { - uLCD.filled_circle(gx1,gy1,1,0xFFFF00); + uLCD.filled_circle(gx1,gy1,1,0xFFFF00); //compare the set of coins to the ghost's previous position and if there is a match redraw coin } lcd_mutex.unlock(); } } +//Checks if the ghost can move right (there is no boundary immediately to the right) void BGclearRIGHT(void) { bgcr = true; @@ -66,12 +74,13 @@ lcd_mutex.lock(); if(uLCD.read_pixel(p,gy1)==uLCD.read_pixel(4,4)) { - bgcr = false; - } + bgcr = false; //compare the pixels immediately in front of the ghost to the boundary up to the spec. clearance + } //if they are the same color, determine the ghost can't move right lcd_mutex.unlock(); } } +//Checks if ghost can move left void BGclearLEFT(void) { bgcl = true; @@ -86,6 +95,7 @@ } } +//Checks if ghost can move up void BGclearUP(void) { bgcu = true; @@ -100,6 +110,7 @@ } } +//Checks if ghost can move down void BGclearDOWN(void) { bgcd = true; @@ -114,19 +125,21 @@ } } +//Moves the blue ghost to the right void bgRIGHT(void) { Thread::wait(50); lcd_mutex.lock(); - uLCD.filled_rectangle(gx1-PAC_SIZE,gy1-PAC_SIZE,gx1+PAC_SIZE,gy1+PAC_SIZE,BLACK); + uLCD.filled_rectangle(gx1-PAC_SIZE,gy1-PAC_SIZE,gx1+PAC_SIZE,gy1+PAC_SIZE,BLACK); //erase the previous ghost drawing lcd_mutex.unlock(); - replaceCOINS(); - if(gx1>124) + replaceCOINS(); //replace the coin the ghost was just on if there was one + if(gx1>124) //This will cause the ghost to wrap around to the left side of the screen if there were no boundary on the far right { gx1 = 0; } - gx1 = gx1+STEP_SIZE; + gx1 = gx1+STEP_SIZE; //Move one step size in the x direction lcd_mutex.lock(); + //redraw the ghost at the new position uLCD.filled_circle(gx1,gy1,PAC_SIZE,BLUE); uLCD.filled_rectangle(gx1-PAC_SIZE,gy1,gx1+PAC_SIZE,gy1+PAC_SIZE,BLUE); uLCD.filled_circle(gx1+2,gy1-2,1,BLACK); @@ -134,6 +147,7 @@ lcd_mutex.unlock(); } +//Moves the blue ghost left void bgLEFT(void) { Thread::wait(50); @@ -154,6 +168,7 @@ lcd_mutex.unlock(); } +//Moves the blue ghost up void bgUP(void) { Thread::wait(50); @@ -174,6 +189,7 @@ lcd_mutex.unlock(); } +//Moves the blue ghost down void bgDOWN(void) { Thread::wait(50); @@ -194,16 +210,17 @@ lcd_mutex.unlock(); } +//Force ghost to chase Pacman void follow(void) { - if(x==gx1 && y==gy1) + if(x==gx1 && y==gy1) //if the ghost and Pacman are at the same position trigger losing condition { - win = true; + win = true; //This is set to true just to exit the check for a win loop and terminate other loops without writing additional conditions lose = true; } - while(x==gx1 && gy1<y && !win) + while(x==gx1 && gy1<y && !win) //If the ghost is directly above Pacman check to see if moving down is possible, then move down { - BGclearDOWN(); + BGclearDOWN(); bgDOWN(); } while(x==gx1 && gy1>y && !win) @@ -223,19 +240,18 @@ } } +//Ghost selects a direction to move void pickMOVE(void) { - while((gx1==x || gy1==y) && abs(x-gx1)+abs(y-gy1)<=16 && !win) + while((gx1==x || gy1==y) && abs(x-gx1)+abs(y-gy1)<=16 && !win) //If Pacman is close by give chase { follow(); - //Thread::wait(100); } - int dec = rand()%4; - //int dec = 0; + int dec = rand()%4; //randomly generate a number from the set 0,1,2,3, which serves as the direction decision if(dec == 0) { BGclearRIGHT(); - while(bgcr && !win) + while(bgcr && !win) //If decision 0 was reached, check to the the move right until a boundary is reached { bgRIGHT(); BGclearRIGHT(); @@ -270,6 +286,7 @@ } } +//Check if Pacman can move one step size to the right (Essentially the same as checking for the ghost) void CHECKclearRIGHT(void) { clearRIGHT = true; @@ -284,6 +301,7 @@ } } +//Check if Pacman can move left void CHECKclearLEFT(void) { clearLEFT = true; @@ -298,6 +316,7 @@ } } +//Check if Pacman can move up void CHECKclearUP(void) { clearUP = true; @@ -312,6 +331,7 @@ } } +//Check if Pacman can move down void CHECKclearDOWN(void) { clearDOWN = true; @@ -326,35 +346,37 @@ } } +//This function tracks the coin Pacman eats as he passes over it void changeCOINS(void) { for(int m=0; m<81; m++) { lcd_mutex.lock(); - if(x == coins[m][0] && y == coins[m][1]) + if(x == coins[m][0] && y == coins[m][1]) //Compare Pacman's position to the set of coins { - coins[m][0]=64; - coins[m][1]=64; + coins[m][0]=64; //If there is a match, change that coins location to the center of the board where Pacman + coins[m][1]=64; //cannot go, but do not draw the coin } lcd_mutex.unlock(); } } +//Move Pacman one step size to the right void PACmoveRIGHT(void) { - while(clearRIGHT && !win) + while(clearRIGHT && !win) //Not win indicates the game has not ended { lcd_mutex.lock(); - uLCD.filled_circle(x,y,PAC_SIZE,BLACK); + uLCD.filled_circle(x,y,PAC_SIZE,BLACK); //Erase Pacman at his last location lcd_mutex.unlock(); - if(x>124) + if(x>124) //wrap around if moving off the board { x = 0; } - x = x+STEP_SIZE; - changeCOINS(); + x = x+STEP_SIZE; //move Pacman one step size to the right + changeCOINS(); //Track the coin that was eaten at the last location - if(x%(2*STEP_SIZE) == 0) + if(x%(2*STEP_SIZE) == 0) //There are two drawings provided for Pacman. The if statement causes Pacman to open his mouth every other move. { lcd_mutex.lock(); uLCD.filled_circle(x,y,PAC_SIZE,0xFFFF00); @@ -368,15 +390,16 @@ uLCD.filled_rectangle(x+2,y,x+PAC_SIZE,y+1,BLACK); lcd_mutex.unlock(); } - if(jsx <= .75) + if(jsx <= .9) //If the user is still holding the joystick to the right, remain in this loop { checkMOVE(); } - CHECKclearRIGHT(); + CHECKclearRIGHT(); //If the user remains in the loop, check for a boundary to the right Thread::wait(10); } } +//Move Pacman left void PACmoveLEFT(void) { while(clearLEFT && !win) @@ -413,6 +436,7 @@ } } +//Move Pacman up void PACmoveUP(void) { while(clearUP && !win) @@ -449,6 +473,7 @@ } } +//Move Pacman down void PACmoveDOWN(void) { while(clearDOWN && !win) @@ -485,6 +510,8 @@ } } +//Read the input from the joystick and select a direction to move +//The thresholds are set near the end of their ranges to eliminate unintentional moves as much as possible void checkMOVE(void) { if(jsx > .9) @@ -509,6 +536,7 @@ } } +//Draw the boudaries for the game using the uLCD graphics commands void drawBORDERS(void) { //Outer Border @@ -562,10 +590,11 @@ { for(int j=0; j<81; j++) { - uLCD.filled_circle(coins[j][0],coins[j][1],1,0xFFFF00); + uLCD.filled_circle(coins[j][0],coins[j][1],1,0xFFFF00); //Draw the coins in their initial locations } } +//Draw all the initial states of the game void initialize(void) { drawBORDERS(); @@ -574,13 +603,14 @@ uLCD.filled_rectangle(x-2,y-2,x-PAC_SIZE,y+2,BLACK); } +//Check to see if all the coins have been eaten void checkWIN(void) { win = true; for(int k=0; k<81; k++) { lcd_mutex.lock(); - if(coins[k][0]!=64 || coins[k][1]!=64) + if(coins[k][0]!=64 || coins[k][1]!=64) //Check the locations of all coins and if 1 has coordinates other than (64,64) the user has not won { win = false; } @@ -588,6 +618,7 @@ } } +//Thread supervising the joystick inputs and moving Pacman accordingly void pacMOVE(void const *args) { while(!win) @@ -597,6 +628,7 @@ } } +//Thread controlling the movement of the blue ghost void blueGHOST(void const *args) { while(!win) @@ -608,29 +640,21 @@ int main() { uLCD.cls(); - //uLCD.background_color(DGREY); uLCD.baudrate(BAUD_3000000); - //int x=64,y=64, - //int xy[2]={64,64}; - //Thread t1(thread1,&x1,&y1); - initialize(); - Thread pm(pacMOVE); - Thread bg(blueGHOST); - //Thread clr(clear); - //pixel = uLCD.read_pixel(128,128); - //for(int k=0; k<10; k++){ - //i = rand(); - //uLCD.printf("rand = %d\n",rand()); - Thread::wait(5000); + initialize(); //Draw the level setup + Thread pm(pacMOVE); //Start the thread for moving Pacman + //Thread bg(blueGHOST); //Start the thread for moving the blue ghost - while(!win) + Thread::wait(5000); //Wait some time before checking the win conditions since it will take around 30 secs to eat all 81 coins + while(!win) //Check to see if there was a win once every tenth of a second { checkWIN(); - Thread::wait(1000); + Thread::wait(100); } - //uLCD.printf("WIN"); - Thread::wait(1000); - if(lose) + + Thread::wait(1000); //Wait one second before displaying end message + + if(lose) //Print game over message if lose (determined in the follow function) { uLCD.cls(); uLCD.printf("Sorry\nGame Over"); @@ -638,8 +662,6 @@ else { uLCD.cls(); - //uLCD.locate(60,60); - //uLCD.set_font_size(10,10); uLCD.printf("Congratulations!\nYou Won!"); }