Saturday, 7 April 2012

Tidy Function Calls

The changes in the last post might seem a little counter productive, they seemed to simply make all the variables longer and it's hard to see the benefit right away.

What it did was to group the information into two global variables and it was part one of a two part process.

Now we tidy up those variables by replacing every statement that reads a UDT field with a function call to provide the same information.

To Start, we add the following functions to the end of the program

// Return Functions  - Display

function PhysWidth()
endfunction display.physWidth#
function PhysHeight()
endfunction display.physHeight#
function VirtWidth()
endfunction display.virtWidth#
function VirtHeight()
endfunction display.virtHeight#
function IconSize()
endfunction display.iconSize#
function TextHeight()
endfunction display.textHeight#
function LastFPS()
endfunction display.lastFPS#

// Return Functions  - Panel

function PanelHeight()
endfunction panel.height#
function PanelSpeed()
endfunction panel.speed#
function PanelIsOpen()
endfunction panel.isOpen
function PanelImage()
endfunction panel.image
function PanelSprite()
endfunction panel.sprite
function PanelText()
endfunction panel.text
function PanelSound()
endfunction panel.sound
function PanelIconMax()
endfunction panel.iconMax

Next we replace all references that read the individual fields with the function calls above, which removes all direct variable reads from the main program.

Next we do the same with direct variable writes in the do/ loop.

A new function is added to get the frame rate and set the panel speed.

function LoopStart()
   display.lastFPS# = screenFPS()
   panel.speed# = panelHeight() / (lastFPS() * 1.25)
endfunction

This is called at the start of every loop immediately after the do command

LoopStart()

Next we add a function to toggle the tray open status

function ToggleTrayOpen()
   panel.isOpen = 1 - panelIsOpen()
   playSound( panelSound() )
endfunction

And put a call to this function, where these two commands used to be.

if getPointerPressed() > 0
   if getPointerY() >= getTextY( panelText() ) and getPointerY() < getSpriteY( panelSprite() )
      ToggleTrayOpen()
   endif
endif

Now there are no direct variable accesses of any kind in the main do / loop.

This means that any problems with values being changed incorrectly can be isolated to the functions which change the variables.  The main loop is effectively "safe" now.

Finally, we create a new function which will handle the moving of the panel

function MovePanel( distance# )
   setSpriteY( panelSprite() , getSpriteY( panelSprite() ) + distance# )
   setTextY( panelText() , getTextY( panelText() ) + distance# )
   PositionPanelIcons()
endfunction

And change the loops which previously moved the panel to call this with either a positive or negative value

if panelIsOpen() = 1
   if getSpriteY( panelSprite() ) > ( PhysHeight() - panelHeight() )
      MovePanel( -panelSpeed() )
    endif
else
   if getSpriteY( panelSprite() ) < PhysHeight()
      MovePanel( panelSpeed() )
    endif
endif

Now there is only one set of instructions which moves the panel, isolated in one function

All this now gives us
(unformatted for copy / paste to editor)

// April 7th - All tabs converted to 3 spaces
#constant PANEL_ROWS   3
#constant PANEL_COLS   4

type displayType
   physWidth#
   physHeight#
   virtWidth#
   virtHeight#
   iconSize#
   textHeight#
   lastFPS#
endtype

global display as displayType
display.physWidth# = getDeviceWidth()
display.physHeight# = getDeviceHeight()
display.iconSize# = PhysWidth() / PANEL_COLS
display.textHeight# = PhysHeight() / 20.0

setVirtualResolution( PhysWidth() , PhysHeight() )
display.virtWidth# = getVirtualWidth()
display.virtHeight# = getVirtualHeight()

type panelType
   height#
   speed#
   isOpen
   image
   sprite
   text
   sound
   iconMax
endtype

global panel as panelType
panel.height# = IconSize() * PANEL_ROWS
panel.speed# = 0.0
panel.isOpen = 0
panel.iconMax = PANEL_ROWS * PANEL_COLS

panel.Image = loadImage( "panel.jpg" )
setImageWrapU( PanelImage() , 1 )
setImageWrapV( PanelImage() , 1 )

panel.sprite = createSprite( PanelImage() )
uScale# = getImageWidth( PanelImage() ) / PhysWidth()
vScale# = getImageHeight( PanelImage() ) / PanelHeight()
setSpriteUVScale( PanelSprite() , uScale# , vScale# )
setSpriteSize( PanelSprite() , PhysWidth() , PanelHeight() )
setSpritePosition( PanelSprite() , 0 , PhysHeight() )

panel.text = createText( "Objects" )
setTextSize( panelText() , textHeight() )
setTextAlignMent( panelText() , 1)
setTextPosition( panelText() , PhysWidth() / 2.0 , PhysHeight() - TextHeight() )

panel.sound = loadSound("panel.wav")

dim panelIconSprite[ panelIconMax() ]
for icon = 1 to panelIconMax()
   panelIconSprite[ icon ] = createSprite( 0 )
   setSpriteSize( panelIconSprite[ icon ] , IconSize() - 4, IconSize() - 4)
   setSpriteColor( panelIconSprite[ icon ] , 255 , 255 , 255 , 127 )
next icon

imageRef = loadImage( "finger.png" )
spriteRef = createSprite( imageRef )

PositionPanelIcons()

do
   LoopStart()
   print( "FPS: " + str ( lastFPS() ) )

   if getPointerPressed() > 0
      if getPointerY() >= getTextY( panelText() ) and getPointerY() < getSpriteY( panelSprite() )
         ToggleTrayOpen()
      endif
   endif

   if panelIsOpen() = 1
      if getSpriteY( panelSprite() ) > ( PhysHeight() - panelHeight() )
         MovePanel( -panelSpeed() )
      endif
   else
      if getSpriteY( panelSprite() ) < PhysHeight()
         MovePanel( panelSpeed() )
      endif
   endif

   setSpritePosition( spriteRef , getPointerX() , getPointerY() )
   printc( "Physical: " )
   print( str( PhysWidth() ) + " x " + str( PhysHeight() ) )
   printc( "Pointer: " )
   print( str( getPointerX() ) + " x " + str( getPointerY() ) )
   sync()
loop

function LoopStart()
   display.lastFPS# = screenFPS()
   panel.speed# = panelHeight() / (lastFPS() * 1.25)
endfunction

function ToggleTrayOpen()
   panel.isOpen = 1 - panelIsOpen()
   playSound( panelSound() )
endfunction

function MovePanel( distance# )
   setSpriteY( panelSprite() , getSpriteY( panelSprite() ) + distance# )
   setTextY( panelText() , getTextY( panelText() ) + distance# )
   PositionPanelIcons()
endfunction

function PositionPanelIcons()
   iconDepth = getSpriteDepth( PanelSprite() ) - 1
   for icon = 1 to panelIconMax()
      offset = icon - 1
      col = offset mod PANEL_COLS
      row = offset / PANEL_COLS
      x = col * IconSize() + 2
      y = row * IconSize() + getSpriteY( PanelSprite() ) + 2
      setSpritePosition( panelIconSprite[ icon ] , x , y )
      setSpriteDepth( panelIconSprite[ icon ] , iconDepth )
   next icon
endfunction

// Return Functions  - Display

function PhysWidth()
endfunction display.physWidth#
function PhysHeight()
endfunction display.physHeight#
function VirtWidth()
endfunction display.virtWidth#
function VirtHeight()
endfunction display.virtHeight#
function IconSize()
endfunction display.iconSize#
function TextHeight()
endfunction display.textHeight#
function LastFPS()
endfunction display.lastFPS#

// Return Functions  - Panel

function PanelHeight()
endfunction panel.height#
function PanelSpeed()
endfunction panel.speed#
function PanelIsOpen()
endfunction panel.isOpen
function PanelImage()
endfunction panel.image
function PanelSprite()
endfunction panel.sprite
function PanelText()
endfunction panel.text
function PanelSound()
endfunction panel.sound
function PanelIconMax()
endfunction panel.iconMax
//

No comments:

Post a Comment