Learning Lingo Corrections

Date:    Wed, 16 Jul 1997 19:26:40 -0400
From:    Michael Scaramozzino 
Subject: D6: Learning Lingo Corrections (The completed list)
I started reading the "Learning Lingo" manual to see what was new in D6. D6 is pretty cool by the way... This manual however... well, let's just say it needs a little more work. ;-) The last time I read this manual (earlier edition obviously) was about 7 or so years ago ( I forget exactly when, it's been a long time...) when Lingo was first introduced.

No wonder Director is hard for newbies to learn. I had no idea that all this old stuff was still incorrect in the manuals. Ouch! ;-)

So it's for all you newbies out there just starting to learn Lingo and relying on the "Learning Lingo" manual that I have put together all these corrections to the manual. This is also a way for me to sharpen my own Lingo skills (I've been busy doing 3D stuff for the past few months) while learning the new exciting Lingo commands in the newly released Director 6. I don't claim that this is an exhaustive list of corrections or that every one of my corrections are entirely without error (Take this as a disclaimer that neither DreamLight nor myself take any responsibility for this document. It is provided as-is without warranty of any kind. For the wellbeing of the Direct-L community) . I do however think that these corrections and clarifications to the manual could be of tremendous help in your efforts to learn Lingo. I sure wish I had something like this when I first learned!

This should help Macromedia correct these errors in future editions of the manual as well. I'd also suggest to MM that before even ONE new feature is contemplated for Director 6.whatever, please, just go back into all the documentation, manuals, examples, samples, on-line help etc. and TEST AND FIX them. I only corrected this one manual. I haven't examined anything else but due to all the errors in this one I'd bet a pretty large sum of dinero that there are many errors elsewhere as well. This step alone will go much further in making Director "easier to use" than any possible added feature such as behaviors etc... What good are new features if nobody can figure out how to use the old features, never mind the new ones? I know in the push to create new and exciting versions of Director it seems pretty boring to edit the manual but really guys, it will make a huge difference... ;-) ;-)

-Michael Scaramozzino
DreamLight Incorporated
http://www.dreamlight.com

PS. I'll watch the mail for my FREE copy of Director 6 for Windows (I already have the D6 Mac version and D5 for Win...) that you guys at MM should send me for reporting all these errors (so they can be fixed), thereby making life in Director land that much more enjoyable... for all.

Well, let's jump right in...



--

Page 21:
"getPropertyDesriptionList" should read "getPropertyDescriptionList" The
"c" is missing.

--

The printed documentation is not in the same order as the Lingo pop-up list
for inserting lingo into scripts. The manual dictionary puts all "on"
handlers under "o". The pop-up list sorts them by the second word. I'd
prefer if both the pop-up and printed manual used the second word and
ignored the "on" during alphabetizing. At least they should both be ordered
consistantly anyway.

--

Page 29:
"if sprite 1 intersects 2 then alert Move Over"
should read: if sprite 1 intersects 2 then alert "Move Over"

--

Page 31: First sentence, second paragraph.

The on rollOver handler frist assigns the value of rollOver to a variable
and then tests the variable.

should read:
The on rolloverTest handler first assigns the value of rollOver to a
variable and then tests the variable.

rollOver and rolloverTest are two distinct elements. rolloverTest is a user
defined handler and rollOver() is a Lingo function.

--

Page 31:
Inappropriate and incorrect example

The example given of testing a member for a size greater than 500K is not
appropriate for a case statement. It would be better suited to a simple if
... then statement since you are only testing one condition. I would
suggest adding at least one additional condition to make it more
appropriate as a case statement.

The example is also incorrect as written and will not run. The first line
needs to end with "of" and ">500000" is not a valid expression. Also, 500K
is 512000, not 500000.

The example must be rewritten to function as expected:

case (the size of member whichMember > 512000) of
   TRUE: preload member whichMember
   otherwise nothing
end case

The parenthesis seem necessary or the case gets confused with the first
"of". It wouldn't run without the parenthesis.

Let's not confuse beginners into which type of statement to use in which
type of circumstances.

This however is an inappropriate and hard to follow use of a case statement
and would be much better expressed with the if ... then statement as
follows:

if the size of member whichMember > 512000 then preload member whichMember

Therefore I would either dispense with this example entirely or come up
with a more appropriate use for using such a condition as a case test
expression.

--
"end case" entry in On-Line help

During these tests I also found an incorrect script example under the "end
case" entry in the on-line Lingo help:

The example handler will not run as written:

on keyDown
   case the key
      of "A": go to frame "Apple"
      of "B", "C" :
         puppetTransition 99
         go to frame "Mango"
      otherwise beep
   end case
end keyDown

It should be rewritten as follows:

on keyDown
   case the key of
      "A": go to frame "Apple"
      "B", "C" :
         puppetTransition 99
         go to frame "Mango"
      otherwise beep
   end case
end keyDown

----

Page 31: Last line, second paragraph, right hand column.

the keyPress should read the keyPressed

--

Page 32: Figure incorrect.

Example and discussion goes from 10 down to 1
however the figure only goes from 10 down to 2.

--

Page 33: First sentence, Third Paragraph, right column:
Should read:

You can also use the set ... to construct to assign a value to a variable.

I'd also add the put ... into construct here especially since you start
using that construct with no explanation  on page 34 and later.

I'd also suggest refraining from naming example variables with the prefix
"the". This can get confusing for beginners since the prefix "the" is
usually used to signify property names such as "the keyDownScript" etc.

--

Page 34: On page 33 which explained how to assign values to variables the
only commands mentioned were the set ... = and the set ... to constructs.
There was no mention of using put ... into. On page 34 however in both
global variable assignments the put ... into construct is used. This is
going to be very confusing to beginners at best. Either you should also
introduce the put ... into constuct on the previous page as well or change
the examples on page 34 to use the set ... = construct.

--

Page 46: Second column, 5th paragraph. Should read:
Backwards. You are just now introducing the "play" command.
Should read as follows:

Note that all the ways that can specify a location with the go to command
also work with the play command.

--

Page 56: Right column, Second to last paragraph, last line:

The description of the Step Into button is not very clearly explained. It
gives the impression that it just runs the nested handler and only stops at
the next line in the current handler. It should be reworded like this:

The debugger stops at the next line of Lingo within the nested handler.

--

Page 62:
The section: When to make a sprite channel a puppet is not entirely clear.
The last paragraph on the left column states:

The following sprite properties require the channel to be under Lingo's
control before Lingo can modify them:

This is not really true. The sprite automatically becomes puppeted if Lingo
attempts to modify any of those properties. This needs to be more clearly
explained.

--

Page 62 + 63:
Some of the examples seem to come from eariler editions of Director. The
text clearly explains that the syntax for puppetSound is as follows:

puppetSound 2, member "Crickets" of castLib "Animal Sounds"

but then the next example reverts to the old syntax without any
explanation. If this is intended to show the shorthand version of the
command it should really be explained with emphasis that the channel being
puppeted defaults to sound channel 1. This is especially true later when
you show the command to stop the sound as puppetSound 0. Again no channel
is specified... This means that the puppetSound 0 will stop a puppetSound
that happens to be playing in channel 1. This also means it will NOT work
with the earlier examples which puppeted sounds into channel 2.

The easiest fix for this would be to rewrite the example at the end of page
62 as:

on mouseUp
   puppetSound 1, "Crickets"
   go to "Scene 4"
end

Even though the "1" is not really necessary, it will be much easier for a
beginner to follow since it follows the syntax of your earlier example and
is more consistant.

I would then rewrite the puppetSound 0 on page 63 as:
puppetSound 1, 0

--

Page 64:

The section that explains puppetTransition time should mention that the
number reflects 1/4 seconds! Especially since ticks are used for some of
your time measurements with other commands so this distinction is critical.

--

Page 64: Right column, second to last paragraph.

When it's suggesting putting the puppetPalette command in the frame
preceding the frame that the new palette is used in it should mention to do
this in the "on exitframe" handler. It should also mention that any
puppetPalettes placed in "on prepareframe" handlers are ignored. (Is this
proper behavior. Lingo ignores them in on prepareFrame, which seems to be a
more appropriate place to put them... or is this a bug?)

Page 65:

Why is it suggested to use puppetPalette 0 before doing a new
puppetPalette? Is this related to the old puppetSound Windows bug where
sounds were locked in RAM unless explicitly released prior to playing new
sounds? I don't seem to need to issue puppetPalette 0 on the Macintosh
before issuing a new puppetPalette. Am I missing something?

--

Page 68:

Turning off the moveableSprite property is incorrect. It should read:

set the moveableSprite of sprite 1 to FALSE

the sprite number is missing and that entire line should be in the script
typface since it is all a Lingo statement.

--

Page 71: Left column, third paragraph

The sprite channel will be autopuppeted if not already under lingo control.

--

Page 71: First "on enterframe" example:
the numbers 250 and 300 are backwards. The text says 250 is the vertical
and 300 is the horizontal coordinate. For this to be true the example must
be reversed to use:

point( 300, 250 )

--

Page 71: on mouseDown example

The example is wrong, it alone has THREE errors, it should be rewritten as:

on mouseDown
        set the loc of sprite 9 to point(the mouseH, the mouseV)
        updateStage
end

The word point was missing, the H & V components were backwards and the
right parenthesis was missing.

--

Page 74: table of properties

scrollTop of member has nothing to do with size as described. This setting
aligns an area of the scrolling field to the top of the visible field. It
is a positional alignment, not a size adjustment.

--

Page 75: Making fields editable, second bullet

Should read:

The Score allows you to make a field sprite editable in selected frames by
turning on the Editable check box at the top of the Score window.

--

Page 77: Right column, example

The example is incorrect. the word "the" in front of "field" must be
deleted or it will not run...

--

Page 78: Left column, Additional ways to update fields, second paragraph,
first sentence

It's backwards... They were already introduced to the "set" command and are
now being shown the "put" command. It should read as follows:

Use the put command in much the same way that you use set to assign a
string to a field cast member or other string, but use different syntax.

--

Page 79: Left column, second example

It's incorrect: Must delete the word "the" in front of lastKey in the case
statement. It's a simple variable not a property. I guess using "the" not
only confuses beginner's as I mentioned previously, but whoever wrote the
manual as well... this is at least the second time this error has cropped
up. ;-)

I'd also suggest changing the variable name since there is indeed also a
"the lastKey" property. However "the lastKey" property returns the time
since the last key, not at all what the example is trying to test!! ;-) I'd
rewrite the example as follows:

set whichKey = the key
case whichKey of
        "S": go to "Start"
        "H": go to "Help"
        "Q": go to "Quit"
end case

Note: I've also changed the action of the Q key from immediately quitting
to branching to the "Quit" label. We typically suggest this so that the
movie has a chance to clean up anything necessary and allow a credits
display etc. (Especially since you guys require the display of the "Made
with Macromedia" logo, we generally display that when the user quits.) This
also makes testing easier since the movie doesn't quit Director every time
you test the Quit key, it simply branches to the last section (where we
usually place the Quit section) and stops on the last frame of the movie.
..

--

Page 81: Left column

Example incorrect, text very confusing...

The text states that the example advances the playback head to the next
marker if the cursor is over sprite 25. This is not true.

The example sets a variable called clickedSprite to whatever the rollover
value is at the time the exitframe runs. It then checks again if the
clickedSprite is still being rolled over and if so it goes to the next
marker. This has nothing to do with sprite 25... and actually doesn't make
much sense to me as an example anyway.

Sometimes, as in the examples in the Lingo Dictionary, it's a good idea to
put a changing value into a variable so you don't need to worry about it
changing if the handler takes time to run especially if you need to make
multiple tests on the same value such as in a case statement. You don't
want the value to change before you are done with it. However, if you are
only testing it once in a simple if statement, I see no need to use
temporary variables.

The example should read as follows:

on exitFrame
        if rollOver( 25 ) then go next
end exitFrame

OR

on exitFrame
        if the rollOver = 25 then go next
end exitFrame

I would further suggest that you use the following syntax for specific
purposes (I know Lingo doesn't care but it's really confusing for beginners
when the same function does different things at different times. Beginners
aren't used to overloaded functions...especially without any explanation!)

the rollOver

should be used for testing which sprite the cursor is currently rolling over.

rollOver( whichSprite )

should be used for testing whether the cursor is currently over a specific
sprite.

Again, this is not enforced by lingo but really makes things MUCH less
confusing. If you don't beleive me, then why did whoever wrote the manual
get confused? Besides, this is the way the examples in the Lingo Dictionary
use the syntax as well.

--

Page 81: Right column: last example.

Though technically not incorrect I would present this example in one of the
following two ways...

on mouseDown
        if the doubleClick = TRUE then openWindow
end

OR simply

on mouseDown
        if the doubleClick then openWindow
end

Using the test "the doubleClick = 1" works but is not as explicit as either
of the other two methods. Sometimes beginners don't remember that TRUE = 1.

--

Page 82: Last bullet

The word "the" in "the timeOutScript" should be in the script typeface. It
is part of the statement as it is in the first bullet...

In general the text is haphazard about putting the word "the" in the proper
script typeface when discussing properties such as "the movieTime of
sprite" sometimes you will see the word "the" in normal face and sometimes
in script face which it should be when used with properties... I'm not
going to point them all out any longer since it's getting very tedious. So
any beginners out there, if it's a property they are talking about, the
word "the" is usually part of the script statement, otherwise it's just
part of the text.... (MM, when re-editing this manual I'd suggest going
over each use of "the" before a property and applying the proper typefaces
as outlined on page 7 of the manual... Everywhere in these corrections
where I mentioned "Script" face, I'm actually referring to your "Code"
typeface. ;-)

--

Page 87: Controlling Sound volume: Third bullet.
Incorrect. It should read...

Test and set a specific channel's volume by using the volume of sound property.

--

Page 87: Right column: Example
Incorrect. This is a real train wreck....

The example in the book attempts to set soundRecord (poor variable name
since it is not recording a sound but rather storing a volume setting) to
the volume of whichChannel which is trying to set it to the volume of a
specific channel. However, then the example sets "the soundLevel" which is
the "machine's" overall level, not the channel's volume. Even so, the
statement trying to use the "volume" is incorrect and missing the word
"sound" before the channel number!

The example also completely ignores the channel that the user wanted to
play the sound in and simply plays it in channel 1, squishing anything that
may already be puppet playing there...

It then tries to set the overall machine soundLevel to what the individual
sound channel was originally set to. That's interesting since "the
soundLevel" can range from 0-7 while "the volume of sound" can range from
0-255. So overall, this example is a complete mess!

the example should be rewritten as follows:

on playThunder whichChannel
        set oldVolume = the volume of sound whichChannel
        set the volume of sound whichChannel = 255

        puppetSound whichChannel, "thunder"
        updateStage

        repeat while soundBusy( whichChannel )
                nothing
        end repeat

        set the volume of sound whichChannel = oldVolume
end playThunder

Of course the paragraph that follows the example is incorrect as well. It
should be rewritten as follows.

This handler first saves the current volume of a user specified sound
channel. It then sets that channel's volume to the maximum of 255. It plays
the thunder sound in the specified channel and when done returns the volume
of the channel to its original value. The repeat loop allows the sound to
finish before the sound level is returned to its original value.

Please note that this does not effect the overall "soundLevel" of the
machine itself. If that is set to 0, then you still won't hear anything.
But the example the way it was originally written (if it were written
correctly) would have raised the volume of ALL sounds playing, not just the
thunder as they set out to do in the text... Also note that unless you had
already lowered any of the sound channels this handler will have no
apparent effect since every sound channel actually defaults to 255. ;-)

--

Page 90:
Synchronization Examples are incorrect: I have rewritten the example to
follow the book's conventions (such as prefixing all globals with "g"),
fixed incorrect comments and variable names, and encapuslated it in a
handler for beginners to follow a little better. The variable names and
comments were incorrect they say that ticks per second are being used when
they really mean ticks per FRAME are being used... Also, there was a space
in "start Timer" it should have been one word "startTimer" and will not run
as written.

The example can be placed in the movie script and it should be rewritten as
follows:

on startAnimation fps
   -- fps (frames-per-second) is passed to the handler as a parameter
   global gStartFrame, gTicksPerFrame

   -- Convert frames per second to ticks per frame
   -- there are 60 ticks in one second
   set gTicksPerFrame = 60 / fps

   startTimer
   set gStartFrame = the frame + 1
end startAnimation

Note, It's not a good idea to put the "go to frame" command in this start
handler as suggested in the text. It can lead to possible infinite loops.
In low fps settings it may actually jump to the frame it's already in which
will then reset the timer again and bingo... infinite loop. I'd also
suggest setting the gStartFrame to the frame + 1 which is the actual start
frame of the animation, remember we invoke this from the frame before the
animation. Otherwise you can still be pulled into an infinite loop on low
frame rates... ;-)

It can then be called from the frame immediately before the animation
starts like so:

on exitFrame
   startAnimation 10
end

Where the number 10 can be set to whatever frames per second you like. It
is better to pass a value like this if you intend to try different values.
That way you don't need to keep editing the internal functionality of the
lower level handler "startAnimation" and can simply call it with different
values. This also enables you to use the same handler for different
sequences of animation synchronized to different rates.

The next example in the book is also incorrect. If called from the
enterframe handler as shown, it will first draw this frame and then may
jump BACK a frame under low settings. This leads to animation glitches. It
should be called from the exitFrame or prepareFrame handlers and rewritten
as follows:

on exitFrame
   global gStartFrame, gTicksPerFrame
   go to frame gStartFrame + ( (the timer) / gTicksPerFrame )
end

This type of synchronization is best used in simple animation sequences
rather than sequences that have heavy Lingo interactivity (unless you are
very careful). Since it may skip around within the sequence you never know
exactly which frames will be played and which won't be played... Also note
that when fps is set pretty high, the playback head may jump off the end of
the animation to further frames in the score than intended. I'll leave
implementing a check for this over-run situation to the student as an
exercise. ;-)

--

Page 90: Right column:
The examples that show how to wait for a QT movie to play are inconsistant
and seem overly complex. First off one of them uses "the memberNum of
sprite 5" while the other uses "the member of sprite 5". While both of
these will technically work, it makes it more difficult to follow the
examples. Also, why are we using the "duration of member" by locating the
cast member of the sprite when we can simply test the sprite itself?

I'd rewrite these examples as follows:

if the movieTime of sprite 5 < the stopTime of sprite 5 then
   go to the frame
end if

Then the "optimized" versions would be:

on exitFrame
   global gMoovLength
   set gMoovLength = the stopTime of sprite 5
end

and...

on exitFrame
   global gMoovLength
   if the movieTime of sprite 5 < gMoovLength then
      go to the frame
   end if
end

However, I haven't run performance tests to see if this would save any time
at all. Since the stopTime of sprite is a property setting I would guess
that accessing it would be rather quick. Has anyone benchmarked this?

--

Page 96: sample menu definition
Though this is technically not incorrect, it is not a great way to
implement a volume menu. If it were a navigation menu, then using the "go
to frame" commands would be fine but it's a little weird handling volume
this way. Personally I wouldn't suggest using different frames for
"logical" elements. I typically suggest using frames in more of a visual
sense and handling strictly logical elements right in lingo without jumping
all over the score.

A better example would be to call a handler that sets the volume directly,
passing a parameter to it.

menu: Volume
Loud | setVolume( 7 )
Medium | setVolume( 4 )
Soft | setVolume( 1 )
Mute | setVolume( 0 )

Then I'd define the setVolume handler in a movie script as so:

on setVolume howLoud
   set the soundLevel = howLoud
   beep
end

--

Page 97: Left Column, Second paragraph, last sentence
This line should be rewritten as follows:
Note that if the custom menu uses keyboard shortcuts, they override
Director's. Any of Director's shortcuts that conflict with the custom menu
won't work while the custom menu is in effect. Director keyboard shortcuts
that do not conflict, still function as usual. (on the Macintosh anyway, I
haven't tested this on Windows)

--

Page 97: Right column, paragraph 4
The text mentions "overlaying" two bitmaps for a cursor. I beleive it is
talking about creating a "mask" for the cursor. I would reword this as
follows:

To use a mask for the cursor, specify the cast members in the list as follows:

cursor [ cursorCastNumber, maskCastNumber ]

See the Lingo Dictionary for more information about cursor masks.

--

Page 106: Right column
Examples:

First example should use gNewWindow as the global variable name to remain
consistant with the suggested naming conventions for globals.

The second example is incorrect and will not run.

the third line of the example sets newWindow to window "theMovie" which
sets the newWindow to the string "theMovie" when what was intended was to
use the file name stored in the variable called theMovie.  I would also use
a "g" in front of the globals and avoid using "the" as part of a variable
name. "the" is already causing enough confusion throughout the manual.

The second example should be rewritten as follows:

on beginNewMovie movieFile
   global gNewWindow
   set gNewWindow to window movieFile
   set the titleVisible of gNewWindow = FALSE
   open gNewWindow
end

--

Page 107: Left column only paragraph

This paragraph is in the wrong place. It does not refer to the example we
just examined but to the example before that one. It should be placed
immediately after the first example on page 106.

--

Page 107:
States windowType defaults to 0 but if I create a new test window and run

put the windowType of window newWindow

I get -1 which seems to be the same style as 0 anyway. I only mention this
because if you write a script that tests for the value 0 (expecting it as
default) you may be surprised.

Also, the text states that numbers 6, 7, 9, ... etc. have no effect when
specifying window type. This is not true, using these numbers sets the
window type to some of the other types, so it does have an effect, but it
may be an undesireable effect.

--

Page 109: Right column, second example
incorrect the first line should read as follows:

set aRect = rect(0, 0, 200, 300)

As written the example was trying to use a list. It should use a rect as in
the example above it.

--

Page 110: right column, on mouseEnter handler

This example is not technically incorrect but is more convoluted than
necessary.
It is used as an example of using a multi line tell handler but if you
examine the handler you'll notice it doesn't make much sense. Why would you
tell the window "Help" to make the window "Help" visible when you could
more easily do that from the stage? A better example would be to tell the
window "Help" to do things that only it can do such as manipulate its own
field members such as this...

on mouseEnter
   tell window "Help"
      go to frame "Glossary"
      put "search item" into field "searcher"
   end tell
   set the visible of window "Help" to TRUE
end

This handler tells the help movie to go to a certain frame and put a string
into one of its fields. The handler then makes the window visible (from the
stage). Then if the searcher field is editable the user can edit its
contents to perform their search.

--

Page 116:
Examples and discussion.

These are not technically incorrect but they are not very good examples of
child scripts. I know that the "advanced" version is better but that is
really no reason to show examples that use less than optimal use of
parent/child capabilities when those capabilities will actually simplify
the examples. I'd let the child keep track of its own sprite channel.

I would also follow the suggested convention about using "g" for global
names. I'd even go one further and suggest a convention for object property
variables of prefixing them with "my". This prefix helps users get into the
feel of treating objects as true entities with their own properties and
handlers.

Also notice that I'm not using the overly verbose syntax of "the propName
of me". This syntax is only needed when accessing ancestors properties. For
simple parent scripts without ancestors it is not necessary and can cause
confusion.

I would rewrite the examples as follows:

--Ball Parent Script
property mySprite, myHorizPos, myStageWidth

on new me, whichSprite
   -- store mySprite, passed to me as whichSprite
   set mySprite to whichSprite

   -- give Lingo control over mySprite
   puppetSprite mySprite, TRUE

   -- position the mySprite on the stage
   set myHorizPos to 200
   set the locH of sprite mySprite to myHorizPos
   set the locV of sprite mySprite to 120

   -- store myStageWidth so I don't recalc it on every move
   set myStageWidth = the stageRight - the stageLeft

   return me
end new

on moveBall me, direction
   set myHorizPos to direction * 50 + myHorizPos

   if myHorizPos > (myStageWidth + 99) then
      set myHorizPos to 0
   else if myHorizPos < -99 then
      set myHorizPos to myStageWidth
   end if

   set the locH of sprite mySprite to myHorizPos
end moveBall

--Here is the calling handler

on createBall
   global gBall1

   -- pass sprite #2 to the child object to take control of
   set gBall1 = new( script "Ball Parent Script", 2 )
   set the visible of sprite 3 to FALSE
   set the visible of sprite 4 to FALSE

   repeat with n = 5 to 8
      set the visible of sprite n to TRUE
   end repeat
end createBall

I would then use these examples on the following pages as well...

--

Page 120:
The text on this page seems to have been taken from an earlier "tutorial"
edition. It refers to scripts that "you wrote earlier" and "Save your
work". Since this is no longer presented as a full "tutorial", I would
remove these references.

Also the word statement in the last line of this page should be in normal
face since it is not part of the Lingo statement: set ball1 = VOID

Again, I'd also prefix ALL uses of global variables throughout the manual
and examples with "g" as was recommended much earlier in the manual. It's a
good recommendation, let's lead by example and follow our own
suggestions... ;-)

--

Page 121: Controlling a child object

If our new Parent script was used, I'd rewrite the mouseDown scripts as
follows:

on mouseDown
   global gBall1
   moveBall gBall1, 1
end

on mouseDown
   global gBall1
   moveBall gBall1, -1
end

--

Page 121: Using multiple objects

A good use of parent scripts that is not mentioned in the text is to
encapsulate properties and handlers for easier organization and access.
This also keeps our global name space from getting all cluttered up wih "g"
this and "g"that. We typically only use a few true global variables which
typically refer to global objects. All the rest of our variables are
property variables of one global object or another... Here are a couple
examples.

We typically create an object called gMovieMan which is a global movie
manager object. This enables us to store property variables and handlers
that are then available to all subsequently branched to movies. We place
common handlers here that handle file IO, memory management etc.

We also create an object called gSoundMan which is a global sound manager
object. This then contains and controls a set of soundChannel objects that
directly control the individual sound channels.

So don't just think of child objects for animated sprites but think of them
as intelligent objects that can be used for almost anything. They each know
certain types of information and they can perform their own actions with
that information.

--

Page 123: Left column bottom statement:
Incorrect, it should read:

set the ancestor of me to new( script "Overall Condition" )

--

Page 123: Understanding the movie script

the puppetSprite command is being used in the on prepareMovie hadler...
This is not incorrect but I prefer to use puppetSprite mySprite directly
within any child objects that need to take control of a sprite. As shown in
the earlier example I rewrote.

This way you are letting the object itself take control and do things on
its own rather than performing some functions in the movie scripts and only
limited functions in the object itself. Anything that an object can do for
itself, it should be allowed to do... Empower those objects, don't cripple
them... ;-)

--

Page 124: Right column
Example incorrect:

the second "add" line is missing a closing quote and comma after the script
name. It should read as follows:

add( ballList, new(script "BW Parent", count(ballList) + 1))

There is also a leftover global variable that is not used "ball1". Again,
I'd prefix all globals with "g" as well...

--

Page 125:
No problem on this page but here's a note for Direct-L members. There is a
lot of additional information about managing the actorList avaliable in the
Direct-L archives. Just search on the word "actorList" and it will pull up
quite a few posts from myself and others...

--

Page 128: Left column, last example
Incorrect:

If typed in as shown you'll get an error. They were probably there to
signify an optional parameter but I have not seen them used anywhere else
in the manual and they simply create confusion.

Should read:

new( type )
or
new( type, member whichCastmember of castLib whichCast )

--

Page 129: Left column last example
Not technically incorrect but personally I'd refrain from using the
gVideoMember  as a global but rather simply return a pointer to the new
member. I suggest this because it is more likely that the digitalVideo
member is only needed temporarily if importing many cast members. If it's
needed for more long term use it's also likely there are many more cast
members we need to track in which case each new cast member could be put
into a managed list rather than all using a single global variable.

It could be done this way...

on newDigitalVideo newName
   set newVideo = new(#digitalVideo)
   set the name of newVideo = newName
   set the crop of newVideo = TRUE
   return newVideo
end

This way if any calling handler needs additional access to the new video
member they can simply call it like this...

set aVideo = newDigitalVideo "videoName"

Then it can do whatever it likes with aVideo without being forced to clog
up the global name space with unnecessary globals.

Or it could use something like this if it needs to track a bunch of them.
..

add gVideoList, newDigitalVideo "videoName"

where gVideoList is a global list... It's just more flexible this way.

--

Page 138: Right column, last example
As we've seen many times already in this manual it's not a very good idea
to use "the" as a prefix for your variables. It leads to confusion into
thinking they may be properties... "theNetID" is too easily mistaken as
some bogus Lingo property called "the netID" It leads to confusion for
newbies... ;-)

--

Page 139: Right column, downLoadNetThing
The description of downLoadNetThing refers to testing whether the
preloading has completed, that should be testing whether the downloading
has completed. Also it states it's disabled in a Shockwave movie playing in
a behavior. This should read that it's disabled in a Shockwave movie
playing in a browser.

--

Page 142: frameReady discussion.
It should be mentioned that this tests for all cast members located in the
score for a specific frame or range of frames. It does not test for
castmembers that may be loaded under Lingo control. Unless you use
frameReady() to test if the entire movie has loaded. Lingo loaded
castmembers would need to be tested separately using the mediaReady of
member property. This would be the case if you used a lingo controlled
button that showed some other media member when clicked.

--

Page 154: Right column fourth paragraph
The text states "and then displays the reference number contained in me for
this instance of the behavior"

I don't see anything in the handler example that would do that... Creating
a new behavior with that handler changes the color but does not display a
reference number anywhere. So either the text is incorrect or the handler
is missing something...

--

Page 156: Left column first example

The first example confuses the issue more than it clarifies since it's
missing the addProp command and the name of the list being added to.

A behavior's properties are nothing more than properties of a property
list. For each behavior property the associated value is nothing more than
a property list itself that contains a list of that particular properties
attributes.

A behavior's property list can be built directly or by adding individual
properties to an empty list. Then this resulting property list is simply
returned by the on getPropertyDescriptionList handler.

A simple single property list could be created like this:

on getPropertyDescriptionList
   return [ #movement:[#default:5,#format:#integer,#comment:"Speed",
                 #range:[#min:1,#max10]] ]
end
(Direct-L NOTE: place the long line continuation symbol after "Speed", in
the example above. I left it off because it messes up the formatting when
this is posted to Direct-L.)

You can build a longer list of properties in the same manner or by adding
individual properties to an empty property list like this...

addProp description, #movement, [#default:5,#format:#integer,
                                 #comment:"Speed", #range:[#min:1,#max10]]
(Direct-L NOTE: place the long line continuation symbol after #integer, in
the example above. I left it off because it messes up the formatting when
this is posted to Direct-L.)

the last sentence in the first bullet should also be reworded as follows:
If building the property list directly, a colon separates the name's
definition and the list of attributes. If using the addProp method, a comma
separates the name's definition and the list of attributes.

--

Page 159: Determining which behaviors are attached to a sprite

The first paragraph is incorrect. The scriptInstanceList can indeed be
tested AND set. You can add new instances of behaviors to this list and
modify it at will if you wish. Be sure you know what you are doing
though... ;-)

Whew!! Now I'm tired...

May all your Lingo code be bug free!! ;-)