As explained in my
previous
news post, I am currently migrating the old DeathMatch game code to
the new
Component System architecture. Just this afternoon I finished dealing
with the "hand grenade" entities in the new system, and I found that
they're noteworthy in many regards:
- Hand grenades are both dynamically created during the course
of a game (when the player throws them) and dynamically removed
again (after they have exploded and their traces have gone). This makes
them different from many other entities that are defined in map files and
often exist from the beginning to the end of the map.
- Hand grenades employ more components than other entities in order to
implement their functionality:
- Model (the hand grenade model as thrown through the map),
- Physics (for computing the flight path and dealing with
collisions, e.g. with walls and the floor),
- Script (for controlling the details, e.g. letting the
detonation timer tick and implementing the explosion effects),
- Light (for the flare when the hand grenade explodes),
- Sound (for the sound at the time of the explosion),
- ParticleSystem (for the smoke and spark particles at the
explosion).
- They very well demonstrate the distinction between Server
State and Client Effects.
It is the last point that I would like to highlight in this post, because a
good understanding of it is crucial for game development with Cafu:
Server State
The server state is characterized by the following properties:
- It is synchronized via the game server to all clients,
- every player (client) sees the same results and consequences,
- server state is relevant for gameplay.
Typical examples are drawbridges, the position and state of elevators and
doors, details about opponents, etc.
As a side note,
events are often a result of a change in the server
state, and transferred to the clients as such.
Client Effects
Client effects can be triggered by some event in the server state, but besides
that, they:
- run independently of each other on the clients only,
- are often used for eye-candy,
- it's ok if not everyone sees exactly the same (not relevant for
gameplay).
Examples include particle effects such as smoke, sparks and small pieces of
debris, many fade or transition effects, model animation frames, etc.
Having both
An important insight is that we sometimes need both server state and client
effects
combined.
For example, consider a light source that illuminates an otherwise pitch black
part of a labyrinth. Whether the light source is on or off clearly makes an
important difference for players who try to navigate the labyrinth, and so the
state of the light source is managed as a part of the server state.
However, there are also other kinds of light sources, e.g. those that are on,
but steadily flicker or pulse. This is often a means to create a specific
atmosphere to a map, but the exact amplitude of the flicker or pulse is really
not something that needs synchronization over the network.
In fact, as a combination we may wish that the light source's on or off state
is synchronized to everyone, and if it is on, have it have a client-side
flicker effect for eye-candy.
This is exactly what we can (starting with commit
d11c6a9) achieve with the light source components, and what I now employ
with the hand grenades: When a hand grenade explodes, the related light source
is turned on in order to mimic the bright flare of the explosion. However, the
exact details of how the bright light fades, changes its color from white over
yellow to red, shrinks and eventually disappears (all in about half a second),
needs not be synchronized over the network.
Instead, a very simple script method is used to implement this. Here is its
entire code:
local clTime = 0.0
local Duration = 0.5
function Light:ClientEffect(t)
if not self:get("On") then
clTime = 0.0
return false
end
clTime = clTime + t
if clTime >= Duration then
return true, 0, 0, 0, 0
end
local Amount = 1.0 - clTime/Duration
return true, Amount, Amount*Amount, Amount*Amount*Amount, 400.0
end
Well, this is one of the reasons why I love the new component system!