This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
dragengine:modules:dragonscript:locomotion [2015/06/17 23:57] – created dragonlord | dragengine:modules:dragonscript:locomotion [2024/03/14 16:43] (current) – dragonlord | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | {{tag> | ||
<WRAP youarehere> | <WRAP youarehere> | ||
[[: | [[: | ||
Line 4: | Line 5: | ||
====== Locomotion ====== | ====== Locomotion ====== | ||
- | Locomotion defines the movement, looking, turnging and stance states of actors. The DragonScript module provides basic locomotion implementation using the [[http:// | + | Locomotion defines the movement, looking, turnging and stance states of actors. The DragonScript module provides basic locomotion implementation using the # |
+ | |||
+ | ====== Parameters ====== | ||
+ | The locomotion class uses various parameters and switches to provide the different kinds of locomotion behaviors. Input parameters are described in this article as // | ||
+ | ^Class-Member^Description^ | ||
+ | |Value|The current value of the parameter. This is the output of the locomotion.| | ||
+ | |Goal|The desired value of the parameter. This is set by the script user according to input from the player or AI. Smoothing is used to adjust the current value over time to arrive at the goal.| | ||
+ | |Adjust time|Time after which the current value approached the goal value. Due to goal values keeping on changing this is only an approximation and should is a best effort value. Compare the current value against the goal value to figure out when the value is close enough to the desired value. Adjust time can be set to 0 in which case the locomotion class sets the current value to the goal value without smoothing.| | ||
+ | |Lower limit|Lower limit to clamp current value to. The goal value is allowed to go below the lower limit to avoid clipping problems. Some parameter sets do not have a lower limit.| | ||
+ | |Upper limit|Upper limit to clamp current value to. The goal value is allowed to go above the upper limit to avoid clipping problems. Some parameter sets do not have an upper limit.| | ||
+ | |||
+ | The following //Input Parameter Sets// are used. | ||
+ | ^Parameter-Set^Type^Description^ | ||
+ | |Look up-down|float|Controls actor looking up and down. Positive values represent looking up and negative values looking down. The default adjust time is 0. This value is typically set from user input for example moving the mouse or gamepad Y Axis. For AI actors this is usually calculated from a look-at point relative to the actor coordinate system.| | ||
+ | |Look left-right|float|Controls actor looking left and right. Positive values represent looking left and negative values looking right. The default adjust time is 0. This value is typically set from user input for example moving the mouse or gamepad X axis. For AI actors this is usually calculated from a look-at point relative to the actor coordinate system.| | ||
+ | |Analog moving direction|float|Controls the direction the actor is moving to. This value is typically set from user input for example pressing direction buttons or using gamepad axes. For AI actors this is usually calculated from a target position. This value is in world space not relative to the actor. The default adjust time is 0.5s to smooth speed and direction changes.| | ||
+ | |Analog moving speed|float|Controls the speed the actor is moving with as meters per second. This parameter does not support smoothing.| | ||
+ | |Turn left-right|float|Controls actor turning left and right. Positive values represent turning left and negative values turning right. This value is typically set from user input for example pressing direction buttons or using gamepad axes. For AI actors this is usually calculated from a target orientation. This value is the amount of degrees to rotate in the next frame update. This input parameter is not smoothed since it is not used directly as output parameter. For player actors turning is usually only required for doing vehicle like locomotion. For natural and FPS type locomotion this parameter is not required since the locomotion class can turn the actor using the Look left-right parameter.| | ||
+ | |Stance|float|Controls the actor stance for example in upright position or crouched. The actual meaning of this value is left for the user to define as long as smoothing is reasonable. This value is typically set from user input for example pressing buttons converting to appropriate goal value.| | ||
+ | |Tilt left-right|float|Controls actors standing on tilted ground. Positive values represent ground tilted downwards to the left side and negative to the right side. This value can be calculated by the script user but it is more efficient and easier to make the locomotion calculate tilt values. See the section below about tilting.| | ||
+ | |Tilt up-down|float|Controls actors standing on tilted ground. Positive values represent ground tilted downwards to the front and negative to the back. This value can be calculated by the script user but it is more efficient and easier to make the locomotion calculate tilt values. See the section below about tilting.| | ||
+ | |||
+ | The following //Output Parameters// | ||
+ | ^Parameter^Value^Description^ | ||
+ | |Look up-down|float|Head up-down orientation relative to actor coordinate system. The current value of the //Look up-down// input parameter set after smoothing.| | ||
+ | |Look left-right|float|Head left-right orientation relative to // | ||
+ | |Orientation|float|Orientation of actor in world space. This value is normalized to the range from -180 degrees to 180 degrees. Rotation is counter-clock-wise. This output value is smoothed after applying all rotation changes. It is possible to smooth input //Look left-right// | ||
+ | |Turning speed|float|Turning speed of actor in degrees per second. This value is also provided as angular velocity (Vector) for convenience.| | ||
+ | |Linear velocity|Vector|Linear velocity of actor in meters per second. This output value is smoothed after applying all movement changes and is used as base for all movement output parameters. It is possible to smooth input //Analog moving direction/ | ||
+ | |Moving orientation|float|Orientation the actor is moving along in world space. Derived from the //Linear velocity// parameter. This value is normalized to the range from -180 degrees to 180 degrees. Rotation is counter-clock-wise. Near 0 movement speed the value of moving orientation becomes undefined. For this reason near 0 movement speed the moving orientation is not updated. The actor thus sticks to the last well defined moving orientation while stopping moving.| | ||
+ | |Moving speed|float|Moving speed of actor in meters per second. Derived from the //Linear velocity// parameter.| | ||
+ | |Moving direction|float|// | ||
+ | |Stance|flot|Stance of active. The current value of the //Stance// input parameter set after smoothing.| | ||
+ | |Turn in-place|float|Actor turning in-place. This is a special value to help properly animate actors turning in place. For moving actors this is not required since the //Turning speed// parameter is enough. For resting actors though this is usually not enough if a good animation is desired.| | ||
+ | |Tilt left-right|float|Actor tilt on ground. The current value of the //Tilt left-right// | ||
+ | |Tilt up-down|float|Actor tilt on ground. The current value of the //Tilt up-down// input parameter set after smoothing.| | ||
+ | |Tilt offset|float|Up-down offset of actor due to tilting. This offset is required if inverse kinematics is used for legs to avoid broken results.| | ||
+ | |||
+ | Different locomotion calculation parts can be individually disabled using // | ||
+ | ^Switch^Description^ | ||
+ | |Can turn|Disabled turning calculations. If disabled the // | ||
+ | |Can turn in-place|If enabled and //Look left-right// | ||
+ | |Turn adjust look left-right|If enabled the rotation applied to the // | ||
+ | |Can tilt|If enabled tilt calculations are applied. If disabled tilt values are pulled towards neutral values.| | ||
====== Natural Locomotion ====== | ====== Natural Locomotion ====== | ||
- | Natural locomotion provides a smooth moving actor locomotion behavior that mimicks a natural locomotion pattern. This is the most complex calculation method but yields a result which is more natural than the other types. With natural locomotion the body **orientation** is the **major orientation**. The major orientation is the orientation lining up with the component, collider and game element orientation. All other orientations are relative to this major orientation. The **looking left/ | ||
- | < | + | <WRAP box right :en 350px> |
{{ : | {{ : | ||
<WRAP centeralign> | <WRAP centeralign> | ||
</ | </ | ||
+ | |||
+ | Natural locomotion provides a smooth moving actor locomotion behavior that mimicks a natural locomotion pattern. This is the most complex calculation method but yields a result which is more natural than the other types. With natural locomotion the body **orientation** is the **major orientation**. The major orientation is the orientation lining up with the component, collider and game element orientation. All other orientations are relative to this major orientation. The **looking left/ | ||
+ | |||
+ | To use natural locomotion use the following // | ||
+ | ^Switch^Value^ | ||
+ | |Can turn|true| | ||
+ | |Turn adjust look left-right|true| | ||
+ | |Can turn in-place|true| | ||
+ | |||
+ | Drive //Input Parameter Sets// like this: | ||
+ | ^Parameter-Set^Goal value^ | ||
+ | |Analog moving direction|Calculate // | ||
+ | |Turn left-right|Turning is used here to turn the body into the direction the actor is moving. Set value to //Look left-right// | ||
Natural locomotion is a good choice for most situations. Actors using natural locomotion move in the direction their body is facing and strafing behavior does not produce broken hips all the time. Another advantage of using natural locomotion is that only a single animation for moving forward and backward is required paired with looking left-right animator rules. | Natural locomotion is a good choice for most situations. Actors using natural locomotion move in the direction their body is facing and strafing behavior does not produce broken hips all the time. Another advantage of using natural locomotion is that only a single animation for moving forward and backward is required paired with looking left-right animator rules. | ||
====== FPS Locomotion ====== | ====== FPS Locomotion ====== | ||
- | FPS locomotion is best known from FPS games as the name implies. In contrary to natural locomotion the **camera direction** and body **orientation** are coupled. The actor component is oriented to look into the same direction the camera is facing. In the case of natural locomotion the body orientation is the major oriented while in the case of FPS locomotion the camera direction is the major orientation. This is a typical coupling in FPS games and allows to animate upper and lower body individually (with the typical broken hip problem). The **moving direction** is now relative to the camera direction using **looking left/ | + | <WRAP box right :en 350px> |
- | + | ||
- | < | + | |
{{ : | {{ : | ||
<WRAP centeralign> | <WRAP centeralign> | ||
</ | </ | ||
+ | FPS locomotion is best known from FPS games as the name implies. In contrary to natural locomotion the **camera direction** and body **orientation** are coupled. The actor component is oriented to look into the same direction the camera is facing. In the case of natural locomotion the body orientation is the major oriented while in the case of FPS locomotion the camera direction is the major orientation. This is a typical coupling in FPS games and allows to animate upper and lower body individually (with the typical broken hip problem). The **moving direction** is now relative to the camera direction using **looking left/ | ||
- | FPS locomotion is somewhat simpler to understand and is somewhat cheaper to calculate. There are two ways to handle the animation. The first solution is to use the same setup as in the natural locomotion | + | To use natural locomotion |
+ | ^Switch^Value^ | ||
+ | |Can turn|true| | ||
+ | |Turn adjust look left-right|true| | ||
+ | |Can turn in-place|true| | ||
- | ====== Vehicle Locomotion ====== | + | Drive //Input Parameter Sets// |
- | Vehicle locomotion matches the typical tank like controls. Actors can only move into the direction | + | ^Parameter-Set^Goal value^ |
+ | |Analog moving direction|Calculate movingDirection depending on pressed buttons (forward, backward, strafe-left, | ||
+ | |Turn left-right|Turning | ||
- | < | + | FPS locomotion is somewhat simpler to understand and is somewhat cheaper to calculate. There are two ways to handle the animation. The first solution is to use the same setup as in the natural locomotion case. Most of the time though an 8-way animation setup is used. In this case 8 animations of walking/ |
+ | |||
+ | ====== Vehicle Locomotion ====== | ||
+ | <WRAP box right :en 350px> | ||
{{ : | {{ : | ||
<WRAP centeralign> | <WRAP centeralign> | ||
</ | </ | ||
+ | Vehicle locomotion matches the typical tank like controls. Actors can only move into the direction their body is oriented. The major direction is thus the body **orientation** similar to natural locomotion. The body orientation though never changes except using **turning left/ | ||
+ | |||
+ | To use natural locomotion use the following // | ||
+ | ^Switch^Value^ | ||
+ | |Can turn|true| | ||
+ | |Turn adjust look left-right|false| | ||
+ | |Can turn in-place|false| | ||
+ | |||
+ | Drive //Input Parameter Sets// like this: | ||
+ | ^Parameter-Set^Goal value^ | ||
+ | |Analog moving direction|0 if moving forward, 180 if moving backward.| | ||
+ | |Turn left-right|CurrentValue +/- turnSpeed * elapsedFrameTime. Turning speed is in degrees per second. Use positive value to turn left and negative to turn right.| | ||
+ | Vehicle locomotion is the simplest locomotion type of the three and the cheapest. Disabling the turning adjustments and in-place turning is important to avoid the vehicle suddenly turning when the looking around approaches the border. | ||
====== Animator and collider control ====== | ====== Animator and collider control ====== | ||
- | Locomotion allows to set an [[http:// | + | Locomotion allows to set an # |
< | < | ||
Line 51: | Line 128: | ||
</ | </ | ||
- | ====== Body tilting ====== | + | The table below lists the available controllers and what they are best used for: |
- | Body tilting provides support to adjust | + | ^Attribute^Description^ |
+ | |Elapsed time|Increments controller using elapsed frame time. Use for all playback driven | ||
+ | |Look up-down|Value of //Look up-down// output parameter. Use for actor looking up-down without moving body.| | ||
+ | |Look left-right|Value of //Look left-right// output parameter. Use for actor looking left-right without moving body. With vehicles this could be used for example for rotating turrets.| | ||
+ | |Moving speed|Value of //Moving speed// output parameter. Use to blend between different movement animations like walking and running. The value can not be used for blending between moving forward and backward since moving speed is always positive.| | ||
+ | |Moving direction|Value of //Moving direction// output parameter. Use for actors using FPS type locomotion | ||
+ | |Relative moving speed|Value of //Moving speed// output parameter using the value of //Moving direction// to produce negative values if moving backwards. Use for actors using natural type locomotion | ||
+ | |Turning speed|Value of //Turning speed// output parameter. Use to blend with animations of the actor turning left or right. Turning speed is positive for turning left and negative for turning right.| | ||
+ | |Stance|Value of //Stance// output parameter. Use to blend between different stances of an actor. The meaning of the value is up to the script user. Only requirement is that values are between 0 and 1.| | ||
+ | |Displacement|Value of //Moving speed// output parameter multiplied by the elapsed time. Use for movement animations to match the playback to the actual distance travelled. For this to work set the animator controller upper limit to the two times the stride length of the actor (if you use an animation with one walk cycle). The actor will then always move with the correct speed avoid feet sliding. This attribute works best for vehicle type locomotion for example tanks.| | ||
+ | |Time turn in-place|Value | ||
+ | |Tilt offset|Value of //Tilt offset// output parameter. Use to offset actor root bone downwards due to tilting. The value is the required offset in meters. Using this attribute moves actors on titled surfaces into a favorable position for inverse kinematic rules.| | ||
+ | |Tilt up-down|Value of //Tilt up-down// output parameter. Use to blend with animation of actor in tilted position. Value is degrees of tilting. Positive values represent ground falling down to the left and negative falling down to the right.| | ||
+ | |Tilt left-right|Value of //Tilt left-right// | ||
- | < | + | ====== Body tilting ====== |
+ | <WRAP box right :en 350px> | ||
{{ : | {{ : | ||
<WRAP centeralign> | <WRAP centeralign> | ||
</ | </ | ||
+ | Body tilting provides support to adjust animations of actors to better fit them to uneven ground. Body tilting require # | ||
The results are weighted to get a best matching virtual ground plane. This mode is most expensive but the results are more stable and of higher quality. Once done the tilt result can be applied to animator instance controlls as any other locomotion state. | The results are weighted to get a best matching virtual ground plane. This mode is most expensive but the results are more stable and of higher quality. Once done the tilt result can be applied to animator instance controlls as any other locomotion state. | ||
< | < | ||
- | // set up locomotion body tilt for an actor using the weighted method | + | func void init() |
- | locomotion.setTiltMode( Locomotion.TILT_WEIGHTED ) | + | |
- | + | locomotion.setTiltMode( Locomotion.TILT_WEIGHTED ) | |
- | // create collision filter shared by all tests | + | |
- | var LayerMask category = LayerMask.new() | + | // create collision filter shared by all tests |
- | category.setBit( GameState.CL_AI ) // we are an collider for doing actor ai | + | var LayerMask category = LayerMask.new() |
- | + | category.setBit( GameState.CL_AI ) // we are an collider for doing actor ai | |
- | var LayerMask filter = LayerMask.new() | + | |
- | filter.setBit( GameState.CL_GEOMETRY ) // we can hit geometry like the ground | + | var LayerMask filter = LayerMask.new() |
- | filter.setBit( GameState.CL_AI ) // we can hit other actor ai colliders | + | filter.setBit( GameState.CL_GEOMETRY ) // we can hit geometry like the ground |
- | + | filter.setBit( GameState.CL_AI ) // we can hit other actor ai colliders | |
- | var CollisionFilter collisionFilter = CollisionFilter.new( category, filter ) | + | |
- | + | var CollisionFilter collisionFilter = CollisionFilter.new( category, filter ) | |
- | // set collision test. the test points are located above the ground since otherwise tilting up can not | + | |
- | // be detected. as a rule of thumb the test distance should be two times the start height. for each | + | // set collision test. the test points are located above the ground since otherwise tilting up can not |
- | // test a ray test is used. this is the fastest solution and works well for most situations. | + | // be detected. as a rule of thumb the test distance should be two times the start height. for each |
- | var float offset = 0.5 // height above ground to start testing | + | // test a ray test is used. this is the fastest solution and works well for most situations. |
- | var Vector testDistance = Vector.new( 0.0, -offset * 2.0, 0.0 ) // distance to test downwards | + | var float offset = 0.5 // height above ground to start testing |
- | + | var Vector testDistance = Vector.new( 0.0, -offset * 2.0, 0.0 ) // distance to test downwards | |
- | locomotion.setCCTTiltFrontLeft( ColliderCollisionTest.new( touchSensor, | + | |
- | collisionFilter, | + | locomotion.setCCTTiltFrontLeft( ColliderCollisionTest.new( touchSensor, |
- | + | collisionFilter, | |
- | locomotion.setCCTTiltFrontRight( ColliderCollisionTest.new( touchSensor, | + | locomotion.setCCTTiltFrontRight( ColliderCollisionTest.new( touchSensor, |
- | collisionFilter, | + | collisionFilter, |
- | + | locomotion.setCCTTiltBackLeft( ColliderCollisionTest.new( touchSensor, | |
- | locomotion.setCCTTiltBackLeft( ColliderCollisionTest.new( touchSensor, | + | collisionFilter, |
- | collisionFilter, | + | locomotion.setCCTTiltBackRight( ColliderCollisionTest.new( touchSensor, |
- | + | collisionFilter, | |
- | locomotion.setCCTTiltBackRight( ColliderCollisionTest.new( touchSensor, | + | |
- | collisionFilter, | + | // add mappings so our animator uses the calculated values |
- | + | locomotion.addControllerMaping( controllerTiltOffset, | |
- | // add mappings so our animator uses the calculated values | + | locomotion.addControllerMaping( controllerTiltUpDown, |
- | locomotion.addControllerMaping( controllerTiltOffset, | + | locomotion.addControllerMaping( controllerTiltLeftRight, |
- | locomotion.addControllerMaping( controllerTiltUpDown, | + | end |
- | locomotion.addControllerMaping( controllerTiltLeftRight, | + | |
// tilt is enabled so during Element.postThink the tilt is updated automatically and the result | // tilt is enabled so during Element.postThink the tilt is updated automatically and the result | ||
// applied to animator instance controllers | // applied to animator instance controllers | ||
- | locomotion.updatePostLocomotion( | + | func void postThink( float elapsedFrameTime ) |
+ | | ||
+ | end | ||
</ | </ | ||
====== State control and frame update ====== | ====== State control and frame update ====== | ||
- | To update the locomomotion multiple calls are used. After the player has provided input the [[http:// | + | To update the locomomotion multiple calls are used. After the player has provided input the # |
If you want to enhance the locomotion class you have to be careful about the calling structure. The native classes methods call themselves internally for performance reasons. The entire late binding is skipped. Overwriting the update calls has no effect in this case. To partially change behavior you have to implement the updateLocomotion() and updatePostLocomotion() calls yourself and call the native methods from the script. This allows to inject your changes in the right place. This all works since it is no problem to call a method from script if it is a native class but the native class. | If you want to enhance the locomotion class you have to be careful about the calling structure. The native classes methods call themselves internally for performance reasons. The entire late binding is skipped. Overwriting the update calls has no effect in this case. To partially change behavior you have to implement the updateLocomotion() and updatePostLocomotion() calls yourself and call the native methods from the script. This allows to inject your changes in the right place. This all works since it is no problem to call a method from script if it is a native class but the native class. | ||
====== Player Input Tracker ====== | ====== Player Input Tracker ====== | ||
- | To help with managing the player input for use with locomotions the DragonScript module provides a helper class [[http:// | + | To help with managing the player input for use with locomotions the DragonScript module provides a helper class # |
+ | The //Player Input Tracker// supports all three mentioned locomotion types and has similar // | ||
+ | < | ||
+ | // create an input tracker and set parameters | ||
+ | func void init() | ||
+ | tracker.setSpeedLookLeftRight( 45.0 ) // degrees per second | ||
+ | tracker.setSpeedLookUpDown( 45.0 ) // degrees per second | ||
+ | tracker.setSpeedTurnLeftRight( 30.0 ) // degrees per second. for vehicle type locomotion | ||
+ | tracker.setCanTurn( true ) // player turning commands are used | ||
+ | tracker.setCanMove( true ) // player movement commands are used | ||
+ | tracker.setCanChangeStance( true ) // player stance change commands are used | ||
+ | tracker.setSpeedWalk( 3.0 ) // meters per second. you can set backward speed individually | ||
+ | tracker.setSpeedRun( 8.0 ) // meters per second. you can set backward speed individually | ||
+ | end | ||
+ | |||
+ | // in reaction to player input commands alter state | ||
+ | func void playerPressForward() | ||
+ | tracker.setMoveForward( true ) // button press (true), button release (false). | ||
+ | end | ||
+ | |||
+ | func void playerMoveMouse( Point mouseMovement ) | ||
+ | // mouse movement during this frame update for natural and fps locomotion | ||
+ | tracker.setAnalogLookLeftRight( mouseMovement.getX() ) | ||
+ | tracker.setAnalogLookUpDown mouseMovement.getY() ) | ||
+ | end | ||
+ | |||
+ | func void playerPressTurnVehicle() | ||
+ | tracker.setTurnLeft( true ) // turning for vehicle type locomotion | ||
+ | end | ||
+ | |||
+ | // then during each Element.think() call let the tracker update the locomotion | ||
+ | func void think( float elapsedFrameTime ) | ||
+ | tracker.updateLocomotion( locomotion, elapsedFrameTime ) | ||
+ | end | ||
+ | </ |