Tutorial: Behavior
This tutorial tells you how to use Behaviors in QuorumWhat is a Behavior?
A Behavior is a critical GUI component that allows items in the user interface to conduct actions or even respond to user interaction. Most of the classes that use Behaviors are user interface controls, such as Buttons and TextBoxes, which will be 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:
package 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
On the surface, you will see that the 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.
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 a running program. However, not all Behaviors do this. For example, when a Behavior is set to a Button via SetBehavior, Update is never called, while the Run action is called when the Button is pressed. In contrast, if the AddBehavior action is called on an item, Update will be called every frame. We will go over the specifics of each GUI element in their respective tutorials, so don't worry about this difference for now.
- 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 using SetBehavior.
- IsFinished - This action returns a boolean, which states if the Behavior has 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 to 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.Game.Graphics.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
In the main, we will be using a Drawable and and 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'll 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.
Next Tutorial
In the next tutorial, we will discuss Buttons, which describes how to use Buttons.