Articles Archive
Articles Search
Director Wiki
 

Now you see it. Now you don't!

May 24, 1999
by Irv Kalb

Techniques for showing and hiding sprites

Very often in a multimedia piece, there is a requirement of being able to show or hide an item on the screen. Many techniques have been developed to handle this requirement. I'll discuss a few, and present what I think is the best solution.

All of these techniques assume that you have puppeted the channel first, either through an explicit:

puppetSprite <someChannelNumber>, TRUE

or through "auto-puppeting" by using behaviors.

Technique #1: Set the visibility on or off

What could be more simple. Lingo has a property for each sprite which you can turn on or off like this:


set the visible of sprite x = TRUE  
-- or FALSE

Beginning Lingo programmers use this all the time. While this does work, and work well, this approach has a major drawback during development. It is not well documented, but "the visible" property is not really a property of the sprite, it is a property of the channel. The difference is subtle but very important. A property of the sprite ends (and reverts) when a sprite span is finished. However, a property of a channel stays until it is explicitly reset.

Here's what can happen. You are running a program and you turn off the visibility of a sprite to hide some graphic, and then jump to some other frame in the score. When you get to the target frame, which may have a very different layout in the score, incorrectly, the visibility of that channel is still off.

Worse yet, let's say you are using this technique and are running a program where you have turned off the visibility of one or more sprites. Now, you encounter a bug and need to stop running your program, make some changes, and run again. When you stop Director, any channels whose visibility had been turned off remain that way.

In both of these cases, depending on your layout, it may appear that one or more sprites have disappeared from the screen. Since Director does not turn the visibility back on for you, this can lead to some real debugging headaches. You often find yourself uttering, "What's going on here?", and much head scratching ensues.

For this reason, I never use "the visible of sprite".

Technique #2: Put your graphic offstage until you need it.

This is a common technique. Let say that you need to have a sprite appear under some circumstances at location point(200, 400). When laying out the score, you can easily place the bitmap at that point. Then you can bring up the "Tweak" window and change the vertical coordinate to move the bitmap up 1000 pixels to location point(200, -600). In this location, it is "above" the screen and the user will not see it. When you want to show the item, you execute code like this:

if the locV of sprite x < 0 then
  set the locV of sprite x = (the locV of sprite ¬
    x) +1000
end if

Likewise, when you want to hide it, you execute code like this:

if the locV of sprite x > 0 then
  set the locV of sprite x = (the locV of sprite ¬
    x) - 1000
end if

I have used this technique for years. However, the basic drawback of this technique is that it is not easy to see how things will line up on the stage while you are just moving through the score and not running in Director. Further, because you don't see the items when you are looking at the score, if you need to move things around in your scene, you must remember to bring all the items which are off-stage back on-stage, re-align them, and then move them off-stage again. A very tedious process.

Technique #3: The single dot castmember

I have seen many Director developers use this technique. You go to the paint window and create a bitmap with just a single dot in it, and name it, for example, "SingleDot". To place the real bitmap, you just drag the bitmap that you want to show into the proper location in the score. Once that's set, you just exchange (Command/Control E) with the "SingleDot" cast member. At run time, you substitute the bitmap you want using the following Lingo:

set the member of sprite x = member "whatever"

Then to hide it again, you reverse it by using:

set the member of sprite x = member "SingleDot"

This has the advantage of having the proper coordinates without needing any code to change locations.

The main drawback of this technique is that, depending on exactly where the dot is located, the user might be able to see this single pixel against the background. For example, if you created a black dot, it would be easily seen against a white background, or vice versa, a light pixel dot could easily be seen against a dark background.

Technique # 4: The ideal solution

From looking at the above techniques it would seem that the ideal solution would be one that would not use "the visibility" property, would allow you to define the correct coordinates at author-time, and would not even be as visible as one pixel. Well, luckily, that solution does exist.

Obviously, the only thing smaller than a one-pixel graphic is a zero-pixel graphic - and that is exactly the solution. You can open the paint window, create a new bitmap, and just give it a name. That's it, just a name. I use the name "Hide".

The approach to using "Hide" is exactly the same as the "SingleDot" cast member above. Place the graphic you want in the correct location, then exchange it for the "Hide" cast member. Director will maintain the locH and locV. Again similar to the single dot cast member solution, when you want to show the sprite, you use the same line of Lingo:

set the member of sprite x = member "whatever"

Then to hide it again, you reverse it by using:

set the member of sprite x = member "Hide"

If you like to use behaviors, you could attach the following behavior to any sprite that you want to hide or show. This behavior allows you to choose which member to show, and to set the initial state of the graphic to either "showing" or "hidden".

-- Hide and show behavior
property spriteNum  
-- sprite number
property pnmHide  
-- number of member Hide
property pnmShow  
-- number of the member to show
property pMemberToShow  
-- name of the member to show
property pStartingState  
-- Initial state of graphic

on beginSprite me
  set pnmHide = the number of member "Hide"
  set pnmShow = the number of member pMemberToShow
  case pStartingState of
    "Hidden":
      mHide(me)
    "Showing":
      mShow(me)
  end case
end

on mHide me
  set the member of sprite spriteNum = pnmHide
end

on mShow me
  set the member of sprite spriteNum = pnmShow
end

on getPropertyDescriptionList 
  set lDescription = [:] 
  
  addProp(lDescription, #pMemberToShow, ¬
    [#default: "", #format: #member, ¬
    #comment: "Member to show"])
    
  addProp(lDescription, #pStartingState, ¬
  [#default:  "Hidden",  #format: #string, ¬
  #range: [ "Hidden", "Showing"], #comment: ¬
  "Starting state?"]) 
     
  return lDescription
end

on getBehaviorDescription
  return "Allows you to show and hide a member"
end

Then, when you want to show that sprite, you execute a:
sendSprite(x, #mShow)
And when you want to hide it, do a:
sendSprite(x, #mHide)

The technique of using a "Hide" cast member should make the job of hiding and showing sprites very easy indeed!

Irv Kalb has been working as an independent software developer in Director and Lingo for over ten years. He has written extensively on object oriented programming in Lingo, and his on-line Ebook on this topic can be found at http://www.furrypants.com/loope. Irv is always interested in discussing new projects.

Copyright 1997-2017, Director Online. Article content copyright by respective authors.