Game Development Reference
In-Depth Information
States can have any number of implementations but are typically implemented with
an abstract base class that defines an update function. Each state implements this
update function to provide the appropriate behavior for that state. Here
'
s the base
state class for teapots:
TeapotState = class(nil,
{
_teapot = nil,
_teapotMoveSpeed = 7,
});
function TeapotState:Init()
if (self._teapot == nil) then
print(
Invalid teapot in TeapotState
);
return false;
end
return true;
end
function TeapotState:Update(deltaMs)
error(
Calling unimplemented TeapotState.Update() function
);
end
This defines the interface for all states. The Init() function is called in the state
machine class when the state is set as the current state, and the Update() function
is called every frame. Notice how the Update() function just throws an error. This
is a way of defining a pure virtual function. All subclasses must implement this func-
tion, or this error will get thrown. If we didn
'
t define this error, a generic
attempting
to call a nil value
error would be thrown instead. At least this error gives us specific
information.
Too Many Script Processes
You might have noticed that the states above look an awful
lot like the
ScriptProcess interface. It
s true that these states could all be made into
script processes with their own update tick, but this doesn
'
t scale very well.
Remember, crossing the Lua/C++ boundary is expensive, especially if you
'
re
doing it every frame. Having 100 script processes all running is much more
expensive than having a single script process that loops through 100 states.
'
The basic logical state machine in Figure 18.1 has been fully implemented for the tea-
pots. I
'
m not going to go through the implementation for each state because it
'
s more
 
Search WWH ::




Custom Search