You’ll often read Lingo properties to obtain information about the user or the run-time environment and set properties to affect the run-time environment. You’ll use variables as containers to store and manipulate any type of data, including Lingo properties. Later we’ll see how you can define your own properties using so-called property variables, which are a particular type of variable but are unrelated to Director’s built-in properties.
Lingo defines dozens of properties (not to be confused with programmer-defined property variables, discussed later), which are always preceded by the keyword
If you omit the word
the, Lingo thinks you are referring to a programmer-defined variable, not a Lingo property.
A property may pertain to the overall system, the current movie or MIAW, a cast member, or a sprite. Lingo properties are universally accessible (they can be used from any script at any time), and they may be static (fixed) or may change over time or based on user actions. For example,
the platform property doesn’t change unless you switch computers, but
the mouseH and
the mouseV properties change whenever the cursor moves.
value is replaced with a meaningful value,
property is a property name and
object is usually a sprite, member, or window reference. The following examples set
the locH of sprite sprite property,
the regPoint of member member property, and
the soundEnabled system property. Note that all three properties start with
the, although no
object is specified for
the soundEnabled property because it is a system property, not a property of a sprite or a cast member.
set the locH of sprite 1 = 17 set the regPoint of member 1 = point(0,0) set the soundEnabled = TRUE
The general format for reading a Lingo property is:
object} such as: set
spritePosition= the locH of sprite 1 set
memberDepth= the depth of member 1 set
mousePosition= the mouseH
Some Lingo keywords are constants (fixed values) that don’t use the word
the, such as PI, TAB, and SPACE. See Table 5-6.
The following are common errors when using properties. Refer also to "Common Errors When Using Variables" later in this chapter.
The following sets stage white by setting
the stageColor property to zero:
set the stageColor = 0
However the following defines a local variable,
stageColor, and assigns it the value zero, which is probably not the desired goal.
set stageColor = 0
Using a property without the preceding
the will cause a "Variable used before assigned a value" error, such as:
if mouseV > 50 then put "The mouseV is greater than 50"
(This won’t fail in the Message window, but it will fail from within a script).
mouseH is a local variable, whereas
the mouseH is a Lingo property. As the mouse continues to move, the property
the mouseH will change, but the variable
mouseH won’t change without your explicit instruction.
set mouseH = the mouseH
set lastMouseH = the mouseH
Some keywords are reserved constants (see Table 5-6) that never change in value, even if you inadvertently try to assign a new value to them. For example, you cannot change the value of
set pi = 54.36 put pi -- 3.1416
Many properties can be both set and read, but some can be only read. The "Cannot set this property" error may result if you attempt to set a property that is read-only, such as
the mouseH. Other properties may appear to be settable, but setting them may have no effect. For example, setting
the colorDepth under Windows, or to an invalid value on the Macintosh, will leave the monitor depth unchanged, although no error results.
Many Lingo properties change based on conditions beyond the programmer’s control. For example,
the shiftDown property changes whenever the user presses or releases the
Shift key, and it may even change during the execution of, say, your
on keyDown handler. If necessary, store the current value of a property in a variable (see details that follow), such as:
shiftKeyState= the shiftDown
There is a single Lingo global variable (global variables are explained later) named
version that returns Director’s version number (as a string) and can not be set nor cleared with
clearGlobals. Do not use the name “version” as a variable name.
version as follows:
on testVersion global version put "The current version is" && version end testVersion testVersion -- "The current version is 6.5"
Director also supports the property
the productVersion, which doesn’t require a
global declaration (although the two methods return different values in Shockwave).
put the productVersion -- "6.5"
A variable is a container for any type of data (such as an integer or a string) that usually stores values that may change or are not known until runtime. You are the master of your own variables. You can create as many as you need and give them whatever names you like. For example, you might store the user’s name and his high score in separate variables named
Variables are not the algebraic “unknowns” that gave you nightmares in school. They are just convenient placeholders that allow your scripts to be flexible. Variables, unlike built-in Lingo properties, change only at your behest.
Once you’ve stored a value in a variable (see the next section) you can obtain that value simply by referring to the variable by name. See "Data Types and Variable Types,” "Type Assignment and Conversion,” and "Constants and Symbols" in Chapter 5 for more details on variables.
item is a variable name, property (such as
the colorDepth), or a field reference (such as
I strongly recommend the first form (
set item = value) because it clearly delineates the variable or property on the left side of the expression from the value being assigned to it on the right side of the expression. For example:
set x = 5 set x = char 1 to 5 of "hello there" set the soundEnabled = TRUE set the loc of sprite 5 = point (50, 200)
I mention the other forms so that you will understand examples that make use of them, although I find these equivalent expressions harder to decipher:
put 5 into x set x to char 1 to 5 of "hello there" put TRUE into the soundEnabled set the loc of sprite 5 to point (50, 200)
You must use the
put...into form when replacing part of a string:
set x = "helloWorld" put "H" into char 1 of x
These won’t work:
set char 1 of x = "H" set field 4 = "Some String"
But these will work:
set the text of field 4 = "Some String" put "Some String" into field 4
put 5 into x -- assigns the value 5 to the variable x put x -- prints the value of x in the message window -- 5
to is also used in chunk expressions, such as
char 1 to 5 of someString. In the example below, the first
to is used to perform the assignment, but the second
to is used to indicate a range of characters.
set x to char 1 to 5 of "hello there"
The equals sign (=) is used for both assignment and comparison. Don’t confuse the two uses. In C, the single equals sign is used only for assignment, and the double equals sign (==) is used for comparison (see the online Chapter 20, Lingo for C Programmers, downloadable from http://www.zeusprod.com/nutshell/chapters/lingoforc.html).
set x = 5 -- assigns the value 5 to the variable X if (x = 5) then put "Yeah" -- Compares x to the value 5
The equals sign assigns a value to an item; it does not indicate an algebraic equality. In algebra, the following would be meaningless because something can never equal one more than itself:
x = x + 1
On the other hand, the following is perfectly legitimate and is used frequently in programming.
set x = x + 1
How is this possible? The right side of the expression always uses the current (old) value for an item. The left side sets the new value for an item. The above example means “Take the current value of the variable
x and add one, and then store the result back into
x again.” So:
set x = 4 set x = x + 1 put x -- 5
An assignment statement is not an algebraic equation to be solved. Only one item can appear on the left side of the following assignment statement:
set x = 5 - y
This is not valid:
set x + y = 5
Although the two statements above may appear algebraically equivalent, they are not programmatically equivalent. The first one says “Subtract the value of
y from 5, and then store the result into the variable
x.” The second one, however, is trying to say “Set
y so that they add up to 5.” This confuses a computer because it wouldn’t know whether to set
x to 4 and
y to 1, or
x to 3 and
y to 2, or one of the infinite number of alternatives.
A variable’s storage class (local, parameter, global, or property) determines its initial value, its scope (by whom it can be accessed), and whether it persists (retains its value) over time. Don’t confuse a variable’s storage class, often called its type, with the data type of its contents. A variable’s data type (integer, string, list, etc.) depends solely on the value assigned to it and is independent of its storage class. See Chapter 5.
There are four main storage classes (although parameters are generally treated as local variables), each of which is created in a different way.
Local variables (or temporary variables) are fleeting; they come into existence when they are first assigned a value, and they disappear at the end of the current handler. Use local variables for temporary needs that are confined to the current handler. To create a local variable, pick an arbitrary name, and assign a value to it. Variables such as
k are commonly used for loops or indices. Variables such as
y are commonly used for coordinates.
In this example,
y are local variables (everything else is a reserved Lingo keyword).
Example 1-9. Using Local Variables
on mouseUp set y = the locV of sprite the currentSpriteNum repeat with i = 1 to 100 set the locV of sprite the currentSpriteNum = y + i updateStage end repeat put i put y showLocals end
Local variables are “private” to the handler in which they are used. The
showLocals command must be used from within the handler for which you wish to display local variables. Likewise, you cannot use
put from the message window to display a local variable.
Local variables are independent of other variables in other handlers that may have the same name. Because they cannot be used until they are assigned a value, local variables have no default value. Using one before assigning it a value results in a "Variable used before assigned a value" error. In this example,
x is an uninitialized local variable and will cause an error.
on mouseUp if x = 5 then go frame 15 end if end
See "Special Treatment of the First Argument Passed" later in this chapter for an explanation of why using an undeclared local variable as the first argument to a function does not generate an error.
Parameters are local variables that automatically receive the value(s) of incoming arguments used in the call to the handler (see "Parameters and Arguments" and "Generalizing Functions" later in this chapter). Parameters are declared (named) on the same line as the handler name.
Example 1-10. Using Parameters
param3-- The && operator assembles the string for output put "The three input parameters are" && [LC]
param3end someFunction 1, "b", 7.5 -- "The three input parameters are 1 b 7.5
Parameters can assume different values each time a handler is called. A different copy of the parameters is created each time the handler is called and disappears when the handler ends. Changes to parameters within a handler generally have no effect outside that handler, but modifying a Lingo list passed as a parameter will modify the original list in the calling routine as well. See Chapter 6, Lists for important additional details. Don’t use the name of a global variable as the name for a parameter or other local variables. See "Common Errors When Using Variables" later in this chapter
Global variables (or simply globals) are declared using the
global keyword, and they persist throughout all movies until your Projector quits. They come into existence when a handler that declares them as
global first runs and can be accessed by any handler that also declares them as
global. Global variables can be displayed in the Message window using
showGlobals (the built-in global variable
version always appears in the list of globals).
showGlobals -- Global Variables -- version = "6.0.2"
Whenever you test or set a variable in the Message window it is treated as a global variable.
set anyVariable = 5 showGlobals -- Global Variables -- version = "6.5" anyVariable = 5
clearGlobals showGlobals -- Global Variables -- version = "6.5"
Globals can be shared by MIAWs and the main movie. Any change to the value of a global variable is reflected everywhere it is used. For clarity, name your globals starting with a “g.” Global variables default to
VOID (they have no value until one is assigned), but they retain their value even when playback stops or a new movie is loaded (unless
clearGlobals is called). Shockwave clears global variables if the browser issues a
Globals are necessary when you want a variable to outlive the handler in which it is used or to send information between two handlers that are not otherwise connected.
In this example,
gTwo are global variables shared by two handlers.
Example 1-11. Using Global Variables
on startMovie global gOne, gTwo set gOne = "Hello" set gTwo = 7 end
This handler can be in a different script than
on mouseUp global gOne, gTwo if gTwo = 7 then put gOne end
Lingo globals are declared, by convention, at the top of a handler immediately under the handler name; declaring globals in the middle of a handler is allowed but discouraged. You can declare more than one global with the
global keyword by separating the variables with commas, as shown above. You can instead use a new line for each global declaration, such as:
global gOne global gTwo
Globals declared outside of a handler (so-called "global" globals) are treated as if they were declared within all subsequent handlers within the same script.
For example, if the two handlers above are in the same script, the
global declarations could be moved outside the handlers themselves and placed at the top of the script:
-- These are "global" globals and can be used-- by all handlers in this script cast member global gOne, gTwo on startMovie set gOne = "Hello" set gTwo = 7 end on mouseUp if gTwo = 7 the put gOne end
Property variables are declared using the
property keyword and persist as long as the object of which they are a property exists. (See Chapter 12, Behaviors and Parent Scripts, if you are not familiar with object-oriented programming, or just ignore this section for now.)
Property variables are programmer-defined and should not be confused with the built-in Lingo properties, although both are attributes of their respective objects.
Built-in Lingo properties are predefined attributes of built-in objects, such as sprites and cast members. Property variables are programmer-defined variables that are used to add attributes to their own objects (namely scripts).
Property variables are instantiated (created) when the parent script or Behavior that declares them is itself instantiated (either by Director or by the programmer). For example, when Director encounters a Behavior attached to a sprite in the Score it instantiates that Behavior and its properties. (This is explained in detail in Chapter 12. For now, just assume that when a Behavior is encountered in the Score, Director assigns appropriate values to any property variables that the Behavior declares.)
Properties can then be accessed by any handler within the same script. Each instance (use or occurrence) of the parent script or Behavior gets its own copy of the property variables that are independent of other copies (despite having the same name), just as all sprites and cast members have independent properties named
Property variables are declared at the top of the parent script or Behavior before the first handler. You can declare multiple property variables, separated by commas, using one
property statement, or you can use separate
property statements for each property variable. Property variables default to
VOID but are usually assigned a value in a parent script’s
new() handler (or in a Behavior’s
getPropertyDescriptionList() handler; see Chapter 12). When a handler inside a parent script or Behavior is called, its private copies of those property values are used, unlike global variables that are shared among all scripts. For clarity, name your properties starting with a “p.”
Property variables must be declared outside of any handlers in the script, as shown in the example below.
In this example,
pTwo are property variables shared by the
showProps handlers, which are both presumed to reside in the same parent script cast member named “ParentScript.”
Example 1-12. Using Property Variables
property pOne, pTwo on new me, a, b set pOne = a set pTwo = b return me end new on showProps me put "pOne is" && pOne put "pTwo is" && pTwo end showProps
To test it in the Message window, first instantiate the parent script by calling the
new() handler. When the programmer instantiates a script, he customarily specifies initial values for the properties by specifying them as arguments to the
new() handler (although some programmers prefer to assign properties as a separate step from instantiating a script). We create one instance using the integer 6 and the string “hello,” for the properties
pTwo. We then create a second instance with different values to be used as
instance1= new (script "ParentScript", 6, "hello") set
instance2= new (script "ParentScript", 9, "goodbye")
We pass an instance created using
instance2). That allows
showProps to determine the correct properties for each instance separately. Note how the results printed by
showProps depend on which instance variable we pass to it.
instance1) -- "pOne is 6" -- "pTwo is hello" showProps (
instance2) -- "pOne is 9" -- "pTwo is goodbye"
Note that inside the script that declares them, property variables are accessed by using their name, as shown in
showProps above. Programmer-defined property variables can also be accessed from outside a script instance using the script instance and the keyword
the, such as:
Property variables belonging to scripts can also be accessed by referencing the script itself rather than an instance of the script, such as:
propertyVariableof (script "myScript")
Although they can also be accessed using the keyword
the, remember that property variables are programmer-defined and are not the built-in Lingo properties that also happen to start with the keyword
Continuing the example above, you can access the properties of
instance2 without using
showProps, instead using:
instance1-- 6 put the
Note that simply typing
put pOne or
put the pOne in the Message window would fail because you must specify the script instance that owns the property. If no script instance is specified, the property name must be a built-in system property, such as:
put the colorDepth -- 8
Refer to Chapter 12, especially if this section left you thoroughly confused.
set the locV of sprite 1 = y
(This won’t fail in the Message window because
y will be treated as global containing the value
VOID, but it will fail from within a script.)
New local variables must first be assigned a value:
set y = 5 set the locV of sprite 1 = y
Global variables can be declared with the
global keyword, without necessarily being assigned a value (we presume the global was assigned a meaningful value elsewhere; if not, it defaults to VOID):
global gLocForSprite set the locV of sprite 1 = gLocForSprite
In the following statement, Director complains about the undeclared local variable
y, which we are attempting to use in the expression although it has not been previously assigned a value. Director does not complain about the new local variable
x, to which we are attempting to assign a value. In other words, the right side of the equation can use only existing variables, but the left side of the equation can be either an existing or a new variable.
Use property variables for attributes that have a different value for each instance of a parent script or Behavior or that must persist for the life of the object. Use global variables when a value must outlive the handler, object, or movie in which it is used or must be accessible to multiple handlers, objects, or movies. Use local variables for values that are used only for convenience within the current handler and then discarded, such as indices in a repeat loop or interim steps in a mathematical calculation. Use parameters to accept inputs that can make a handler more flexible (see "Parameters and Arguments" later in this chapter).
set x = y
Most novices use either too many or too few variables. Use variables whenever you want Director to remember something, such as the results of calculations, user input, lists of items, or anything that you need more than once. Programming is like cooking. You may be able to cook dinner in one pot, or you may need two frying pans and a pressure cooker; it depends on the recipe and your personal style. This example:
on mouseDown if the locH of sprite (the currentSpriteNum) > 50 then put the locH of sprite (the currentSpriteNum) end if end
could be rewritten as:
on mouseDown set myLocH = the locH of sprite (the currentSpriteNum) if myLocH > 50 then put myLocH end if end
Both examples are equivalent, but the second one is somewhat easier to read and maintain because the result of the lengthy expression is stored in
myLocH, which is then used for comparing and displaying the value.
When you assign a variable, it records a snapshot in time. You must recalculate values that are expected to change. The following is wrong because
y never changes after its initial value is assigned:
set y = the mouseV repeat while y > 50 put "The mouseV is greater than 50" end repeat
Instead, check the current value of
the mouseV property repeatedly:
repeat while the mouseV > 50 put "The mouseV is greater than 50" end repeat
the when using a Lingo property name:
mouseV cause a "Variable used before assigned a value" error?
repeat while mouseV > 50 put "The mouseV is greater than 50" end repeat
Compare the above
repeat...while statement to the previous example.
ClearGlobals indiscriminately resets all global variables to
VOID. (In D6, it also sets
the actorList to
.) This will make any Lingo code that relies on global variables or
the actorList lose whatever it had stored in them. This is usually a very bad thing, and it can be hard to track down if you are working with multiple programmers or large projects. Set individual globals to
VOID to clear them separately instead.
The most common error is to declare a variable
global in one handler and forget to declare it
In that case, it is implicitly a separate local variable in the second handler, despite having the same name as a global in the first handler, such as shown in Example 1-13.
Example 1-13. Common Errors with Global Variables
on initGlobal global gMyValue set gMyValue = 27 end initGlobal on readGlobal -- This causes a syntax error put gMyValue end
on readGlobal global gMyValue put gMyValue end
Test it from the Message window:
initGlobal readGlobal -- 27
Here the error is reversed. The programmer forgot to declare
gMyValue as a global in the first handler.
on initGlobal -- gMyValue is treated as a local variable. -- Setting it has no effect outside the handler. set gMyValue = 27 end initGlobal on readGlobal global gMyValue -- The global, also named gMyValue, defaults to VOID put gMyValue end
Test it from the Message window:
initGlobal readGlobal -- Void
It is acceptable, even common, to pass a global as an argument to a function (see "Parameters and Arguments" later in this chapter). In the receiving function, however, you must decide whether you intend to modify the global or merely use the global’s value for a local operation.
In Example 1-14,
gUserTries is a local variable within
gameOver(). The global of the same name in
finishGame will not be incremented.
Example 1-14. Passing Globals Variables as Parameters
on finishGame global gUserTries gameOver (gUserTries) end finishGame on gameOver gUserTries set gUserTries = gUserTries + 1 end gameOver
This can be rewritten in one of two ways. Here,
gUserTries is declared
on gameOver global gUserTries set gUserTries = gUserTries + 1 end gameOver
Alternatively, a local variable can be used and passed back to
on finishGame global gUserTries set gUserTries = gameOver (gUserTries) end finishGame on gameOver inValue return (inValue + 1) end gameOver
Recall that each time a handler is called, any local variables are discarded when the handler finishes. If you want a variable’s value to persist over repeated calls to a handler, you must declare it as a global or property variable. (See Chapter 12 for details on property variables that persist for the life of the object that declares them.)
Example 1-15 counts the number of times that
countMe is called. Don’t forget to reset the global as needed, as shown in
Example 1-15. Persistent Variables
on countMe global gCounter set gCounter = gCounter + 1 put "This handler has been called" && gCounter && "time(s)" end countMe on testCount global gCounter set gCounter = 0 repeat with i = 1 to 10 countMe end repeat end testCount -- This handler has been called 1 time(s) -- This handler has been called 2 time(s) -- etc.
property gCounter on mouseUp me if gCounter > 10 then alert "Are you tired of clicking yet" else set gCounter = gCounter + 1 end if end mouseUp
You may wish to perform some initialization once and only once. You can use a global variable, as shown in Example 1-16, to track whether the initialization has taken place.
Table 1-1 shows the Lingo commands related to variables, including declaration, assignment, instantiation, and deallocation of various variable types.
Table 1-1. Variable-Related Commands
Reserved name for declaring an ancestor property. See Chapter 12.
Obsolete, previously used to instantiate an object. See new
Resets all global variables, except version, to
Declares one or more global variables.
Declares the reserved global version.
list(), , or [:]
Allocates a list. See Chapter 6.
Used to instantiate an XObject. See Chapter 13
Used to deallocate an XObject instance. Chapter 13.
new (xtra "
Creates a child object or Xtra instance.
Indicates the value of the
Indicates the number of parameters received by a handler. Use it to check how many arguments were specified in the function call.
Declares one or more property variables.
Declares an ancestor property. See Chapter 12.
Prints a variable’s value in the Message window.[a]
Assigns a value to a variable. I prefer using the setcommand.
Assigns a value to a variable. See also
Prints all local variables in the current handler. Must be used from within a handler, not from the Message window.
Prints all global variables in the Message window.
Stops a Shockwave movie from within the browser and clears global variables.
Refers to a built-in Lingo property.
Refers to a programmer-defined property variable of a parent script or Behavior.
Refers to properties within a property list. See Chapter 6.
A global variable containing Director’s current version. Use the productVersion property to determine the version without declaring a global.
[a] 1 Use put from within a handler to display the value of any variable (including local variables) within that handler in the Message window. Global variables can be tested using the put command in the Message window iitself. Use the alert command to display the value of variables in a dialog box, especially from within a Projector where the put command has no effect.
Local variables in Director are allocated implicitly (that is, without your explicit instruction) when you assign a value to them. Global and property variables are allocated explicitly using the
property keywords. The amount of memory variables require depends on what is stored in them. Local variables are deallocated automatically when a handler terminates. Properties are deallocated when the object of which they are a property is disposed.
The main concern is objects that you never dispose and global variables (which persist indefinitely) that refer to items that require a lot of memory, such as long lists or strings. Global variables are never truly disposed, but you can reduce the memory they use by assigning them to zero or
VOID. (Avoid using
clearGlobals for this purpose, as it resets all global variables indiscriminately and in D6 it also clears
the actorList.) Objects are disposed by setting all variables that refer to the object to zero or
VOID. See Chapter 12 and Chapter 13. Table 1-2 shows the scope of individual variables of the different data storage classes.
Table 1-2. Data Storage Class Scope
Manner in Which Variable Is Declared
No explicit declaration; variable is implicitly local
Can be used in current handler, but only after it is assigned a value, using set...= or put...into.
Declared as arguments in the handler definition
Implicitly local, but automatically initialized to value of incoming arguments. Same scope as a local variable. See "Parameters and Arguments.”
Assigned a value in Message window
Variables assigned in the Message window are implicitly global. They must still be declared global within scripts that wish to make use of them.
Explicitly declared as a global inside a handler
Variable is global only within handler in which it is declared.
Explicitly declared as a global
Variable is global only within handlers in the same script cast member after the point at which it is declared.
Explicitly declared as a property within a handler
Explicitly declared as a property outside of a handler, at the top of a parent script or Behavior
Property variable is accessible within any handler in the parent script or Behavior. Its scope is limited to the current instance of the script. Outside the script, it can be accessed with the property of scriptInstance.
Explicitly declared as a property within an ancestor script
Property variable is accessible within the ancestor script or to any object using that script as an ancestor