Listing 1

-- Sprite Manager by Irv Kalb
-- Copyright Furry Pants Productions
-- Used with permission of Irv Kalb, OOP expert
-- extraordinaire and author of LOOPE 
-- (Lingo Object Oriented Programming Environment) 
-- Visit him at www.furrypants.com

property plAllocation -- property which is a list of allocations
property pchLow -- channel of the first sprite to manage
property pchHigh -- channel of the last sprite to manage

on new me, chLow, chHigh
  pchLow = chLow
  pchHigh = chHigh
  me.mInit()
  return me
end

on mInit me
  plAllocation = [:]
  repeat with ch = pchLow to pchHigh
    -- initialize all to FALSE (unallocated)
    addProp(plAllocation, ch, FALSE) 
  end repeat
end


on mAllocateChannel me
  -- find the first empty channel
  repeat with ch = pchLow to pchHigh
    fAllocated = getAProp(plAllocation, ch)
    if not(fAllocated) then -- found one
      setProp(plAllocation, ch, TRUE) -- now mark it as allocated
      return ch -- and return it to the user
    end if
  end repeat
  alert("Attempting to allocate a channel, but there are none left")
end

on mDeallocateChannel me, chToDeallocate
  if (chToDeallocate < pchLow) or (chToDeallocate > pchHigh) then
    alert("Trying to deallocate" && chToDeallocate && "but it is not being managed.")
    return
  end if
  fAllocated = getProp(plAllocation, chToDeallocate)
  if not(fAllocated) then
    alert("Trying to deallocate" && chToDeallocate && "but it has not been allocated")
    return
  end if
  -- set the allocation back to false 
  setProp(plAllocation, chToDeallocate, FALSE) 
end

on mDebug me
  put "Channel Allocation:"
  repeat with ch = pchLow to pchHigh
    fAllocated = getProp(plAllocation, ch)
    if fAllocated then
      put ch && ": Allocated"
    else
      put ch && ": Not allocated"
    end if
  end repeat
end

on mCleanup me
  plAllocation = [:]
end

Listing 2

property ancestor

on new me
  ancestor = script ("Activity parent").new()
end

on beginSprite
  -- do your activity-specific initialization here
  -- and call the same routine in the ancestor
  call ancestor.beginSprite()
end

on endSprite
  -- do your activity-specific cleanup here
  -- and call the same routine in the ancestor
  call ancestor.endSprite()
end

Listing 3

-- Activity 1 Key Handler
--***********************************************************
--* This object handles keystrokes for activity 1.
--* Any keys not specifically handled by the activity are
--* sent to the ancestor object.
--***********************************************************

property ancestor
property pOwnerActivity

on new me, ownerActivity
  ancestor = script ("Key Handler Parent").new(ownerActivity, me)
  pOwnerActivity = ownerActivity
  return me
end

--* mDoKey gets the keystroke from the ancestor code
--* and processes keys specific to the activity. If
--* the key isn't used by the activity, the keystroke
--* is passed back to the ancestor for handling.
on mDoKey me, keyID
  -- If the key is a backspace, valid English letter, numeral, 
  -- or punctuation mark, act on it
  if ((keyID > 31) and (keyID < 127)) or (keyID = 8) then
    pOwnerActivity.mActOnKey(keyID) 
  else -- send the keyDown to my ancestor.
    ancestor.mDoKey(keyID)
  end if
end

Listing 4

property pTextMember

on mActOnKey me, whatKey
  if (whatKey = 8) and pTextMember.text.length > 0 then
    delete pTextMember.char[pTextMember.text.length]
  else
    if pTextMember.text.length = 0 then
      put numToChar(whatKey) into pTextMember.char[1]
    else
      put numToChar(whatKey) after pTextMember.char[pTextMember.text.length]
    end if
  end if
end

Listing 5

property pBallSprite

on mActOnKey me, whatKey, cntlDown, cmdDown, optDown
  case whatKey of
    28: -- left arrow
      if pBallSprite.locH > 16 then
        pBallSprite.locH = pBallSprite.locH - 2
      end if
    29: -- right arrow
      if pBallSprite.locH < 622 then
        pBallSprite.locH = pBallSprite.locH + 2
      end if
    30: -- up arrow
      if pBallSprite.locV > 18 then
        pBallSprite.locV = pBallSprite.locV - 2
      end if
    31: -- down arrow
      if pBallSprite.locV < 462 then
        pBallSprite.locV = pBallSprite.locV + 2
      end if
  end case
end

Listing 6

-- Key Handler Parent
--*************************************************************
--*  This handles keystroke response that span activities.
--*
--*  Its descendant will be an activity key handler that handles
--*  activity-specific keystrokes
--* 
--*  This is a parent script that will be instantiated by the key
--*  handler for each activity.  It will check the keystoke and
--*  hand it off to its descendant. When the descendant has
--*  had a chance to process the key, it will then pass it 
--*  back to me.
--*************************************************************
property pKey
property pKeyCode
property ancestor
property pCntlDown
property pCmdDown
property pOptDown
property pOwnerActivity
property pMasterObject
property pDescendant

on new me, ownerActivity, descendant, masterObject
  -- this ancestor contains key code definitions
  ancestor = script ("Key Definitions").new(me)
  pOwnerActivity = ownerActivity
  pMasterObject = masterObject
  pDescendant = descendant
  return me
end

--*******************************************
-- process the key down event
--*******************************************
on keyDown me
  pKey = chartonum(the key)
  -- check for control keys, function keys, etc.
  keyID = mDefineKey(me)
  -- pass it to the descendant first
  if objectP (pDescendant) then
    pDescendant.mDoKey (keyID, pCntlDown, pCmdDown, pOptDown)
  else
    mDoKey
  end if
end

--***************************************************
-- Do additional key definition here
-- This could be used to handle control, command,
-- or option/Alt key combinations
--***************************************************
on mDefineKey me
  -- initialize properties in case the modifier keys are released 
  -- before the key can be processed
  pCntlDown = the controlDown
  -- check for function keys
  -- function keys have key codes between 96 (f5) and 122 (f1)
  if (pKeyCode > 96) and (pKeyCode < 123)  then 
    pKeyCode = pKeyCode + 256
    return pKeyCode
  else  
    return pKey
  end if
end

--***********************************************************
-- Here is where the parent handles the universal
-- keystrokes. In this example, for simplicity, it
-- only handles f1. In practice,
-- it could call special events for each key that it handles
--***********************************************************
on mDoKey me, keyID
  if keyID = ancestor.pF1 then
    -- a movie-level handler that switches activities
    mSwitchActivities()
  end if
end 

Listing 7

property pF1
property pF2
property pF3
property pF4
property pF5
property pF6
property pF7
property pF8
property pF9
property pF10
property pF11
property pHomeKey
property pEndKey

on new me
  pF1 = 122 + 256
  pF2 = 120 + 256
  pF3 = 99 + 256
  pF4 = 118 + 256
  pF5 = 96 + 256
  pF6 = 97 + 256
  pF7 = 98  + 256
  pF8 = 100  + 256
  pF9 = 101 + 256
  pF10 = 109 + 256
  pF11 = 103 + 256
  pHomeKey = 115 + 256
  pEndKey = 119 + 256
  return me
end