Lingo Basics
Script types, handlers, events, syntax styles, and how Lingo code is organized inside a Director movie.
The shape of Lingo
Lingo is an event-driven scripting language. Code lives in handlers (functions named after the event or message they respond to) inside script cast members. When something happens (mouse click, frame change, network completion), Director sends a same-named message through a defined hierarchy of scripts, and the first matching handler runs.
-- a complete Lingo script: two handlers
on mouseUp me
puppetSound "click"
go to frame "menu"
end
on helloWorld
alert "Hello World"
endThree facts orient everything else:
- Lingo is case-insensitive for identifiers and keywords (
MouseUp,mouseup, andmouseUpare identical). String contents are case-sensitive. - Lingo is dynamically typed; a variable holds any type and can change type.
- Almost everything reacts to the playback head: the loop of frame events documented in Event lifecycle.
The five script types
| Type | Lives where | Gets events for | Typical use |
|---|---|---|---|
| Behavior (sprite script) | Attached to a sprite span in the Score | That sprite | Buttons, draggables, per-sprite logic |
| Behavior (frame script) | The script channel of a frame | That frame | go to the frame loops, frame setup |
| Movie script | Its own script cast member | The whole movie | Global handlers, utilities, startMovie |
| Cast member script | Attached directly to a media cast member | Any sprite showing that member | Shared click behavior for a member |
| Parent script | Its own script cast member | Nothing until instantiated | OOP: create child objects with new() |
The script type is a property of the script cast member (scriptType: #movie, #score, or #parent). Behaviors attached to sprites and frames are both "score" scripts; a cast member script is stored on the member itself and does not appear as a separate cast member.
Which script receives an event first, and how events fall through, is defined by the message hierarchy.
Handlers
on customHandler me, arg1, arg2
return arg1 + arg2
endon name ... enddefines a handler. Arguments are untyped and optional at call sites (missing args arrive asVOID; extra args are dropped;the paramCountreports how many were passed).- In behaviors and parent scripts the first parameter is conventionally
me: a reference to the script instance receiving the message. return exprexits with a value; bareexitleaves the handler with no value.- Calling a handler that returns a value requires parentheses:
x = myFunc(3). Command-style calls without a return value can omit them:myCommand 3.
Two syntax styles
Verbose (classic) Lingo and dot syntax coexist from Director 7 onward. Old game code freely mixes both, so you must read both:
-- verbose (Director 4-6 style; still runs in MX 2004)
set the locH of sprite 1 to 100
put the text of member "Greeting" into t
set x = the mouseH
-- dot syntax (Director 7+; recommended in MX 2004)
sprite(1).locH = 100
t = member("Greeting").text
x = _mouse.mouseHRules of thumb when reading old code:
the propNamereads a global system property (the milliseconds,the key,the frame).the propName of sprite n / member mis verbose object property access; identical in effect tosprite(n).propName.set a = b,set a to b, andput b into aare all assignment. Plaina = balso assigns in D7+ code.put exprwith no destination prints to the Message window (debug output).
JavaScript syntax (MX 2004)
Director MX 2004 added a JavaScript 1.5 syntax layer over the same object model. A script cast member is either Lingo or JavaScript syntax; both can coexist in one movie and call each other's handlers.
function mouseUp() {
sprite(1).locH = 100;
member("Greeting").text = "Hello";
_movie.go("Main");
}Notes for readers and emulator authors:
- JavaScript syntax is case-sensitive; Lingo is not. The bridge normalizes handler names.
- Lingo lists map to Director list objects (
list(),propList()), not JS arrays; JS arrays are also available but are a different type. - Lingo symbols appear as
symbol("name"). - The global facades
_movie,_player,_mouse,_key,_sound,_system,_globalare the shared object model both syntaxes target.
In practice, preservation targets (1998-2005 web games, CD-ROMs) are almost entirely classic Lingo; JavaScript syntax movies are rare.
Comments, continuation, whitespace
-- this is a comment (double hyphen)
x = 5 -- trailing comments work too
-- line continuation: backslash in MX 2004 listings,
-- the "¬" character (Option-Return) in older code
total = price + tax + \
shipping- Blank lines and indentation are insignificant (indentation is convention only).
- One statement per line; there is no statement separator character.
- The continuation character in pre-MX code is
¬(0xAC); MX 2004 documentation shows\. Decompilers usually emit single long lines instead.
Minimal working examples
A frame loop (the single most common Lingo idiom in existence):
on exitFrame
go to the frame
endA button behavior:
property pDown
on mouseDown me
pDown = TRUE
sprite(me.spriteNum).member = member "btnPressed"
end
on mouseUp me
pDown = FALSE
sprite(me.spriteNum).member = member "btnNormal"
if rollover(me.spriteNum) then doButtonAction me
endMovie initialization:
global gScore
on prepareMovie
gScore = 0
the itemDelimiter = ","
end