Articles Archive
Articles Search
Director Wiki

Drag and Drop puzzles

September 14, 1998
by Pat McClellan

Dear Multimedia Handyman,

I'm a Director beginner and I need to create a puzzle so that each piece is moveable, but then locks into place when it is dropped in the right spot. I have checked the Moveable box on the score, but I don't know how to test the location and turn that off. Help please...


Dear Singh,

This seems like a common task that many people would want to do, so that makes it perfect for creating a behavior. That way, you can re-use it on future projects. This is also a fairly simple task, so it makes for a good "first behavior" for you to tackle.

Here's what we need to accomplish. In the beginSprite handler, we'll want to set the moveable property of the sprite to true. This is the same as clicking on the box in the score window, but we'll take care of it with Lingo instead. Next task, check immediately to see if the piece is in place (by chance). We can use create a testLoc handler for that. In the testLoc handler, we need to compare the current location of the sprite to our target location. That means that we'll want to allow the author to specify a target locH and a target locV during development. I also recommend that we allow for some "slop" or variance of position. If the user gets within a few pixels of the correct location, then we should lock the piece into place and give them credit as correct.

Now, when the user clicks on the mouse and drags the piece, we really don't do anything. We spring into action when the user releases the mouse. So in the mouseUp handler, we'll simply call the testLoc handler again.

Once the piece is in place, we will want to turn the moveable property off. I also like to play a little click sound for a little style. The last task is a little more complicated -- checking to see if they've won. After a piece locks into place, we'll set a status property to #inPlace, then go check the status of the other pieces. If any of the pieces report that that are #notInPlace, then we know the puzzle is not finished so we don't have to do anything else. However, if all of the other sprites report that they are #inPlace, then we will execute a puzzleFinished handler.

Here's the behavior:

--PuzzleDrop Behavior 
--copyright © 1998 ZZP Online, LLC
--This behavior allows a sprite to be moved around 
-- the stage. On mouseUp, the sprite will compare 
-- its loc to a targetLoc. If it is within the 
-- acceptable target range, then the sprite locks 
-- into place.
property pTargetH
property pTargetV
property pVariance
property pTargetLoc -- point(pTargetH, pTargetV)
property pMySprite
property pStatus -- #inPlace or #notInPlace
on getPropertyDescriptionList me
  set pdlist to [:]
  addprop pdlist, #pTargetH, [#comment:"Target ¬
    locH", #format:#integer, #default:0]
  addprop pdlist, #pTargetV, [#comment:"Target ¬
    locV", #format:#integer, #default:0]
  addprop pdlist, #pVariance, [#comment:"Acceptable¬
    Variance", #format:#integer, #default:0]
  return pdlist
end getPropertyDescriptionList
on beginSprite me
  set pMySprite = the spriteNum of me
  set the moveableSprite of sprite pMySprite to TRUE
  set pTargetLoc = point(pTargetH, pTargetV)
  set pStatus = #notInPlace
  testLoc me
on mouseUp me
  testLoc me
on testLoc me
  set testH = the locH of sprite pMySprite
  set testV = the locV of sprite pMySprite
  if abs(pTargetH - testH) < pVariance then
    if abs(pTargetV - testV) < pVariance then
      set the loc of sprite pMySprite = pTargetLoc
      set the moveableSprite of sprite pMySprite ¬
        to FALSE
      puppetSound 3, "click"
      set pStatus = #inPlace
      checkWin me
    end if
  end if
on checkWin me
  set statusList = []
  sendAllSprites (#reportStatus, pMySprite, statusList)
  if getOne(statusList, #notInPlace) then
    puzzleFinished me
  end if
on reportStatus me, whichSprite, statusList
  if whichSprite <> pMySprite then
    add statusList, pStatus
  end if
on puzzleFinished me
  alert "You did it!"

The trickiest part of this behavior is the way that I'm communicating between sprites. In the checkWin handler, I initiate the intersprite communcation by issuing a sendAllSprites command. This tells all the sprites to report their status by adding their status property to the statusList. This list is copied and altered by each sprite. Since it's a copy of the list, all changes are reflected on the orginal statusList. Therefore, we don't even have to pass the list back to the initiating sprite. Then, the checkWin handler scans the resulting list for determining whether all the pieces are in place.

This behavior makes it a simple task to assemble a drag and drop-in-place exercise. The only tedious part is writing down all the target locs for your sprites. If you do a lot of these or have a lot of pieces, you might want to create a quick utility handler. For example, put all of the sprites in the correct location. For this example, I'll assume we have 50 pieces, in sprite channels 5-54. Create the following movie script:

on listLocs firstSprite, lastSprite
        set spriteList = [:]
        repeat with i = firstSprite to lastSprite
        addProp spriteList, i, the loc of sprite i
  end repeat
  put spriteList

Now, with the score on the frame where all of the sprites are in place, open the Message window and enter:

listLocs 7,10

The listLocs handler will return a property list, which you can refer to when entering the target locH and locV for your sprites.

-- [5: point(232, 148), 6: point(72, 170), 7: ¬
    point(168, 183), 8: point(13, 218)... etc.]

Good luck with your program.

For those of you who like jigsaw puzzles -- or just damn impressive Lingo -- check out Jim Collins' puzzles at

Patrick McClellan is Director Online's co-founder. Pat is Vice President, Managing Director for Jack Morton Worldwide, a global experiential marketing company. He is responsible for the San Francisco office, which helps major technology clients to develop marketing communications programs to reach enterprise and consumer audiences.

Copyright 1997-2019, Director Online. Article content copyright by respective authors.