| <<home | <<list | <<week 3 | <<week 4 LINGO INTRODUCTION Key: Message Window • Scripts • Messages and Handlers • Variables • Global Variables • Property Variables • Me • Creating Navigation Behaviors • Linear Lists • Property Lists • Creating Rollover Behaviors • Simple Button Behavior • Button Rollover Tip Lingo is a programming language. Lingo scripts are usually stored in cast windows. Message Window You can also run short, one-line programs in the message window (window -> message). The message window is a lingo interpreter. It enables you to type and interpret one line of lingo code at a time. The message window is nice for taking your first Lingo steps, and it continues to be useful as you learn new Lingo commands. The put command is actually used to place text into the message window. If you leave put commands in your code when you make a projector or shockwave movie, it does not affect your movie's performance or cause errors. (Note to De: Use text inspector to change font size in message window to show the class on the projector) Examples Type the following in the message window (remember to press the return key after each line, not the enter key on the keypad): put 42 + 1 beep The double-hyphen indicates a comment. A comment is code that is not executed. You can put comments on the same line as executable code: put 42 + 1 -- this code adds the two numbers 42 and 1 Scripts There are four types of scripts:
Make sure that a movie script is not set to be a behavior script or vice versa. Use the script's cast member properties dialog box to change it to the proper script type. *Handlers in movie scripts are global in scope, meaning that they can be called from handlers in any of the other types of scripts and the message window. Movie scripts can include handlers that are automatically executed when the movie starts, stops, or idles. Movie scripts can also be used to define and initialize global variables and to store user-defined handlers. **A sprite can have more than one behavior or script attached to it. A frame can have only one behavior attached to it. Whenever you attach a behavior to a sprite from the library palette, that behavior is added to the cast. When you edit a behavior, that change takes effect in every frame and every sprite to which it is attached. ***Cast scripts are rarely used. They are not used with modern Lingo programming. Behaviors can accomplish the same tasks and are much more flexible. ****parent scripts are a much more advanced type of script. They actually don't do anything until you use some object-oriented programming Lingo commands to tell them how and when they are to be used. Messages and Handlers A message is a signal sent by an event. An event is some action that occurs in a program. An event can be the action generated by a user typing or clicking the mouse, or it can be generated within director when the playback head moves, or it can even be generated by a handler. For example, when the user clicks the mouse button down and then releases it (an event), a "mouseUp" message is sent. Similarly, the initial click down sends a "mouseDown" message. Tip: Use Mouse Up vs. Mouse Down User interface standards for Macs and Windows machines specify that actions take place only after the user clicks down and then lifts up again. Otherwise, users can click and hold and the action can happen while they are still holding. It's not a big deal for simple Director projects, but because a standard has been set, its' best to use it. Messages get sent to any Director object that is related to the action itself. A "mouseUp" message is sent to the sprite that was clicked. If a behavior happens to be attached to that sprite, Director checks to see whether that behavior handles a "mouseUp" message. A behavior, or any script, handles a message such as this by defining a handler. Handlers start with the word on. A handler is a way of grouping together several lingo statements to perform a single task. In other words, handlers enable you to execute many lines of code with one word. Lingo has many built-in handlers, such as on mouseUp, but you can also create your own custom handlers (see Creating your own handlers below). In the preceding example, the first line of the handler is on mouseUp. This means that the handler is to handle any "mouseUp" messages sent to that sprite. The contents of the handler, beep, are the lingo commands that are to be executed if the handler is triggered by the message. The series of commands ends with end, which signifies the end of the handler. on mouseUp beep end Many programmers like to place the name of the handler after the end. So the last line of the previous example would look like this: on mouseUp beep end mouseUp Lingo doesn't require this, but some programmers use it anyway. You can place more than one handler in a script. For example, you can have an on mouseUp and an on mouseDown handler both in one behavior. They are triggered by different messages, so they won't get in each other's way. Example One Create a movie script (Window -> Script Note default is movie script.): You can change the type of script by selecting Property Inspector -> Script on playBeep beep end When you type playBeep in the message window, your playBeep handler is executed and a beep is played. Example Two Put a bitmap castmember on the first three channels in the score. Create another movie script: on makeInvisible sprite(1).visible = FALSE sprite(2).visible = FALSE sprite(3).visible = FALSE end type makeInvisible in the message window A handler name can't contain spaces. To make these names easier to read, capitalize the first letter of each word after the first word. However, lingo is not case sensitive so "myNumber" and "mynumber" are the same. Another function of the message window is to enable you to send messages to the movie. Do this by typing the name of the message. If a movie script has handler that deals with this message, the handler runs. Otherwise, an error message tells you that no handler is defined to receive the message. DO NOT use an event handler name as a custom handler or a variable name. You should also avoid using any other Lingo syntax as handler names or variable names. Variables A variable is a storage container for a value. It is like a box that can hold one item at a time. Variables can store numbers or strings (a series of characters). Variable names are only one word, so you can't have spaces in the name. It is a good idea to assign variables meaningful names, because the name of the variable should give you an idea of the value it holds. You might be tempted to give it a meaningless name, if you are in a rush or not feeling very creative. Don't do it! Although a is a legal name, it won't make much sense to you in a week from now. It'll be even worse for someone else trying to figure out your code. In some programming languages, the case of a variable is important. This is not true with lingo. Again, lingo is not case sensitive so the variable "myname" is the same as "myName". In some programming languages, you need to declare a variable before you can initialize it (initialize means to give it a value). In lingo, a variable is created as soon as you use it. type in message window (remember to press the return key after each line): myNumber = 42 put myNumber myNumber = 42+1 put myNumber myNumber = 5 myOtherNumber = 3 put myNumber+myOtherNumber a string such as my name must be written with quotes. myName = "De" put myName A string can be one character long or even zero characters long (""). Variables can be used in handlers as well. For example, create a movie script: on playWithVariables myNumber = 5 myNumber = myNumber + 4 myNumber = myNumber - 2 put myNumber end Then type playWithVariables in the message window. There are three types of variables:
Global Variables You can declare a global variable in any handler or in any script in a movie. If you want to initialize a global variable, use the global keyword followed by the name of the variable. You can declare more than one global variable on the same line. To easily differentiate between local and global variables, it is recommended that you begin global variables with the lowercase letter g. This is not required, but highly recommended. For example: global gMyNewVariable global gCost, gRetail, gProfit To use a global variable in a specific script, you must repeat the global statement within the script. Once declared, the current value or string stored by a global variable is available for use and modification within the handler. You can use the clearGlobals command in the message window or in a handler to erase all global variables. You can also use the showGlobals command in the message window to see a list of all current globals and their values. For example, create a movie script: global gMyNumber on initNumber gMyNumber = 42 end on addOneToNumber gMyNumber = gMyNumber + 1 end on putNumberInMessageWindow put gMyNumber end Then type the following in the message window: initNumber putNumberInMessageWindow addOneToNumber putNumberInMessageWindow To reiterate, a local variable is destroyed when a handler is done. The next time that handler begins, it will not have a value. If you want a variable to retain its value, you should use a global or a behavior property variable. Properties or Property Variables A behavior script is an object-oriented programming method. Object-oriented just means that both a program and data are stored in the same place. In the case of behavior scripts, the program is the handlers of the behavior, and the data is the variables used by the behavior. These variables are called properties. A property is something in between a local and a global variable. A local variable exists only inside a single handler. A global variable exists throughout the entire movie. A property exists throughout the entire behavior script, accessible for all the handlers in the behavior, but not normally accessible outside of it. You create properties like the way you create global variables. Rather than use a global command, you use a property command. The best place for this is in the first lines at the top of a behavior script. Some programmers like to place a "p" as the first letter of property variables as "g" is a common prefix for global variables. Some developers prefer to place an "i" in front of property variables, to stand for "instance." A "p" or "i" is not required, but highly recommended. Properties hold the data that is important to the behavior. For instance, if a behavior needs to move a sprite horizontally across the stage, two properties might be "horizLoc" and "horizSpeed". They would correspond to the current location of the sprite and the number of pixels that the sprite moves each frame, respectively. Using Me A behavior script by itself is just a bunch of text in a cast member. when you attach it to a sprite, it is still just a bunch of text with which the sprite knows it has a relationship. However, when you run the movie and the sprite appears on the stage, an object is created. The object, called an instance of the behavior, is sort of a copy of the behavior. The lingo code is loaded into a new location of memory and the property variables are created. This instance is now attached to and controlling the sprite. If the same behavior is attached to two different sprites, and they both appear on the stage at the same time, they actually have two different instances of the behavior. Both instances have copies of the same handlers, and both have properties of the same names, but the values of these properties are stored in different locations and can have different values. The idea of an instance needs to be present in your behavior code. Each handler needs to know that it is part of a behavior. To signify this in your code, you should place the parameter me as the very first parameter of all handlers in the behavior. me is a reference to the behavior in the same way that sprite is a reference to a sprite, or that member is a reference to a member. me has properties, the most useful of which is spriteNum. You can use it to get the sprite channel number of the sprite to which the behavior is currently attached: For example, create a behavior (or sprite) script: on mouseUp me put me.spriteNum end If you don't place the me after the handler name, the script does not work. As a matter of fact, it gives you an error message when you try to close the script window because Director doesn't even know what me is supposed to refer to if it is not included after the handler name as a parameter. Creating Navigation Behaviors Previously, we have been creating scripts for every frame we wanted to specifically navigate to. For example: on mouseUp go to "sally" end However, we had to create a different script for each marker we wanted to navigate to. This is time-consuming and repetitive. You can create a behavior that can be used on many different buttons. For example, create a behavior (or sprite) script: property pTargetMarker on getPropertyDescriptionList me return [#pTargetMarker: [#comment: "Target Marker:", #format: #marker, #default: VOID]] end on mouseUp me go to frame pTargetMarker end The list in the on getPropertyDescriptionList function is a property list that contains one or more other property lists. (A variable can hold only one value at time, but a list, a collection of items, can store multiple values or strings at the same time. A list can hold any data type that a simple variable can -an integer, a string, a reference to a cast member, even another list. If the data you add is a string, be sure to enclose it within double quotation marks. If the data is numeric, quotation marks are not used. Lingo supports two types of lists:
The property name for the first (and only in this case) item of the list is the name of the property, turned into a symbol by adding a "#" in front of it. (Computers deal with numbers much more quickly than strings. Sometimes you want the speed of a number and the descriptiveness of a string. Symbols are lingo's way of satisfying this need.) The list that is its property value contains three items:
scores = ["Pat": 1200, "Joan": 1545, "Mary Ellen": 950] In this example, the names (or strings) are properties and the scores (or numbers) are data. Each string is paired with a value (or data) by a : in between them. The name data pairs are then separated by a comma enclosed in brackets. Strings are not the best choice for property labels. They are slower to process, but more important, using a string as a property label is the only time that you encounter a case-sensitivity issue with Lingo. Suppose that you tried to get one of the properties and used the wrong case, such as: put getProp(scores, "pat") The result is a syntax error. Most of the time, it is preferable to use symbols, which are not case sensitive. scores = [#Pat: 1200, #Joan: 1545, #MaryEllen: 950] You can initialize or create an empty property list named Scores by using this syntax: scores = [:] An empty linear list consists of two square brackets [ ]. Reusability is one of the powerful features of behaviors. To complete this behavior, you should add an on getBehaviorDescription function to it. This function displays some informative text in the Behavior Inspector when the script is added to a sprite: on getBehaviorDescription me return "Jumps to a specified marker on mouseUp." end To further enhance your custom behavior, you can create a tool tip, the yellow box that appears when you rollover a behavior in the library palette. These should be as short as possible. on getBehaviorTooltip me return "Jumps to a specified marker on mouseUp." end Putting your custom behaviors in your library palette The library palette is just a collection of external casts that are stored in the "Libs" folder located in the director application folder. An external cast can include any kind of cast member (bitmap, text, script, video, etc). For instance, if you're using a logo that appears in all of your movies, you can put the logo into an external cast and then move it into the Libs folder; it will appear in the Library Palette when you reopen Director. Creating Rollover Behaviors Create two button bitmaps with the text "normal" on one and the text "rollover" on the other. Name the cast members respectively "button rollover" and "button normal."Make sure the buttons are different colors. For example, create a behavior (or sprite) script: on mouseEnter me sprite(1).member = member("button rollover") end on mouseLeave me sprite(1).member = member("button normal") end Test it. Now move the button to another channel. Test again. You will notice that the script no longer works. How can we make this reusable? First of all, we shouldn't hard-code the number "1" as the sprite channel. What is the syntax that we learned earlier that we can use? me.spriteNum Modify the behavior (or sprite) script you just created: on mouseEnter me sprite(me.spriteNum).member = member("button rollover") end on mouseLeave me sprite(me.spriteNum).member = member("button normal") end When you test it, you will notice that the cast member names are still hard-coded. You can easily figure out the normal state of a button because it is probably the member with which that button is set to begin with. You can get that member and store it in a property in the on beginSprite handler. Modify the behavior (or sprite) script again: property pButtonNormal on beginSprite me pButtonNormal = sprite(me.spriteNum).member end on mouseEnter me sprite(me.spriteNum).member = member("button rollover") end on mouseLeave me sprite(me.spriteNum).member = pButtonNormal end Now you have only one hard-coded element left: the member of the rollover state. There are three techniques for completing this behavior:
Simple Button Behavior A simple button behavior should do several things. It should enable you to have a different cast member as a down state when the button is pressed. Second, it should recognize the difference between the mouse bing released above the sprite and it being released ouside the sprite. This enables the user to click down, but then move the mouse so that it doesn't activate the button when it's released. Third, the button should perform a task, such as simple navigation, when there is a succesful button press. A behavior such as this should have two parameters:
property pMemberNormal, pMemberDown, pTargetMarker on getPropertyDescriptionList me list = [:] addProp list, #pMemberDown, [#comment: "Down State Member:", #format: #member, #default: VOID] addProp list, #pTargetMarker, [#comment: "Target Marker:", #format: #marker, #default: VOID] return list end (This list is built property by property, and then returned. This makes the code easeir to read than a one-line return command does as we have been doing. Also note that the #marker #format adds the markers #next, #previous, and #loop which can be used along with the go to frame command to go to the next, preceding, or current marker.) on mouseDown me sprite(me.spriteNum).member = pMemberDown end on mouseUp me sprite(me.spriteNum).member = pMemberNormal go to frame pTargetMarker end on mouseUpOutside me sprite(me.spriteNum).member = pMemberNormal end Button Rollover Tip if importing from photoshop make sure the image dimensions are the same so that the registration points automatically line up. compare to: library palette -> interactive -> rollover member change library palette -> controls -> push button <<home | <<list | <<week 3 | <<week 4 |