User Tools

Site Tools


dragengine:modules:dragonscript:behavior_elements

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
dragengine:modules:dragonscript:behavior_elements [2025/03/10 16:53] dragonlorddragengine:modules:dragonscript:behavior_elements [2025/03/13 23:15] (current) – [XML Element Classes] dragonlord
Line 35: Line 35:
 This is an example of an element class which which has a visual appearance, physical interaction, is animated, has two lights, has a speaker and moves along a rail. Basically this describes a kind of train running on a rail between two destinations. This is an example of an element class which which has a visual appearance, physical interaction, is animated, has two lights, has a speaker and moves along a rail. Basically this describes a kind of train running on a rail between two destinations.
  
 +++++ Show Example|
 <code> <code>
 pin Dragengine.Gui pin Dragengine.Gui
Line 85: Line 86:
 end end
 </code> </code>
 +++++
  
 The above script code creates a working element class which adds instances of BehaviorElement to the game world set up with the defined behaviors. If you want to have a unique element instance for your class to work with you can modify the code like this: The above script code creates a working element class which adds instances of BehaviorElement to the game world set up with the defined behaviors. If you want to have a unique element instance for your class to work with you can modify the code like this:
 +
 +++++ Show Example|
 <code> <code>
 class MyTrainClass extends BehaviorElementClass class MyTrainClass extends BehaviorElementClass
Line 101: Line 105:
 end end
 </code> </code>
 +++++
  
 Using unique instances allows to add run-time features to your class on top of what BehaviorElement provides without creating an own behavior. In general it is recommended to work with behaviors only and creating your own ones. This way you can reuse game logic across different projects easily. Using unique instances allows to add run-time features to your class on top of what BehaviorElement provides without creating an own behavior. In general it is recommended to work with behaviors only and creating your own ones. This way you can reuse game logic across different projects easily.
  
 ====== XML Element Classes ====== ====== XML Element Classes ======
 +
 +<WRAP center 100%>
 +<WRAP center box 1050px>
 +{{ youtube>heBLyt3b6G0?1000x591 }}
 +<WRAP centeralign>\\
 +Video explaining what behavior factories are, what they can be used for and how they are created. Shown using ExampleApp which contains an example for this.</WRAP>
 +</WRAP>
 +</WRAP>
  
 XML Element classes allow to create new element classes using an XML file (''*.deeclass'') instead of writing script code. XML element classes always subclass from an existing script class or XML element class. Using an XML element class you can change properties added by the behavior definitions. XML Element classes allow to create new element classes using an XML file (''*.deeclass'') instead of writing script code. XML element classes always subclass from an existing script class or XML element class. Using an XML element class you can change properties added by the behavior definitions.
 +
 +Element class properties are typically in the form ''behavior.property'' or ''behavior(id).property''. The identifier is omitted if it is empty string. For example the ECBehaviorComponent behavior uses the prefix ''component.''. Hence ''component.model'' would set the _model_ property. The same for an ECBehaviorComponent with the identifier ''second''. Here the name would be ''component(second).model''.
 +
 +Behaviors can be complex and nested. This allows behaviors to add other behaviors to achieve their goals. Such nested behaviors need to be differentiated from other behaviors of the same kind. The rule is to prefix the property names of the behaviors with their parent prefix to make them unique. For example if you have a fictional behavior MyBehavior with the prefix ''mybehavior.'' which adds one or more ECBehaviorComponent then the property names of those component behaviors would look like ''mybehavior.component.model'' or ''mybehavior.component(second).model''. This nesting can go deeper depending on how complex of a behavior you are designing. In general it is favorable to keep the nesting as little as possible as this is easier to use for team members and modders.
 +
 +===== Behavior Factories =====
  
 Scripted element classes can be also assigned a list of #@LinkApiDocDEDS2_HTML~classDragengine_1_1Scenery_1_1BehaviorFactor.html,Behavior Factories~@#. This allows the user to add behaviors to XML element classes if they are in the list of allowed behavior factories. The DragonScript module provides the #@LinkApiDocDEDS2_HTML~classDragengine_1_1Scenery_1_1GenericBehaviorElementClass.html,GenericBehaviorElementClass~@# which contains the factories of all DragonScript module provided behavior factories. You can create your own behaviors and make them available to the generic behavior element class by extending #@LinkApiDocDEDS2_HTML~classDragengine_1_1BaseGameApp.html,BaseGameApp.createAndAddBehaviorFactories()~@#. Scripted element classes can be also assigned a list of #@LinkApiDocDEDS2_HTML~classDragengine_1_1Scenery_1_1BehaviorFactor.html,Behavior Factories~@#. This allows the user to add behaviors to XML element classes if they are in the list of allowed behavior factories. The DragonScript module provides the #@LinkApiDocDEDS2_HTML~classDragengine_1_1Scenery_1_1GenericBehaviorElementClass.html,GenericBehaviorElementClass~@# which contains the factories of all DragonScript module provided behavior factories. You can create your own behaviors and make them available to the generic behavior element class by extending #@LinkApiDocDEDS2_HTML~classDragengine_1_1BaseGameApp.html,BaseGameApp.createAndAddBehaviorFactories()~@#.
 +
 +Adding behaviors is done using the ''behavior'' tag. Some behaviors require additional parameters during construction time. These parameters can be defined inside the ''behavior'' tag using the same tags as you use to define element properties. The behavior documentation list the supported parameters. After adding a behavior you can set the element properties outside the ''behavior'' tag as you usually would do.
 +
 +To simplify the adding of behaviors properties of a just added behavior can be also defined by moving the property tags inside the ''behavior'' tag. If you do this you have to remove the behavior property prefix from the property names leaving being only the ''.'' as first character in the name. This way the DragonScript module prepends the behavior property prefix while setting the property values. This is easier to write, increases readability and has less possibility for errors. It is thus recommended to set properties of just added behaviors in this way.
  
 (TODO: add video of behavior factories) (TODO: add video of behavior factories)
Line 503: Line 526:
   * key: Key to assign value to. Required.   * key: Key to assign value to. Required.
 </WRAP>|0..N|-| </WRAP>|0..N|-|
 +
 +===== Examples =====
 +
 +This example creates a simple XML element class based on the #@LinkApiDocDEDS2_HTML~classDragengine_1_1Scenery_1_1SimpleElementClass.html,SimpleElementClass~@#. It modifies some element properties to use a specific model, skin and rig resource. The path are either absolute path (if starting with ''/'') or relative to the directory the ''*.deeclass'' file is located in.
 +
 +++++ Show Example|
 +<code xml>
 +<?xml version='1.0' encoding='UTF-8'?>
 +<elementClass name='PropBox' class='SimpleElement'>
 + <string name='component.model'>box.demodel</string>
 + <string name='component.skin'>/content/materials/concrete/material.deskin</string>
 + <string name='component.rig'>box.derig</string>
 + <string name='component.audioModel'>box.demodel</string>
 + <string name='navigationSpace.blockerShape'>box:position,0,0.3,-0.05:extends,1.3,0.5,1.3</string>
 +</elementClass>
 +</code>
 +++++
 +
 +This example creates a complex XML element class which is based on the #@LinkApiDocDEDS2_HTML~classDragengine_1_1Scenery_1_1GenericBehaviorElementClass.html,GenericBehaviorElementClass~@#. This allows adding behaviors inside the ''*.deeclass'' file avoiding the need to write an explicit script class to do the same. This is the example file used in the behavior factory video above.
 +
 +++++ Show Example|
 +<code xml>
 +<?xml version='1.0' encoding='ISO-8859-1'?>
 +<elementClass name='ExtendedCustomColor' class='GenericBehaviorElement'>
 + <!--
 + Example element class creating a similar element class as CustomColorExampleClass
 + but using GenericBehaviorElement as base class and adding behaviors in XML.
 + Furthermore some additional behaviors are added to show the flexibility of this approach.
 + -->
 +
 + <!--
 + Add component behavior. This adds a visible presence to the element. Also set some of
 + the parameters of the behavior. This could be done later in the XML file but it helps
 + to group the behavior and it's parameters to improve the readability.
 + -->
 + <behavior type='ECBehaviorComponent'>
 + <string name='.model'>/content/models/box/box.demodel</string>
 + <string name='.rig'>/content/models/box/box.derig</string>
 + <string name='.skin'>customColor.deskin</string>
 + </behavior>
 +
 + <!--
 + Add collider behavior. This adds physical presence to the element. Adding this behavior
 + automatically attaches to the component behavior previously added.
 + -->
 + <behavior type='ECBehaviorCollider'/>
 +
 + <!--
 + Add navigation space behavior. This adds support for adding navigation space and blockers.
 + We do not need navigation space but blockers. The behavior automatically uses the previously
 + added collider behavior.
 + -->
 + <behavior type='ECBehaviorNavigationSpace'/>
 +
 + <!--
 + In SimpleElementClass used as base class for CustomColorExampleClass the behaviors
 + ECBehaviorNavigationSpace and ECBehaviorAttachToParent are present too. We do not need
 + them in this class so we can skip them.
 + -->
 +
 + <!--
 + Add a couple of custom color behaviors. In SimpleElementClass 5 such behaviors are added.
 + We do the same thing here. Each behavior requires a unique identifier.
 + -->
 + <behavior type='ECBehaviorCustomColor' id='color1'>
 + <string name='.name'>Background</string>
 + <color name='.defaultColor' r='0' g='0' b='0.5'/>
 +
 + <!--
 + In SimpleElementClass there is also an example to define allowed colors. As mentioned
 + in the element class limiting to these colors is not implemented. Nevertheless it is
 + shown here how such a list of colors would be defined.
 + -->
 + <list name='.allowedColors'>
 + <color r='0' g='0' b='0.5'/> <!-- darkBlue -->
 + <color r='0.25' g='0.25' b='0.25'/> <!-- darkGray -->
 + <color r='0' g='0.5' b='0'/> <!-- darkGreen -->
 + <color r='0.5' g='0' b='0'/> <!-- darkRed -->
 + <color r='1' g='1' b='1'/> <!-- white -->
 + <color r='0' g='0' b='0'/> <!-- black -->
 + </list>
 + </behavior>
 +
 + <behavior type='ECBehaviorCustomColor' id='color2'>
 + <string name='.name'>Dragoness</string>
 + <color name='.defaultColor' r='0.85' g='0.3' b='1'/>
 + </behavior>
 +
 + <behavior type='ECBehaviorCustomColor' id='color3'>
 + <string name='.name'>Text Left</string>
 + <color name='.defaultColor' r='0.33' g='0.44' b='0.7'/>
 + </behavior>
 +
 + <behavior type='ECBehaviorCustomColor' id='color4'>
 + <string name='.name'>Text Right</string>
 + <color name='.defaultColor' r='0.8' g='0.8' b='0.8'/>
 + </behavior>
 +
 + <behavior type='ECBehaviorCustomColor' id='color5'>
 + <string name='.name'>Text Center</string>
 + <color name='.defaultColor' r='0.65' g='0.65' b='0.65'/>
 + </behavior>
 +
 + <!--
 + Add dynamic skin behavior. This allows the textures of the component behavior to be
 + modified dynamically at runtime. The behavior automatically uses the previously added
 + component behavior.
 + -->
 + <behavior type='ECBehaviorDynamicSkin'/>
 +
 + <!--
 + Add renderable canvas behavior. This modifies the "customColor" renderable defined
 + in the skin file. You need one per renderable you want to modify. Since we use only
 + one renderable canvas here we are not required to set an identifier. It is though
 + good practice to set one. This behavior automatically uses the previously added
 + dynamic skin behavior.
 + -->
 + <behavior type='ECBehaviorRenderableCanvas' id='customColor'>
 + <string name='.renderable'>customColor</string>
 + <point name='.size' x='512' y='512'/>
 + <color name='.backgroundColor' r='1' g='1' b='1'/>
 + </behavior>
 +
 + <!--
 + Add behaviors to apply the custom colors to the renderable canvas. These behaviors
 + automatically use the previously added renderable canvas behavior. Here we have
 + something new. Some behaviors support (or require) parameters at construction time.
 + This is done by adding parameter definitions inside the behavior tag. In general the
 + parameters required to be placed inside the behavior tag can not be changed later on
 + using regular property definition tags outside the behavior tag. See the respective
 + Factory inner classes inside the behavior of interest for information on such parameters.
 + In the case of the ECBehaviorRenderableCustomColor behavior we have to define which
 + ECBehaviorCustomColor behavior to use.
 +
 + Because we created above a renderable canvas behavior with a non-empty identifier
 + we have to define below which renderable canvas we want to use. If the identifier
 + would be empty (not set) we could remove the renderCanvas string tag and the factory
 + would use the renderable canvas with the empty identifier.
 + -->
 + <behavior type='ECBehaviorRenderableCustomColor' id='color1'>
 + <string name='customColor'>color1</string>
 + <string name='renderableCanvas'>customColor</string>
 +
 + <string name='.image'>color1.png</string>
 + </behavior>
 +
 + <behavior type='ECBehaviorRenderableCustomColor' id='color2'>
 + <string name='customColor'>color2</string>
 + <string name='renderableCanvas'>customColor</string>
 +
 + <string name='.image'>color2.png</string>
 + </behavior>
 +
 + <behavior type='ECBehaviorRenderableCustomColor' id='color3'>
 + <string name='customColor'>color3</string>
 + <string name='renderableCanvas'>customColor</string>
 +
 + <string name='.image'>color3.png</string>
 + </behavior>
 +
 + <behavior type='ECBehaviorRenderableCustomColor' id='color4'>
 + <string name='customColor'>color4</string>
 + <string name='renderableCanvas'>customColor</string>
 +
 + <string name='.image'>color4.png</string>
 + </behavior>
 +
 + <behavior type='ECBehaviorRenderableCustomColor' id='color5'>
 + <string name='customColor'>color5</string>
 + <string name='renderableCanvas'>customColor</string>
 +
 + <string name='.image'>color5.png</string>
 + </behavior>
 +
 + <!--
 + Add behavior for player to interact with this element. Adjust the interaction zone
 + to work with the box. This is a behavior specific to the example application. For this
 + reason it uses the prefix "Behavior" instead of "ECBehavior" as the behaviors provided
 + by the Drag[en]gine. Another typical prefix is "ECB". This prefix can be used to avoid
 + confusion with game world behaviors which use prefix "GWBehavior".
 + -->
 + <behavior type='BehaviorChooseColors'>
 + <vector name='.interactionSpot.position' x='0' y='0' z='3'/>
 + <vector name='.interactionSpot.lookAt' x='0.5' y='1' z='1'/>
 + </behavior>
 +
 + <!--
 + At this point we have replicated the behaviors present in the SimpleElementClass but
 + using an XML element class instead of a DragonScript class. The advantage of using
 + the XML element class way is that no script changes are required. It is also possible
 + to use automated tools to produce or modify such files.
 + -->
 +
 + <!--
 + Let's add some more behaviors to extend the element class, even if it is silly. Let's first
 + add a light near the front side which is red and strong enough against the sun.
 + -->
 + <behavior type='ECBehaviorLight'>
 + <float name='.intensity'>50</float>
 + <float name='.halfIntensityDistance'>0.5</float>
 + <float name='.range'>1</float>
 + <color name='.color' r='1'/>
 + <vector name='.position' x='0' y='0.25' z='1.1'/>
 + </behavior>
 +
 + <!--
 + And just because we can also add two particle emitters on top of it. The first one produces
 + a flame and the second one the smoke. Actually this can be done using a single particle
 + emitter emitting two types of particles but for this example two emitters are used.
 + -->
 + <behavior type='ECBehaviorParticleEmitter' id='flame'>
 + <string name='.path'>/content/emitters/flame1.depemit</string>
 + <vector name='.position' y='2.05' z='0.75'/>
 + <vector name='.orientation' x='90'/>
 + </behavior>
 +
 + <behavior type='ECBehaviorParticleEmitter' id='smoke'>
 + <string name='.path'>/content/emitters/smoke.depemit</string>
 + <vector name='.position' y='2.3' z='0.75'/>
 + <vector name='.orientation' x='90'/>
 + </behavior>
 +
 + <!--
 + And where there is fire should be also sound. Add a speaker behavior with some sound playing.
 + -->
 + <behavior type='ECBehaviorSpeaker'>
 + <string name='.sound'>/content/sound/crackle.ogg</string>
 + <float name='.range'>15</float>
 + <float name='.volume'>0.5</float>
 + <vector name='.position' y='2.5' z='0.75'/>
 + </behavior>
 +</elementClass>
 +</code>
 +++++
  
dragengine/modules/dragonscript/behavior_elements.1741625628.txt.gz · Last modified: 2025/03/10 16:53 by dragonlord