Scrolling text with Graphics
November 30, 1999
by Mario Victor
Scrolling graphics within a text field has been a perpetual problem in Director. But as you can see below, it's not impossible to do.
A sample movie is available for download in Mac or PC format. This is a D7 movie.
How is this achieved? Well, let's think about the problem. What happens when the user clicks on the arrows? Since text and bitmaps are different sprites (the graphics aren't actually embedded inside the text but rather the text is arranged so that it leaves enough space for the graphic to simulate it wrapping around it), we have to make sure that when the text moves, the bitmaps move as well, in the same direction and at the same speed and distance. So all that you need to do is to create a set of behaviors that move the sprites in the correct direction when the user clicks on the arrows and co-ordinates all the different sprites so that the movement appears seamless.
The first step involves the correct distribution of the cast members in the the score. The background image must be in the lowest channel right after the text, the bitmaps, the frames and the arrows. As you can see, the background image creates the shadows for the green frames.
I created the image in Photoshop and saved it with an alpha channel so that Director could use the transparency values.
Now lets look at the Lingo scripts. I begin by creating a prepareMovie handler in a movie script where I declare the global variables. I create a single global variable, a property list, and use that to store all the variables, and values, that I use in the movie. Then when I need to add a new variable I can simply append it to the existing list instead of having to create a new variable.
on prepareMovie global g g = [:] addProp g,#offset,10 addProp g,#TextSprite,2 addProp g,#boundary,[#up:10,#down:-316,#left:67,right:-256] end
The g.offset indicates the offset amount, in pixels, to move the text and graphics when the user scrolls them. In this case a displacement of 10 pixels was used. The g.textSprite contains the number of the sprite where the text member is located. The g.boundary determines the limit of displacement of the text in the four corners of the screen area. For example, "#up:10" indicates that 10 is the highest value possible for the locV of the text sprite, the lowest value is -316, while 67 to -256 is valid range for locH. You can determine the values of boundary dragging the text sprite through the stage and checking the values of locH and locV.
Now we need to create an offset behavior to attach to the text and bitmaps that must be scrolled. There's a handler for each possible movement (up, down, left, right). In each one, the sprite moves the amount of pixels in g.offset. The handles are activated by the sendAllSprites command sent by arrow button behavior (detailed below).
-- offset behavior global g property mySprite on beginSprite me mySprite = sprite(me.spriteNum) end on down me mySprite.rect = offset(mySprite.rect,0,g.offset) end on up me mySprite.rect = offset(mySprite.rect,0,-g.offset) end on right me mySprite.rect = offset(mySprite.rect,g.offset,0) end on left me mySprite.rect = offset(mySprite.rect,-g.offset,0) end
Then we need the behavior that is attached to each of the arrows. You determine the arrow type as a parameter (up,down,left,right) when you apply the behavior by dragging it onto a sprite. The sendSprites handler is called during a mouseUp event and during all the time that user is pressing the mouse button. If it is a legal movement -- inside of the borders (g.boundary) -- then the corresponding message is sent to all sprites, but only will affect the sprites with the offset behavior attached, of course.
-- arrow behavior global g property kind on getPropertyDescriptionList me cpos = [:] addProp cpos,#kind,[#comment:"Arrows type:",¬ #default:#up, #format:#symbol, ¬ #range:[#up,#Down,#right,#left]] return cpos end getPropertyDescriptionList on mouseUp me sendSprites() end mouseUp on mouseWithin me if the stillDown then sendSprites() end mouseWithin on sendSprites me st = sprite(g.TextSprite) case kind of: #up: if (st.locv - g.offset) < g.boundary.up then nothing else sendAllSprites(#up) #down: if (st.locV + g.offset) > g.boundary.down then nothing sendAllSprites(#down) #right: if (st.locH+g.offset) > g.boundary.right then nothing else sendAllSprites(#right) #left: if (st.locH-g.offset) < g.boundary.left then nothing else sendAllSprites(#left) end case end sendSprites
The final thing in this sample is to create the hyperlinks for text and bitmaps. For the bitmaps, just use a go to command in the mouseUp handler. For the text, I manually entered the hyperlinks with the text inspector and I used as the name of the hyperlink the same name of the marker that I wanted to go to. This behavior shows how to read those hyperlinks and use them to naviagte inside the movie. For a more in-depth look at hyperlinks check out the recent hyperlinks article posted on DOUG.
-- text hyperlink behavior global g on beginSprite me g.textSprite=me.spriteNum end on hyperLinkClicked me, data, range go data end
In beginSprite I put the sprite number into the value of the g.textSprite. This way the number of the channel of the text will be always updated, even if you moved its place.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.