Please note that I consider "The Castle", as a game, finished now.
Hey, it was fun, it was great, and thank you for everyone that helped!
Now let's make something even better :)
New game, using much improved "The Castle" engine, is planned —
this new game will be technically "The Castle 2.0" (although actual name planned
now is "Human Programming").
I don't plan to further extend "The Castle" data (no new levels,
no new creatures etc.). It makes more sense for me to focus on new game data,
that will use many engine features added after "The Castle" release.
This isn't supposed to discourage you from dabbling in "The Castle"
data :). On the contrary, feel free to experiment even more, create
levels / creatures not necessarily tied to the current "The Castle" mood.
Hey, you're welcome to start a new game on your own, using "The Castle" engine.
(Almost) everything documented
here will also apply to the new game, so information on this page
will certainly remain relevant.
"The Castle" is developed in
an open-source manner, which means that if anyone wants to help —
you're more than welcome. You don't even have to be a programmer —
3D level/creature designers are wanted (alive!),
and sending simple feedback is definitely useful too.
This page collects various developer information how you can
help, and how you can compile and extend the game's code and data.
All questions, feedback, etc. may be posted to
our forum or mailing list (link to vrmlengine.sf.net).
Of course, any help with designing levels, items, monsters, creating
sounds and / or providing significant feedback will be mentioned in the
credits list and in-game credits dialog. You want some fame and fortune ? We got it.
Contents:
Most important TODOs for now are:
More detailed list is inside game archive in TODO file.
Any kind of feedback will be useful. This includes:
Bug reports. If anything goes wrong, I obviously
want to know about it. Describe how to reproduce the bug —
i.e. what you did, what happened, and what you expected to happen.
If you think that something works strange, this also qualifies as
a bug. If some text inside the documentation (these HTML pages)
is unclear, this also qualifies as a bug.
Note that this game requires rather good graphic card available.
If the game is awfully slow, then (probably) it's not a bug —
it's just the way it is, and I will not be able to help much.
Make sure you have absolutely newest drivers (including OpenGL
library) for your graphic card.
Bugs should be submitted to
bug tracker,
or our forum or mailing list (link to vrmlengine.sf.net).
Features. Do you think that anything should be added ?
Maybe something should be changed ? Any ideas may be useful here
— new key / mouse commands, changing the behavior of
present commands, displaying some things in a different way, etc.
Feature requests should be submitted to
feature request
tracker
or our forum or mailing list (link to vrmlengine.sf.net).
Below I describe how you can create new levels, items or monsters for
this game. This requires at least some knowledge of a 3d modelling program
(I use Blender).
Depending on what exactly you will want to do, this may also
require some programming knowledge — of course I will help
here, which means that you can just design 3d model and tell me
what it's supposed to do in the game (e.g. if it's an item then
what happens when player uses it ?), and I will write appropriate code.
You don't have to make all images, textures, 3d parts yourself
— you can freely use things available on the Internet.
Just be sure that what you take is available on GNU General Public License
(or anything that can be treated like a super-set of GNU GPL, like LGPL
or public domain), as I will want to include
this in the game licensed on GNU GPL. For a list of various sites
with useful programs and collections of textures etc. see
The short 1-sentence introduction is: you can use any 3D modelling program
able to create VRML or X3D (link to vrmlengine.sf.net) files.
VRML and X3D formats have official specifications
and our engine is capable of handling most of their features
(actually,
even more than that (link to vrmlengine.sf.net)).
So the engine is not tied to any particular modelling program.
Use view3dscene (link to vrmlengine.sf.net) to view the various models outside of the game.
You may want to view in view3dscene some of the models from
Kambi VRML test suite (link to vrmlengine.sf.net) —
there are many testcases and demos of what can be expressed in VRML / X3D
and what our engine can understand and render.
My favourite 3d modeller is Blender.
It's open source, it's available for Linux (yeah, Windows and others too
if you insist :), and it has an enormous set of features.
Including good export for VRML / X3D, of course.
Basically there are no special
rules for designing in Blender models for our engine —
just do whatever you like (and whatever can be exported to VRML / X3D).
The engine also handles perfectly VRML files exported from 3ds Max.
So you can use 3ds Max to make models too. Also VRMLs produced
by open-source modeller Art of Illusion
are perfect. I suspect that all significant 3D modelling tools are able
to export decently to VRML or X3D, so you can probably use any modeller you like.
(This was one of the reasons that I chose VRML / X3D format as my basic format
— it's nice to see that it pays off :) ).
Note that I'd like to make the game using as much open-source tools as possible,
so using open-source modeller is strongly favored over proprietary modellers.
Some detailed hints / tricks:
I often "wrap" (using WWWInline VRML 1.0 or
Inline VRML 2.0 / X3D node) models produced by
Blender inside some small VRML files written by hand.
For example, data/levels/castle_hall_final.wrl is a small VRML file that is
maintained by hand. It sets up some things that were uncomfortable
(or impossible, due to lacks of VRML 1.0 exporter) to set up from Blender,
and includes (using WWWInline node) other VRML / X3D file
(data/levels/castle_hall_processed.wrl in this case)
that defines geometry,
materials and textures of the level.
Moreover, I sometimes want to post-process VRML / X3D files generated from
Blender. I use EmacsLisp macros for this (since this is a great language
for text operations, and it's built in my favourite editor :) ).
For example data/levels/castle_hall.wrl in VRML file
exported from Blender (from data/levels/castle_hall.blend),
and it's processed to data/levels/castle_hall_processed.wrl.
VRML 2.0 (aka 97) notes:
For Blender, it's adviced to use our customized VRML 97 exporter,
see Blender VRML stuff (link to vrmlengine.sf.net).
3DS / MD3 / Collada / other formats notes:
Actually, you can also use models in other formats instead
of VRML / X3D. Our engine can handle other formats, see
view3dscene (link to vrmlengine.sf.net) for more detailed info.
So if your favourite 3d modelling program is not able to export
to VRML / X3D but it's able to export to e.g. 3DS — you can use it too.
But, since 3DS is a closed format, it will never be supported
completely by our engine (just like by any other program, since everyone
has to "reverse engineer" 3DS).
Collada format is a positive exception to this. It's an XML format with
an open specification, pretty much like VRML / X3D.
So using 3D models in Collada format is actually not a bad idea —
except that we do not handle all features from Collada files currently.
But Collada support can (and will be, if needed) easily improved —
don't hesitate to report if some Collada feature is not handled, we'll fix it.
Still, note that everything that can be expressed
in other 3D formats handled and that is understood
by our engine can also be expressed in VRML / X3D.
But not vice-versa, i.e. there are some features that
are available with my engine when using VRML / X3D but are not available
when using e.g. 3DS.
So the bottom line is: well, you can use 3DS or some other formats
with my engine, it works OK, but VRML / X3D format is just way better :)
If you want to modify game content heavily, I advice to get
familiar with our debug menu. The debug menu contains
many useful commands that will make your life much easier. By default,
debug menu is activated by backquote key (the one with tilde, the same
key used to bring console in many FPS games).
Using the debug menu
you can turn on some special features useful for designers/debugging
(e.g. to see bounding volumes of objects) or turn off normal game features
that may be annoying when designing (e.g. stop time for creatures).
You can also request a reload of particular creature/item/level VRML/XML
etc. files. This is extremely useful when you changed some data file
and you would like to quickly reload just this one file,
to see how things work now — without exiting the game.
There are also some command-line debug options (but not too much —
it's always more flexible to have things available at runtime instead
of only at the start). Run the program with --help
to get their list. --debug-no-creatures is one such useful option:
it avoids this lengthy "Loading creatures" loading time, which is useful
when you're not interested in testing creatures
(e.g. when you only design new level geometry).
The very concept of this game (much like any other modern game)
is that you can design new levels without writing a single line
of "real" (in this case: ObjectPascal) code.
Basically, you design your level, then you add it to
data/levels/index.xml file, and it's done.
There's a special level called "Hello world" in the game data.
This is a level that is intentionally an ultra-simple example
of how a level can be done. If you want to create your
own level, you can start by modifying this level.
See files in data/level/hello_world/ subdirectory.
Note that "Hello world" was done in VRML 1.0. For a sample
level done in pure VRML 2.0, look at "Fountain" level.
To place items and creatures on the level you place
a special "stub" objects on the level. Every stub object will be removed
when the level is loaded (so you can use any shape for it —
I usually use wire cubes). Stub object position and name will
determine the actual item/creature position, kind and quantity
(quantity in case of items).
Name format for items is
Item<item-kind-name><quantity>_<ignored>.
Name format for creatures is
Crea<creature-kind-name>_<ignored>.
See lower in this file for more details.
When loading level, we search for node named LevelBox.
In VRML 1.0, such node should be a parent of some shape
(e.g. IndexedFaceSet) node.
In VRML 2.0 / X3D, such node should be within Shape node that
has parent named ME_LevelBox.
What this means in practice, is that in Blender you can simply
name the Blender's mesh LevelBox and it will be correctly
recognized by our engine if you export to VRML / X3D using
standard Blender exporters.
When such node is found, we calculate it's BoundingBox and remove
it from the scene. Calculated BoundingBox becomes Level.LevelBox
value. And Level.LevelBox is used to limit allowed player positions.
This can be used to disallow player to move to the very edge of
the level.
Usually you will add LevelBox node using Blender, you can also
use view3dscene (link to vrmlengine.sf.net) —
see command 'Console -> Print scene bounding box'.
Similar to LevelBox, I do identical trick to calculate
water boxes. Just place a mesh with name 'WaterBox'.
At some point this will be extended (when I'll need it) to
include every 'WaterBox_<ignored>', so that you will be able to
define water by a sum of boxes.
On some particular levels I use similar trick with XxxBox
for other other purposes too.
For example "Castle Hall" level has HintButtonBox to indicate
where to show "Hint: press this button by the "p" key".
Levels must be oriented such that +Z is "up".
While all things in my general units are flexible
and allow any up vector to be used, I made in "The Castle" a couple
of assumptions that really need +Z to be up.
(like TItemOnLevel.PlayerCollision).
Typical VRML / X3D nodes that I write "by hand"
(in level_final.wrl file) are:
- Background, NavigationInfo nodes
These nodes were introduced in VRML 2.0 (although I implemented them
for VRML 1.0 also). But Blender exporter to VRML 1.0 does not write
these nodes. So I just write them by hand. Blender exporter for VRML 2.0
does write them, but still it's usually easier to set them up by hand.
- PerspectiveCamera / Viewpoint node
VRML 1.0 Blender exporter: exports camera settings,
but in an uncomfortable
format (as a transformation, instead of as VRML camera node).
This is OK for simple viewing of VRML models, but it's not OK
if you want to "tweak" VRML models. In particular, it's bad
when you want to add Background node (see above) and light nodes
(see hints below) by hand. Then you have to either insert it
into the middle of Blender's generated VRML file, or use awkward
coordinates (because of additional transformation).
So I usually generate camera node by opening model in my view3dscene
(see view3dscene (link to vrmlengine.sf.net))
and using "Print current camera node (Ctrl+C)" feature.
VRML 2.0 Blender exporter generates better Viewpoint
from camera, but still it doesn't have gravityUp like we want,
so it's much better to use
view3dscene (link to vrmlengine.sf.net) "Print current camera node (Ctrl+C)" feature.
- Light nodes
I usually write light nodes in a separate VRML / X3D file
(that contains only light nodes; see e.g. data/levels/castle_hall_lights.wrl).
This is comfortable, because I usually want to use level lights
also on other objects (like enemies) that are not part of the level
object.
(Also, while Blender exporters can export Blender lights to VRML,
it doesn't allow me to use all features of VRML lights.)
Since version 0.5.7 you can also edit the lights from the game
— see "Debug options" menu for "Edit lights" command.
So you have to add appropriate nodes to xxx_lights.wrl
file by hand, and then you can just run the game and configure lights
properties from the game.
All levels should keep the same general sizes. In other words,
it's not good to just make your new level of arbitrary
size and then set player's avatarSize such that things "look sensible".
Why ? Because I place items and enemies on the level.
So size of all these various models must match.
In other words: just make sure you use
NavigationInfo {
avatarSize [ 0.5, 2 ]
speed 20
...
type "WALK" # "WALK" is not really needed for castle,
# but useful for testing
# with general VRML browsers like view3dscene
}
in your level. And force yourself to design a level that "fits"
such avatarSize.
As for speed: I know that the speed 20 is quite fast,
like "always running". On some levels it feels good (e.g. large, outdoor
"The Gate" level), on some levels ("Fountain") it would be awkward to
always run. So you can set the speed to 10 if your level
should feel more like walking (this usually means smaller, "indoor feeling"
level).
Sectors and waypoints (aka portals) for the level:
Shapes placed under the name Sector<index>_<ignored>
are removed from the real level in TLevel constructor.
The geometry of given sector is understood to be the sum
of all Sector<index> boxes.
Also VisibleSectors for each sector are coded in CastleLevel.pas unit.
For programmers: in cases when the sum of bounding boxes
is not flexible enough to define a geometry,
you can define any kind of geometry in Pascal code,
by overriding TSceneSector.IsPointInside.
In the future, treatment of the shape inside Sector<index>_<ignored>
may change, so that any kind of closed shape will be allowed there
and it will be stored and used precisely (not only as it's bounding box).
Remember that sectors are numbered starting from 0.
Shapes placed under the name Waypoint<index>_<ignored>
are also removed from the real level in TLevel constructor.
Middle point of bounding box of such shape determines
waypoint's Posiiton.
Remember that waypoints are numbered starting from 0.
Sectors of waypoints (and reverse property, Waypoints
of sectors) are automatically calculated, by looking for waypoints
that have a Position that falls inside Sector's BoundingBoxes
enlarged by margin 0.5.
Note that sectors' BoundingBoxes need not be strictly separated.
When object (like player or creature) is within two sectors,
it's arbitrarily assigned to any allowed sector.
And for the rendering optimization, such sectors would work fine.
However, for monster AI, sectors should not have any common
large non-zero volume.
So in practice, each sector should usually place
waypoint's Position at it's border. Sectors may overlap but only
for a minimal distance (otherwise awkward movement may happen
when creature is in the common part).
You don't have to cover whole level with sectors.
If some object (like player or creature) is not within any defined
sector, it's considered to be inside the "implicit whole sector",
that is a little special. It's geometry is considered
infinte (every 3D point belongs to it, if it doesn't belong to any
of the explicitly defined scetors). VisibleSectors
is treated like filled with values "true" (so all other sectors
are assumed to be visible).
For programmers: SectorWithPoint returns nil when no sector found,
and this indicates such "implicit whole sector".
FindWay accepts SectorBegin and SectorEnd as nil
(and always returns then false).
Sectors and waypoints are used for 2 things:
- To speed up rendering: When player's Position is within
a given sector (not nil), we have to render only the sectors
for which VisibleSectors is true.
TODO: right now it's not used to speed up rendering,
and VisibleSectors is ignored.
- To make creature moving AI more intelligent:
If a creature wants to move from SectionBegin to SectorEnd,
and SectionBegin <> SectorEnd (and none of them is nil),
creature knows that it must pass through appropriate waypoints.
It's assumed that there will not be too many sectors on the level
(100 sectors is really around maximum. 10-20 is reasonable.)
So sectors are not (at least right now) stored in any "intelligent"
structure (like an octree) and creature moving AI uses
the simplest search on the graph to find a satisfiable path
(no A* algorithm or anything; it's simply not needed for the kind of
sectors layouts that I will typically use).
If you made a completely new level, you want to add it to the game.
That's easy: just add new <level> element to
data/levels/index.xml file. Now the level is known to the program.
You can switch to the level by debug menu "Change to level" command
(or even you can start "new game" from this level, if you set it's
default_available_for_new_game to true).
Note that when starting "New Game" player can choose to start
from any level that he (she ? :) previously visited ("visited"
either as part of normal game story of through debug command
"Change to level"). This feature may be removed in the future when
real "Save game" / "Load game" feature will be implemented.
If you don't mind a little programming, you may want to create
new TLevel descendant in the program and use it for your level,
this allows for many tricks.
See existing level implementations in CastleLevelSpecific unit
for examples what can be achieved.
You may even want to move your new level class
to a completely separate unit file if you want.
With a little programming, you can add various dynamic parts
to your level. I call these things "level objects".
For example, this is used to make the moving cart (gate level), button
(castle hall level), exit gate (cages level), elevator (tower level),
doors (doom level)... and many more. Level objects can also cast shadows,
see notes about shadows for creatures.
It's expected that at some point it will be possible to add such
level objects only by editing levels/index.xml file, with no need
to modify game sources.
Item up vector must be +Z.
Item should be oriented such that:
Z = 0 plane is the base plane of the item. It will be aligned with the base
(i.e. lowest Z) of "stub" object placed on the level.
X = 0 and Y = 0 is the line around which object will rotate
when shown on the level. It will be aligned with the X, Y middle
of "stub" object placed on the level.
I had an idea to just automatically take item's bounding box,
it's middle X, Y and lowest Z and automatically adjust to this.
But this would disable some possible visual tricks.
Size of item model is exactly the size that will be used to display
it on level, so set this to look good. Sensible default
is size around 1.0.
About the "stub" objects on the level:
You can place items on the level by placing a "stub" object
on the level with appropriate name.
When loading, I search for shape nodes that have a parent node
named like "Item<item-kind-name><quantity>_<ignored>".
Where "<item-kind-name>" is "LifePotion" or "Sword" or any
other TItemKind.VRMLNodeName value (see CastleItems unit),
"<quantity>" is, well, the integer quantity
("1" is assumed if "<quantity>" is omitted), and "<ignored>"
is just anything that will be ignored (you can use this
to make object names in your model unique,
which is obviously desirable).
Some reasoning about convention above: Blender's names
have quite limited length, that's why CamelCase is used
for "<item-kind-name>" and components are generally "glued"
without any "_" or "-" or " " between.
Such "stub" object is removed from the actual level and
instead I insert into level an item. Item position is determined
by stub lowest Z and middle X,Y line (see above).
You can easily insert such "stub" with Blender — just insert
any shape (I usually insert Cube, and set it's rendering to
"wireframe" in Blender), and then edit Blender's mesh name
as appropriate.
Prepare appropriate 2d image of item (to be shown in inventory slots etc.).
(Once I tried just automatically rendering models inside inventory slots
but this doesn't look good enough). You can do it however you like.
One way to do it is to use my raytracer, called
rayhunter (link to vrmlengine.sf.net) :
set up appropriate light and camera settings and then just render
item's model to the image. data/items/sword/image.png
is done like this.
Another is to open a model with
view3dscene (link to vrmlengine.sf.net),
set your camera however you like and make a screenshot.
Then you can edit it in whatever program you like
(like GIMP) to suit your needs.
Note that all items' images must be of equal size.
See data/items/Makefile.common for
IMAGE_WIDTH and IMAGE_HEIGHT constants.
Traditionally this image is stored inside
data/items/your_item/image.png image.
You may also provide data/items/your_item/image.wrl
3D file, that includes item's model file and sets camera to
the same viewport you used to render the image.
This is essential for people that may later want to modify your model
and remake the image.
If this is a weapon, then additionally you want to prepare what I call
a ScreenImage of this weapon — this will be displayed on player's
screen when it's equipped. See e.g. equipped.png images for
sword or bow items.
Once again, you can do this image however you like.
I used rayhunter to render screen for sword.
In the future the need for this image will be removed —
I'll render weapon's
3D model in the game (probably using the 1st attack animation frame).
You must also prepare an animation of "swinging" the weapon.
See e.g. attack_*.wrl files for sword or bow items.
Finally, to really add the item to the game add 1 line to
CastleItems units in DoInitialization call creating your
TItemKind instance.
For some items you may be able to just reuse some existing TItemKind
class, for others you will want to derive new class from TItemKind
and override there things you want.
- For simple customizations you can set various item
parameters by editing data/items/kinds.xml file.
Many notes about items apply also to creatures:
- Up vector must be +Z.
Moreover, for creatures: the looking direction
(i.e. whatever should be considered the "front" of the creature)
should be +X.
- Z = 0 is the base plane (ground) of the creature
- X = 0 and Y = 0 is the middle of the creature on XY plane
- Size of creature's model as rendered in the game is exactly
the size of it's model. A good reference is player's camera
height: 2. So creatures have generally height around 2.
- Like with items, initial creatures positions can be set
by placing a "stubs" on the level. Name of stub object is like
"Crea<creature-kind-name><creature-life>_<ignored>".
Creature position is determined by stub lowest Z and
middle X,Y line.
If <creature-life> part is not present, the default
MaxLife value (taken from creatures kinds.xml file,
attribute default_max_life) will be used.
You can also use this feature to place already dead corpses on the level
(e.g. the Doom E1M1 level uses this):
just specify <creature-life> as 0 (zero).
Initial creature looking direction
is determined by ... TODO: right now starting creature direction
just points into player starting position.
This is more-or-less sensible, usually.
But it's meant to be comfortably configurable in scene file in the future.
Plan to fix this: It's already possible to add a creature
in game, using debug menu Add creature commands.
Together with debug menu command Time stop for creatures,
this allows you quite easily and comfortably place creatures on the level,
and you're able to freely set both their position and direction
then. This should be extended: 1. new VRML / X3D nodes specially for
"The Castle" that express creatures on the level (as alternative
to creatures "stub boxes", or maybe inside such stub boxes ?)
2. debug menu command to dump current creatures to such VRML / X3D nodes,
so that you can paste them to level xxx_final.wrl file.
- To really add the creature to the game add 1 line to
CastleCreatures unit in DoInitialization call creating your
TCreatureKind instance.
- For some creatures you may be able to just reuse some existing TCreatureKind
and TCreature descendants, for others you will want to derive
your own descendants.
- For simple customizations you can set various creature
parameters by editing data/creatures/kinds.xml file.
When you want to use this creature on particular level(s),
you should add it to required_resources in levels/index.xml
file. Alternatively, if the creature should be always loaded
when the player is present (for example, special creature Arrow
should be always loaded, as the player may come to any level with a bow
and shoot some arrows), then it can be added to required_resources in
player.xml.
For testing various animations of creatures (and adjusting their time
parameters) you can use view3dscene (link to vrmlengine.sf.net).
For shadows to work fast, creature model (all animation
frames etc.) should be composed from a number of 2-manifold parts.
It's allowed to not make them perfectly 2-manifold, but then
in some cases, some artifacts are unavoidable — see
VRML engine documentation (link to vrmlengine.sf.net),
chapter "Shadows" for description.
To be manifold, edge must have exactly two neighboring faces,
so that ideally the creature shape is a correct closed volume.
Also, faces must be oriented consistently (e.g. CCW outside).
This requirement is usually quite naturally satisfiable for creature
models, and consistent ordering allows you to use backface culling which
is a good thing on it's own.
You can inspect whether your model is detected as a 2-manifold
by view3dscene (link to vrmlengine.sf.net):
see menu item Help -> Manifold Edges Information.
To check which edges are actually detected as border you can use
View -> Fill mode -> Silhouette and Border Edges,
manifold silhouette edges are displayed yellow and border edges
(you want to get rid of them) are blue.
You can also check it when running "the castle" itself:
run with --debug-log parameter (possibly redirecting
stdout to a file then). Look there for lines that indicate loading
of your creature, e.g. for Alien creature:
Animation info: Alien.Stand animation: 1 scenes * 4276 triangles
Bump mapping: ...
Shadows: Shadows casters triangles ...
Shadows: Edges: 6414 manifold, 0 border
... the "Edges:" line tells you that Alien is a perfect manifold
(0 border edges). So shadows will be fast.
In Blender, you can easily detect why the mesh is not
manifold by Select non-manifold command (in edit mode).
Also, remember that faces must be ordered consistently CCW
— I think that in some cases Recalculate normals outside
may be needed to reorder them properly.
This whole issue doesn't concern creatures with
casts_shadow="False" in creatures/kinds.xml file.
But remember that the default value of casts_shadow is
"True" — to encourage you to make all creatures cast a shadow.
Let's show these beatiful shadows to players!
Notes for animations: beware. Animations are done with a method
that essentially makes their rendering very fast (rendering each
animation frame should be as fast as if it was a still scene).
However it costs much in terms of memory consumption (and in
"Loading creatures" time). So be sure to test how much memory is consumed
by the game after your new animation is loaded. (using system monitors
or such).
As a final note, our engine supports some nice graphic features, and you
may want to use them to make your models nicer. Some of the more important
eye-candy features are:
I need sounds (effects and music) for my game. If you can
produce good sounds — send them to me.
If you cannot make your own sounds but you're willing to spend
some time just finding the sounds on the Internet, that's also great.
There are many places from where you can download free sounds on the Internet
(so many that it actually takes some time to find the good sounds).
So your help here is welcomed as well.
(Still, remember that sounds have to be available under GNU GPL or some
super-set of it, like LGPL or public domain.)
Some useful links to start searching for sounds can be found at
"Where
do you get your sounds and samples ?" thread on PGD.
In particular
- Sounds found by
FlashKit (soundfx) and
FlashKit (loops)
are OK when marked as freeware. This is a great resource
of sounds.
- Sounds found by FindSounds
are sometimes OK — click on "Show page" for each sound to
see what the author of the sound allow you.
What sounds are wanted ?
Basically, any sound that fits into the game is wanted.
This includes "environmental" sounds that could match some
levels (e.g. wind blowing, birds singing, river flowing —
many ideas; such sounds add a great "atmosphere" to the levels.).
This also includes sounds for some player's action, and sounds for some
creature's actions.
In general, don't feel limited.
If you see some place in my game that could deserve playing
some nice sound, feel free to create it and I will put it inside
my game. The more good quality sounds,
the more realistic the game experience will be.
Now, if you really want concrete examples of sounds that are
needed: Look into the data file data/sounds.xml,
search there for sounds with empty filename (file_name="").
They indicate missing sound effects. These are places where I imagined
playing some sound — but I couldn't make/find any good sound
for it.
The names should be
more-or-less self explanatory, e.g. player_sudden_pain
means a sound that will be played when player's life points
will significantly drop down (this will be played along with
showing "red-out" effect). If you have doubts what given sound
is intended to be, just ask on
our forum or mailing list (link to vrmlengine.sf.net).
Notes about sound files:
Sound format requirements: my engine can play WAV
and OggVorbis files. Short sounds should be stored as WAV,
long sounds (like level music) may be stored as OggVorbis files.
Do not make your sounds more silent
just because you're recording some "silent" thing.
For example, mouse_squeek.wav should be as loud
as plane_engines_starting.wav. The fact that mouse squeek
is in reality much more quiet than plane engine doesn't matter here.
You should always make your sound files with maximum quality,
and this means that they should use all the available sound range.
Music: as of 2006-04-25, music is done and it's great.
To create a music I just need a sound file that can be nicely
played in a loop.
- Special notes for creating footsteps sound:
- Don't make the footsteps sound too long.
Preferably you should put there only 2 footsteps. Reason ?
When progress is displayed (e.g. because player changes levels),
or when player enters the game menu, footsteps sound is not
immediately stopped — it's just played until the end.
Yes, this is desired, as it makes better effect than suddenly
stopping all the sounds.
- These 2 footsteps should take about 1 second. This is the amount
of time that "feels good" with head bobbing.
(See the data/player.xml file, head_bobbing_time = 0.5
there means that 1 footstep = 0.5 of the second for head bobbing.)
Remember that if sounds are supposed to be spatialized (i.e. played
by Sound3d procedures), then you must make them mono (never stereo!).
That's because Windows OpenAL will never spatialize stereo sounds.
You can use any editor you like to convert your sounds to mono.
I like this sox command-line:
sox input.wav -c 1 output.wav
See also data/sounds/scripts/example_make_mono.sh
Download game sources.
You will also need
Kambi VRML game engine (link to vrmlengine.sf.net) sources, unpack them in such way that kambi_vrml_game_engine/
and castle/ directories are together within the same directory.
Then compile inside castle/ directory by simple
make build-unix
under Unixes (Linux, FreeBSD, Mac OS X) or
make build-windows
under Windows. Note that you must use GNU make.
Required compiler is
FreePascal
(you can look at notes about FPC version required (link to vrmlengine.sf.net) — usually this is "latest stable FPC version").
There is no Delphi support — I live in the open source world.
Old notes for compiling with FPC <= 2.0.4 :
Sometimes FPC 2.0.4 fails with Fatal: Internal error 200310221.
This is a bug in FPC 2.0.4, fixed since a long time in trunk 2.1.1 and later.
I don't know the exact cause of it, but it has
something to do with FPC 2.0.4 inability to handle unit dependencies in
"The Castle" (no, there are no circular interface dependencies, but still there is
something that confuses FPC 2.0.4). The workaround was usually to do
make clean before each compilation (so that each FPC run starts
from a "clean" state and has to recompile all castle units), fortunately
FPC is so fast that this wasn't a big problem. Sometimes also retrying the
compilation (i.e. without make clean) pushed it to "move forward".
Best workaround is of course to upgrade to FPC 2.2.0.
I don't plan to keep FPC 2.0.4 compilation supported much longer,
now that stable FPC 2.2.0 is released.
Before you run the compiled executable, make sure that it's properly
installed: Unix users can make sure that symlink
$HOME/.castle.data is appropriate (you can easily
make this symlink by make install), although this is not required
for newer versions (> 0.8.3).
And on all OSes make sure that you have the appropriate libraries
installed. Windows developers may be comfortable with simply copying
appropriate DLL files from precompiled version of the game,
or download and use these DLLs.
In the game sources archive I include all the sources needed to compile
the game. Also everything needed to tweak with various parts of the game
(e.g. GIMP *.xcf files, that are the "source" version of *.png images,
and Blender's *.blend files that are the "source" version of some *.wrl files).
Everything is open source,
GNU GPL.
Below are some long-term plans. The game I'm dreaming about here
is something like "The Castle 2.0", or even "The Castle 3.0",
and probably will not be actually named "The Castle" anymore.
Still, technically it will be "The Castle" continuation, based
on next-generation of our VRML/X3D engine.
I feel obligated here to say what exactly this game is going to be.
So beware, I'm going to be dreaming in the next paragraph.
Basically the game is intended to be like FPS but with some nice storyline.
This also means that it should feel more like RPG (in more-or-less
fantasy setting) — large world, many items, weapons, some character
stats and levels etc. Also I want to utilize my engine to make
levels more "interactive" — some objects on the level
are able to move etc. There are many such games, some very old, some quite new.
I'm just going to do this once again, in the way I want,
and make it really good :)
Now, going back to reality: for PGD competition, no storyline,
no real character stats were done (player has just Life and MaxLife —
that's it), and the world is small (3 levels)
and there are not so many items and creatures (as of 0.6.2 version,
there are 5 creatures and 7 items). Basically
my intention for PGD compo was to do something like
"Quake, but with more short-range weapons and only 3-4 levels".
(yeah, very innovative, I know :).
As for the development style — this game is developed
fully open-source (including the game data). Part of the game
sources is a general-purpose 3D game engine
(I used it already to make small games and tools
like
malfunction (link to vrmlengine.sf.net),
lets_take_a_walk (link to vrmlengine.sf.net) and
view3dscene (link to vrmlengine.sf.net)).
Everything should run on any modern OS/processor supported by
FreePascal compiler,
see Kambi VRML game engine (link to vrmlengine.sf.net) for exact listing (if you want to port
it to other system, you're welcome to provide the patches and compiled binaries).
And I'm trying to do all game data using open-source things,
most important here is Blender
used to make all the models (see
credits page for
full list of things and resources used).
Collisions:
Everywhere in the game GetCameraHeight returns normal HeightAboveTheGround.
Usually in my general units (kambi_vrml_game_engine units) I don't make
any assumptions about InitialUp, it can be any vector — which means
that SqrHeightAboveTheGround is easier to calculate,
and calculating actual HeightAboveTheGround costs us Sqrt call.
But in this game, we know that InitialUp is always (0, 0, 1),
and this means that actual HeightAboveTheGround can be calculated
easily (by TVRMLTriangleOctree.GetCameraHeightZ), without the cost
of Sqrt.
Creatures collisions are done sometimes by a Sphere and sometimes by
the bounding Box.
Sphere doesn't change. I.e. throughout entire creature life, it's
bounding sphere has the same radius.
Box does change. It always corresponds to the bounding box of the actual
animation frame, so it closely represents current creature state.
E.g. dead humanoid creature will have low and wide box, while alive
will have tall and thin box.
This means that sometimes Box is better, sometimes the Sphere.
Sphere advantages:
You cannot guarantee that creature Box will never collide
with the level/player/other creatures etc. — because each
animation frame change changes also the Box, so the creature's Box
may suddenly enter collision with something just because the time
changed and next animation frame has larger BoundingBox.
I cannot just stop animation in the middle (preventing such collision),
because I don't know what to do with such animation then...
So I just allow such collisions. Code that uses creature collision
by bounding box has to be prepared for this possibility.
On the other hand, I can guarantee that creature's Sphere never
enters colliding state. That's easy, since creature's Sphere moves
only when creature Position changes.
So I can prevent creature move before it enters colliding state.
(well, actually bounding sphere center (MiddlePosition)
also changes with time, as usually it's calculated
looking at current bounding box... But this is not a problem as long
as sphere radius is chosen to be small enough.)
Also, for non-flying creatures, the Sphere is placed above the ground,
and this allows creature to climb the stairs — just like the player.
Creature just walks into the stairs, and then "growing up" mechanism
(using GetCameraHeight) pushes them up. This creates a short time
when creature's lower parts collide with the stairs, but this is
almost unnoticeable for the player, since "growing up" works fast.
Sphere disadvantage:
Well, Sphere is far from perfect as bounding volume — it's too small,
sometimes also too large, sometimes both at the same time...
Since the Sphere radius remains always the same, it must be good
for all creature animation frames. This problem is somewhat cured
by new (as of this writing, 2007-03) UseBoundingSphere feature,
that allows you to use bounding box when you know that you will
not need Sphere advantages anymore. E.g. when creature is dead,
we don't need the advantages 1. and 2. above --- dead creature
may be stuck in a wall, and it doesn't have to climb stairs.
This means that what happens during the creature's Dying animation
doesn't affect CameraRadius.
But still it may be a problem sometimes, if some creature states
have entirely different animations and bounding boxes. Then you
will be forced to choose one universal CameraRadius for all creature
states.
- Obviously you can't set radius too small, because if it's much smaller
than actual creature's geometry then the creature will noticeably collide
with level geometry and other creatures.
- On the other hand, you can't set radius too large
(or move creature's MiddlePosition, that decides where's the Sphere center,
much lower). This would block stair climbing.
|
|