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

Dependencies:   uLCD_4DGL_SE PinDetect SDFileSystem mbed wave_player

Revision:
0:218d3fb75950
Child:
1:2a7e2f5aeda4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Ghost.h	Thu Nov 26 02:58:17 2015 +0000
@@ -0,0 +1,551 @@
+/******************************************************
+ * Author: Yuanzhe Xu
+ * Institution: Georgia Institute of Technology
+ * Date: October 18, 2015
+ *
+ * This header file declares all the functions and
+ * variables needed for the Ghost object. Specific
+ * ghost functionalities can be found in main.cpp.
+ ******************************************************/
+
+
+// Ghost class
+class Ghost {
+    public:
+        // Ghost constructor
+        Ghost(int color, Pacman& pacman, PinDetect &ghostRight, PinDetect &ghostDown, PinDetect &ghostLeft, PinDetect &ghostUp, Stage& stage, uLCD_4DGL& uLCD)
+            : color(color), pacman(pacman), ghostRight(ghostRight), ghostDown(ghostDown), ghostLeft(ghostLeft), ghostUp(ghostUp), stage(stage), uLCD(uLCD) {
+            // Use internal pullups
+            ghostRight.mode(PullUp);
+            ghostDown.mode(PullUp);
+            ghostLeft.mode(PullUp);
+            ghostUp.mode(PullUp);
+            wait(0.01);
+            // Interrupt callback functions
+            ghostRight.attach_deasserted(this, &Ghost::ghostRightTrigger);
+            ghostDown.attach_deasserted(this, &Ghost::ghostDownTrigger);
+            ghostLeft.attach_deasserted(this, &Ghost::ghostLeftTrigger);
+            ghostUp.attach_deasserted(this, &Ghost::ghostUpTrigger);
+            wait(0.01);
+            // Set sampling frequency
+            ghostRight.setSampleFrequency();
+            ghostDown.setSampleFrequency();
+            ghostLeft.setSampleFrequency();
+            ghostUp.setSampleFrequency();
+            wait(1);
+        }        
+
+        // Initialize the ghost at the beginning of the game
+        void initialize(int xCoordinate, int yCoordinate, int facingDirection) {
+            startingX = xCoordinate;
+            startingY = yCoordinate;
+            x = xCoordinate;
+            y = yCoordinate;
+            direction = facingDirection;
+            immobile = false;
+            draw(x, y);
+        }
+
+        // Move the ghost
+        void move() {
+            // If Pac-Man died
+            if (pacman.dead == true) {
+                // Reset the ghost
+                erase(x, y);
+                reinitialize();
+                pacman.dead = false;
+            }
+
+            // If the ghost is not moving
+            if (immobile == true) {
+                // Reset the ghost
+                erase(x, y);
+                stage.redrawPacDots();
+                reinitialize();
+            }
+
+            // Move the ghost in its current direction
+            switch (direction) {
+                case FACERIGHT:
+                    moveRight();
+                    break;
+                case FACEDOWN:
+                    moveDown();
+                    break;
+                case FACELEFT:
+                    moveLeft();
+                    break;
+                case FACEUP:
+                    moveUp();
+                    break;
+                default:
+                    break;
+            }
+
+            // If Pac-Man and the ghost occupy the same position
+            if ((abs(pacman.x - x) < 5) && (abs(pacman.y - y) < 5)) {
+                // If Pac-Man is not invincible
+                if (pacman.powerUp == 0) {
+                    // Reset Pac-Man and the ghost
+                    pacman.ghostsEaten = 0;
+                    pacman.erase(pacman.x, pacman.y);
+                    erase(x, y);
+                    pacman.draw(pacman.x, pacman.y);
+                    wait(0.5);
+                    pacman.die();
+                    pacman.dead = true;
+                    reinitialize();
+                // If Pac-Man is invincible
+                } else {
+                    // Reset the ghost
+                    pacman.ghostsEaten++;
+                    pacman.score += pacman.ghostsEaten * 200;
+                    pacman.scoreChanged = true;
+                    erase(x, y);
+                    stage.redrawPacDots();
+                    pacman.draw(pacman.x, pacman.y);
+                    wait(0.5);
+                    reinitialize();
+                }
+            }
+        }        
+
+
+    private:
+        int color;
+        Pacman& pacman;
+        PinDetect &ghostRight;
+        PinDetect &ghostDown;
+        PinDetect &ghostLeft;
+        PinDetect &ghostUp;
+        Stage& stage;
+        uLCD_4DGL& uLCD;
+        int startingX;
+        int startingY;
+        int x;
+        int y;
+        volatile int previousDirection;
+        int direction;
+        volatile int nextDirection;
+        bool immobile;
+
+        // Set the next direction to be right
+        void ghostRightTrigger() {
+            previousDirection = (direction + 2) % 4;
+
+            if (previousDirection != FACERIGHT) {
+                nextDirection = FACERIGHT;
+            }
+        }
+
+        // Set the next direction to be down
+        void ghostDownTrigger() {
+            previousDirection = (direction + 2) % 4;
+
+            if (previousDirection != FACEDOWN) {
+                nextDirection = FACEDOWN;
+            }
+        }
+
+        // Set the next direction to be left
+        void ghostLeftTrigger() {
+            previousDirection = (direction + 2) % 4;
+
+            if (previousDirection != FACELEFT) {
+                nextDirection = FACELEFT;
+            }
+        }
+
+        // Set the next direction to be up
+        void ghostUpTrigger() {
+            previousDirection = (direction + 2) % 4;
+
+            if (previousDirection != FACEUP) {
+                nextDirection = FACEUP;
+            }
+        }
+
+        // Reset function for each ghost
+        void reinitialize() {
+            // Red ghost reset
+            if (color == RED) {
+                initialize(startingX, startingY, FACELEFT);
+            // Yellow ghost reset
+            } else if (color == YELLOW) {
+                initialize(startingX, startingY, FACERIGHT);
+            }
+        }
+
+        // Draw the ghost based on its direction
+        void draw(int xCoordinate, int yCoordinate) {
+            // Outer bound rectangular coordinates of the ghost
+            int x1 = xCoordinate - 3;
+            int x2 = xCoordinate + 3;
+            int y1 = yCoordinate - 3;
+            int y2 = yCoordinate + 3;
+
+            // If Pac-Man is currently invincible
+            if (pacman.powerUp > 0) {
+                // Draw the ghost in blue
+                uLCD.filled_rectangle(x1, y1, x2, y2, BLUE);
+            // If Pac-Man is not currently invincible
+            } else {
+                // Draw the ghost in its original color
+                uLCD.filled_rectangle(x1, y1, x2, y2, color);
+            }
+
+            // Specify the pixels
+            uLCD.pixel(x1, y1, BLACK);
+            uLCD.pixel(x2, y1, BLACK);
+            uLCD.pixel(xCoordinate - 2, y2, BLACK);
+            uLCD.pixel(xCoordinate, y2, BLACK);
+            uLCD.pixel(xCoordinate + 2, y2, BLACK);
+            uLCD.pixel(x1, yCoordinate - 1, WHITE);
+            uLCD.pixel(xCoordinate - 2, yCoordinate - 2, WHITE);
+            uLCD.pixel(xCoordinate - 2, yCoordinate - 1, WHITE);
+            uLCD.pixel(xCoordinate - 2, yCoordinate, WHITE);
+            uLCD.pixel(xCoordinate - 1, yCoordinate - 1, WHITE);
+            uLCD.pixel(x2, yCoordinate - 1, WHITE);
+            uLCD.pixel(xCoordinate + 2, yCoordinate - 2, WHITE);
+            uLCD.pixel(xCoordinate + 2, yCoordinate - 1, WHITE);
+            uLCD.pixel(xCoordinate + 2, yCoordinate, WHITE);
+            uLCD.pixel(xCoordinate + 1, yCoordinate - 1, WHITE);
+
+            // Draw the ghost's eyes based on its current direction
+            switch (direction) {
+                case FACERIGHT:
+                    uLCD.pixel(xCoordinate - 1, yCoordinate - 1, BLACK);
+                    uLCD.pixel(x2, yCoordinate - 1, BLACK);
+                    break;
+                case FACEDOWN:
+                    uLCD.pixel(xCoordinate - 2, yCoordinate, BLACK);
+                    uLCD.pixel(xCoordinate + 2, yCoordinate, BLACK);
+                    break;
+                case FACELEFT:
+                    uLCD.pixel(x1, yCoordinate - 1, BLACK);
+                    uLCD.pixel(xCoordinate + 1, yCoordinate - 1, BLACK);
+                    break;
+                case FACEUP:
+                    uLCD.pixel(xCoordinate - 2, yCoordinate - 2, BLACK);
+                    uLCD.pixel(xCoordinate + 2, yCoordinate - 2, BLACK);
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        // Erase the ghost from the given position
+        void erase(int xCoordinate, int yCoordinate) {
+            int x1 = xCoordinate - 3;
+            int x2 = xCoordinate + 3;
+            int y1 = yCoordinate - 3;
+            int y2 = yCoordinate + 3;
+            uLCD.filled_rectangle(x1, y1, x2, y2, BLACK);
+        }
+
+        // Move the ghost right
+        void moveRight() {
+            // If the space to the right is a valid position and is not the rightmost space
+            if ((stage.positions[x + 1][y] != 0) && (x != 124)) {
+                // The ghost is mobile
+                immobile = false;
+                // Erase the ghost from its current position
+                erase(x, y);
+                // Increment the ghost's x-coordinate
+                x++;
+
+                // If passed over a pac dot
+                if (stage.positions[x - 4][y] == 2) {
+                    // Redraw the pac dot
+                    uLCD.pixel(x - 4, y, YELLOW);
+                // If passed over a big pac dot
+                } else {
+                    // Redraw the big pac dot
+                    for (int i = x - 2; i >= x - 5; i--) {
+                        if (stage.positions[i][y] == 3) {
+                            uLCD.filled_circle(i, y, 1, YELLOW);
+                        }
+                    }
+                }
+
+                // Draw the ghost in its new position
+                draw(x, y);
+            // If the space to the right is not a valid positions
+            } else if (stage.positions[x + 1][y] == 0) {
+                // The ghost is immobile
+                immobile = true;
+                wait(0.03);
+            }
+
+            // If the rightmost position is reached
+            if (x == 124) {
+                // The ghost is mobile
+                immobile = false;
+                // Erase the ghost from its current position
+                erase(x, y);
+                // Set the ghost's x-coordinate to 4
+                x = 4;
+
+                // If passed over a pac dot
+                if (stage.positions[124][68] == 2) {
+                    // Redraw the pac dot
+                    uLCD.pixel(124, 68, YELLOW);
+                }
+
+                // Draw the ghost in its new position
+                draw(x, y);
+            }
+
+            // If Pac-Man's invincibility status changed
+            if (pacman.powerUpChanged == true) {
+                // Change the color of the ghost
+                draw(x, y);
+                // Reset Pac-Man's invincibility status change
+                pacman.powerUpChanged = false;
+            }
+
+            // Set the ghost's next direction
+            switch (nextDirection) {
+                case FACEDOWN:
+                    if (stage.positions[x][y + 1] != 0) {
+                        direction = nextDirection;
+                    }
+    
+                    break;
+                case FACELEFT:
+                    if (stage.positions[x - 1][y] != 0) {
+                        direction = nextDirection;
+                    }
+    
+                    break;
+                case FACEUP:
+                    if (stage.positions[x][y - 1] != 0) {
+                        direction = nextDirection;
+                    }
+    
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        // Move the ghost down
+        void moveDown() {
+            // If the space in the downward direction is a valid position
+            if (stage.positions[x][y + 1] != 0) {
+                // The ghost is mobile
+                immobile = false;
+                // Erase the ghost from its current position
+                erase(x, y);
+                // Increment the ghost's y-coordinate
+                y++;
+
+                // If passed over a pac dot
+                if (stage.positions[x][y - 4] == 2) {
+                    // Redraw the pac dot
+                    uLCD.pixel(x, y - 4, YELLOW);
+                // If passed over a big pac dot
+                } else {
+                    // Redraw the big pac dot
+                    for (int j = y - 2; j >= y - 5; j--) {
+                        if (stage.positions[x][j] == 3) {
+                            uLCD.filled_circle(x, j, 1, YELLOW);
+                        }
+                    }
+                }
+
+                // Draw the ghost in its new position
+                draw(x, y);
+            // If the space in the downward direction is not a valid position
+            } else {
+                // The ghost is immobile
+                immobile = true;
+                wait(0.03);
+            }
+
+            // If Pac-Man's invincibility status changed
+            if (pacman.powerUpChanged == true) {
+                // Change the color of the ghost
+                draw(x, y);
+                // Reset Pac-Man's invincibility status change
+                pacman.powerUpChanged = false;
+            }
+
+            // Set the ghost's next direction
+            switch (nextDirection) {
+                case FACERIGHT:
+                    if (stage.positions[x + 1][y] != 0) {
+                        direction = nextDirection;
+                    }
+
+                    break;
+                case FACELEFT:
+                    if (stage.positions[x - 1][y] != 0) {
+                        direction = nextDirection;
+                    }
+
+                    break;
+                case FACEUP:
+                    if (stage.positions[x][y - 1] != 0) {
+                        direction = nextDirection;
+                    }
+
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        // Move the ghost left
+        void moveLeft() {
+            // If the space to the left is a valid position and is not the leftmost space
+            if ((stage.positions[x - 1][y] != 0) && (x != 4)) {
+                // The ghost is mobile
+                immobile = false;
+                // Erase the ghost from its current position
+                erase(x, y);
+                // Decrement the ghost's x-coordinate
+                x--;
+
+                // If passed over a pac dot
+                if (stage.positions[x + 4][y] == 2) {
+                    // Redraw the pac dot
+                    uLCD.pixel(x + 4, y, YELLOW);
+                // If passed over a big pac dot
+                } else {
+                    // Redraw the big pac dot
+                    for (int i = x + 2; i <= x + 5; i++) {
+                        if (stage.positions[i][y] == 3) {
+                            uLCD.filled_circle(i, y, 1, YELLOW);
+                        }
+                    }
+                }
+
+                // Draw the ghost in its new position
+                draw(x, y);
+            // If the space to the left is not a valid position
+            } else if (stage.positions[x - 1][y] == 0) {
+                // The ghost is immobile
+                immobile = true;
+                wait(0.03);
+            }
+
+            // If the leftmost position is reached
+            if (x == 4) {
+                // The ghost is mobile
+                immobile = false;
+                // Erase the ghost from its current position
+                erase(x, y);
+                // Set the ghost's x-coordinate to 124
+                x = 124;
+
+                // If passed over a pac dot
+                if (stage.positions[4][68] == 2) {
+                    // Redraw the pac dot
+                    uLCD.pixel(4, 68, YELLOW);
+                }
+
+                // Draw the ghost in its new position
+                draw(x, y);
+            }
+
+            // If Pac-Man's invincibility status changed
+            if (pacman.powerUpChanged == true) {
+                // Change the color of the ghost
+                draw(x, y);
+                // Reset Pac-Man's invincibility status change
+                pacman.powerUpChanged = false;
+            }
+
+            // Set the ghost's next direction
+            switch (nextDirection) {
+                case FACERIGHT:
+                    if (stage.positions[x + 1][y] != 0) {
+                        direction = nextDirection;
+                    }
+
+                    break;
+                case FACEDOWN:
+                    if (stage.positions[x][y + 1] != 0) {
+                        direction = nextDirection;
+                    }
+
+                    break;
+                case FACEUP:
+                    if (stage.positions[x][y - 1] != 0) {
+                        direction = nextDirection;
+                    }
+
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        // Move the ghost up
+        void moveUp() {
+            // If the space in the upward direction is a valid position
+            if (stage.positions[x][y - 1] != 0) {
+                // The ghost is mobile
+                immobile = false;
+                // Erase the ghost from its current position
+                erase(x, y);
+                // Decrement the ghost's y-coordinate
+                y--;
+
+                // If passed over a pac dot
+                if (stage.positions[x][y + 4] == 2) {
+                    // Redraw the pac dot
+                    uLCD.pixel(x, y + 4, YELLOW);
+                // If passed over a big pac dot
+                } else {
+                    // Redraw the big pac dot
+                    for (int j = y + 2; j <= y + 5; j++) {
+                        if (stage.positions[x][j] == 3) {
+                            uLCD.filled_circle(x, j, 1, YELLOW);
+                        }
+                    }
+                }
+
+                // Draw the ghost in its new position
+                draw(x, y);
+            // If the space in the upward direction is not a valid position
+            } else {
+                // The ghost is immobile
+                immobile = true;
+                wait(0.03);
+            }
+
+            // If Pac-Man's invincibility status changed
+            if (pacman.powerUpChanged == true) {
+                // Change the color of the ghost
+                draw(x, y);
+                // Reset Pac-Man's invincibility status change
+                pacman.powerUpChanged = false;
+            }
+
+            // Set the ghost's next direction
+            switch (nextDirection) {
+                case FACERIGHT:
+                    if (stage.positions[x + 1][y] != 0) {
+                        direction = nextDirection;
+                    }
+
+                    break;
+                case FACEDOWN:
+                    if (stage.positions[x][y + 1] != 0) {
+                        direction = nextDirection;
+                    }
+
+                    break;
+                case FACELEFT:
+                    if (stage.positions[x - 1][y] != 0) {
+                        direction = nextDirection;
+                    }
+
+                    break;
+                default:
+                    break;
+            }
+        }
+};
\ No newline at end of file