Better Scripts, Better Games

of programming patterns that have proven over time to be successful. Though developers use these programming patterns in creating game behavior, the scripting languages usually do not support them explicitly. One of the reasons object-oriented programming languages have been so successful is that object-oriented programming patterns existed long before the languages that supported them. Similarly, by examining existing programming practices in game development, we can design scripting languages that require very little retraining of developers. The challenge in developing a scripting language is identifying those patterns and creating language features to support them most effectively.

THE S TA TE-EFFEC T PA T TERN

One popular pattern in game development is the state-effect pattern. Every game consists of a long-running simulation loop. The responsiveness of the game to player input depends entirely on the speed at which the

FIGURE

2

Example of the State-Effect Pattern

// State variables vector position, velocity; scalar q, damping, mass;

// Outer simulation loop for each timestep {

// Effect variables vector force;

// Compute effects for all for each particle o {

o.effectPhase();

}

// Update state for all for each particle o {

o.updatePhase() ;

}

simulation loop can be processed. In the state-effect pattern, each iteration of the simulation loop consists of two phases: effect and update. In the effect phase, each game object selects an action and determines individually the effects of this action. In the update phase, all the effects are combined and update the current state of the game to create the new state for the next iteration of the simulation loop.

Because of these two phases, we can separate the attributes of game objects into states and effects. State attributes represent the snapshot of the world after the last iteration of the simulation loop. They are altered only in the update phase and are read-only in the effect phase. Effect attributes, on the other hand, contain the new actions of the game objects, and the state of the game is updated with effects during the update phase. Because interactions between game objects are logically simultaneous, effect values are never read until the update phase. Hence, effect values are, in some sense, write-only during the effect phase.

Game physics provides many examples of this pattern. At the beginning of the simulation loop, each game object has a current position and velocity recorded as state attributes. To compute the new velocity, each object computes the vector sum of all of the forces acting upon it, such as collisions, gravity, or friction. In other words, the force attribute may be written to multiple times during the simulation loop, but it is never read until all of the force values have been summed together at the end of the loop. The example in figure 2 illustrates the use of the state-effect pattern to simulate objects moving about in a potential field. The variable force is an effect in this calculation. During the effect phase we only increment its value and never read it to determine control flow. Whereas most implementations would read the old value of force to perform this increment, this is not necessary; we could also gather all of

// Read state, write effects effectPhase() {

for each particle p { r = position-this.p.position; s = ((this.q*p.q)/( r.magnitude())^ 3; force += s*r;

}

}

}

// Read and write state, read effects updatePhase() {

velocity = damping*velocity+force/mass;

}

22 November/December 2008 ACM QUEUE

rants: feedback@acmqueue.com

References:

mailto:feedback@acmqueue.com

Archives