Director News
Director Web Sites
Mailing Lists
News Groups
Project Examples
Useful Web Sites

Don't miss these
All Purpose Status Bar
Hold for MPEG then go to marker X
Sprite on/off
Pauseable Timer with Progress Bar
Check For Previous Open
Easy Navigation System
PowerPoint / PPT Access
Pause Button



Article Puzzler II, Slide it!

Added on 10/25/1999


D7 D8 Mac PC Shockwave

This item has not yet been rated

Author: MediaMacros (website)

I want to create a puzzle game where you have the pieces cut in squares and you have to slide the pieces around with one empty space. How can I set this up?

Get the source
This is a project that first looks like a great use for arrays, lists, etc., but it can really be a lot simpler.  The first step is to set up all the pieces and make sure the edges just touch but do not overlap.  Director's "snap to grid" features can help a lot in the initial layout.  Choose your grid (3X3, 4X4, 5X6, etc.) and make the pieces.  For this example we will use simple numbers.

Now that we have our graphics, lets make sure all of them are exactly the same size and center all the registration points.  This allows us to swap the cast members without alignment problems.  Now we can randomize things a bit.  We start off by adding all the pieces to a global list.  This is used to track which pieces we have on the board, and to allow them to shuffle to any location, without missing any pieces. In the beginSprite handler we can have each piece add its cast member to the list and also set a property for the default piece.  This we will use later to check if all pieces are in the correct location and the user has "won" our game.

Once every piece knows where is should be we start moving them around.   By making a duplicate of the master list of pieces we can then get a random piece and delete it from the list.  When we are done, every piece has a new graphic and there are no duplicates. Now we need to move them.  The only way a piece can move is to slide into the "empty" slot.  To do this we can check the current piece and see if it borders an empty space. The initial reaction would be to avoid the intersect() command because the pieces touch, but do not overlap, but with a little modification we can have this work for us and simplify the whole process.

If we set up our board correctly, no 2 pieces intersect, but by passing a modified rectangle for a sprite to the function we can determine if the 2 pieces are touching.  We do this by inflating the rectangle we are checking by one pixel in each direction.  If we add the rectangle of the sprite we click on to the rectangle rect(-1,-1,1,1) we can then test this against out "empty" space.  If the 2 intersect, then the pieces touch.  We then add a conditional statement to keep diagonal pieces from being included and the rest solves itself.

Below is the code.  Note the use of the sendAllSprites command to broadcast the intersect and solve commands to the sprites, avoiding the need to constantly track where each piece and the blank square are.

--Copyright 1999 Chuck Neal
--If you find this code helpful, send me an e-mail and let me know. :-)

property spriteNum, piece

global pieceList, pickList

on beginSprite me
  --name the pieces by number
  piece = sprite(spriteNum)
  if pieceList = void then
    pieceList = []
  end if
  if pieceList.getOne(piece) <> 0 then
    --old list, reinitialize
    pieceList = []
  end if

on shuffle me
  if pickList = void then
    pickList = duplicate(pieceList)
  else if pickList.count = 0 then
    pickList = duplicate(pieceList)
  end if
  thisOne = random(pickList.count)
  sprite(spriteNum).member = member(pickList[thisOne])

on swap me, whatRect, whatSprite
  --check for lastOne
  if sprite(spriteNum).member = member(pieceList[pieceList.count]) and spriteNum <> whatSprite then
    --is the "last one" (blank space)
    overlap = intersect(sprite(spriteNum).rect, whatRect)
    if (overLap.width > 0 or overlap.height > 0) then
      --do they overLap?
      if overLap.width > 1 or overlap.height > 1 then
        --make sure they don;t overlap diagonally
        --if they intersect, swap
        whatMember = sprite(spriteNum).member
        sprite(spriteNum).member = sprite(whatSprite).member
        sprite(whatSprite).member = whatMember
      end if
    end if
  end if

on checkWin me, winList
  if sprite(spriteNum) = piece then
  end if

on mouseUp me
  sendAllSprites(#swap, (sprite(spriteNum).rect + rect(-1,-1,1,1), spriteNum)
  winList = []
  sendAllSprites(#checkWin, winList)
  if winList.getOne(0) = 0 then
    go "win"
  end if

on getBehaviorDescription me
  describe = "This behavior can be dropped on a grid of images to create a sliding puzzle game."
  describe = describe & return & "Be sure to name your pieces concurrently and name the " & quote & "empty" & quote & " piece so that it will fall at the end of the list when sorted alphabetically."
  describe = describe & return & "A working example with full source code can be found in the learning arcade at"
  return describe



36 South Court Sq
Suite 300
Newnan, GA 30263

Send e-mail