NAME
Games::3D - a package containing an object system for (not only) 3D games
SYNOPSIS
use Games::3D::World;
my $world = Games::3D::World->new();
$world->save_to_file( $filename );
my $loaded = Games::3D::world->load_from_file( $filename );
my $thing1 = $world->add ( Games::3D::Thingy->new( ... ) );
my $thing2 = $world->add ( Games::3D::Thingy->new( ... ) );
$world->link($thing1, $thing2);
EXPORTS
Exports nothing.
INTRODUCTION
This package is just the basis documentation for all the classes contained under Games::3D. It does not need to be used, unless you want to require a specific version of this package.
DESCRIPTION
Overview
Games::3D::World provides you with a container class that will contain every object in your game object system. This are primarily objects that have states, change these states and need to announce the states to other objects.
The Games::3D::World container also enables you to save and restore snapshots of your objects system.
Basic things that you object system contains are derived from a class called Games::3D::Thingy. These can represent physical objects (buttons, levers, doors, lights etc) as well as virtual objects (trigger, sensors, links, markers, sound sources etc).
You can link Thingy
s together, either directly or via Games::3D::Links. The links have some more features than direct linking, which are explained below.
This package also provides you with Games::3D::Sensor, a class for objects that sense state changes and act upon them. Or not, depending on the sensor. Sensors are primarily used to watch for certain conditions and then act when they are met. Examples are the death of an object, values that go below a certain threshold etc.
State changes are transported in the object system with signals.
A detailed explanation of all these basic building blocks follows below.
World and Things
The Games::3D::World is just a container to hold all the things. One advantage of having a global container is that you can get a snapshot of the world and save it to a file, and later restore it.
There are also certan performance advantages, for instance, if you want an event to trigger if one object from a certain class of objects dies, you can just ask the container to notify you. This is better than linking every object of that class to each sensor to watch for this particular state change.
The world contains Thingy
s, Link
s and Sensors
.
Thingys
Each Thingy
has the ability to link itself to another object. If the Thingy
receives a signal, it will pass it along to all other objects that it is linked to (except for a few signals that the Thingy
will act upon, but not pass along. See below).
From now on Thingy
s will be simple called object
because even Link
s and Sensor
s are Thingy
s underneath.
Signals
While you can create arbitrary signals and have your object act upon, there are a few basic signals an object knows. Here is an overview:
Signals that are not relayed:
- SIGNAL_DIE, SIGNAL_KILL
-
This causes the object that receives the signal to be destroyed. It will send out a SIGNAL_DESTROYED to all linked objects.
- SIGNAL_ACTIVATE, SIGNAL_DEACTIVATE
-
This causes the object that receives the signal to be (de)activated. Once deactivated, an object will stop receiving and sending signals until it get's SIGNAL_ACTIVATE again.
Upon receiving such a signal, will send out a SIGNAL_ACTIVATED respectively a SIGNAL_DEACTIVATED to all linked objects.
Signals that are relayed:
- SIGNAL_ON, SIGNAL_OFF
-
These signals will change two-state objects between the ON and OFF state, and will be relayed to other objects as they are and immidiately.
- SIGNAL_NOW_ON, SIGNAL_NOW_OFF
-
When an object receives ON or OFF, it will turn itself ON, or OFF, respectively, and once it finished, it will send NOW_ON or NOW_OFF, respectively.
- SIGNAL_FLIP
-
The same as ON or OFF, but instead flips the state between ON and OFF.
When you invert a SIGNAL_ON, it becomes SIGNAL_OFF, and vice versa. SIGNAL_FLIP cannot be inverted.
(SIGNAL_DIE inverted is SIGNAL_KILL, and vice versa. Since both are treated the same, inversion on them does not matter.)
Various other signals:
- SIGNAL_CHANGED
-
This signal is send out when a certain value changes. It is only send out to objects that requested to be notified of state changes (e.g. typically
Sensor
s). It carries the type (what was changed) and the new value. - SIGNAL_SET, SIGNAL_ADD, SIGNAL_MUL
-
This is used to signal an object that it should change a setting of itself. SET is used to set the value directly, ADD brings in a (possible negative) change (e.g. 5 +2 => 7), and MUL multiplies the old value with the new one (5 * -3 => -15).
Links
Link
s are special objects that link other objects together. While you could just link two objects directly, links enhance this by adding some features:
- Delays
-
A link can delay any signal coming across by a fixed (or randomized) time.
- Invert
-
Links can invert signals. Thus SIGNAL_ON becomes SIGNAL_OFF, and vice versa.
- Repeat
-
They can also repeat signals, e.g each incomming signal is send out multiple times with delays in between.
- Fixed Output
-
By setting the output of the link to a specific signal, we can make the link send out always the same signal, regardless of input signal.
A further advantage of link objects is that you can send a SIGNAL_DIE to the link object itself, and thus destroying it. This breaks the link between the two objects in a finite manner. You can also deactivate and later activate the link again, without effecting the objects linked together itself.
Sensors
Sensors sense state changes and when they happen, send out a signal. Each sensor attaches either to a specific object ("Player"), or to an entire class ("->Food"). The sensor also announces what type of change it wants to watch, for instance 'origin', 'health', 'position', 'age' etc. Whenever this value changes, the sensor get's notified.
EXAMPLES
The aforementioned system is quite flexible, but there is also a certain rendunancy, which means there are sometimes multiple was to accomplish something. Here follow some real-game examples on how to represent often occuring scenaries with the given system.
We assume that you have physical objects which can be manipulated by the player, and that have two states: ON and OFF (or OPEN, CLOSED, UP, DOWN etc). This is often sufficient, and in the few cases were we need more than two states, custom scripting can solve the problem.
In the following text you will see some ASCII art drawings representing the game world as a network. Signals travel along the arrows (-->), and only in one direction. The possible signals are mentioned on the path.
The placement in the following networks has nothing to do with the actual object placement in the game world!
Door-Opener Button
Imagine a button that sends, when pressed, an ON signal.
ON
[ OnButton ] ---------------> [ Door ]
Press the button, and the door will be opened. Pressing it again will do nothing, since the door is already open.
(Of course, the door must prevent player interaction on itself, otherwise the player would just walk to the door and open it :)
Self-disabling Door-Opener Button
The button in the first example has one slight problem: It can be pressed again and again, even though without effect. If you want the button to be disabled, we can route it's signal to a link, anduse this:
[ OnButton ] +--------------> [ Door ]
^ | ON
| | DEACTIVATE
| +-> [ Link ] --------------+
| |
+-----------------------------------+
Pressing the button will open the door and deactivate the button.
Two-state button
The OnButton in the former examples only send one signal: ON. What if we have a button that sends ON when pressed and OFF when the player stops pressing it? Linking it to a door would do no good, because the door would open and immidiately close again. But you could use this to turn a light on while the button is pressed:
ON, OFF
[ Button ] ---------------> [ Light ]
You could also supress one signal:
ON, OFF ON
[ Button ] ----------> [ LINK ] ---------> [ Door ]
via a link that only sends an ON signal.
TODO: Filters, that only allow (a) certain signal(s) to pass or filter (a) certain signal(s).
Lever
The same network as before would work with a lever, that sends an ON and OFF signal, provided the lever is in the OFF position after start. The first signal, ON, send when the lever is flipped, would open the door and disable the lever. If you want the lever to open and close the door, connect it directly:
ON, OFF
[ Lever ] ---------------> [ Door ]
But what if the should be able to open the door from both sides? Simple placing two levers and link them directly would work, but have the side effect that if you open the door with one lever, walk through and try to close it with the other lever would not work immidiately. This is because the second lever is also in the OFF setting and would try to open the door again, and you need to flip it twice to close the door:
ON, OFF
[ Lever ] ---------------> [ Door ]
^
ON, OFF |
[ Lever ] -------------------+
There are two solutions: syncronise the levers, or easier, let each lever flip the door's status:
ON, OFF FLIP
[ Lever ] ---------------> [ Link ] --------> [ Door ]
^
ON, OFF |
[ Lever ] -------------------+
Here is the diagram to syncronise the levers:
ON, OFF
[ Lever ] +--------------> [ Door ]
^ | ^
| | |
| | |
| v ON, OFF |
| [ Lever ] +----------+
| |
| | ON, OFF
+------+
If you flip the first lever, it will open the door and also set the second lever to ON. Flipping either the first or second lever will switch both of them OFF again, as well as close the door. It even needs on object less (the link object is not neccessary).
However, there is a slight problem, can you spot it?
We have just created a loop, flipping the first lever would flip the second, which would send ON to the first, which would send ON to the second, which would send ON to the first etc. etc. However, the network will prevent this by not relaying signals from the originating object back to itself.
Sound and delayed action
Let's assume you want, if a lever is flipped, a x seconds long sound sample be played (for instance sound of some heavy machinery), and then open a door.
There are again, multiple ways to solve this:
2s ON
[ OnButton ] +----> [ Link ] -------> [ Door ]
^ | ON
| | DEACTIVATE
| +----> [ SoundEmitter ] --> [ Link ]------------+
| |
+--------------------------------------------------------+
Pressing the button will play the sound, and deactivate the button. It will also open the door after 2 seconds. If you don't know in advance how long the sound plays, try this:
Invert ON, OFF
[ OnButton ] + [ Link ] -------> [ Door ]
^ | ON ^
| | | DEACTIVATE
| +----> [ SoundEmitter ] --> [ Link ]------------+
| |
+--------------------------------------------------------+
Pressing the button will play the sound, and deactivate the button. If the sound is finished, the emitter will send a signal OFF, and this will be turned into an ON signal by the link (it is inverted) and open the door. The first signal, ON, will be inverted to OFF and do nothing, because the door is already closed.
Note: You could not used a link that just converted every signal into ON, because the first ON signal, send by the Button to the SoundEmitter, would also be relayed to the door, and open it to early.
Lever combinations
Imagine you want a door to be opened after the player has flipped two levers (but only then!):
Both levers have to be on the same side of the door, naturally:
The following would not work, because either lever would open the door alone:
ON, OFF
[ Lever ] ---------------> [ Door ]
^
ON, OFF |
[ Lever ] -------------------+
So, we use a link, and also turn the link into an AND gate. Normaly links act as OR gate, relaying each signal as it comes in. In AND gate mode, links only relay a signals if all inputs have received the same signal. Each input stores the last signal that arrives there and as soon as they are all in the same setting, the signal is send out (possible inverted, and delayed, though).
ON, OFF AND ON, OFF
[ Lever ] ---------------> [ Link ] --------> [ Door ]
^
ON, OFF |
[ Lever ] -------------------+
Setting both levers to ON opens the door, setting both to OFF closes it. Setting on lever different than the other does nothing.
METHODS
This package defines no methods.
BUGS
None known yet.
AUTHORS
(c) 2003, 2004 Tels <http://bloodgate.com/>
SEE ALSO
Games::Irrlicht as well as:
Games::3D::Thingy, Games::3D::Link, Games::3D::Signal, Games::3D::Sensor.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 131:
'=item' outside of any '=over'