Multi-game multiplayer arcade gaming system meant for the blue O when playing Super Tic-Tac-Toe.

Dependencies:   4DGL-uLCD-SE PinDetect SDFileSystem mbed wave_player

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Ghost.h Source File

Ghost.h

00001 /******************************************************
00002  * This header program declares all the functions and
00003  * variables used by Ghost players in Pac-Man.
00004  ******************************************************/
00005 
00006 
00007 // Ghost class
00008 class Ghost {
00009     public:
00010         // Ghost constructor
00011         Ghost(int color, Pacman& pacman, PinDetect &ghostRight, PinDetect &ghostDown, PinDetect &ghostLeft, PinDetect &ghostUp, Stage& stage, uLCD_4DGL& uLCD) :
00012             color(color), pacman(pacman), ghostRight(ghostRight), ghostDown(ghostDown), ghostLeft(ghostLeft), ghostUp(ghostUp), stage(stage), uLCD(uLCD) {
00013             // Use internal pullups
00014             ghostRight.mode(PullUp);
00015             ghostDown.mode(PullUp);
00016             ghostLeft.mode(PullUp);
00017             ghostUp.mode(PullUp);
00018             wait(0.01);
00019             // Interrupt callback functions
00020             ghostRight.attach_deasserted(this, &Ghost::ghostRightTrigger);
00021             ghostDown.attach_deasserted(this, &Ghost::ghostDownTrigger);
00022             ghostLeft.attach_deasserted(this, &Ghost::ghostLeftTrigger);
00023             ghostUp.attach_deasserted(this, &Ghost::ghostUpTrigger);
00024             wait(0.01);
00025             // Set sampling frequency
00026             ghostRight.setSampleFrequency();
00027             ghostDown.setSampleFrequency();
00028             ghostLeft.setSampleFrequency();
00029             ghostUp.setSampleFrequency();
00030             wait(1);
00031         }        
00032 
00033         // Initialize the ghost at the beginning of the game
00034         void initialize(int xCoordinate, int yCoordinate, int facingDirection) {
00035             startingX = xCoordinate;
00036             startingY = yCoordinate;
00037             x = xCoordinate;
00038             y = yCoordinate;
00039             direction = facingDirection;
00040             immobile = false;
00041             draw(x, y);
00042         }
00043 
00044         // Move the ghost
00045         void move() {
00046             // If Pac-Man died
00047             if (pacman.dead == true) {
00048                 // Reset the ghost
00049                 erase(x, y);
00050                 reinitialize();
00051                 pacman.dead = false;
00052             }
00053 
00054             // If the ghost is not moving
00055             if (immobile == true) {
00056                 // Reset the ghost
00057                 erase(x, y);
00058                 stage.redrawPacDots();
00059                 reinitialize();
00060             }
00061 
00062             // Move the ghost in its current direction
00063             switch (direction) {
00064                 case FACERIGHT:
00065                     moveRight();
00066                     break;
00067                 case FACEDOWN:
00068                     moveDown();
00069                     break;
00070                 case FACELEFT:
00071                     moveLeft();
00072                     break;
00073                 case FACEUP:
00074                     moveUp();
00075                     break;
00076                 default:
00077                     break;
00078             }
00079 
00080             // If Pac-Man and the ghost occupy the same position
00081             if ((abs(pacman.x - x) < 5) && (abs(pacman.y - y) < 5)) {
00082                 // If Pac-Man is not invincible
00083                 if (pacman.powerUp == 0) {
00084                     // Reset Pac-Man and the ghost
00085                     pacman.ghostsEaten = 0;
00086                     pacman.erase(pacman.x, pacman.y);
00087                     erase(x, y);
00088                     pacman.draw(pacman.x, pacman.y);
00089                     wait(0.5);
00090                     pacman.die();
00091                     pacman.dead = true;
00092                     reinitialize();
00093                 // If Pac-Man is invincible
00094                 } else {
00095                     // Reset the ghost
00096                     pacman.ghostsEaten++;
00097                     pacman.score += pacman.ghostsEaten * 200;
00098                     pacman.scoreChanged = true;
00099                     erase(x, y);
00100                     stage.redrawPacDots();
00101                     pacman.draw(pacman.x, pacman.y);
00102                     wait(0.5);
00103                     reinitialize();
00104                 }
00105             }
00106         }        
00107 
00108 
00109     private:
00110         int color;
00111         Pacman& pacman;
00112         PinDetect &ghostRight;
00113         PinDetect &ghostDown;
00114         PinDetect &ghostLeft;
00115         PinDetect &ghostUp;
00116         Stage& stage;
00117         uLCD_4DGL& uLCD;
00118         int startingX;
00119         int startingY;
00120         int x;
00121         int y;
00122         volatile int previousDirection;
00123         int direction;
00124         volatile int nextDirection;
00125         bool immobile;
00126 
00127         // Set the next direction to be right
00128         void ghostRightTrigger() {
00129             previousDirection = (direction + 2) % 4;
00130 
00131             if (previousDirection != FACERIGHT) {
00132                 nextDirection = FACERIGHT;
00133             }
00134         }
00135 
00136         // Set the next direction to be down
00137         void ghostDownTrigger() {
00138             previousDirection = (direction + 2) % 4;
00139 
00140             if (previousDirection != FACEDOWN) {
00141                 nextDirection = FACEDOWN;
00142             }
00143         }
00144 
00145         // Set the next direction to be left
00146         void ghostLeftTrigger() {
00147             previousDirection = (direction + 2) % 4;
00148 
00149             if (previousDirection != FACELEFT) {
00150                 nextDirection = FACELEFT;
00151             }
00152         }
00153 
00154         // Set the next direction to be up
00155         void ghostUpTrigger() {
00156             previousDirection = (direction + 2) % 4;
00157 
00158             if (previousDirection != FACEUP) {
00159                 nextDirection = FACEUP;
00160             }
00161         }
00162 
00163         // Reset function for each ghost
00164         void reinitialize() {
00165             // Red ghost reset
00166             if (color == RED) {
00167                 initialize(startingX, startingY, FACELEFT);
00168             // Yellow ghost reset
00169             } else if (color == YELLOW) {
00170                 initialize(startingX, startingY, FACERIGHT);
00171             }
00172         }
00173 
00174         // Draw the ghost based on its direction
00175         void draw(int xCoordinate, int yCoordinate) {
00176             // Outer bound rectangular coordinates of the ghost
00177             int x1 = xCoordinate - 3;
00178             int x2 = xCoordinate + 3;
00179             int y1 = yCoordinate - 3;
00180             int y2 = yCoordinate + 3;
00181 
00182             // If Pac-Man is currently invincible
00183             if (pacman.powerUp > 0) {
00184                 // Draw the ghost in blue
00185                 uLCD.filled_rectangle(x1, y1, x2, y2, BLUE);
00186             // If Pac-Man is not currently invincible
00187             } else {
00188                 // Draw the ghost in its original color
00189                 uLCD.filled_rectangle(x1, y1, x2, y2, color);
00190             }
00191 
00192             // Specify the pixels
00193             uLCD.pixel(x1, y1, BLACK);
00194             uLCD.pixel(x2, y1, BLACK);
00195             uLCD.pixel(xCoordinate - 2, y2, BLACK);
00196             uLCD.pixel(xCoordinate, y2, BLACK);
00197             uLCD.pixel(xCoordinate + 2, y2, BLACK);
00198             uLCD.pixel(x1, yCoordinate - 1, WHITE);
00199             uLCD.pixel(xCoordinate - 2, yCoordinate - 2, WHITE);
00200             uLCD.pixel(xCoordinate - 2, yCoordinate - 1, WHITE);
00201             uLCD.pixel(xCoordinate - 2, yCoordinate, WHITE);
00202             uLCD.pixel(xCoordinate - 1, yCoordinate - 1, WHITE);
00203             uLCD.pixel(x2, yCoordinate - 1, WHITE);
00204             uLCD.pixel(xCoordinate + 2, yCoordinate - 2, WHITE);
00205             uLCD.pixel(xCoordinate + 2, yCoordinate - 1, WHITE);
00206             uLCD.pixel(xCoordinate + 2, yCoordinate, WHITE);
00207             uLCD.pixel(xCoordinate + 1, yCoordinate - 1, WHITE);
00208 
00209             // Draw the ghost's eyes based on its current direction
00210             switch (direction) {
00211                 case FACERIGHT:
00212                     uLCD.pixel(xCoordinate - 1, yCoordinate - 1, BLACK);
00213                     uLCD.pixel(x2, yCoordinate - 1, BLACK);
00214                     break;
00215                 case FACEDOWN:
00216                     uLCD.pixel(xCoordinate - 2, yCoordinate, BLACK);
00217                     uLCD.pixel(xCoordinate + 2, yCoordinate, BLACK);
00218                     break;
00219                 case FACELEFT:
00220                     uLCD.pixel(x1, yCoordinate - 1, BLACK);
00221                     uLCD.pixel(xCoordinate + 1, yCoordinate - 1, BLACK);
00222                     break;
00223                 case FACEUP:
00224                     uLCD.pixel(xCoordinate - 2, yCoordinate - 2, BLACK);
00225                     uLCD.pixel(xCoordinate + 2, yCoordinate - 2, BLACK);
00226                     break;
00227                 default:
00228                     break;
00229             }
00230         }
00231 
00232         // Erase the ghost from the given position
00233         void erase(int xCoordinate, int yCoordinate) {
00234             int x1 = xCoordinate - 3;
00235             int x2 = xCoordinate + 3;
00236             int y1 = yCoordinate - 3;
00237             int y2 = yCoordinate + 3;
00238             uLCD.filled_rectangle(x1, y1, x2, y2, BLACK);
00239         }
00240 
00241         // Move the ghost right
00242         void moveRight() {
00243             // If the space to the right is a valid position and is not the rightmost space
00244             if ((stage.positions[x + 1][y] != 0) && (x != 124)) {
00245                 // The ghost is mobile
00246                 immobile = false;
00247                 // Erase the ghost from its current position
00248                 erase(x, y);
00249                 // Increment the ghost's x-coordinate
00250                 x++;
00251 
00252                 // If passed over a pac dot
00253                 if (stage.positions[x - 4][y] == 2) {
00254                     // Redraw the pac dot
00255                     uLCD.pixel(x - 4, y, YELLOW);
00256                 // If passed over a big pac dot
00257                 } else {
00258                     // Redraw the big pac dot
00259                     for (int i = x - 2; i >= x - 5; i--) {
00260                         if (stage.positions[i][y] == 3) {
00261                             uLCD.filled_circle(i, y, 1, YELLOW);
00262                         }
00263                     }
00264                 }
00265 
00266                 // Draw the ghost in its new position
00267                 draw(x, y);
00268             // If the space to the right is not a valid positions
00269             } else if (stage.positions[x + 1][y] == 0) {
00270                 // The ghost is immobile
00271                 immobile = true;
00272                 wait(0.03);
00273             }
00274 
00275             // If the rightmost position is reached
00276             if (x == 124) {
00277                 // The ghost is mobile
00278                 immobile = false;
00279                 // Erase the ghost from its current position
00280                 erase(x, y);
00281                 // Set the ghost's x-coordinate to 4
00282                 x = 4;
00283 
00284                 // If passed over a pac dot
00285                 if (stage.positions[124][68] == 2) {
00286                     // Redraw the pac dot
00287                     uLCD.pixel(124, 68, YELLOW);
00288                 }
00289 
00290                 // Draw the ghost in its new position
00291                 draw(x, y);
00292             }
00293 
00294             // If Pac-Man's invincibility status changed
00295             if (pacman.powerUpChanged == true) {
00296                 // Change the color of the ghost
00297                 draw(x, y);
00298                 // Reset Pac-Man's invincibility status change
00299                 pacman.powerUpChanged = false;
00300             }
00301 
00302             // Set the ghost's next direction
00303             switch (nextDirection) {
00304                 case FACEDOWN:
00305                     if (stage.positions[x][y + 1] != 0) {
00306                         direction = nextDirection;
00307                     }
00308     
00309                     break;
00310                 case FACELEFT:
00311                     if (stage.positions[x - 1][y] != 0) {
00312                         direction = nextDirection;
00313                     }
00314     
00315                     break;
00316                 case FACEUP:
00317                     if (stage.positions[x][y - 1] != 0) {
00318                         direction = nextDirection;
00319                     }
00320     
00321                     break;
00322                 default:
00323                     break;
00324             }
00325         }
00326 
00327         // Move the ghost down
00328         void moveDown() {
00329             // If the space in the downward direction is a valid position
00330             if (stage.positions[x][y + 1] != 0) {
00331                 // The ghost is mobile
00332                 immobile = false;
00333                 // Erase the ghost from its current position
00334                 erase(x, y);
00335                 // Increment the ghost's y-coordinate
00336                 y++;
00337 
00338                 // If passed over a pac dot
00339                 if (stage.positions[x][y - 4] == 2) {
00340                     // Redraw the pac dot
00341                     uLCD.pixel(x, y - 4, YELLOW);
00342                 // If passed over a big pac dot
00343                 } else {
00344                     // Redraw the big pac dot
00345                     for (int j = y - 2; j >= y - 5; j--) {
00346                         if (stage.positions[x][j] == 3) {
00347                             uLCD.filled_circle(x, j, 1, YELLOW);
00348                         }
00349                     }
00350                 }
00351 
00352                 // Draw the ghost in its new position
00353                 draw(x, y);
00354             // If the space in the downward direction is not a valid position
00355             } else {
00356                 // The ghost is immobile
00357                 immobile = true;
00358                 wait(0.03);
00359             }
00360 
00361             // If Pac-Man's invincibility status changed
00362             if (pacman.powerUpChanged == true) {
00363                 // Change the color of the ghost
00364                 draw(x, y);
00365                 // Reset Pac-Man's invincibility status change
00366                 pacman.powerUpChanged = false;
00367             }
00368 
00369             // Set the ghost's next direction
00370             switch (nextDirection) {
00371                 case FACERIGHT:
00372                     if (stage.positions[x + 1][y] != 0) {
00373                         direction = nextDirection;
00374                     }
00375 
00376                     break;
00377                 case FACELEFT:
00378                     if (stage.positions[x - 1][y] != 0) {
00379                         direction = nextDirection;
00380                     }
00381 
00382                     break;
00383                 case FACEUP:
00384                     if (stage.positions[x][y - 1] != 0) {
00385                         direction = nextDirection;
00386                     }
00387 
00388                     break;
00389                 default:
00390                     break;
00391             }
00392         }
00393 
00394         // Move the ghost left
00395         void moveLeft() {
00396             // If the space to the left is a valid position and is not the leftmost space
00397             if ((stage.positions[x - 1][y] != 0) && (x != 4)) {
00398                 // The ghost is mobile
00399                 immobile = false;
00400                 // Erase the ghost from its current position
00401                 erase(x, y);
00402                 // Decrement the ghost's x-coordinate
00403                 x--;
00404 
00405                 // If passed over a pac dot
00406                 if (stage.positions[x + 4][y] == 2) {
00407                     // Redraw the pac dot
00408                     uLCD.pixel(x + 4, y, YELLOW);
00409                 // If passed over a big pac dot
00410                 } else {
00411                     // Redraw the big pac dot
00412                     for (int i = x + 2; i <= x + 5; i++) {
00413                         if (stage.positions[i][y] == 3) {
00414                             uLCD.filled_circle(i, y, 1, YELLOW);
00415                         }
00416                     }
00417                 }
00418 
00419                 // Draw the ghost in its new position
00420                 draw(x, y);
00421             // If the space to the left is not a valid position
00422             } else if (stage.positions[x - 1][y] == 0) {
00423                 // The ghost is immobile
00424                 immobile = true;
00425                 wait(0.03);
00426             }
00427 
00428             // If the leftmost position is reached
00429             if (x == 4) {
00430                 // The ghost is mobile
00431                 immobile = false;
00432                 // Erase the ghost from its current position
00433                 erase(x, y);
00434                 // Set the ghost's x-coordinate to 124
00435                 x = 124;
00436 
00437                 // If passed over a pac dot
00438                 if (stage.positions[4][68] == 2) {
00439                     // Redraw the pac dot
00440                     uLCD.pixel(4, 68, YELLOW);
00441                 }
00442 
00443                 // Draw the ghost in its new position
00444                 draw(x, y);
00445             }
00446 
00447             // If Pac-Man's invincibility status changed
00448             if (pacman.powerUpChanged == true) {
00449                 // Change the color of the ghost
00450                 draw(x, y);
00451                 // Reset Pac-Man's invincibility status change
00452                 pacman.powerUpChanged = false;
00453             }
00454 
00455             // Set the ghost's next direction
00456             switch (nextDirection) {
00457                 case FACERIGHT:
00458                     if (stage.positions[x + 1][y] != 0) {
00459                         direction = nextDirection;
00460                     }
00461 
00462                     break;
00463                 case FACEDOWN:
00464                     if (stage.positions[x][y + 1] != 0) {
00465                         direction = nextDirection;
00466                     }
00467 
00468                     break;
00469                 case FACEUP:
00470                     if (stage.positions[x][y - 1] != 0) {
00471                         direction = nextDirection;
00472                     }
00473 
00474                     break;
00475                 default:
00476                     break;
00477             }
00478         }
00479 
00480         // Move the ghost up
00481         void moveUp() {
00482             // If the space in the upward direction is a valid position
00483             if (stage.positions[x][y - 1] != 0) {
00484                 // The ghost is mobile
00485                 immobile = false;
00486                 // Erase the ghost from its current position
00487                 erase(x, y);
00488                 // Decrement the ghost's y-coordinate
00489                 y--;
00490 
00491                 // If passed over a pac dot
00492                 if (stage.positions[x][y + 4] == 2) {
00493                     // Redraw the pac dot
00494                     uLCD.pixel(x, y + 4, YELLOW);
00495                 // If passed over a big pac dot
00496                 } else {
00497                     // Redraw the big pac dot
00498                     for (int j = y + 2; j <= y + 5; j++) {
00499                         if (stage.positions[x][j] == 3) {
00500                             uLCD.filled_circle(x, j, 1, YELLOW);
00501                         }
00502                     }
00503                 }
00504 
00505                 // Draw the ghost in its new position
00506                 draw(x, y);
00507             // If the space in the upward direction is not a valid position
00508             } else {
00509                 // The ghost is immobile
00510                 immobile = true;
00511                 wait(0.03);
00512             }
00513 
00514             // If Pac-Man's invincibility status changed
00515             if (pacman.powerUpChanged == true) {
00516                 // Change the color of the ghost
00517                 draw(x, y);
00518                 // Reset Pac-Man's invincibility status change
00519                 pacman.powerUpChanged = false;
00520             }
00521 
00522             // Set the ghost's next direction
00523             switch (nextDirection) {
00524                 case FACERIGHT:
00525                     if (stage.positions[x + 1][y] != 0) {
00526                         direction = nextDirection;
00527                     }
00528 
00529                     break;
00530                 case FACEDOWN:
00531                     if (stage.positions[x][y + 1] != 0) {
00532                         direction = nextDirection;
00533                     }
00534 
00535                     break;
00536                 case FACELEFT:
00537                     if (stage.positions[x - 1][y] != 0) {
00538                         direction = nextDirection;
00539                     }
00540 
00541                     break;
00542                 default:
00543                     break;
00544             }
00545         }
00546 };