resource.xml files define the properties of resources: creatures and items.
Below is a sample
with links to documentation for every attribute.
WalkAttack(indicating TWalkAttackCreatureResource class), there are other resource types (for creatures and items) with a little different properties.
<?xml version="1.0"?> <resource name="RequiredCreatureName" type="WalkAttack" knockback_speed="1.0" knockback_distance="4.0" flying="False" sound_die_tied_to_creature="True" default_max_life="100.0" radius="0.0" middle_height="0.5" sound_sudden_pain="" sound_die="" move_speed="1.0" min_life_loss_to_hurt="0.0" chance_to_hurt="1.0" max_height_acceptable_to_fall="1.5" random_walk_distance="10.0" remove_dead="False" preferred_distance="2.0" smell_distance="0.0" always_prepared="False" fall_speed="10.0" grow_speed="5.0" receive_shadow_volumes="True" cast_shadow_volumes="True"> <!-- See lower on this page for explanation how to export animations and define <model> element. Below we only show all possible attributes, in practice you will not want to set them all. --> <model url="main.x3d"> <idle url="idle.x3d" time_sensor="TimeSensorIdle" /> <idle_to_walk url="idle_to_walk.x3d" time_sensor="TimeSensorIdleToWalk" /> <walk url="walk.x3d" time_sensor="TimeSensorWalk" /> <fire_missile url="fire_missile.x3d" time_sensor="TimeSensorFireMissile" /> <attack url="attack.x3d" time_sensor="TimeSensorAttack" /> <die url="die.x3d" time_sensor="TimeSensorDie" /> <die_back url="die_back.x3d" time_sensor="TimeSensorDieBack" /> <hurt url="hurt.x3d" time_sensor="TimeSensorHurt" /> </model> <attack knockback_distance="0.0" time="0.0" max_distance="2.0" max_angle="0.523598776" min_delay="2.0" sound_hit="" sound_start="" > <damage const="0.0" random="0.0" /> </attack> <fire_missile time="0.0" max_distance="30.0" max_angle="0.523598776" min_delay="2.0" sound="" name="" height="0.5" /> <fall> <sound min_height="1.0" name="creature_fall" /> <damage min_height="5.0" scale_min="0.8" scale_max="1.2" /> </fall> <run_away life="0.3" distance="10.0" /> <visibility angle="2.094395102" /> </resource>
type attribute determines the exact class (ObjectPascal
implementation) used to instantiate this resource.
You can use the same type many types of course,
for example you can define many creatures of type
Missile and many items of type
This type determines the behavior that is coded in ObjectPascal — like creature artificial intelligence, whether item can be equipped, what happens when item is used and so on.
The type also determines available attributes and animations of this resource.
For example, only creature type
WalkAttack (or it's descendants)
<attack> animation. See the properties of resource
classes to know what is available:
Resources models (creatures, items and such) should be modeled around 0,0,0 point. In case of resources using gravity (items and non-flying creatures), they will be placed on the ground relative to the 0 level of their model. In other words, if you want your model to float slightly above the ground, you can just move it higher above the 0 level. If the model is slightly below 0 level, it will sink into the ground. This is usually the most comfortable approach.
For flying resources (not using gravity), this doesn't matter, basically you can place 0,0,0 wherever you like. See T3DCustomTransform.MiddleHeight for precise details.
3D resources, like creatures and items, display various 3D
animations. Depending on the creature state, like standing / attacking
/ dying, we may want to display different animation of the given
creature instance. We define these animations using the
element of creature/item
As a developer, you can
also create T3DResourceAnimation instance adding it to a
this way you can add new animations for your own/extended resources.
At this point, I highly advice you compile and run the
examples/resource_animations example program from the engine sources.
data/ subdirectory of it shows examples of how you can define
discussed below. It is also a great program to test your own
creatures/items animations (before using in the actual game), you
can load their
resource.xml using the "Add resource..." button and
directly play loaded animations.
There are three approaches to indicate animations
<model> element in
Which one to choose depends on what 3D
modeler / exporter you use to design your models:
The best way (best for memory and loading time, which is really important in these situations) is to use a single X3D model, with many X3D TimeSensors representing different animations. You declare it in resource.xml file like this:
<model url="model.x3d"> <stand time_sensor="TimeSensorStand"/> <walk time_sensor="TimeSensorWalk"/> </model>
This is nice if your 3D modeler / exporter can record multiple animations inside a single X3D file, and each animation is controlled by a different X3D TimeSensor node. This is the most natural way to record multiple animations in a single X3D file. We will detect animation length from the TimeSensor.cycleInterval, and we'll simulate sending appropriate time and fraction_changed from this TimeSensor to activate the desired moment of the desired animation.
Unfortunately, I don't know of any open-source 3D modeler / exporter right now that can nicely produce such multiple animations in a single X3D file. I plan to extend Blender X3D exporter to allow this in the future.
You can also use a separate X3D model for each animation state, like this:
<model> <stand url="stand.x3d" time_sensor="MainTimeSensor"/> <walk url="walk.x3d" time_sensor="MainTimeSensor"/> </model>
You can also use a precalculated animation for each animation, from KAnim or MD3 (Quake 3 engine format) file. This is useful if your 3D modeler / exporter cannot produce animated X3D files at all, but it can export to kanim (see our Blender to KAnim exporter) or MD3. In the worst case, you can also just export a couple of still frames and write the xxx.kanim file in a text editor, because the kanim format is a trivial XML file that just describes a transition between a couple of still 3D models. Internally, we'll use TCastlePrecalculatedAnimation for each animation state.
<model> <stand url="stand.kanim"/> <walk url="walk.kanim"/> </model>
This is probably the most comfortable approach to export animations from Blender to our engine. For now — in the future we hope to extend Blender X3D exporter to store whole animation inside a single X3D file.
To describe above three cases in more precise manner for developers:
(Case 3. above) When animation state, like
doesn't have a
time_sensor attribute — then it must have
url attribute, and we use precalculated animation,
TCastlePrecalculatedAnimation, to play it. Suitable for kanim and
X3D animations. Suitable also when the model is just a still 3D
model, as then TCastlePrecalculatedAnimation simply renders it.
(Case 2. above) Otherwise, if an animation state like
<walk> has both
url, then we load it to a
TCastleScene and use appropriate TimeSensor to play the animation.
(Case 1. above) Otherwise, if an animation state like
<walk> has only
time_sensor, then we use a 3D model defined at
<model> element to choose and play appropriate animation. This also
means using TCastleScene and appropriate TimeSensor to play it,
but this time it's a single TCastleScene potentially shared by various
In some situations, we have to know the animation duration (for
example, to know when
<attack> animation ends and we should get back
For TCastlePrecalculatedAnimation, the animation always starts from
the local time 0, goes to the last time (time of last
kanim file). Then it eventually goes backward, it backwards="true"
in kanim file. So we know the duration by looking at frames time and
backwards property: TimeEnd + (if Backwards then TimeEnd-TimeBegin
So using backwards="true" in KAnim works, useful for some animations when you do some gesture and then go back to original position by reversing this gesture — e.g. dog-like creature biting.
For TCastleScene and TimeSensor: in this case, X3D TimeSensor.cycleInterval gives us animation duration.
The looping is done automatically for animations that require it (like walk). So using loop attribute in kanim file, or loop field for TimeSensor is not necessary (it's ignored).
Design notes about X3D TimeSensor usage: All creatures of a given kind must share the same resources. E.g. imagine you have a creature type "werewolf" (defined by a resource.xml file with name="Werewolf" inside, resulting in TCastleResource instance with TCastleResource.Name="Werewolf"). You can instantiate this creature many times on the level, and all visible werewolves will actually use the same resource underneath. That is why we use TimeSensors by directly sending their time/fraction_changed, instead of just activating them by TimeSensor.startTime: in the latter case, all werewolves visible on the level would be forced to be in the same state (and moment) of the animation.