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

Ghost.h

Committer:
soapy12312
Date:
2015-12-04
Revision:
2:d35fde2d82cd
Parent:
1:2a7e2f5aeda4

File content as of revision 2:d35fde2d82cd:

/******************************************************
 * This header program declares all the functions and
 * variables used by Ghost players in Pac-Man.
 ******************************************************/


// 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;
            }
        }
};