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
Diff: Ghost.h
- 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