Design

edition 0.1_01
by heavyz
2003-05-19


Here explains what is the structure of "Expresso Game Template", and how it works.


Basic Concepts

This part explains the basic concepts of "Expresso Game Template" (in short, "EGT"). They are: Role, AttributeSet, RoleView, GameContainer and GameEvent. While introducing these concepts, i'd like to consider a simplest "pacman" game as an example, that has only one screen.

Pacman Game Rules

The screen shot of the simplest pacman game is as following:

The rules of this game are defined as below:

  1. There are 4 components on the map: pacman, fantome, bean and big bean.
  2. While running across a bean or a big bean, pacman can eat it. The goal of the game is that pacman eats up all the beans (including big beans).
  3. At the beginning, fantomes are stronger than pacman, and when they are encountered, pacman will be killed by the fantome. Whenever pacman is killed, game is over.
  4. After the pacman eats a big bean, all the living fantomes (excluding the dead fantomes) will become weak. In this status, when pacman and a fantome are encountered, pacman can kill the fantome. This weak status will last for a certain period of time.
  5. If a fantome is killed by the pacman, it is said to be dead. When a dead fantome returns to its nest at the center of the map, it will revive and become strong again.


Role, AttributeSet and RoleView

Within the game screen, the game can be divided into several parts.

Firstly, every role, such as the pacman, a fantome, a bean, a big bean, a nest unit and even a wall unit, should be considered as a Role object. A Role knows how it acts in the game. It holds an Attribute set that describes its current status. While it acts in the game, it actually changes its AttributeSet and then draws itself onto the screen.

Each Role contains a AttributeSet object, that describes the logical status of this Role. For example, a basic AttributeSet class has the following instance variables:

  1. status indicates the status of the Role. For example, a fantome may be weak, dead or strong. So its status variable can have three possible values.
  2. direction indicates the current moving direction of the Role. They are used for only active Roles such as fantome and pacman. For a wall unit or a nest unit, they are useless.
  3. action indicates the current action of the Role. It's also designed for the active Roles. An action is an integer. The status of a Role contains a certain number of actions. During each game loop, the action of the current status increases one unit. When the action reaches the max action number of the current status, it means that the current status is finished, and a new status needs to be generated. For example, a fantome may have a status called "dying". While it is being killed by the pacman, its status will change from "strong" to "dying" and then to "dead". The "dying" status contains 4 actions, and after 4 game loop, the fantome's "dying" status is finished, and a new status "dead" is generated. That's how a fantome is killed in detail. Note that the newly generated status may be the same as the previous status.
  4. position indicates the position of the Role on the map.

A Role does not draw itself onto the screen directly. Instead, it calls its RoleView reference to do the drawing work. A RoleView contains all the images of one kind of Roles, and it knows how to draw a Role object onto the screen according to its AttributeSet. For example, there exists in the pacman game only one RoleView for all the 4 fantomes, and there are 4 different fantome Roles, each containing a different AttributeSet. When a fantome wants to draw itself, it calls the public void draw(AttributeSet attrSet) method of its RoleView reference, and passes its AttributeSet to the method as the parameter. The fantome RoleView gets the AttributeSet and draws the calling fantome onto the screen. In this way, there may be hundreds of fantome Role instances on the map, but only one copy of the fantome images needs to be kept by the fantome RoleView instance.

The design of Role, AttributeSet and RoleView is based on the Model-View-Controller (MVC) design pattern. The model part cares about only the logical status of a role, and the view part cares about the physical drawing details of a role.


GameContainer

A GameContainer object is created to hold all the Roles in the game. All the Roles should register itself to the GameContainer. The GameContainer holds a vector containing all the Roles registered to it, and also, a registered Role holds a GameContainer reference to which it is registered.

During each game loop, the GameContainer firstly calls the public void act() method of each registered Role. This will cause the Roles to act. Then the GameContainer calls the public void draw() method of each registered Role. This will cause the Roles to draw itself onto the screen and thus update the game frame.

The acting rules of a Role are defined in its act() method. For example, in the act() method of a fantome Role, it updates its AttributeSet. The actual work is:

  1. Move its position according to its current direction.
  2. Increase its action. If its action reaches the maximum action number of its current status, generate a new status and a new random direction.

The draw() method of the Role is simple and easy to understand: it calls the draw(AttributeSet attrSet) method of its RoleView reference to draw itself.


GameEvent and the Interaction among Roles

A Role may interact with other Roles. For example, pacman may eat a bean, eat a big bean, or kill a fantome. The interaction among Roles is implemented by using GameEvent objects.

Every interaction has an active side and a passive side. At the active side, there is one Role; At the passive side, there may be one or more Roles. The two sides use GameEvents to communicate with each other. Consider that the pacman eats a big bean, which cause all the fantomes to become weak.

1) In the act() method, a Role fires all the GameEvents that are possible to happen, and passes them to the GameContainer reference by calling the broadcastGameEvent(GameEvent evt) method. For example, the pacman may fire a GameEvent called "WHERE_AM_I". Note that at this moment, an interaction has not actually happened yet. It is only POSSIBLE to happen.

2) In the broadcaseGameEvent(GameEvent evt) method, the GameContainer broadcasts the GameEvent parameter to all the registered Roles by calling their receiveGameEvent(GameEvent evt) method.

3) In the receiveGameEvent(GameEvent evt) method, the Role checks that whether this GameEvent will have effects on itself or not. For example, a "WHERE_AM_I" GameEvent may have effects only on a bean, a big bean or a fantome Role if and only if the position of the pacman is the same as that of the Role. And it has no effects on a wall unit or a nest unit Role. If the result of the checking is "yes", go to step 4), and else go to step 5).

4) Since the GameEvent has effects on the Role, the Role becomes the passive side of the interaction, and the GameEvent-generator Role becomes the active side. The passive Role will handle the GameEvent by updating its current AttributeSet, creating a response of the interaction (also a GameEvent), and passing the response back to the GameContainer by calling the broadcastGameEvent(GameEvent evt) method. For example, the big bean Role will modify its status from "NORMAL" to "EATEN" if it decides to handle the "WHERE_AM_I" GameEvent, and it will create a "BIGBEAN_EATEN" GameEvent and pass it to the GameContainer. This results in step 2) again. Next time, the fantome Roles will handle the "BIGBEAN_EATEN" GameEvent and become weak. No more GameEvents are generated by the fantomes.

5) If the GameEvent has no effects on any Role, it will be ignored and nothing happens.

A GameEvent contains the following instance variables:

  1. id indicates the type of the event. It may be "WHERE_AM_I" or "BIGBEAN_EATEN" or something else.
  2. attributeSet contains the logical status of the event. In most cases, it's only a copy of the AttributeSet of the event generator Role. But this is NOT always true.
  3. source is a reference of the event generator Role.



Other Chapters

This document is still under development.