We figured out how to move a Ghost entity around the screen and directing its movement by giving it a point of interest. Now let's get into the nitty gritty details of all four ghosts and their respective points of interests and how those points of interests change during the game.
The ghosts have several modes in which they operate. The main two modes we need to worry about at this point are called "scatter" and "chase". When the game starts, the ghosts are in scatter mode. During scatter mode they retreat to their respective corners. There are four corners in the maze and there are four ghosts. I'll explain which ghosts go to which corners, but it doesn't really matter. Two of the ghosts actually start inside a box in the middle of the maze and can't go to their corners initially. Right now we'll assume that all four ghosts are outside that box. We'll have to deal with the "penalty box" later. The scatter mode lasts for a certain amount of time, after which they change their mode to "chase" mode. During the chase mode they'll hunt Pacman down. The only real difference between these two modes is the point of interest we give the ghosts. For the scatter mode we'll give each ghost a corner of the screen as their point of interest. That's easy. For the chase mode their points of interest are different for each ghost. I'll explain those now below.
In the image on the right we're assuming that the yellow circle is Pacman and the red circle is Blinky. Blinky targets Pacman directly. During Chase mode we set Blinky's point of interest to be Pacman's position. This will make it look like Blinky is following Pacman around the maze. Wherever Pacman is, Blinky will try and get there. So, we need to constantly update Blinky's point of interest while in chase mode by just passing in Pacman's position to him.
During the scatter mode, Blinky's point of interest is the top right corner.
Inky has the most complex method of determining his point of interest during the chase mode. He needs to know Pacman's position, the direction Pacman is moving, and Blinky's position. We determine his point of interest by first taking Pacman's position and the direction he is facing. We then extend a line from Pacman two grid units in front of him (white line). If we think of the maze as a grid, a grid unit is the smallest possible distance between two nodes. Only one node can exist on a grid line. So we draw a line pointing from Pacman to two grid units in front of him. We then draw a line from Blinky's position to that location (dark red line). Then we double the length of that line. The location the final vector points to is Inky's point of interest (pink line). This point is always going to be changing depending on where Pacman and Blinky are.
In scatter mode, Inky's point of interest is the bottom right corner.
Pinky's point of interest during the chase mode is similar to Blinky's, however, instead of targeting Pacman directly, Blinky targets 4 grid units in front of Pacman. So Pinky just needs to know Pacman's position and direction. In the image on the right we're assuming Pacman is moving to the right.
During the scatter mode, Pinky's point of interest is the top left corner.
During chase mode Clyde's point of interest depends on how close he is to Pacman. If Clyde is more than 8 grid units radius away from Pacman, then Clyde's point of interest is Pacman's position (like Blinky). When Clyde is within the 8 grid unit radius his point of interest changes to his scatter point of interest. So basically, when Clyde is far away, he goes straight for Pacman, however when he gets too close to Pacman, he retreats to his corner. The image on the right just shows an 8 tile radius centered on Pacman. When Clyde is outside of this region, he targets Pacman, when he enters this region he retreats to his corner.
In scatter mode, Clyde's point of interest is the bottom left tile.
So during the course of the game we flip the mode back and forth between scatter and chase. We can play around to determine how long each mode should last. I think normally, the scatter mode lasts for 7 seconds and the chase mode lasts for around 20 seconds, so we'll use those values. Let's code these behaviors for the four ghosts and add them to our game.
In the ghosts.py file I created four new classes for each ghost. These classes inherit from the Ghost class, so each class can do everything Ghost can do. All we need to do here for each class is to specify the color of the circle we want to draw so we can differentiate between the ghosts. We also put in their specific point of interests. Right now we'll just put in the scatter points of interests as described above. We don't need to put one in for Pinky because the default point of interest is the top left corner, and that's where we want Pinky to go anyways.
In the run.py file we'll need to create objects from these classes. We'll have them all start on the same node for now. It doesn't matter where they start right now. Also import these classes from the ghosts.py file or you'll get an error.
In the game loop we update each ghost, and then draw each ghost to the screen.
This video shows the result of the above code. Each ghost is circling their respective corners. This is their behavior in the scatter mode. Now, let's define their chase mode.
In each individual ghost class we'll add a setChasePOI method and a setScatterPOI method. These methods will set the ghosts point of interest depending on which method we call. When we want the ghost to scatter, we'll call the setScatterPOI method. When we want the ghost to hunt Pacman, then we'll set the setChasePOI method.
I should mention that I placed the gridUnit and SCREENSIZE constants in the constants.py file so I could use that info without passing it in. It's good to put all the constants there and have all of the files import that file.
In the game loop we call the setChasePOI methods for all the ghosts to test it out. See the video below to see the ghosts chasing Pacman.
You can see that the ghosts are chasing Pacman now anywhere he goes with their own behaviors. If the ghosts were always chasing Pacman, then it would be way too frustrating. So instead we'll send the ghosts in waves. We'll have them chase Pacman for 20 seconds, then they retreat for about 7 seconds, then they chase again for 20 seconds, and so forth. That way we give the player a break from the onslaught of ghosts.
All this does is switch between the two modes. When it's chase mode we'll call the setChasePOI method and when it's scatter mode we'll call the setScatterPOI method.
We're not finished with the ghosts yet since there's still more to do, but we'll worry about the rest later. Next we'll add some pellets to the maze.