DreamLight Interactive

Shockwave Game Design

DreamLight.com

Search/Index Help
Click to view DreamLight's 3D Animation Demo Reel
20+ Years of Award-winning Multimedia, 1987-2007

Object Oriented Lingo Programming of an Award-winning Interactive Shockwave Game

 

Previous Contents Next

Object Oriented Lingo Programming

Top

The real power of DreamLight Verttice lies in the object oriented Lingo code that makes it all work.

In order to keep this relatively short, we will only scratch the surface of the programming used in Verttice here. The original source code for DreamLight Verttice was included on Macromedia’s first Authorized Developer CD-ROM. The code here was originally written in the first version of Director capable of object oriented programming, Director 3, using factories. As such, the syntax seen here no longer works in current versions of Director. The concepts used are still relevant though, so the samples do provide a useful learning purpose. Newer versions of Director make object oriented programming much easier than ever before.

For a more current example of just how far we can push object oriented Lingo programming, download and try Quipples, The Internet Game Show of Satirical Riddles, hosted by NineOh, the world’s first Autiton, Intelligent Interactive 3D Character.

For additional Lingo samples, tips & tricks, be sure to visit the DreamLight Director Talisman

BlastOff! The Award-winning 3D Animated Short film by Michael Scaramozzino - Special Edition DVD

Please Support Our Continuing Independent Film Making Efforts!
Order your Award-winning BlastOff! Special Edition DVD today!

BlastOff!™ Merchandise Available @ Telebites.com BlastOff! T-Shirts BlastOff! Hats BlastOff! Mugs BlastOff! Calendar, Prints & Posters BlastOff! Mousepads

A Stack Factory

Top

This is a simple building block that was used throughout Verttice. One of the data structures that we needed to keep track of objects was a stack. Rather than a normal array, a stack allows you to push items onto it for storage and then pop them back off when needed. The last item pushed on the top of the stack is the first item popped off it.

Before we write the code, we first map out the object. We list all input, output, and methods, that the object will need to manipulate. This is not a complete detail, but rather an overview to help plan out the code.

[Object Map]

The dumpObject() Handler for Cleaner Code Writing.

Since Director 3 Factory objects needed to be explicitly disposed of, or Director could crash, we wrote a dumpObject handler to make such manual disposal easier to manage by the objects themselves. Newer versions of Director have no such problem.

on dumpObject whichObject
  -- releases and disposes of an object
  if objectP(whichObject) then
    whichObject(mRelease)
    whichObject(mDispose)
  end if
  return whichObject -- pass back empty object pointer
end dumpObject


--========================================================================
-- makeStack: factory
--========================================================================
--* (C) 1993 DreamLight(R) Incorporated, All Rights Reserved
--------------------------------------------------------------------------
-- Used to create and control stack arrays
-- Stacks are built from position 1 up
--------------------------------------------------------------------------
factory makeStack
  
method mNew masterObject, theObject
  instance myLength
  
  -- does this stack hold master objects that need disposal or redundant
  -- pointers to objects that will be disposed of elsewhere. This is 
  -- critical because if you attempt to dispose of a dangling pointer 
  -- the system will crash miserably
  instance myMaster  
  
  set myMaster = masterObject
  set theObject = dumpObject(theObject) -- delete any pre-existing objects
  set myLength = 0
  me( mReset )
end mNew
--
method mReset
  repeat with i = 1 to myLength
    me( mPut, i, 0)  -- reset contents
  end repeat
  set myLength = 0 -- zero out the length value
end mReset

--------------------------------------------------------------------------
-- Communication methods
--------------------------------------------------------------------------
method mName
  --** DEBUGGING METHOD
  Return "Stack:Factory"
end mName
--
method mPush value
  set myLength = myLength + 1  -- increment length value
  me( mPut, myLength, value )  -- put value at end
end mPush
--
method mPop
  if myLength > 0 then
    set value = me( mGet, myLength ) -- get value from end LIFO
    set myLength = myLength - 1      -- decrement length value
    return value
  else
    return #StackUnderflow
  end if
end mPop
--
method mPull
  if myLength > 0 then
    set value = me( mGet, 1 )  -- get value from start of stack FIFO
    me(mRemove, 1)             -- remove first value
    return value
  else
    return #StackUnderflow
  end if
end mPull  
--
method mRemove position
  if (myLength > 0) AND¬
     (position > 0) AND (position <= myLength) then
    repeat with i = position to myLength - 1
      me( mPut, i, me( mGet, i + 1 ) ) -- Copy value down one
    end repeat
    set myLength = myLength - 1 -- decrement length value
  end if
end mRemove
--
method mGetLength
  return myLength
end mGetLength
--
method mPutLength whatLength
  set myLength = whatLength
end mGetLength
--
--** DEBUGGING PROCEDURE
method mShow
  put "** makeStack: mShow"  
  put "Stack length:" && myLength
  repeat with i = 1 to myLength
    set value = me(mGet, i)
    if objectP(value) then set value = value( mName )
    put "Stack position" && i && ":" && value
  end repeat
end mShow

method mRelease
  
  --**DEBUG
  --put "makeStack: mRelease"
  
  if myMaster then  -- only dispose of objects if this is a master stack
    repeat with i = 1 to myLength
      me(mPut, i, dumpObject(me(mGet, i)) ) -- delete any stored objects
    end repeat
    set myLength = 0
  else   -- otherwise it holds numbers or pointers
    me(mReset)
  end if
end mRelease

--------------------------------------------------------------------------
--END makeStack
--------------------------------------------------------------------------

An Array Table

Top

[Object Map]

This is the code that creates the table...

--========================================================================
-- makeTable: factory
--========================================================================
--* (C) 1993 DreamLight(R) Incorporated, All Rights Reserved
--------------------------------------------------------------------------
-- Used to create and control square 2D tables
-- The table is accessed by Row, Column
-- The center of the table is 0,0 so it must be odd sized
-- The actual array is (0 - size-1 x 0 - size-1 )
-- The table methods convert all coords by adding 1/2 size-1
--------------------------------------------------------------------------
factory makeTable
  
method mNew size, theObject
  -- Create the squaretable size x size
  instance myShift     -- The length to shift coordinates by
  instance myTempRow   -- Temp variable used to access rows
  instance myTempNum   -- Temp variable for indexing
  instance myTable
  
  set theObject = dumpObject(theObject) -- delete any existing objects
  
  set myShift = ( size - 1 ) / 2
  
  -- Create Table
  set myTable = makeStack(mNew, True, myTable)
  repeat with whichRow = - myShift to myShift
    set myTempNum = me( mShiftIt, whichRow ) 
    myTable(mPut,myTempNum,makeStack(mNew,True,myTable(mGet,myTempNum)))
    repeat with whichCol = -myShift to myShift
      set myTempRow = myTable(mGet, myTempNum)
      myTempRow(mPush, 0)
    end repeat
  end repeat
end mNew
--
method mReset
  repeat with whichRow = - myShift to myShift
    repeat with whichCol = - myShift to myShift
      me( mPutIt, whichRow, whichCol,0) 
    end repeat
  end repeat  
end mReset

--------------------------------------------------------------------------
-- Communication methods
--------------------------------------------------------------------------
method mName
  --** DEBUGGING METHOD
  Return( "Table")
end mName
--
method mGetIt whichRow, whichCol
  -- Retrieve the value or object located at whichRow, whichCol
  set myTempRow = myTable( mGet, me(mShiftIt, whichRow) )
  return myTempRow( mGet, me(mShiftIt, whichCol) )
end mGetIt
--
method mPutIt whichRow, whichCol, theValue
  -- Place the value or object in table at whichRow, whichCol
  set myTempRow = myTable( mGet, me(mShiftIt, whichRow) )
  myTempRow( mPut, me(mShiftIt, whichCol), theValue )
end mGetIt
--
method mShiftIt coordinate
  -- Shifts coordinates from +-2 to 1-5 for stack access
  return coordinate + myShift + 1
end mShiftIt
--
method mShow
  -- **FOR DEBUGGING PURPOSES**
  put "--------------"
  put "* LATTICE  *"
  put "--------------"
  repeat with whichRow = - myShift to myShift
    set row = ""
    repeat with whichCol = - myShift to myShift
      set myTempNum = me( mGetIt, whichRow, whichCol) 
      if myTempNum >= 0 then put " " after row
      if objectP(myTempNum) then put myTempNum(mName) after row
      else put myTempNum after row
      put " " after row
    end repeat
    put row
  end repeat  
  put "--------------"
end mShow
--
method mRelease
  -- Dispose of the table
  
  --**DEBUG
  --put "makeTable: mRelease"
  
  repeat with whichRow = - myShift to myShift
    set myTempNum = me(mShiftIt, whichRow)
    myTable(mPut, myTempNum, dumpObject(myTable(mGet, myTempNum)) )
  end repeat  
end mRelease

--------------------------------------------------------------------------
--END makeTable
--------------------------------------------------------------------------

The Laser Lattice

Top

The array table is used to keep track of all the objects used on the laser Lattice...

[Object Map]

The DreamLight PhantomSprite

Top

Here is a more sophisticated code segment that makes use of the stack objects. We very quickly ran out of sprites when designing Verttice since Director 3.1 only allowed 24 sprites (Newer versions of Director have overcome this problem) so we created what we call a PhantomSprite. The PhantomSprite is one sprite that actually can paint multiple sprites on the screen. It keeps a stack of which sprites need to be added, and then on each new frame, it paints one of the sprites needed. The way the PhantomSprite works is that it uses the trails effect to paint a sprite, leaving an afterimage, and then moves on to the next sprite. The main drawback to a PhantomSprite is that no other sprites may be drawn over the PhantomSprite or it will be erased, this includes screen savers or other program windows. The PhantomSprites were used primarily for items that were updated periodically but didn’t need to be constantly animated. We used them for the Lattices and Photons indicators as well as the energized Power Nodes and Warp Nodes.

--========================================================================
-- makePhantom Factory
--========================================================================
--* (C) 1993 DreamLight(R) Incorporated, All Rights Reserved
--------------------------------------------------------------------------
factory makePhantom
  
method mNew theObject
  global phantomSprite, theSprites
  instance mySprite
  instance myUpdates         -- stack of items stacks to update
  instance myPhantoms        -- stack of stacks of coordinates
  instance myActive
  
  set theObject = dumpObject(theObject) -- delete any existing objects
  
  set mySprite = phantomSprite
  set myFrame = 1
  set myActive = False
  
  set myUpdates = makeStack(mNew, True, myUpdates)
  set myPhantoms = makeStack(mNew, True, myPhantoms)
  
  me(mLoadPhantoms)
  activateSprite(mySprite, me)
end mNew
--
method mReset
end mReset
--
method mRelease
  deActivateSprite(mySprite)  
  set myUpdates = dumpObject(myUpdates)
  set myPhantoms = dumpObject(myPhantoms)
end mRelease

--------------------------------------------------------------------------
-- User Interactive methods
--------------------------------------------------------------------------
method mMouseDown
  global controlSprite, theControl
  
  if sprite mySprite within controlSprite then
    theControl(mMouseDown)
  end if
end mMouseDown
--
method mMouseUp
  global controlSprite, theControl
  
  if sprite mySprite within controlSprite then
    theControl(mMouseUp)
  end if
end mMouseUp

--------------------------------------------------------------------------
-- Communication methods
--------------------------------------------------------------------------
method mName
  --** DEBUGGING METHOD
  Return "Phantom"
end mName
--
method mShowPhantom whichPhantom, whichCast
  global thePhantom
  
  set aPhantom = myPhantoms(mGet, whichPhantom)
  
  aPhantom(mPut, 2, whichCast) -- update cast modifier
  
  if NOT myActive then  -- not currently active, so activate
    activateObject(thePhantom)
    set myActive = True
  end if
  myUpdates(mPush, aPhantom) -- put on update stack for nextframe
  
  --**DEBUG
  --put "mShowPhantom: " & aPhantom(mGet,1) & aPhantom(mGet,2)
  
end mShowPhantom

--------------------------------------------------------------------------
-- Animation methods
--------------------------------------------------------------------------
method mNextFrame
  global thePhantom, phantomVolume
  
  if myUpdates(mGetLength) > 0 then
    me(mUpdatePhantom, myUpdates(mPull) )
  else
    me(mUpdatePhantom, myPhantoms(mGet, phantomVolume) )
    deActivateObject(thePhantom)
    set myActive = False
  end if
end mNextFrame
--
method mUpdatePhantom updatePhantom
  
  --**DEBUG
  --put "mUpdatePhantom: " & updatePhantom(mGet,1) && the frame
  
  set the castNum of sprite mySprite = ¬
      the number of cast (updatePhantom(mGet,1) & updatePhantom(mGet,2))
  set the locH of sprite mySprite to updatePhantom(mGet, 3)
  set the locV of sprite mySprite to updatePhantom(mGet, 4)
  
end mUpdatePhantom

--------------------------------------------------------------------------
-- Internal methods
--------------------------------------------------------------------------
method mLoadPhantoms
  global phantomVolume, phantomPhotons, phantomLattices
  global phantomPNode, phantomWNode
  
  repeat with i = 1 to 7
    myPhantoms(mPush, makeStack(mNew, False, myPhantoms(mGet, i)) )
  end repeat
  
  set phantomVolume = 1
  set phantomPhotons = 2
  set phantomLattices = 3
  set phantomWNode = 4
  
  set aPhantom = myPhantoms(mGet, phantomVolume)
  aPhantom(mPush, "Volume:")   -- Base Cast Name
  aPhantom(mPush, 3)           -- Cast modifier
  aPhantom(mPush, 63)          -- H coord
  aPhantom(mPush, 319)         -- V coord
  
  set aPhantom = myPhantoms(mGet, phantomPhotons)
  aPhantom(mPush, "Photons:")  -- Base Cast Name
  aPhantom(mPush, 10)          -- Cast modifier
  aPhantom(mPush, 59)          -- H coord
  aPhantom(mPush, 104)         -- V coord
  
  set aPhantom = myPhantoms(mGet, phantomLattices)
  aPhantom(mPush, "Lattices:") -- Base Cast Name
  aPhantom(mPush, 0)           -- Cast modifier
  aPhantom(mPush, 14)          -- H coord
  aPhantom(mPush, 104)         -- V coord
  
  set aPhantom = myPhantoms(mGet, phantomWNode + 0)
  aPhantom(mPush, "WNode:L:")      -- Base Cast Name
  aPhantom(mPush, "Unlock")        -- Cast modifier
  aPhantom(mPush, me(mGetHCoord,-2) ) -- H coord
  aPhantom(mPush, me(mGetVCoord, 0) ) -- V coord
  
  set aPhantom = myPhantoms(mGet, phantomWNode + 1)
  aPhantom(mPush, "WNode:T:")      -- Base Cast Name
  aPhantom(mPush, "Unlock")        -- Cast modifier
  aPhantom(mPush, me(mGetHCoord, 0) ) -- H coord
  aPhantom(mPush, me(mGetVCoord,-2) ) -- V coord
  
  set aPhantom = myPhantoms(mGet, phantomWNode + 2)
  aPhantom(mPush, "WNode:R:")      -- Base Cast Name
  aPhantom(mPush, "Unlock")        -- Cast modifier
  aPhantom(mPush, me(mGetHCoord, 2) ) -- H coord
  aPhantom(mPush, me(mGetVCoord, 0) ) -- V coord
  
  set aPhantom = myPhantoms(mGet, phantomWNode + 3)
  aPhantom(mPush, "WNode:B:")      -- Base Cast Name
  aPhantom(mPush, "Unlock")        -- Cast modifier
  aPhantom(mPush, me(mGetHCoord, 0) ) -- H coord
  aPhantom(mPush, me(mGetVCoord, 2) ) -- V coord
  
end mLoadPhantoms
--
method mGetHCoord whichCol
  global boardCenterH
  return boardCenterH + (whichCol * 75)
end mGetCoord
--
method mGetVCoord whichRow
  global boardCenterV
  return boardCenterV + (whichRow * 75)
end mGetCoord

--========================================================================
-- end makePhantom 
--========================================================================

This is only the beginning of what you can do with Lingo.

These few examples only scratch the surface of the Lingo language. With Lingo in the hands of a professional programmer, Director can be pushed much farther than a simple slide show with buttons. That was what we set out to prove with DreamLight Verttice. We hope you enjoyed this peek into Verttice’s development and that this will help you push Director even further than you have already. Remember, if there is something Director “can’t do” you may be able to write code right in Lingo to make it do it.

For a more current example of just how far we can push object oriented Lingo programming, download and try Quipples, The Internet Game Show of Satirical Riddles, hosted by NineOh, the world’s first Autiton, Intelligent Interactive 3D Character.

For additional Lingo samples, tips & tricks, be sure to visit the DreamLight Director Talisman

BlastOff! The Award-winning 3D Animated Short film by Michael Scaramozzino - Special Edition DVD

Please Support Our Continuing Independent Film Making Efforts!
Order your Award-winning BlastOff! Special Edition DVD today!

BlastOff!™ Merchandise Available @ Telebites.com BlastOff! T-Shirts BlastOff! Hats BlastOff! Mugs BlastOff! Calendar, Prints & Posters BlastOff! Mousepads

Silver Sage Scrolls™ inspiration through the ages Available @ Telebites.com

To view this site properly, please upgrade to a browser that supports current Web standards.

 

BlastOff! Wins a Silver W3 Award in the Pioneering Category of Web Video - 3D Animation

BlastOff! Wins an Official Honoree Webby Award in the category of 3D Animation

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

DreamLight Incorporated, 323 Andover Street, Suite 6, Wilmington, MA 01887 USA, Telephone: 978-658-5110
Search/Index Top Help