[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Some Documents
Here are two documents I have been perparing for a while.
One describes what I call ObjectSpace. This is a layer O
thing which deals which things like Monsters, and games
objects. Read the actuall document for more info.
The other document is a license which I think is appropriate
for us. It is a lot like the LGPL, except there is no
obligation on people who distribute binaries to distribute
the source.
Since it is more relaxed than the LGPL, which is more relaxed
than the GPL, there should be no trouble putting [L]GPLed code
under this new license. What do people think?
Best viewed with monospace font, with tab stops=4
PENGUIN PLAY GAMESPACE
Adrian Ratnapala
----------------------
"Games Space" is my word for that component a of a game which is probably
most readily apparent to the user. This component contains a "level"
or some such thing, and a set of visible "objects" within it such as
people, bullets, monsters and trees. (Just to confuse you, that is not
the terminology which I will be using through the rest of this document).
The framework bellow is an outline of an API designed to help programmers
handle Game Space issues. It hopefully quite general and can be applied
to many kinds of games. It is designed for re-usability, and is
isolated from both the underlying graphics system and the input system.
In fact, a proper implementation should be able to work correctly without
any other PenguinPlay components.
Although this system is meant to be general I will use a 2d platform
style game as an example.
Games Space will consist of the following components (plus more which
we will need later).
* Worlds
* Entities
* Things
* View Managers
* Signal and Slots
* Views
All of these represented by abstract classes, except possibly for
view, which might not represent any real class.
THINGS AND THEIR WORLD
----------------------
Basically the whole system is about Things moving around in the World.
The "World" is what the game designer created using his map editor, it
contains all the things which make up level. Actually "level" might be
a more appropriate word, since each level in the game would correspond
to a different World object.
>From the programmer's point of view, the world is a smart container for
all the things it contains. Saving the game simply involves saving
the World, under whatever persistent object mechanism we settle for.
The World object also represents a "map" which other objects could
consult to see what is where (in terms of user visible geometry).
Finally the world is probably also what takes care of flow control.
i.e it is responsible for giving all the Things and Entities, their
little time slices.
In the context of our platform game, Things are always represented
by a (possibly empty) 2d sprite. The things would include:
* Parts of the landscape.
* Things the user can pick up.
* Monsters and the player will be represented partially by Things.
The important things about Things are:
* They have knowledge of where in space they are.
* They can move about. When they do this they
must inform the World, and possibly the View Manager.
* The can collide with one another Thing.
* They can be collided with.
* They can be drawn. They can probably do other things,
like make noises, but I haven't thought about how that
fits in yet.
All things contain a View. A view is a conceptual abstraction of
some entity within the graphics layer. It may or may not correspond to
any real C++ object. In our case it corresponds to whatever graphics
object implements animated sprites. Together with the View Manager, the
Thing is responsible for telling the View where to draw itself and how.
More about that when we get to the view manager.
Things can move about. They do this by informing the World that they
have moved. Dynamic things will be given a little timeslice during which
they have a chance to do things like move about. We shall call the motion
caused by this behavior the "trajectory" of the thing.
CRASH AND BANG
--------------
OK, so Things participate in collision detection. How?
Collision detection is done in two steps. First is the rough
step, in this step Things will export some datum like a bounding
box to the World. (What exactly happens will depend on the game,
remember the programmer will be defining their own World and Thing
types).
In our platform game example, the Thing does in fact export a bounding
box (or circle). This case is probably so common we would have some
library support for it.
The idea is that the when a Thing moves, or does anything else which
could cause a collision, world checks these bounding boxes. If it finds
a collision, then it informs both Things involved, they can decide among
themselves whether they are really colliding or not.
Presumably the World will have some sort of optimized implementation
for this. If there are thousands of Things it would not want to check
each one against the other, it would divide the world into blocks or
something.
ENTITIES AND THOUGHT
--------------------
Things are meant to be quite simple, with a smallish memory footprint
(we might have to create thousands of them). Things are active in
that they could be represented by animated images, and they can move
about the world, but that should be limited simple motions like a body
following a gravitational trajectory or a creature walking a straight.
Entities are designed to take care of more complex thought processes.
And are therefore suitable for monsters and players. You may ask why
not just program a Thing with a more complex trajectory? I say no real
reason, it just turns out cleaner this way.
Conceptually an Entity is similar to a finite state machine, except
that it can examine its environment. In these terms, an Entity consists
of
* An environment. This means it can consult the World's "map", and
maybe some other things.
* A State. Hence the name Finite State Machine. The player for
example might have such states as:
+ Walking
+ Running
+ Standing
+ Falling
The idea is that every Entity contains an underlying Thing,
which is its state variable. Changing the state would mean
replacing or modifying that Thing.
* Inputs. Just like "input characters" can be given to real FSMs,
various events will happen to Entities. When such an input
arrives, the Entity/FSM changes state. For example the player
Entity could receive a left-arrow keystroke, which will tell
it to go into the "Walk left" state. (Well actually Entities
should not receive keyboard events directly, but you get the
gist).
This could mean it deletes the old underlying Thing and replaces
it with a new one representing the new state. Or it could be
less drastic and perform just some operation on the Thing,
changing its state.
In our example, the Entity will make sure that the current Thing
is one which is represented by a "player walking" animation,
and that it is programmed to move left at some speed. Now the
Thing is in autopilot, the Entity need not intervene to make
the player walk. When we hit an obstacle and can't move any
further, then the Thing will report the exception by sending
the Entity another input.
Please notice that the whole FSM thing is just conceptual. Nowhere
does there have to be a variable called "state" or anything like that.
In fact ANY object could be thought of as one of these "augmented FSMs",
I just think this is a convenient way of thinking about Entities.
SHOWING OFF
-----------
The game world will have some kind of geometry. In our case it is a
nice 2d Euclidean one. It doesn't have to be. The user interface will
have some other geometry, in our case it will be another 2d Euclidean
one. The job of the View Manager is to map between the two geometries.
It must also use this mapping to make sure everything is drawn correctly.
For concreteness let us look at what the View Manager for a platform
game does. It must:
* Keep track of the coordinates of in Game Space of the current viewport.
* Keep track of which Things are currently within that viewport
(presumably using the same bounding boxes as are used for
collision detection).
* Use this information along with the View attached to the Things
to actually draw the Things at appropriate positions, in the right
order etc.
* Draw things like backgrounds.
A special method in the View Manager will be invoked once each frame
which will cause everything that is visible to be drawn. Why not
make the View Manager part of the World?
Here is one example: we have _two_ views of the world, one is the
"main" screen, while the other is a "radar". We could have one
View Manager for each, but they would share the same World.
SIGNALS AND SLOTS
-----------------
Signal/Slots are an event passing mechanism which should be familiar
to users of the Qt GUI Toolkit. The mechanism here will be similar
but less elaborate.
The idea is that a object can, during the course of its life emit Signals
(not to be confused with system signals). Also objects can listen for
signals through Slots. When a Signal reaches a Slot, some callback
is called (a virtual function I suppose).
In Qt Signals can send arbitrary arguments and have full type checking.
I think we won't bother with that.
The beauty of the system is how Signals are routed to Slots. A object
could be busily emitting signals, but no one will be listening unless
someone "connects" the Signal to the Slot. The wonderful thing
is that the connection need not and probably _will_ not be made by
either of the objects at either end of the connection. In fact, the
whole idea is that objects can be made to communicate without having
to even know about each other's existence.
Why do we have this? Let our two objects be a door D somewhere in the
game, and a button or switch B which opens that door. The idea is that
when B is pressed by the player, then it will send a Signal. D
will have a Slot which is connected to that signal. When it receives
the signal, the door will open.
Now presumably these will be the standard door and standard switch,
of which their could be many in each level. The programmers don't
want to be worried about what switch is connected to what door, that
is a job for the level designers. The programmers can simply write a
door implementation, and an button implementation without worrying about
how they interact. The only code which has to think about that
interaction is the World construction code, which reads the level file
and make the signal/slot connections which are requested in that file.
Here is one reason we may not use a signal/slot mechanism. If the
GUI chooses to use an event mechanism which is different, but gives
us the same functionality, we may choose to use that instead, to avoid
duplication.
LISCENSE FOR THE PENGUIN GRAPHICS LIBRARY
The goal of this license is to allow the Library to be freely used,
distributed and modified without putting any undue restrictions on any
parties involved with the Library. It is not intended in any way to
hinder commercial use or distribution of the Library.
DEFINITIONS
It should be noted that a library here is meant to be a piece of software
is designed and packaged to be easily combined with (i.e linked against)
other software to produce a program. "The Library", or "This library"
is meant to be some library (or collection of libraries), which has been
placed under this license by its author.
"Source code" for a work means the usual form in which it is modified.
"Binary code" is some form in which software is not easily modifiable,
but in which the software can easily be used or prepared for use.
This includes compiled executables, libraries and object code or any
equivalent. "Compiling" a work means to convert the source code for the
work into binary code for that work. Both the source and any binary
code compiled from the source are covered by this license.
0. YOU MUST AGREE TO THIS LICENSE IN ORDER TO USE, COPY, DISTRIBUTE OR
MODIFY THIS SOFTWARE!! Nothing else gives you the right do these things.
By using, copying, distributing or modifying this software, you
automatically indicate your acceptance of this license.
1. NO WARRANTY
AS THIS SOFTWARE IS MADE AVAILABLE FREE OF CHARGE THERE IS NO
WARRANTY FOR IT (UNLESS SOME THIRD PARTY HAS UNDERTAKEN TO PROVIDE
ONE). EXCEPT WHEN SPECIFIED IN WRITING THIS SOFTWARE IS PROVIDED
"AS IS" WITHOUT WARRANTY OF ANY KIND, BE IT EXPRESSED OR IMPLIED,
NOT EVEN THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR
A PARTICULAR USE.
THIS DISCLAIMER OF WARRANTY APPLIES TO ANY DOCUMENTATION
DISTRIBUTED ALONG WITH THIS SOFTWARE AS WELL AS THE SOFTWARE
ITSELF.
2. You may copy and redistribute this software through any medium,
but if you do this you must:
a) Distribute a copyright notice for the copyright holder
of the software referring to this license as well
as any disclaimer of warranty.
b) Distribute this license verbatim. (Although you or
any third party may of course undertake to provide a
warranty).
3. When you distribute this software, the recipient automatically
receives permission from the copyright holder to use, copy,
distribute or modify the software under the terms of this license.
You may not impose any additional restrictions on them. You are
not responsible for their compliance with this license.
4. You may modify your copy of this software, or any part of it
to produce a work based on this software, you may then distribute
the modified copy. If you do this, you must:
a) Put a notices on the new work to show that you have modified
it, when you modified it, and the nature of the modification.
b) You must give due credit to the original authors.
That is, it must be made clear that the new work is a
derivative work of this software, and who wrote the original
software.
c) You must distribute it under the terms of this license.
5. If you have received the source code of this software you may compile
it to produce binary code. You may then redistribute that binary
code, but only under the terms of this license (in so far as they
can be applied to binary code). That is the recipient of the binary
code must be given all the rights granted by this license, and is
bound by it if they use, distribute or modify that binary code.
If you distribure binary code for this software, there is no
obligation on you to distribute or offer the source code for the
software.
6. If a program is linked against the Library to form an executable,
then that executable shall, for the purposes of this license be
defined, as _not_ being derivative work based of the library and
is not covered by this license. But that portion of it which is
came from the library, is still covered by this license.
This means you must distribute this license and any copyright
notices for the Library.
Explanation: The effect of this is that if you link a program with
this library, then you can put any license you like on it so long
anyone who manages to extract this library out of it can do what
they like with it under the terms of this license. This section is
intended for situations in which you do something like distribute
a copy of this library alongside an executable dynamically linked
against it.