Articles Archive
Articles Search
Director Wiki
 

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.

Mario Victor began programming computers in 1975 and has used Cobol, C, DBASE and Clipper. He began using Director 4 years ago and it was "love at first sight". He is currently a partner and development manager of multimedia creation at BragaVictor in Fortaleza, Cear?° Brazil.

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