[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.2.3 BTTest Tutorial

This is a tutorial to show how you can use a Behaviour Tree (BT) in your application.

The source files of this tutorial can be found in the 'apps/bttest' directory that is included with CEL. The world and entity file can be found in the 'data' directory ('walktut_world' and 'walktut_entities').

During the game you can use the following inputs:

This tutorial adds a Behaviour Tree to the previous tutorial WalkTut. As before with the QuestTest tutorial, this tutorial will focus only on the changes to WalkTut neccesary to add a behaviour tree. Most of the additional code can be found in either the MainApp::CreateBehaviourTree () or MainApp::LoadBehaviourTreeFromXML () methods in app.cpp.

The sole exception is adding a behaviour tree to the player entity when creating it at line 55 of app.cpp. This is done by simply adding "pclogic.behaviourtree" to the list of arguments passed to CreateEntity.

A CEL behaviour tree is made up of nodes (classes implementing iBTNode) which come in the forms of selectors, decorators and leaf nodes. Each node upon completing its execution returns a BTStatus signalling its success or failure.

A behaviour tree running in CEL will, by default, execute one node per frame. To speed up the parsing of a behaviour tree, and so the rate of decisions, the property "update rate" can be set to change how many nodes are executed per frame.

By default, appbttest loads the players behaviour tree from data/bttest.xml. This example behaviour tree tests all behaviour tree nodes provided by CEL. If everything is working correctly it simply prints a welcome message to the console. The MainApp::LoadBehaviourTreeFromXML () method loads this file, sets it as the "xml" property and loads it by performing the propclass action "Load From XML."

Alternatively MainApp::CreateBehaviourTree (), demonstrates how to code a behaviour tree, first all nodes of the tree must be created. This requires a reference to the plugin manager that can be obtained by:

 
csRef<iPluginManager> plugin_mgr = 
  csQueryRegistry<iPluginManager> (object_reg);

Each node is then created by a call to the method csLoadPlugin(). An example of this for a default selector is:

 
csRef<iBTNode> root_node = 
  csLoadPlugin<iBTNode> (plugin_mgr, "cel.selectors.default"); 

The default selector, executes its children in the order they were added until one succeeds. Provided one child succeeds so does the selector, but if all children fail the selector fails. Other standard BT nodes can be loaded with the following identifiers.

In the bttest application in lines 243 to 283, you will see a number of nodes set up representing each of the above types at least once. These will shortly be connected to demonstrate a working bt but first a number of specific details for certain nodes will need to be set up.

Selectors require no further setup, other than the connection of children that will be covered later. Some decorators, however, do. For example:

 
csRef<iExecutionLimitDecorator> explicit_execution_limit_node = 
  scfQueryInterface<iExecutionLimitDecorator> (execution_limit_node); 
explicit_execution_limit_node->SetExecutionLimit("1");

This sets up the execution limit decorator to only allow its child to be executed once. Similarly, the loop decorator must be set up with the number of iterations to perform and the parameter check condition must be set up with a value and parameter to compare. Examples of this can be found in lines 284-297 of app.cpp.

Finally the triggerfired node and btaction nodes, that act as wrappers to the recently refactored cel triggers and rewards, must be set up. The trigger fired node requires a trigger be created and assigned whilst the btaction node requires a reward to be created and assigned. This is marginally more complex as the trigger example below shows:

 
csRef<iTriggerType> trigger_type = csLoadPlugin<iTriggerType> (plugin_mgr, 
  "cel.triggers.inventory"); 
csRef<iTriggerFactory> trigger_factory = trigger_type->CreateTriggerFactory (); 
csRef<iInventoryTriggerFactory> explicit_trigger_factory = 
  scfQueryInterface<iInventoryTriggerFactory> (trigger_factory); 
explicit_trigger_factory->SetEntityParameter ("player"); 
explicit_trigger_factory->SetChildEntityParameter ("box3"); 
csRef<iTrigger> trigger = trigger_factory->CreateTrigger (params); 
csRef<iTriggerFiredCondition> explicit_trigger_node = 
  scfQueryInterface<iTriggerFiredCondition> (trigger_check_node); 
explicit_trigger_node->SetTrigger (trigger);

First a trigger type object of the required type must be loaded. This can be used to create a trigger factory, that is set up to create the required trigger. The specific setup details for the trigger factory will depend on the type of trigger used. The BT wrapper for triggers is capable of using any CEL trigger.

A similar method is used for rewards, in lines 316-363, however as all rewards in this behaviour tree are of the same type (debug message) the type need only be loaded once and the factory only created once. After that the message parameter (for this specific reward type) can be edited and a new reward made. There is no need to repeat the loading of the type and creation of the reward factory. This method of editing the setup and not recreating the factory can also be applied to triggers where multiple instances of the same trigger type are needed.

With all nodes setup they must now be connected. This is a relatively simple process whereby a child is added to a parent using the parent's AddChild () method. For example:

 
root_node->AddChild (initial_sequence_node);

The full process of connecting this tree is encapsulated in lines 365-386 of app.cpp. The connected tree's behaviour can be described as:

Finally, in lines 389-398, the root node is set as a property of the propclass and the behaviour tree is started by performing the action "BT Start".

And so completes this tutorial. Hopefully, by following this example you can now construct your own cel behaviour tree. The more interesting design challenges now come from how to combine these tools to create complex and fun behaviours for the characters in your game. For discussions on design choices when constructing behaviour trees, the author highly recommends http://www.aigamedev.com.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated using texi2html 1.76.