During the game, the ghosts are always in one of four different modes or states. The main difference we need to understand between the modes is the goal the ghost is trying to reach. So, during the game, we periodically change the ghost's mode which in turn changes it's goals. I'll explain more about this in a bit, but for now here are the four different modes and their general description.
SCATTER: This mode tells the ghosts to scatter to one of the four corners of the maze. Each ghost has their own corner and I'll explain what they are when we start talking about the individual ghosts. For now, the corner we'll give to our current ghost is the top left corner.
CHASE: This, like the scatter mode, is different for all of the ghosts. I'll explain this in much more detail when we talk about the individual ghosts. But, in general, each ghost has a way of tracking Pacman down. The simplest of these is to just have Pacman's position as the goal. Doing this will make the ghost follow Pacman wherever he goes like a lost puppy. This is what we'll use for our test ghost since it's the simplest.
FREIGHT: We don't have to worry about this yet, but when Pacman eats a Power Pellet the ghosts are vulnerable and Pacman is able to eat them. During this mode the ghosts move around the maze randomly and slower. The length of time this mode lasts depends on the level. Longer in the earlier levels and shorter in the later levels.
SPAWN: This is the mode the ghosts are in after Pacman eats them. In this mode their goal is to get to their spawn location which we haven't defined yet so that they can respawn. They also move much faster in this mode. They stay in this mode until they reach their spawn location.
Right now the two main Modes we need to worry about are Scatter and Chase. We'll deal with the other modes in a future section. There are a few other things we need to understand about the Scatter and Chase modes. When the game first starts, all of the ghosts are in Scatter mode. Scatter mode only lasts for 7 seconds, then automatically switches to Chase mode. Chase mode then lasts for 20 seconds before switching back to Scatter mode. Throughout the game these modes keep switching back and forth. That's easy enough, but we also have to keep in mind that the other modes can happen at any time. For example, the FREIGHT mode can happen when the ghosts are either in SCATTER or CHASE mode. When the FREIGHT mode ends, the ghosts go back to whatever it was they were doing previously, SCATTER or CHASE.
You can think of SCATTER and CHASE being the main modes and all of the other modes as interrupt modes. Throughout the game, all of the ghosts should be synchronized to SCATTER and CHASE at the same time. So there should be some object that continuously flips back and forth between these modes independent of what the ghosts are doing. The ghosts can individually go into one of the interrupt modes, but once those are finished then they can easily find out if they should be in SCATTER or CHASE by asking the main mode object.
First off, lets define some constants that describe the modes. The values here don't matter, just as long as they are different. You can also just as easily use strings like "SCATTER", but I like using numbers rather than strings in general when I can. All we'll be doing with this anyways is comparing if we're in this mode or that mode and so forth.
Create a new file called modes.py and copy the following into it. Looking at this you see that I have 2 mode methods defined: scatter and chase. When created, this will start with the scatter mode, then there's a timer that will keep track of how long the mode is running for. When that time is exceeded it will switch to the chase mode and then that will run for however long we set it to. This will just continue flipping back and forth between these two modes throughout the game.
I'm going to create a class that controls the modes and so that we can always know which mode the ghost has to be in. RIght now it's only passing along the main mode (either SCATTER or CHASE). We'll also pass in the entity this mode controller is controlling in case it needs to send any messages back to the entity.
First off, we need to make the ghosts aware of this mode class so that they can easily find out what the main mode is so they know what to do. Like I said before, as far as the ghosts are concerned, the only difference between the modes is what their goal is. Right now the ghost only has one goal defined, and that's the scatter goal which is defined to be the upper left corner of the screen. We'll also need to define what their chase goal is. Again, like I mentioned before, we'll set the chase goal to be Pacman's position. So we'll also need to make them aware of where Pacman is at all times.
Let's first update the __init__ method in the Ghost class. Along with the node the ghost should start on we'll pass in the Pacman and mode objects. We'll also create scatter and chase methods so we can replace our goal with the output of the scatter method.
Alright, so as you can see the scatter and chase methods are really simple, they just define the goal. The scatter goal is the top left corner of the screen and the chase goal is just Pacman's position.
We'll also override the default update method. We're not going to overwrite it though, we just want to extend it. Here, we're simply asking the main mode which mode it is in, either SCATTER or CHASE and then we call the appropriate method. Then notice that we call the parent's update method at the end so all of that code will still run.
All we need to do here is pass in the Pacman object to the ghost so he can keep track of where Pacman is.
Running the game you should see the ghost start moving around the top left corner of the screen as before, but after a few seconds he'll start chasing Pacman around the maze. Then he'll go back to the left corner and will repeat the cycle.