This program runs through one level of Pacman. Be advised. This game is not fully functional. The ghost character was commented out due to its seeming inability to coexist with the Pacman character using my current code.
Dependencies: 4DGL-uLCD-SE mbed-rtos mbed
Revision 1:b86030cf57c4, committed 2014-03-25
- Comitter:
- srigdon3
- Date:
- Tue Mar 25 18:49:05 2014 +0000
- Parent:
- 0:0a900ff9a788
- Commit message:
- This program runs through one level of Pacman. Be advised the game is not fully functional. The ghost character was commented out due to the game freezing with multiple characters present.
Changed in this revision
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- 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!"); }