Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revisionBoth sides next revision
quick:program [2018/05/18 21:22] pedroquick:program [2018/05/18 21:27] pedro
Line 104: Line 104:
 - Create a new node in the canvas for the `ShootOnce` action. Note the action parameters in the inspector and, specifically, the default value for the `velocity` parameter. - Create a new node in the canvas for the `ShootOnce` action. Note the action parameters in the inspector and, specifically, the default value for the `velocity` parameter.
  
-    ![Our action in the Collection, and its parameters in the inspector](images/ProgrammersQuickStartGuide/FirstActionInTheCollection.png "Our action in the Collection, and its parameters in the inspector")+{{ :images:program:FirstActionInTheCollection.png }}
  
 - We want the shooting parameters to be available in the inspector of those game objects that use the behavior. Select _blackboard_ for all the three input parameters, and create a new field for each one. Use the default names except for `velocity`, where something like `bulletVelocity` is preferred to avoid confusion. - We want the shooting parameters to be available in the inspector of those game objects that use the behavior. Select _blackboard_ for all the three input parameters, and create a new field for each one. Use the default names except for `velocity`, where something like `bulletVelocity` is preferred to avoid confusion.
 - The `velocity` default value has vanished. Keep in mind that it is only used when the parameter is set _using a constant_ in the editor. When using a blackboard parameter, the default value specified in the code attribute is discarded. Fortunately, we can still provide a default value in the behavior. In the `Blackboard` tab see the blackboard parameters just created, and since `bulletVelocity` has a primitive type, you can provide the 30 again. - The `velocity` default value has vanished. Keep in mind that it is only used when the parameter is set _using a constant_ in the editor. When using a blackboard parameter, the default value specified in the code attribute is discarded. Fortunately, we can still provide a default value in the behavior. In the `Blackboard` tab see the blackboard parameters just created, and since `bulletVelocity` has a primitive type, you can provide the 30 again.
  
-    ![`ShootOnce` blackboard parameters](images/ProgrammersQuickStartGuide/ShootOnceBlackboardParameters.png "ShootOnce blackboard parameters")+{{ :images:program:ShootOnceBlackboardParameters.png }}
  
 - Connect the priority selector and the `ShootOnce` action so that shooting is the first child to be considered (higher priority). - Connect the priority selector and the `ShootOnce` action so that shooting is the first child to be considered (higher priority).
 - Right click on the default guard `AlwaysTrue` of the `ShootOnce` node, select `Replace with ...` and choose `Perception/IsTargetClose` from the condition list. Configure the condition with the `Player` as `target`, and 7 as `closeDistance`. As you might remember, the condition for the `MoveToGameObject` action (pursue the player) is exactly the same but the `closeDistance` is set to 15. - Right click on the default guard `AlwaysTrue` of the `ShootOnce` node, select `Replace with ...` and choose `Perception/IsTargetClose` from the condition list. Configure the condition with the `Player` as `target`, and 7 as `closeDistance`. As you might remember, the condition for the `MoveToGameObject` action (pursue the player) is exactly the same but the `closeDistance` is set to 15.
  
-    ![Complete behavior using the `ShootOnce` action](images/ProgrammersQuickStartGuide/BBUsingShootOnce.png "Complete behavior using the ShootOnce action")+{{ :images:program:BBUsingShootOnce.png }}
  
 - Close the editor. We will now create the bullet prefab that will be cloned each time the enemy shoots: - Close the editor. We will now create the bullet prefab that will be cloned each time the enemy shoots:
Line 120: Line 120:
     - Change the scale to (0.3, 0.3, 0.3) and the rotation to (90, 0, 0) so it will lay horizontally.     - Change the scale to (0.3, 0.3, 0.3) and the rotation to (90, 0, 0) so it will lay horizontally.
     - Add it a new C# script and change the `Start()` method so the bullet autodestroys itself after two seconds:     - Add it a new C# script and change the `Start()` method so the bullet autodestroys itself after two seconds:
 +    - Drag and drop the `Bullet` into the Project panel so a new prefab is created based on it, and remove the game object.
  
 <code csharp> <code csharp>
Line 127: Line 128:
 </code> </code>
  
- 
-    - Drag and drop the `Bullet` into the Project panel so a new prefab is created based on it, and remove the game object. 
  
 - Now we must create the shooting point. We will create a child node in the `Enemy` game object, that will be placed in the middle of his front face. When the enemy moves, so do the shooting point. - Now we must create the shooting point. We will create a child node in the `Enemy` game object, that will be placed in the middle of his front face. When the enemy moves, so do the shooting point.
Line 181: Line 180:
 Although our action just shoots a bullet, if you have played the scene you will have noticed that the enemy shoots a high-frequency stream of bullets. Although our action just shoots a bullet, if you have played the scene you will have noticed that the enemy shoots a high-frequency stream of bullets.
  
-![Final behavior using the `ShootOnce` action](images/ProgrammersQuickStartGuide/ShootOnceFinalyBT.png "Final behavior using the ShootOnce action")+{{ :images:program:ShootOnceFinalyBT.png }}
  
 Our `ShootOnce` action ends immediately after instantiating the bullet. That causes _the end of the parent_ priority selector. Fortunately, the root node is a `Repeat` that relaunches the behavior again in the next game loop. Usually, the condition that determines whether the player is near enough to be shot will still be true and the enemy shoots again, repeating the complete cycle. The bullet stream becomes maximum, because the enemy is shooting as fast as possible. Our `ShootOnce` action ends immediately after instantiating the bullet. That causes _the end of the parent_ priority selector. Fortunately, the root node is a `Repeat` that relaunches the behavior again in the next game loop. Usually, the condition that determines whether the player is near enough to be shot will still be true and the enemy shoots again, repeating the complete cycle. The bullet stream becomes maximum, because the enemy is shooting as fast as possible.
Line 383: Line 382:
  
  
-    The `lightIntensity` calculation looks quite tricky. It uses the math `sin` function that cycles between -1.0 and 1.0 depending on the parameter. We must scale the parameter so that cycle corresponds with our day duration. We must also adjust the resulting value to convert the [-1.0, 1.0] interval of the `sin` function to [0.0, 1.0] as the subsequent `Lerp` (linear interpolation) requires.+The `lightIntensity` calculation looks quite tricky. It uses the math `sin` function that cycles between -1.0 and 1.0 depending on the parameter. We must scale the parameter so that cycle corresponds with our day duration. We must also adjust the resulting value to convert the [-1.0, 1.0] interval of the `sin` function to [0.0, 1.0] as the subsequent `Lerp` (linear interpolation) requires.
  
 - Select the `Directional light` again, and label it with a new tag called `MainLight`. The condition will look for the light by that tag. Please note that a real game will had a better thought out implementation, using some kind of game state manager, for example. But, for shortness sake, we will get along with this one. - Select the `Directional light` again, and label it with a new tag called `MainLight`. The condition will look for the light by that tag. Please note that a real game will had a better thought out implementation, using some kind of game state manager, for example. But, for shortness sake, we will get along with this one.
  
-![Adding the `MainLight` tag](images/ProgrammersQuickStartGuide/AddTag.png "Adding the MainLight tag")+{{ :images:program:AddTag.png }}
  
 In Behavior Bricks, conditions are implemented creating a new subclass of `ConditionBase` of the `Pada1.BBCore.Framework` package. It is essentially equal to the known `BasePrimitiveAction` with the exception of some key points: In Behavior Bricks, conditions are implemented creating a new subclass of `ConditionBase` of the `Pada1.BBCore.Framework` package. It is essentially equal to the known `BasePrimitiveAction` with the exception of some key points:
Line 435: Line 434:
 - Set the condition for this new branch to `IsNightCondition`. As soon as night arrives, the condition will be true and the `SleepForever` action, with higher priority, will be chosen. - Set the condition for this new branch to `IsNightCondition`. As soon as night arrives, the condition will be true and the `SleepForever` action, with higher priority, will be chosen.
  
-    ![Final enemy behavior](images/ProgrammersQuickStartGuide/FinalEnemyBehavior.png "Final enemy behavior")+{{ :images:program:FinalEnemyBehavior.png }}
  
 - Play the scene. Note that the enemy stops whatever was doing when the light is nearly off. - Play the scene. Note that the enemy stops whatever was doing when the light is nearly off.
Line 450: Line 449:
 But when a condition is used in a priority selector or a guard decorator, something unpleasant occurs: the execution engine could need to continually call to its `Check()` method to monitor its state. That will happen with higher priority conditions that are currently false, or with the first condition that is currently true. In our example, imagine the light is on (it is daytime), and the enemy is near enough to the player, so it is shooting at him. The state is summarized in the figure, where the `Shoot` action is highlighted as the current action. But when a condition is used in a priority selector or a guard decorator, something unpleasant occurs: the execution engine could need to continually call to its `Check()` method to monitor its state. That will happen with higher priority conditions that are currently false, or with the first condition that is currently true. In our example, imagine the light is on (it is daytime), and the enemy is near enough to the player, so it is shooting at him. The state is summarized in the figure, where the `Shoot` action is highlighted as the current action.
  
-![Execution state example](images/ProgrammersQuickStartGuide/PriroityExecutionExample.png "Execution state example")+{{ :images:program:PriroityExecutionExample.png }}
  
 In this situation, the execution state must guarantee _each cycle_ that the night has not yet fallen (`A` condition is still false) _and_ the player is still near enough to be shot (`B` condition is still true). As far as we currently know, that requires the execution engine to invoke `Check()` in both conditions. In general, if a priority selector is executing its n-th child, then _n_ conditions must be checked. When night has fallen, our `SleepForever` does not require CPU at all; but the `IsNightCondition` is checked every frame in order to know if the sleeping `SleepForever` should be still used. In this situation, the execution state must guarantee _each cycle_ that the night has not yet fallen (`A` condition is still false) _and_ the player is still near enough to be shot (`B` condition is still true). As far as we currently know, that requires the execution engine to invoke `Check()` in both conditions. In general, if a priority selector is executing its n-th child, then _n_ conditions must be checked. When night has fallen, our `SleepForever` does not require CPU at all; but the `IsNightCondition` is checked every frame in order to know if the sleeping `SleepForever` should be still used.