Articles Archive
Articles Search
Director Wiki

Wheels go spinnin’

September 7, 1998
by Pat McClellan

Dear Multimedia Handyman,

I am trying to make a wheel spin (like on wheel of fortune) and when it stops the user will have to answer a question based on the color of that part of the wheel. I need it to stop on (or have the appearance of) a random color.

5335 / at /

Dear 5335,

You've got several options to get a spinning wheel. First, you could do it the "traditional Director-way" by creating a series of graphic cast members which represent the various degrees of rotation for the wheel. This approach would require you to cycle through the cast members in order to "animate" the wheel spin. If you animate across a series of frames, you could use a random number to determine which frame you stop on. If you use a Lingo script to swap cast members, again, you could use the random() function to determine when to stop.

For a true rotating cast member, you have 2 options. The first is the Effector Set xtra from Media Lab. This xtra is great (an fast) at generating smoothly rotating, anti-aliased sprites. The lingo is built right in, so it shouldn't be very difficult to customize some of the behaviors. The major drawback for using any xtra is that, if you want to deliver the program as Shockwave, the user must download and correctly install the xtra. For this reason, I chose another approach.

Now that Shockwave will playback Flash assets integrated into Director movies, this seems like the best approach for internet delivery of a rotating sprite. The only drawback is that Flash assets are very demanding on the processor, so you should re-read David Calaprice's recommendations [link to David's article in UD] on optimizing performance.

For our example, I created a Flash format graphic of the wheel, with colors and text included.

<img src="howto/handy_articles/handy44/wheel.swf" width="122" height="122" />

I then imported the flash graphic into my Director cast as an internal Flash Asset cast member (not linked). With a Flash asset, you can use new Flash Lingo -- "the rotation of sprite whatever" -- to spin it around. Notice that I adjusted the rotation in the cast member's dialog box so that it starts in a position that is 30 degrees rotated from the original image. But, it is important to note that at Zero degrees of rotation, the "pointer" points exactly to a line between segments. The importance of this will become obvious later. For now, give my demo a spin.

To make the wheel spin, I created a behavior and attached it to the button, though it could easily have been placed on the wheel itself. So let's look as what we need this behavior to do:

As I wrote this behavior, the trickiest part was making the wheel decelerate over time. This is accomplished by using a property I called pDrop -- a "friction" value which is calculated by dividing the speed (degrees of rotation per frame) by the maximum duration of the spin. This assures that over the duration of the spin, the wheel will have dropped its speed to 0.

To get the randomnesss factored in, I use a random number between 1 and 15, which is subtracted from the maximum speed. For example, let's say you set the maximum speed (degrees of change per frame) to 45, as I have in the demo. Now, each time I press the spin button, a random number between 1 and 15 is generated and subtracted from 45. So, each spin will randomly fall between 30 and 45 degrees of rotation per frame.

So let's look at the code.

-- Wheel o' Fortune Behavior 
-- copyright © 1998 ZZP Online, LLC
--This behavior simulates a spinning wheel,
-- like on the popular game show.  It can
-- only be used with Flash Assets because
-- it uses the "rotation" property.
property pSegments
-- how many pie shaped pieces?
property pSpeed
-- adjusts the maximum speed of the spin 
-- (degrees of rotation/frame)
property pDuration
-- adjusts the maximum duration of a spin 
-- to stop sequence (in ticks)
property pSprite
-- which sprite number is the Flash Asset?
property pSpinFlag
-- flag to indicate whether to spin the wheel 
-- on exitFrame
property pForce
-- randomizes the individual spins
property pTicks
-- used to track duration of spin
property pLine
-- 360/pSegments
property pRamp
-- a flag to ramp up the spin speed
property pDrop
-- rate of speed drop in degrees/tick 
-- (pSpeed/pDuration)
property pDegrees
-- the number of degrees to change
on getPropertyDescriptionList me
  set pdlist to [:]
  addprop pdlist, #pSegments, [#comment:"How many ¬
    pie-shaped pieces?", #format:#integer, #default:6]
  addprop pdlist, #pSpeed, [#comment:"Max degree of ¬
    spin/frame:", #format:#integer, #default:45, ¬
    #range:[#min:30, #max:60]]
  addprop pdlist, #pDuration, [#comment:"Max ticks ¬
    to stop:", #format:#integer, #default:8*60]
  addprop pdlist, #pSprite, [#comment:"Which sprite ¬
    spins?", #format:#integer, #default:1]
  return pdlist
end getPropertyDescriptionList
on beginSprite me
  set pSpinFlag to #stopped
  set pLine = 360/pSegments
  set pDrop = pSpeed/(1.00 * pDuration)
on mouseDown me
  if pSpinFlag = #stopped then
    set pRamp to #start
    set randomFactor = random (15)
    set pForce = pSpeed - randomFactor
    set pSpinFlag to #spin
    put "Spinning..." into field "display"
  end if  
on exitFrame me
  if pSpinFlag = #spin then
    case pRamp of 
      #start :  -- ramp speed to 1/2
        set pDegrees = 0.50 * pForce
        set pRamp = #half      
      #half:  -- speed is maxed
        set pDegrees = pForce
        set pRamp = #max
        set pTicks = the ticks     
      #max: -- spin slows
        set lapse = the ticks - pTicks
        set pTicks = the ticks -- reset
        set drag = lapse * pDrop
        set pDegrees = pDegrees - drag  
    end case
    set curRotation = the rotation of sprite pSprite
    set newRotation = curRotation + pDegrees
    if newRotation > 360 then
      set newRotation = newRotation - 360
    end if
    set the rotation of sprite pSprite = newRotation
    --     check to see if it is stopped
    if pDegrees « 1 then
      set pSpinFlag = #stopped
      put "pSpinFlag =" && pSpinFlag
    end if    
  else -- avoid stopping on a line
    set curRotation = integer(the rotation of ¬
      sprite pSprite)
    set segLine = curRotation mod pLine
    case segLine of
      58,59,0: bounce me, - 1
      1,2: bounce me, 1
    end case
    -- output the result
    set whichSeg = (curRotation/(360/pSegments)) + 1
    put "Segment" && whichSeg into field "display"
  end if
on bounce me, degrees
  set curRotation = the rotation of sprite pSprite
  set newRotation = curRotation + degrees
  set the rotation of sprite pSprite = newRotation

Now, to explain the important part I was referring to before. Toward the end of the exitFrame handler, there's a section which avoids stopping on a line between pieces. The way that it checks is this: 360 divided by the number of segments is 60. So if the wheel comes to rest at 0, 60, 120, 180, 240, or 300 degrees of rotation, the pointer is pointing at a line and needs to be adjusted. So the wheel gets "bounced".

The on bounce handler is there to replicate the behavior of the "pegs" on the real Wheel which keep the wheel from stopping on a line. In our case, if the wheel comes to rest within 2 degrees of the line, it gets advanced or bumped back a couple of degrees so that there's no question which segment is selected.

You'll probably want to alter the lines of code which relate to how the result of the spin is handled. In this example, I simply plugged the result into a field for display on the stage. In a game, you would want to create a lookup table so that the selected segment could be correlated to a score value. In the demo, the values are as follows:

- Segment 1 = yellow
- Segment 2 = blue
- Segment 3 = green
- Segment 4 = red
- Segment 5 = magenta
- Segment 6 = cyan

Good luck with your project!

Patrick McClellan is Director Online's co-founder. Pat is Vice President, Managing Director for Jack Morton Worldwide, a global experiential marketing company. He is responsible for the San Francisco office, which helps major technology clients to develop marketing communications programs to reach enterprise and consumer audiences.

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