Chapter 3. Behaviors and Scripting

Up until now, we have shied away from doing much with scripting, but all of that is about to change. Scripting is essential for even the most basic game because user interaction is handled through scripts. We can also give enemies artificial intelligence, trigger animations, and manage scene resources. In this chapter, we will consider the following:

  • Learn the Lua syntax used in ShiVa
  • Cover the basics of the API
  • Add user controls and other scripting into our game
  • Add some cool stuff to our game

Lua syntax

ShiVa3D uses Lua as the basis of its scripting language, StoneScript , so if you have experience with Lua then you will have a leg up on everyone else, but you also have to keep in mind that the Lua APIs and many of the language features are not implemented.

The first thing to know about StoneScript, especially if you have programmed with C-based languages, is that there is no semicolon line termination. StoneScript uses the end-of-line to signify line terminations.

Comments

We'll cover comments first, because it is always handy to document parts of your code that are hard to follow. Of course, you could always refactor code that is hard to understand and make it more self-documenting, but comments can be valuable when used correctly.

In this book, we will always tend toward variable and function names that are descriptive, and we'll break the code into manageable pieces. A good rule of thumb is to have functions perform a single task, that is, creating an enemy, processing user input, and so on. Try to stay away from having one function do something such as, check collisions, get user input, and load a resource—you will have too many reasons to change the code when making modifications and it will be easy to introduce bugs.

To comment a single line, append -- to the line. This can also be used inline with actual code, as shown in the following snippet:

local nRx, nRz = 0, 0 -- Initialize rotation

To comment multiple lines, use --[[comments]], as shown in the following code:

--[[ 
This script controls the loading of the first scene
and the game resources.
]]

Variables

StoneScript is a dynamically typed language meaning that the type of the variable is declared at runtime. We declare variables using the local keyword, as shown in the following code snippet:

local nX = 0
local nY, nZ = 0, 0
local hObject = application.getCurrentUserSceneTaggedObject ( "Ship" )

We can see that in each case, we are not explicitly declaring what kind of variable we want. The first three variables will become numbers and the last will be a handle to an object. The other thing to notice is that on the second line we declared and initialized two variables using the comma operator. Lua also doesn't care if we change the type of a variable on the fly, as done with the hObject variable in the following code:

hObject = 3

Remember that we previously assigned a handle to an object to hObject, but now we have assigned a number. Because variable types can be a bit ambiguous, ShiVa3D community developers follow a naming convention for variables because it makes code easier to follow. You can find this information at http://www.stonetrip.com/developer/doc/api/introduction#_Toc275785466. We use a prefix to declare what we intend to use the variable for.

The prefixes used—along with their description and an example of each—are explained are follows:

  • h: Handle to an object, for example, hShip = this.getObject()
  • n: Numerical value, for example, nRx = 7
  • b: Boolean value (true or false), for example, bRotating = true
  • s: String value, for example, sTitle = "Commander"
  • v: Mutable variable—if you really need to use one variable for multiple types, for example, vWhoKnows
  • t: Tables, for example, tMonsterLocations
  • ht: Hash tables, for example, htUserPasswords
  • k: StoneScript constants, for example, object.kGlobalSpace
  • xml: XML data, for example, xmlGameSettings

Is it mandatory to use these prefixes and will our code run differently if we do? No to both questions, but it will make your code easier to read, especially if you need to post it to the forum when you have questions.

For objects, Lua uses nil as the keyword to mean no value; it is similar to null in C.

Functions

In ShiVa, functions are declared in the user interface, which we will go over later, but for now we will take a look at the syntax of defining a function and how a function is subsequently called. In ShiVa, functions can be standalone, or an event handler, with the major difference being in how they are called. We call functions directly in our code, whereas event handlers are called in response to an event. The event can be generated automatically in response to user input or some other game mechanic, or we can generate the event in our code. We will talk more about event handlers later in the chapter when we add user interaction, but for now let's look at functions.

Functions are defined by the function keyword, followed by the name of the function, and finally the function arguments in parentheses, as shown in the following code:

function ShipAI.onKeyboardKeyUp ( kKeyCode )
…
end

Multiple arguments are separated by commas. Note that there is no need to declare the function return type or the types of the arguments. The function is closed by an end statement. If the function had return values, we would simply use the return keyword to return as many values as needed, separated by commas, as seen in the following code:

function ShipAI.returnsManyValues ( )
  return x, y, z
end

To call a function, we simply enter the function name followed by parentheses surrounding any arguments being passed. As we begin scripting our game behavior, we will see another aspect of functions within ShiVa that affect how they are called—we precede the function name with the AI module that contains it, but since we can only call a function from within the AI that owns the function, we use the this keyword. All of our function calls end up looking like the following line of code:

this.GoVertical ( true )

Flow control

Flow control does exactly what it sounds like—it controls the flow of our scripts. There are several different kinds of flow control from simple if statements to complex loops. Let's take a look at what we can do.

If statements

This is the bread and butter of programming. We use a Boolean expression to determine which block of code gets executed. The basic statement is as follows:

if(boolean expression) then
   Statements
   …
end

And the else version is as follows:

if(boolean expression) then
   statements
   …
else
   statements
   …
end

ShiVa also has a specific form for elseif, shown as follows:

if(boolean expression) then
   statements
   …
elseif(boolean expression) then
   statements
   …
else
   statements
   …
end

The hard part for me has been remembering to use then and end. So don't forget those!

The return and the break keywords

The return keyword is part of the flow control statements, because it can return program flow from a function. In ShiVa, the return keyword can return up to thirty-two arguments. The following line of code returns multiple arguments:

return "hello", 3, 5.3, "time"

To use these return values, you need to specify a range of values in the assignment expression. If we had a function that returned a set of x, y, and z coordinates, then the assignment would look like the following line of code:

local nCurrentX, nCurrentY, nCurrentZ = object.getTranslation ( this.hShip ( ), object.kGlobalSpace )

The three return values will be assigned to the variables that we have specified. If we don't provide enough variables, the extra return values are simply discarded, but if all you need are the middle or end values, such as the z coordinate, you will have to provide variables for the x and y coordinates even if you only plan to ignore them.

The break keyword, on the other hand, simply exits the current loop without returning a value.

The for loop

ShiVa's for loop is a bit different from C-based languages; it is shown in the following code snippet:

for i = from, to
do
   statements
   ...
end

This version sets the increment to one by default, while the following version declares the increment to be two:

for i = from, to, step
do
   statements
   ...
end

The while loop

The while loop provides the usual loop mechanism that checks a condition before looping; its syntax (parentheses are optional) is as follows:

while(boolean expression)
do
   statements
   …
end

The repeat loop

The repeat loop is similar to the while loop, but performs a loop before checking a condition; its syntax is as follows:

repeat
   statements
   …
until (boolean expression)

As with the while loop, the parentheses are optional.

Operators

ShiVa uses all the same operators that you would expect; these operators are as follows:

  • Greater than: >
  • Lesser than: <
  • Greater or equal: >=
  • Lesser or equal: <=
  • Equals: ==
  • Not equal: ~=
  • Addition: +
  • Subtraction: -
  • Multiplication: *
  • Division: /
  • String concatenation: ..
  • And operator: and
  • Or operator: or
  • Parentheses

When dealing with objects, the comparison is done using the isEqualTo() method, for example, object.isEqualTo(hObject1, hObject2).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.12.34