Developing a soccer video game has been more fun that I thought it would be. It has also been harder than I expected. Aside from coding, the part of development that has taken me time is creating the animations. I have done my best to create several animations that mimic a player movement on the field. As of today, I have created 21 animations and counting.
This month, I focused on developing a State Design Pattern and a messaging system for the AI. As the video below shows, the players can now communicate among themselves and be alerted whenever the ball is being passed to them.
State Design Pattern
State machines are taught using if-then or switch statements. Although such implementation is OK for small projects, it also leads to spaghetti code in complex projects.
A better way to implement a State Machine is with a Design Pattern known as State Pattern. The pros of using such pattern are that your State machine becomes modular and flexible. That is, you can remove or add as many States into your code without making it a chaotic mess.
Thus, instead of using a switch statement to implement a state machine, you use classes to represent a state object. Below is an illustration of the State Object:
Every state object contains an enter, execute and exit methods.
The enter and exit methods are useful methods in an A.I. system. For example, you may have a 3D model that as it enters the "state," it waves his hand. Or it performs a goodbye gestures as it exits the "state."
Let's see how this works:
Assume that the player is in an idle state; it is just standing on the field waiting to change from an idle to dribbling state.
When the player changes to a "dribbling" state, the "enter" method is called. The "enter" method plays the dribbling animation.
The "execute" method is then called in a continuous loop. In our instance, the player keeps dribbling the ball, until a message is sent to change state.
When the player receives a message to change state, the "execute" method is stopped, and the "exit" method is called. The "exit" method ends the dribbling animation.
Here is an illustration of the process mentioned above:
A soccer player requires several State Objects. For example, every player needs a running, passing, dribbling and marking state. A State Manager class is required to manage all these state objects.
The state manager is responsible for changing the state of the player, and for keeping track of the previous state. The State Manager is also responsible for calling the "enter," "execute" and "exit" methods in the appropriate order.
For example, when a player changes states, the State Manager calls the "exit" method of the current State object. It then calls the "enter" and "execute" methods of the new State object.
An AI system requires a messaging system to allow objects to communicate. For example, the player dribbling the ball can alert a nearby player of an incoming pass.
However, players don't receive these messages directly. Instead, the messages are received by the players' state objects.
Thus, aside from implementing an "enter," "execute" and "exit" methods, each state object also implements a "receiveMessage" method. The "receiveMessage" method acts upon the message received. For example, it can ask the player to change to a new state, or if the message is not appropriate for the current state, it ignores the message.
In the video above, when the button is pressed, a message is sent to the dribbling player with a request to pass the ball. The player changes states from dribbling to Passing state. Then another message is sent to the nearby player most likely to receive the ball.