|
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 Macromedias 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 worlds first Autiton, Intelligent Interactive 3D Character.
For additional Lingo samples, tips & tricks, be sure to visit the DreamLight Director Talisman
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.
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
--------------------------------------------------------------------------
|

|
|
|
 |
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 array table is used to keep track of all the objects used on the laser Lattice...
|

|
|
|
 |
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 didnt 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 Verttices development and that this will help you push Director even further than you have already. Remember, if there is something Director cant 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 worlds first Autiton, Intelligent Interactive 3D Character.
For additional Lingo samples, tips & tricks, be sure to visit the DreamLight Director Talisman
|