Kambi VRML game engine
← Users Developers →
 
Intro and News
 
view3dscene
 
The Castle
 
All Programs
 
Forum
 
Engine
 
VRML/X3D
 
Other
 

The Castle — development

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:

TODO things

Most important TODOs for now are:

  • Make bow much more interesting. (I had a nice idea how to make aiming from the bow difficult, but it was not implemented for PGD compo, not enough time. But it will be done.)

  • Visual effects (on creature wound (some blood etc.), ball missile better rendering (some pulsating flare etc.), ball missile explosion), decals on walls.
More detailed list is inside game archive in TODO file.

Feedback

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).

Creating 3d objects

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

3D model formats

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 :)

Debug menu, debug options

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).

Levels

  • 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:

      1. 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.
      2. 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.

Items

  • 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.

Creatures

  • 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).

Advanced effects

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:

Creating sounds

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

Compiling

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.

Game goals

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).

Some implementation notes (interesting only for programmers probably)

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:

    1. 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.)

    2. 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:

    1. 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.