What is a Behavior?
A Behavior is a critical GUI component that allows for items in the user interface to conduct actions or even respond to user interaction. The classes that use Behaviors the most are the user interface controls, like Buttons, TextBoxes, or others covered in the following tutorials. Together, these classes provide a way to efficiently route user input throughout the system.
This is what the Behavior class in Quorum looks like:
On the surface, you will see that Behavior class does not do anything itself. This is because it is heavily subclassed for specific actions. For more information on inheritance and overriding actions, see the tutorial on Inheritance.
pakage Libraries.Interface.Behaviors use Libraries.Interface.Events.BehaviorEvent class Behavior action Run(BehaviorEvent event) end action Update(number seconds) end action Dispose end action IsFinished returns boolean return false end end
Lets run through the four actions in a Behavior:
- Run - Run is called when an action is taken with the Behavior. For example, If a Button is clicked in the user interface, then Run would be called.
- Update - A Behavior can also be set to Update on every frame of running program. However, not all Behaviors do this. For example, Update is never called on a Button's default behavior, only the Run action is. In contrast, if the AddBehavior action is called on an item, Update would be called every frame.
- Dispose - This action does nothing by default, but it can be overridden for cleanup actions when the Behavior is finished. Note that, like the Update action, Dispose is only called if the Behavior is added through AddBehavior, not if it is set as a default Behavior.
- IsFinished - This action states if the Behavior completed its work.
For this tutorial, we will first create a simple Behavior that outputs and says text. To start, create a new Game Application project.Note: We will use the Drawable and Speech classes in this tutorial. For more information on using Drawables, check out the tutorial on Drawing in 2D, and for more information on Speech, see the documentation on the Speech class.
Outputting with a Behavior
To create our own Behavior, we will create a new Quorum Class, which we will name "OutputBehavior.quorum." This class will use the libraries for Behavior, BehaviorEvent, and Speech. The class itself will override the Behavior's Run action to output and say the desired text. This gives the following OutputBehavior class:
use Libraries.Interface.Behaviors.Behavior use Libraries.Interface.Events.BehaviorEvent use Libraries.Sound.Speech class OutputBehavior is Behavior action Run(BehaviorEvent event) Speech speech speech:Say("Hello world!", false) output "Hello world!" end end
We now have our completed OutputBehavior class, but nothing will happen yet because it has to be added an object for the Behavior to run. To do so, we will make a Drawable and use it so our behavior can run. Return to the main class and in the CreateGame action we will make a Drawable and add our Behavior to it.
The complete main class will be as follows:
use Libraries.Game.Game use Libraries.Interface.Drawable class Main is Game action Main StartGame() end action CreateGame Drawable box OutputBehavior behavior box:AddBehavior(behavior) end end
If we run the program now, nothing will be in the game window, but "Hello World!" will output to the console and you will hear the program say "Hello World."
This was a simple Behavior that only needed to override the Run action, but most Behaviors will perform more complex actions and may need to override all 4 of a Behavior's actions. For a deeper look into Behaviors, in the next section of this tutorial we will rotate a drawable for 5 seconds and change its color using Behaviors.
Rotation with a Behavior
Creating a New Behavior
To begin, we will create a new Quorum class, which we will name "RotationBehavior.quorum".In addition to the Behavior and BehaviorEvent libraries needed to make a behavior, we will be using the Color, Drawable, and Speech libraries.
The RotationBehavior class will inherit the Behavior class, and we will override the actions for Run, Update, Dispose, and IsFinished. Additionally, we need to create a Drawable class variable to store our rectangle for use in all actions, and we must also create a timer so that we can make our Behavior last for five seconds, giving the following template:
use Libraries.Interface.Behaviors.Behavior use Libraries.Interface.Events.BehaviorEvent use Libraries.Game.Graphics.Color use Libraries.Game.Graphics.Drawable use Libraries.Sound.Speech class RotationBehavior is Behavior Drawable rectangle = undefined number timer = 0 action Run(BehaviorEvent event) end action Update(number seconds) end action Dispose end action IsFinished returns boolean end end
In the Run action, we must first obtain the Drawable we want to rotate. Since the RotationBehavior will later be added to the Drawable itself in the main class, we can use the BehaviorEvent's GetItem action to get the object associated with the Behavior. However, this action returns an Item, not a Drawable, so we must cast it. This gives us the following line:
rectangle = cast(Drawable, event:GetItem())
Next, for the program to say "Rotate," we will need to use the Speech class's Say action, giving us the following lines:
Speech speech speech:Say("Rotate")
This gives the following complete Run action:
action Run(BehaviorEvent event) rectangle = cast(Drawable, event:GetItem()) Speech speech speech:Say("Rotate") end
Moving on to the Update action, we want our rectangle to rotate, and we want to keep track of the time elapsed. Therefore, we need to increment the timer and call the Drawable's Rotate action. Since the Update action will be used for five seconds, a rotation of 72 degrees per second will result in a full 360 degrees rotation, giving us the following Update action:
action Update(number seconds) timer = timer + seconds if rectangle not= undefined rectangle:Rotate(72 * seconds) end end
Note that the conditional if-statement checks if the "rectangle" variable is defined. If we did not include this, then the program could potentially crash by attempting to rotate an object that does not exist.
In the Dispose action, we want our rectangle to change color to indicate that the Behavior is finished. As such, we need to create a Color variable and call the Drawable's SetColor action. Lastly, for the program to say "Rotation complete," we will once again need to use the Speech class's Say action. This gives the following Dispose action:
action Dispose if rectangle not= undefined Color color rectangle:SetColor(color:Green()) Speech speech speech:Say("Rotation complete") end end
With this, once the Behavior is finished, the rectangle will change from Red to Green, and the program will say "Rotation complete."
In the IsFinished action, we need to set the action to return true once five seconds have passed. Thus, we simply add the line "return timer >= 5" to get the following action:
action IsFinished returns boolean return timer >= 5 end
Altogether, the resulting RotationBehavior class looks like this:
use Libraries.Interface.Behaviors.Behavior use Libraries.Interface.Events.BehaviorEvent use Libraries.Game.Graphics.Color use Libraries.Game.Graphics.Drawable use Libraries.Sound.Speech class RotationBehavior is Behavior Drawable rectangle number timer = 0 action Run(BehaviorEvent event) rectangle = cast(Drawable, event:GetItem()) Speech speech speech:Say("Rotate", false) end action Update(number seconds) timer = timer + seconds if rectangle not= undefined rectangle:Rotate(72 * seconds) end end action Dispose if rectangle not= undefined Color color rectangle:SetColor(color:Green()) Speech speech speech:Say("Rotation complete", false) end end action IsFinished returns boolean return timer >= 5 end end
Setting up Main
We will be using a Drawable and we will be altering its Color, so we must include the Drawable and Color libraries.
First, we will create a Drawable object and a Color object. For the purposes of this tutorial, we want the Drawable to use its Behavior as soon as the game begins, so we'll add it to the game in the CreateGame action.
Next, let's load a rectangle shape using the Drawable's LoadFilledRectangle action. We are going to make it red for this tutorial. Then, we give it a position with the SetPosition action. Finally, we'll add it to the game using "Add(box)".
Lastly, we must return to the main class and give a RotationBehavior to our Drawable. At the end of the CreateGame action, this can be done creating a RotationBehavior variable and calling the Drawable's AddBehavior action, giving us the following lines:
RotationBehavior rotate box:AddBehavior(rotate)
The resulting final version of the Main class is as follows:
use Libraries.Game.Game use Libraries.Game.Graphics.Drawable use Libraries.Game.Graphics.Color class Main is Game action Main StartGame() end action CreateGame Drawable box Color color box:LoadFilledRectangle(300, 200, color:Red()) box:SetPosition(250, 250) Add(box) RotationBehavior rotate box:AddBehavior(rotate) end action Update(number seconds) end end
Now, when the program is run, the rectangle will start as red, the program will say "Rotate," the rectangle will make one full rotation over five seconds, and then turn green while the program says "Rotation complete." The following images show a sample of the beginning, middle, and end of the Behavior's execution.
In the next tutorial, we will discuss Buttons, which describes how to use Buttons.