Tuesday 17 April 2012

Menu Transitions

In order for the menu to fade in and out, the program needs two things.
  • An indicator that a fade is in progress
  • A value representing the current fade amount.
Fading is a type of transition - a way of changing from one display to another.  Since more transitions may be added later, constants are used to identify the type of transition being used.
#constant TRANS_NONE 0
#constant TRANS_FADEIN 1
#constant TRANS_FADEOUT 2
Initially we have just three, one to indicate no transition and one each for fade in and fade out.  A field is created for the transition type and another for it's counter.   As transitions are display features, these are added to the displayType definition.
   transType
   transCount#
These have the usual return functions.
function Transition()
endfunction display.transType
function TransitionCount()
endfunction display.transCount#
And reset in the Initialise() function.
   display.transType = TRANS_NONE
   display.transCount# = 0.0
When the menu is first displayed, the transition is selected and the counter reset.
   // Activate Transition
   display.transType = TRANS_FADEIN
   display.transCount# = 0.0
This is done immediately after the if getTextVisible( menuText[ 1 ]) = 0 command.

Another line is added within the loop which sets up the text objects, to set the text alpha value to zero.
setTextColorAlpha( menuText[ i ] , 0)
This ensures the text is completely transparent when first displayed.

To fade the text in on each subsequent program loop, we add a second condition before the endif command to start a loop to handle the transition.
elseif Transition() = TRANS_FADEIN or Transition() = TRANSFADEOUT
This block is used whenever the transition is set to fade in or fade out. This way both fades are handled in one block.

Between this line and the endif is the transition routine. We'll do this one part at a time so each can be explained.
thisNumSteps = LastFPS() * MENU_FADE
thisValue# = TransitionCount() + (1.0 / thisNumSteps)
display.transCount# = thisValue#
The number of frames per second multiplied by the length of the transition, gives us the number of frames the transition will take.

Dividing one by the number of steps will give the amount of change per step to make the transition count go from zero to one.  This is added to the current count value anmd stored back in the global field for next time.
thisAlpha = 255.0 * thisValue#
if thisAlpha > 255 then thisAlpha = 255
The count value is converted to an alpha value. But because of maths rounding, it could go slightly over, so a check is used to limit the alpha to 255.
So now we have an alpha value which ranges from just above zero to 255, depending on the counter.
for i=1 to MENU_ITEMS
   if Transition() = TRANS_FADEIN
      setTextColorAlpha( menuText[ i ] , thisAlpha )
   else
      setTextColorAlpha( menuText[ i ] , 255 - thisAlpha )
   endif
next i
A loop is performed to set the alpha value of each of the text items.

Within this loop, if the transition is a fade in, then thisAlpha is used, otherwise 255-thisAlpha is used.
if thisAlpha = 255 then display.transType = TRANS_NONE
Finally, if the alpha value is 255, then the transition is complete and the Transition type set to none.

The menu will now fade in over a period of five seconds and then stop.

When we come to leave the menu, we have the necessary code in place to fade it back out again.

Here is the complete menu function as it stands at the moment.
      case STATE_MENU
         // Menu Code
         if getTextVisible( menuText[ 1 ]) = 0
            // Activate Transition
            display.transType = TRANS_FADEIN
            display.transCount# = 0.0

            thisX# = VirtWidth() / 2.0
            thisY# = VirtHeight() * MENU_DIVTOP
            thisSize# = VirtHeight() * MENU_DIVSIZE
            for i=1 to MENU_ITEMS
               setTextSize( menuText[ i ] , thisSize# )
               setTextAlignment( menuText[ i ] , 1 )
               setTextDepth( menuText[ i ] , DEPTH_MENU )
               setTextPosition( menuText[ i ] , thisX# , thisY# )
               setTextVisible( menuText[ i ] , 1 )
               setTextColorAlpha( menuText[ i ] , 0)
               thisY# = thisY# + getTextTotalHeight( menuText[ i ] ) * 2.0
            next i
         elseif (Transition() = TRANS_FADEIN) or (Transition() = TRANS_FADEOUT)
            thisNumSteps = LastFPS() * MENU_FADE
            thisValue# = TransitionCount() + (1.0 / thisNumSteps)
            display.transCount# = thisValue#
            thisAlpha = 255.0 * thisValue#
            if thisAlpha > 255 then thisAlpha = 255
            for i=1 to MENU_ITEMS
               if thisTransType = TRANS_FADEIN
                  setTextColorAlpha( menuText[ i ] , thisAlpha )
               else
                  setTextColorAlpha( menuText[ i ] , 255 - thisAlpha )
               endif
            next i
            if thisAlpha = 255 then display.transType = TRANS_NONE
         endif
      endcase
This works exactly as hoped, but there is a way it can be improved.  Can you see how?

No comments:

Post a Comment