Development: engine 4.0.0 - almost there: levels, items, player improvements

September 15, 2012
Testing dropping items on level. These items were dropped when standing still and looking around — it's good that they arrange in a nice ring.
Testing many items dropped on level.
Testing behavior (AI) of a group of creatures.
Testing behavior (AI) of a group of creatures, with debug bounding volume visualization.
Getting shot with a fireball.
Blackout (well, redout) after getting shot with a fireball.
Dropping items, testing gravity on items.
The blue crosses show the "random position" that creatures use when they cannot seem to reach the target (player) directly.

Work on the new Castle Game Engine 4.0.0 version continues :) Many improvements for the programmers that want to develop their own games using our engine:

  1. Many improvements to engine tutorial, classes diagram and level.xml and resource.xml files documentation. It's still a lot of raw, unformatted text, but the content pretty much covers now everything I want, and it describes the latest engine workings in SVN.

  2. Previous index.xml are now named level.xml (for levels), or resource.xml (for creatures, items, and other heavy 3D stuff that may be shared by levels). This makes things cleaner, and LoadFromFiles calls easier (you can just let it search whole ProgramDataPath).

  3. Placeholder 3D objects have now consistent naming. "Placeholders" are 3D objects that have special meaning when you load your level through TGameSceneManager.LoadLevel — objects with some special names are removed from normal level geometry, and they indicate... well, various things. See TGameSceneManager.LoadLevel docs (from engine SVN reference) for full reference. Short:

  4. Fix a lot of code to honour the "up" world vector to be +Y as well as +Z. Gravity is decided looking at Viewpoint gravity in VRML/X3D, and creature orientation is decided looking at T3DOrient.DefaultOrientation. See also engine tutorial section Which way is up. And see TOrientationType type values.

  5. CastleLevels improvements:

    • LoadLevel interface much simpler.
    • Much more docs around TGameSceneManager and TLevelInfo.
    • Ugly MenuBackground parameter removed, it's not needed at all.
    • Oh, and TCastleWindow.SceneManager and TCastleControl.SceneManager is now of TGameSceneManager class. So if you use TCastleWindow / TCastleControl, you can use the levels system designed in CastleLevels really trivially:
        Levels.LoadFromFiles;
        Window.SceneManager.LoadLevel('my_level_name');
      

      Congratulations, you just wrote a game :) All that remains is to prepare a game 3D data, and level.xml file with name="my_level_name". You already have all the code you need :) See castle_game_engine/examples/3d_sound_game/ for a larger working example using this.

      (Update: 2012-09-16: the very next day after writing this, the API changed a little again; the example above was adapted.)

  6. An easy way to debug AI information, to see how AI "thinks". Just set global boolean RenderDebug3D (formerly RenderDebugBoundingVolumes) to true, and you will see:

    • Yellow axis is the middle (eyes) position for each creature and item. This determines the line of sight, and helps with other collision decisions when "legs" position would be uncomfortable.

    • Red axis, for each creature, is the last seen target (usually enemy, which is usually player) position. You often don't see it, because you're actually standing on it. But it can be seen when you dodge behind a corner, and you look at your previous position.

    • Blue axis, for each creature, is the alternative walk target. Used when creature cannot seem to reach it's normal target. Basically, when straight line and sectors/waypoints fail, the creature wanders randomly hoping to get on the right track (or at least to avoid player shooting them easy).

      Of course, this is the last resort. If your creatures seem to be blocked too often, you may want to divide your level into more sectors and use more waypoints to "guide" the creatures. Unless you want your creatures to be dumb, of course, which is quite sensible for many games.

  7. Sound: engine units and classes simpler, no AL prefix everywhere. Also fixes to AudioClip X3D node (it wasn't always releasing reference when it should, causing crashes in special situations).

  8. Limit amount of logging by default. Our InitializeLog (see CastleLog unit docs, try --debug-log options of various programs) was producing way too much information by default, and important things were difficult to spot. Now by default it's shorter, showing only seldom happening things or important warnings.

  9. Much cleanup in CastleInputs unit. TInputShortcut and TInputConfiguration merged. Idea of "global" and "local" key shortcuts clearly defined and documented.

  10. TCastleSceneManager automatically handles now key combinations related to player inventory.

  11. Many renames in the new API. We want to get the new engine API as good as possible, before it's released and breaking compatibility will not be as easy.

    • T3D.Pushable to T3D.CollidesWithMoving (it means that doors/elevators push or avoid crushing this object)
    • ItemOnLevel, PutOnLevel etc. to ItemOnWorld, PutOnWorld etc. (we try to consistently use the term "World" to refer to your 3D world, and reserve the word "level" for levels recognized by CastleLevels.TLevelInfo)
    • TItem to TInventoryItem, and some Items properties renamed to Inventory. TItem was too generic, and in ObjectPascal "Items" has too generic meaning (many generic lists have "Items" properties referring to their contents; our "Inventory" is a now a list of TInventoryItem, which are things that can be used by player).
    • MoveAllowed, Height renamed to MoveCollision, HeightCollision, consistent with SegmentCollision, BoxCollision and such. These check collision of other things with current 3D object (current T3D instance).
    • Rename MyMoveAllowed, MyHeight to just MoveAllowed, Height etc. These check collision of point belonging to current 3D object with everything else (with the whole World, except current 3D object).