Articles Archive
Articles Search
Director Wiki
 

Screen Capture Screen Saver

December 31, 2002
by Andrew Murchie

Animating characters, or any suitable graphics, over a user's desktop gives a really interesting effect that can be used in any number of ways. In this article I'd like to cover a technique that I used to develop a particular screen saver with an animating, slightly naughty donkey, popping up and "messing" all over the users desktop. It's a bit of a "grab bag" of lingo, but hopefully demonstrates real life use for a particular project. The final (shockwave projector) screen saver for PC's can be downloaded from my site and you will find the source files at the end of this article.

Apology

Before we get going I must apologise for not completely behaviorising the code -- however I'm sure you can take the pieces you like and adapt them to be a little more generic.

The Animation

The first stage of the process is to create the little looping animation, which is going to be the animating character. I'm not going into any depth here as it is a basic Macromedia Flash timeline animation. This was hand-drawn and scanned into Adobe Photoshop, then the graphics were traced in Macromedia Freehand and exported to Flash to build the animation. The animation was then exported as a SWF, ready to be imported and used within the screen saver.

The Screen Capture

Now to the most interesting part of building this screen saver: capturing the screen the animation plays over. The trick here is to start with a 1-pixel square Stage for your movie and set it off to the top left of the screen at loc 0,0. Next use Kent Kersten's free Screen Xtra to capture the user's desktop and replace a dummy image. Finally this image is centred on the Stage, which is resized to match the monitor resolution. Make sense? I hope so!

This is actually incredibly easy to achieve, the handler for this handy little trick is as follows.

on doScreenStuff

  --screengrab the desktop into a cast member named "background"
  ScreenToMember (the deskTopRectList[1][1],the deskTopRectList[1][2], the deskTopRectList[1][3],the deskTopRectList[1][4], "background")
  --restore the name of the cast member
  member (5).name = "background"
  --Set the desktop size variables for use in the rest of the script
  pRight = integer (the deskTopRectList[1][3])
  pBottom = integer (the deskTopRectList[1][4])
  --Reset the stage size to match the desktop
  (the stage).rect = rect (0, 0,pRight, pBottom)
  --Position the desktop background image sprite on the centre of the screen
  sprite(1).loc = point ((integer (pRight/2)),(integer (pBottom/2)))
  --Switch the cursor to the blank version
  cursor 200
  --I like to call a little updatestage to trigger a redraw as soon as this
  is done
  updatestage

end

So, piece by piece, how does it work? The important term is deskTopRectList -- this returns the current resolution of the monitor (or monitors if there is more than one) in the format [rect(left,top,right,bottom)]. The first call then using this is to the Xtra; this captures an image of the desktop and uses the deskTopRectList[monitor][coordinate] to get the size of the main monitor, then saves it into cast member5, which we then name "background". I then request the info for the width and height of the screen again using the deskTopRectList[monitor][coordinate] -- I could have done this first but what the heck, you only live once, so live dangerously! The Stage is then resized to match the resolution of the monitor, and finally we move the background sprite into the centre of the stage. I like to call an updatestage at this point -- I'm not sure whether it's superstition or I'm just plain old- fashioned, but I do it anyway.

Randomising the Animation

The next piece of the puzzle is placing the animation randomly on screen, pretty obvious and easy. There are a multitude of ways to achieve the randomised placement and mine is probably not the most graceful, especially with my aversion to formal mathematics. However here we go: Director's playback head hits the script in the frame containing the Flash sprite (which is set not to loop). The frame script checks if the animation is not playing and decides what to do based on this. If the animation has stopped playing, the sprite is moved to a new random location on the screen and the animation restarts - easy. Let's have a look at the script.

on enterFrame me

  --Check if the animation is playing or not
  if not sprite (2).playing then
    --move sprite to random location
    sprite (2).loc = point (((random ((the stageright) - 200)) + 100), ((random ((the stageBottom) - 200)) + 100))
    --set it to play again
    sprite (2).play ()
  end if

end


on exitframe me

  --hey, no comment you know what this does
  go the frame
  --...and check if the mouse has moved
  testMouse

end

The only line that may need some explaining is the randomising of the sprite location. Apologies for the number of brackets but I was aiming for a world bracketing record with this line. As we all know a sprite's loc is returned as a point -- so we are generating a horizontal value based on the screen width minus 200; this is to make sure that the sprite does not go off the screen to the right. Then we are adding 100 to this value to make sure it does not go off to the left either. We then do basically the same for the vertical position. If you follow that, you'll follow anything! We finally give the Flash sprite the go-ahead to play in it's new location and we are nearly ready to roll.

A Little Reminder

Finally we want to leave a little reminder, as my Grandmother used to say, of the donkey's droppings on the screen. Here we will use a little imaging Lingo to replicate the area containing the donkey's droppings into the background image.

--Check to see that the animation is at a suitable point and grab the fresh donkey droppings
if sprite (2).frame > 148 and sprite (2).frame < 150 then
  pAssLocV = sprite (2).locV
  pAssLocH = sprite (2).locH
  member ("background").image.copyPixels ((the stage).image,\
  rect (pAssLocH + 40, pAssLocV + 30,pAssLocH + 100, pAssLocV + 100),\
    rect (pAssLocH + 40, pAssLocV + 30,pAssLocH + 100, pAssLocV + 100))
end if

Firstly we check if we are at a suitable part of the animation to do the capture, I've given it two frames just in case there are any problems and the first frame doesn't trigger the code (belt and braces coding). Once triggered, the code then checks the current location of the animation. A section of the screen is captured back into the member, using these coordinates. The action really happens in the copyPixels line -- this takes the rect of the lower right part of the animation from the Stage and copies this into the identical position in the cast member.

Screensaver Mouse and Key Quit Code

I'm not going to reproduce this here as this is covered in detail by the Multimedia Handyman article "Screen Saver". One point to note here is that it is imperative that when you build your projector you set it to run in a window without a title bar -- this will give us exactly the effect we want with initially just a single pixel in the top left of the screen. The final part of the process is to convert the projector to a screensaver, for which I use CineMac from ScreenTime Media - again this is covered in the Handyman's article so I'm not going to labour the point.

Summary

Of course there are many other things that can be done with this technique, capturing part of the screen and overlaying alpha channelled graphics can be a seriously funky effect. Just consider the possibilities once you have the background image, you can start spinning it, warping it or just plain messin' with it to your hearts content.

Download the sample movie in SIT or ZIP archive format.

Download a free demo of Cine Mac.

All colorized Lingo code samples have been processed by Dave Mennenoh's brilliant HTMLingo Xtra, available from his site at http://www.crackconspiracy.com/~davem/

Andrew Murchie has been working with Director since version 3 and currently heads up the interactive development team for a leading UK marketing agency. In his spare time, when not out and about playing with his young family, he writes and develops ideas for his slightly offbeat personal hobby site rancidass.com.

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