This program simulates a game of Pac-Man that allows for multiplayer. One player controls Pac-Man, while two other players control a red and yellow ghost using different tactile switches.

Dependencies:   4DGL-uLCD-SE PinDetect mbed

Fork of Pac-Man by Eric Xu

Committer:
soapy12312
Date:
Mon Oct 19 17:51:14 2015 +0000
Revision:
1:839f59c6d021
Parent:
0:8b6686f2d4be
Multiplayer Pac-Man.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
soapy12312 0:8b6686f2d4be 1 /*******************************************************
soapy12312 0:8b6686f2d4be 2 * Author: Yuanzhe Xu
soapy12312 0:8b6686f2d4be 3 * Institution: Georgia Institute of Technology
soapy12312 0:8b6686f2d4be 4 * Date: October 18, 2015
soapy12312 0:8b6686f2d4be 5 *
soapy12312 0:8b6686f2d4be 6 * This main program simulates a game of Pac-Man that
soapy12312 0:8b6686f2d4be 7 * allows for multiplayer. One player controls Pac-Man,
soapy12312 0:8b6686f2d4be 8 * while two other players control a red and yellow
soapy12312 0:8b6686f2d4be 9 * ghost using different tactile switches. Pac-Man
soapy12312 0:8b6686f2d4be 10 * starts with three lives, and the ghosts have
soapy12312 0:8b6686f2d4be 11 * infinite lives. Pac-Man's objective is to eat all of
soapy12312 0:8b6686f2d4be 12 * the pac dots before running out of lives. Eating a
soapy12312 0:8b6686f2d4be 13 * regular pac dot adds 10 points to Pac-Man's score;
soapy12312 0:8b6686f2d4be 14 * eating a big pac dot adds 50 points to Pac-Man's
soapy12312 0:8b6686f2d4be 15 * score. The ghosts' objective is to prevent Pac-Man
soapy12312 0:8b6686f2d4be 16 * from doing so. If Pac-Man comes into contact with a
soapy12312 0:8b6686f2d4be 17 * ghost, he dies and loses a life, causing Pac-Man and
soapy12312 0:8b6686f2d4be 18 * both of the ghosts to reset. If Pac-Man runs out of
soapy12312 0:8b6686f2d4be 19 * lives, he loses the game. As a countermeasure to the
soapy12312 0:8b6686f2d4be 20 * ghosts, the big pac dots are used as power-ups. The
soapy12312 0:8b6686f2d4be 21 * power-ups allow Pac-Man to be invincible for a fixed
soapy12312 0:8b6686f2d4be 22 * amount of time, during which Pac-Man can also eat the
soapy12312 0:8b6686f2d4be 23 * ghosts and force them to reset to their starting
soapy12312 0:8b6686f2d4be 24 * position. During each power-up period, the first
soapy12312 0:8b6686f2d4be 25 * ghost Pac-Man eats adds 200 points to Pac-Man's
soapy12312 0:8b6686f2d4be 26 * score, the second adds 400 points, the third adds 600
soapy12312 0:8b6686f2d4be 27 * points, and so on. The ghosts have two movement
soapy12312 0:8b6686f2d4be 28 * constraints: they must be moving at all times and
soapy12312 0:8b6686f2d4be 29 * they cannot move backwards in the direction they came
soapy12312 0:8b6686f2d4be 30 * (for example, when a ghost is moving to the right, it
soapy12312 0:8b6686f2d4be 31 * cannot change directions and move to the left).
soapy12312 0:8b6686f2d4be 32 * Failure to comply to the mobility constraint causes
soapy12312 0:8b6686f2d4be 33 * the ghost to reset to its original starting position.
soapy12312 0:8b6686f2d4be 34 * When the game ends (Pac-Man completes his objective
soapy12312 0:8b6686f2d4be 35 * or runs out of lives), a final screen is displayed
soapy12312 0:8b6686f2d4be 36 * saying whether Pac-Man wins or loses and prints out
soapy12312 0:8b6686f2d4be 37 * Pac-Man's final score.
soapy12312 0:8b6686f2d4be 38 *******************************************************/
soapy12312 0:8b6686f2d4be 39
soapy12312 0:8b6686f2d4be 40 #include "mbed.h"
soapy12312 0:8b6686f2d4be 41 #include "uLCD_4DGL.h"
soapy12312 0:8b6686f2d4be 42 #include "PinDetect.h"
soapy12312 0:8b6686f2d4be 43 #include "Stage.h"
soapy12312 0:8b6686f2d4be 44 #include "Pacman.h"
soapy12312 0:8b6686f2d4be 45 #include "Ghost.h"
soapy12312 0:8b6686f2d4be 46
soapy12312 0:8b6686f2d4be 47 // Pac-Man controller
soapy12312 0:8b6686f2d4be 48 PinDetect PacmanRight(p9);
soapy12312 0:8b6686f2d4be 49 PinDetect PacmanDown(p10);
soapy12312 0:8b6686f2d4be 50 PinDetect PacmanLeft(p11);
soapy12312 0:8b6686f2d4be 51 PinDetect PacmanClick(p12);
soapy12312 0:8b6686f2d4be 52 PinDetect PacmanUp(p13);
soapy12312 0:8b6686f2d4be 53
soapy12312 0:8b6686f2d4be 54 // Red ghost controller
soapy12312 0:8b6686f2d4be 55 PinDetect redGhostRight(p14);
soapy12312 0:8b6686f2d4be 56 PinDetect redGhostDown(p15);
soapy12312 0:8b6686f2d4be 57 PinDetect redGhostLeft(p16);
soapy12312 0:8b6686f2d4be 58 PinDetect redGhostClick(p17);
soapy12312 0:8b6686f2d4be 59 PinDetect redGhostUp(p19);
soapy12312 0:8b6686f2d4be 60
soapy12312 0:8b6686f2d4be 61 // Yellow ghost controller
soapy12312 0:8b6686f2d4be 62 PinDetect yellowGhostRight(p25);
soapy12312 0:8b6686f2d4be 63 PinDetect yellowGhostDown(p24);
soapy12312 0:8b6686f2d4be 64 PinDetect yellowGhostLeft(p23);
soapy12312 0:8b6686f2d4be 65 PinDetect yellowGhostClick(p22);
soapy12312 0:8b6686f2d4be 66 PinDetect yellowGhostUp(p21);
soapy12312 0:8b6686f2d4be 67
soapy12312 0:8b6686f2d4be 68 // uLCD display
soapy12312 0:8b6686f2d4be 69 uLCD_4DGL uLCD(p28, p27, p30);
soapy12312 0:8b6686f2d4be 70
soapy12312 0:8b6686f2d4be 71
soapy12312 0:8b6686f2d4be 72 // Direction inputs
soapy12312 0:8b6686f2d4be 73 int volatile nextPacmanDirection = FACEUP;
soapy12312 0:8b6686f2d4be 74 int volatile nextRedGhostDirection = FACELEFT;
soapy12312 0:8b6686f2d4be 75 int volatile nextYellowGhostDirection = FACERIGHT;
soapy12312 0:8b6686f2d4be 76
soapy12312 0:8b6686f2d4be 77
soapy12312 0:8b6686f2d4be 78 // Set the next Pac-Man direction to be right
soapy12312 0:8b6686f2d4be 79 void PacmanRightTrigger() {
soapy12312 0:8b6686f2d4be 80 nextPacmanDirection = FACERIGHT;
soapy12312 0:8b6686f2d4be 81 }
soapy12312 0:8b6686f2d4be 82
soapy12312 0:8b6686f2d4be 83 // Set the next Pac-Man direction to be down
soapy12312 0:8b6686f2d4be 84 void PacmanDownTrigger() {
soapy12312 0:8b6686f2d4be 85 nextPacmanDirection = FACEDOWN;
soapy12312 0:8b6686f2d4be 86 }
soapy12312 0:8b6686f2d4be 87
soapy12312 0:8b6686f2d4be 88 // Set the next Pac-Man direction to be left
soapy12312 0:8b6686f2d4be 89 void PacmanLeftTrigger() {
soapy12312 0:8b6686f2d4be 90 nextPacmanDirection = FACELEFT;
soapy12312 0:8b6686f2d4be 91 }
soapy12312 0:8b6686f2d4be 92
soapy12312 0:8b6686f2d4be 93 // Resume/Pause the game
soapy12312 0:8b6686f2d4be 94 void PacmanClickTrigger() {
soapy12312 0:8b6686f2d4be 95 wait(0.5);
soapy12312 0:8b6686f2d4be 96
soapy12312 0:8b6686f2d4be 97 while (PacmanClick == 1) {
soapy12312 0:8b6686f2d4be 98 }
soapy12312 0:8b6686f2d4be 99 }
soapy12312 0:8b6686f2d4be 100
soapy12312 0:8b6686f2d4be 101 // Set the next Pac-Man direction to be up
soapy12312 0:8b6686f2d4be 102 void PacmanUpTrigger() {
soapy12312 0:8b6686f2d4be 103 nextPacmanDirection = FACEUP;
soapy12312 0:8b6686f2d4be 104 }
soapy12312 0:8b6686f2d4be 105
soapy12312 0:8b6686f2d4be 106
soapy12312 0:8b6686f2d4be 107 // Set the next red ghost direction to be right
soapy12312 0:8b6686f2d4be 108 void redGhostRightTrigger() {
soapy12312 0:8b6686f2d4be 109 nextRedGhostDirection = FACERIGHT;
soapy12312 0:8b6686f2d4be 110 }
soapy12312 0:8b6686f2d4be 111
soapy12312 0:8b6686f2d4be 112 // Set the next red ghost direction to be down
soapy12312 0:8b6686f2d4be 113 void redGhostDownTrigger() {
soapy12312 0:8b6686f2d4be 114 nextRedGhostDirection = FACEDOWN;
soapy12312 0:8b6686f2d4be 115 }
soapy12312 0:8b6686f2d4be 116
soapy12312 0:8b6686f2d4be 117 // Set the next red ghost direction to be left
soapy12312 0:8b6686f2d4be 118 void redGhostLeftTrigger() {
soapy12312 0:8b6686f2d4be 119 nextRedGhostDirection = FACELEFT;
soapy12312 0:8b6686f2d4be 120 }
soapy12312 0:8b6686f2d4be 121
soapy12312 0:8b6686f2d4be 122 // Resume/Pause the game
soapy12312 0:8b6686f2d4be 123 void redGhostClickTrigger() {
soapy12312 0:8b6686f2d4be 124 wait(0.5);
soapy12312 0:8b6686f2d4be 125
soapy12312 0:8b6686f2d4be 126 while (redGhostClick == 1) {
soapy12312 0:8b6686f2d4be 127 }
soapy12312 0:8b6686f2d4be 128 }
soapy12312 0:8b6686f2d4be 129
soapy12312 0:8b6686f2d4be 130 // Set the next red ghost direction to be up
soapy12312 0:8b6686f2d4be 131 void redGhostUpTrigger() {
soapy12312 0:8b6686f2d4be 132 nextRedGhostDirection = FACEUP;
soapy12312 0:8b6686f2d4be 133 }
soapy12312 0:8b6686f2d4be 134
soapy12312 0:8b6686f2d4be 135
soapy12312 0:8b6686f2d4be 136 // Move the yellow ghost right
soapy12312 0:8b6686f2d4be 137 void yellowGhostRightTrigger() {
soapy12312 0:8b6686f2d4be 138 nextYellowGhostDirection = FACERIGHT;
soapy12312 0:8b6686f2d4be 139 }
soapy12312 0:8b6686f2d4be 140
soapy12312 0:8b6686f2d4be 141 // Set the next yellow ghost direction to be down
soapy12312 0:8b6686f2d4be 142 void yellowGhostDownTrigger() {
soapy12312 0:8b6686f2d4be 143 nextYellowGhostDirection = FACEDOWN;
soapy12312 0:8b6686f2d4be 144 }
soapy12312 0:8b6686f2d4be 145
soapy12312 0:8b6686f2d4be 146 // Set the next yellow ghost direction to be left
soapy12312 0:8b6686f2d4be 147 void yellowGhostLeftTrigger() {
soapy12312 0:8b6686f2d4be 148 nextYellowGhostDirection = FACELEFT;
soapy12312 0:8b6686f2d4be 149 }
soapy12312 0:8b6686f2d4be 150
soapy12312 0:8b6686f2d4be 151 // Resume/Pause the game
soapy12312 0:8b6686f2d4be 152 void yellowGhostClickTrigger() {
soapy12312 0:8b6686f2d4be 153 wait(0.5);
soapy12312 0:8b6686f2d4be 154
soapy12312 0:8b6686f2d4be 155 while (yellowGhostClick == 1) {
soapy12312 0:8b6686f2d4be 156 }
soapy12312 0:8b6686f2d4be 157 }
soapy12312 0:8b6686f2d4be 158
soapy12312 0:8b6686f2d4be 159 // Set the next yellow ghost direction to be up
soapy12312 0:8b6686f2d4be 160 void yellowGhostUpTrigger() {
soapy12312 0:8b6686f2d4be 161 nextYellowGhostDirection = FACEUP;
soapy12312 0:8b6686f2d4be 162 }
soapy12312 0:8b6686f2d4be 163
soapy12312 0:8b6686f2d4be 164
soapy12312 0:8b6686f2d4be 165 int main() {
soapy12312 0:8b6686f2d4be 166 // Maximize the baud rate
soapy12312 0:8b6686f2d4be 167 uLCD.baudrate(3000000);
soapy12312 0:8b6686f2d4be 168
soapy12312 0:8b6686f2d4be 169 // Use internal pullups
soapy12312 0:8b6686f2d4be 170 PacmanRight.mode(PullUp);
soapy12312 0:8b6686f2d4be 171 PacmanDown.mode(PullUp);
soapy12312 0:8b6686f2d4be 172 PacmanLeft.mode(PullUp);
soapy12312 0:8b6686f2d4be 173 PacmanClick.mode(PullUp);
soapy12312 0:8b6686f2d4be 174 PacmanUp.mode(PullUp);
soapy12312 0:8b6686f2d4be 175 redGhostRight.mode(PullUp);
soapy12312 0:8b6686f2d4be 176 redGhostDown.mode(PullUp);
soapy12312 0:8b6686f2d4be 177 redGhostLeft.mode(PullUp);
soapy12312 0:8b6686f2d4be 178 redGhostClick.mode(PullUp);
soapy12312 0:8b6686f2d4be 179 redGhostUp.mode(PullUp);
soapy12312 0:8b6686f2d4be 180 yellowGhostRight.mode(PullUp);
soapy12312 0:8b6686f2d4be 181 yellowGhostDown.mode(PullUp);
soapy12312 0:8b6686f2d4be 182 yellowGhostLeft.mode(PullUp);
soapy12312 0:8b6686f2d4be 183 yellowGhostClick.mode(PullUp);
soapy12312 0:8b6686f2d4be 184 yellowGhostUp.mode(PullUp);
soapy12312 0:8b6686f2d4be 185 wait(0.01);
soapy12312 0:8b6686f2d4be 186 // Interrupt callback functions
soapy12312 0:8b6686f2d4be 187 PacmanRight.attach_deasserted(&PacmanRightTrigger);
soapy12312 0:8b6686f2d4be 188 PacmanDown.attach_deasserted(&PacmanDownTrigger);
soapy12312 0:8b6686f2d4be 189 PacmanLeft.attach_deasserted(&PacmanLeftTrigger);
soapy12312 0:8b6686f2d4be 190 PacmanClick.attach_deasserted(&PacmanClickTrigger);
soapy12312 0:8b6686f2d4be 191 PacmanUp.attach_deasserted(&PacmanUpTrigger);
soapy12312 0:8b6686f2d4be 192 redGhostRight.attach_deasserted(&redGhostRightTrigger);
soapy12312 0:8b6686f2d4be 193 redGhostDown.attach_deasserted(&redGhostDownTrigger);
soapy12312 0:8b6686f2d4be 194 redGhostLeft.attach_deasserted(&redGhostLeftTrigger);
soapy12312 0:8b6686f2d4be 195 redGhostClick.attach_deasserted(&redGhostClickTrigger);
soapy12312 0:8b6686f2d4be 196 redGhostUp.attach_deasserted(&redGhostUpTrigger);
soapy12312 0:8b6686f2d4be 197 yellowGhostRight.attach_deasserted(&yellowGhostRightTrigger);
soapy12312 0:8b6686f2d4be 198 yellowGhostDown.attach_deasserted(&yellowGhostDownTrigger);
soapy12312 0:8b6686f2d4be 199 yellowGhostLeft.attach_deasserted(&yellowGhostLeftTrigger);
soapy12312 0:8b6686f2d4be 200 yellowGhostClick.attach_deasserted(&yellowGhostClickTrigger);
soapy12312 0:8b6686f2d4be 201 yellowGhostUp.attach_deasserted(&yellowGhostUpTrigger);
soapy12312 0:8b6686f2d4be 202 // Set sampling frequency
soapy12312 0:8b6686f2d4be 203 PacmanRight.setSampleFrequency();
soapy12312 0:8b6686f2d4be 204 PacmanDown.setSampleFrequency();
soapy12312 0:8b6686f2d4be 205 PacmanLeft.setSampleFrequency();
soapy12312 0:8b6686f2d4be 206 PacmanClick.setSampleFrequency();
soapy12312 0:8b6686f2d4be 207 PacmanUp.setSampleFrequency();
soapy12312 0:8b6686f2d4be 208 redGhostRight.setSampleFrequency();
soapy12312 0:8b6686f2d4be 209 redGhostDown.setSampleFrequency();
soapy12312 0:8b6686f2d4be 210 redGhostLeft.setSampleFrequency();
soapy12312 0:8b6686f2d4be 211 redGhostClick.setSampleFrequency();
soapy12312 0:8b6686f2d4be 212 redGhostUp.setSampleFrequency();
soapy12312 0:8b6686f2d4be 213 yellowGhostRight.setSampleFrequency();
soapy12312 0:8b6686f2d4be 214 yellowGhostDown.setSampleFrequency();
soapy12312 0:8b6686f2d4be 215 yellowGhostLeft.setSampleFrequency();
soapy12312 0:8b6686f2d4be 216 yellowGhostClick.setSampleFrequency();
soapy12312 0:8b6686f2d4be 217 yellowGhostUp.setSampleFrequency();
soapy12312 0:8b6686f2d4be 218
soapy12312 0:8b6686f2d4be 219 // Set up the stage
soapy12312 0:8b6686f2d4be 220 Stage stage(uLCD);
soapy12312 0:8b6686f2d4be 221 stage.initialize();
soapy12312 0:8b6686f2d4be 222
soapy12312 0:8b6686f2d4be 223 // Set up Pac-Man
soapy12312 0:8b6686f2d4be 224 Pacman pacman(uLCD, stage);
soapy12312 0:8b6686f2d4be 225 pacman.initialize();
soapy12312 0:8b6686f2d4be 226
soapy12312 0:8b6686f2d4be 227 // Set up the red ghost
soapy12312 0:8b6686f2d4be 228 Ghost redGhost(RED, uLCD, stage, pacman);
soapy12312 0:8b6686f2d4be 229 redGhost.initialize(60, 60, nextRedGhostDirection);
soapy12312 0:8b6686f2d4be 230
soapy12312 0:8b6686f2d4be 231 // Set up the yellow ghost
soapy12312 0:8b6686f2d4be 232 Ghost yellowGhost(YELLOW, uLCD, stage, pacman);
soapy12312 0:8b6686f2d4be 233 yellowGhost.initialize(68, 60, nextYellowGhostDirection);
soapy12312 0:8b6686f2d4be 234
soapy12312 0:8b6686f2d4be 235 // Wait 3 seconds
soapy12312 0:8b6686f2d4be 236 wait(3);
soapy12312 0:8b6686f2d4be 237
soapy12312 0:8b6686f2d4be 238 // Checks to see whether the game is over
soapy12312 0:8b6686f2d4be 239 bool gameOver;
soapy12312 0:8b6686f2d4be 240
soapy12312 0:8b6686f2d4be 241 // Loop through the game
soapy12312 0:8b6686f2d4be 242 while (1) {
soapy12312 0:8b6686f2d4be 243 pacman.setNextDirection(nextPacmanDirection);
soapy12312 0:8b6686f2d4be 244 pacman.displayStatus();
soapy12312 0:8b6686f2d4be 245 gameOver = pacman.move();
soapy12312 0:8b6686f2d4be 246
soapy12312 0:8b6686f2d4be 247 // If all pac dots are eaten or Pac-Man runs out of lives
soapy12312 0:8b6686f2d4be 248 if (gameOver == true) {
soapy12312 0:8b6686f2d4be 249 // Break out of the loop
soapy12312 0:8b6686f2d4be 250 break;
soapy12312 0:8b6686f2d4be 251 }
soapy12312 0:8b6686f2d4be 252
soapy12312 0:8b6686f2d4be 253 redGhost.setNextDirection(nextRedGhostDirection);
soapy12312 0:8b6686f2d4be 254 redGhost.move();
soapy12312 0:8b6686f2d4be 255
soapy12312 0:8b6686f2d4be 256 yellowGhost.setNextDirection(nextYellowGhostDirection);
soapy12312 0:8b6686f2d4be 257 yellowGhost.move();
soapy12312 0:8b6686f2d4be 258 }
soapy12312 0:8b6686f2d4be 259
soapy12312 0:8b6686f2d4be 260 // Game over display
soapy12312 0:8b6686f2d4be 261 pacman.gameOver();
soapy12312 0:8b6686f2d4be 262 }