Build Jigsaw Puzzle Pieces with Imaging Lingo
March 5, 2004
by Michael Pelzer
Intro
I built a jigsaw puzzle game to improve my daughter's mouse usage skills. I wanted to have the game take one of her favorite pictures and divide it into several pieces.
The challenge was how to cut the whole picture - on the fly - into pieces. The pieces should look like real jigsaw pieces, each with a unique shape.
I decided to use a mask for cutting the pieces with imaging lingo.
Preparation
My pictures must be the same size - so I used Fireworks for resizing them. Then I built a a black and white image of the jigsaw piece shapes. I did this by using a some jigsaw software, importing a black image, and then taking a screenshot of the cut-up black jigsaw puzzle. You can hand-draw yours or use a different method to create the puzzle mask.
Then I colored each piece of the puzzle a different color and changed the borders to gray.
Now the mask was ready. It contained n+1 different colors. It is important that the borders have one color, as this gives me the possibility to get a frame image as well.
Lingo Coding
In Director I created a cast library named "Pieces" as a container for all the single pieces.
on DeletePieces
-- delete the old/last pieces ...
repeat with n = 1 to the number of members of castLib("Pieces")
member(n, "Pieces").erase()
end repeat
end
Imaging Lingo
Let's start with initializing some variables and basic information about the used pictures.
on BuildPieces
DeletePieces -- delete the old/last pieces ...
maskMem = member("PuzzleMask")
maskImg = member(maskMem).image -- Puzzle-Mask
pictMem = member("venedig")
pictImg = member(pictMem).image -- Picture
if (maskMem.width <> pictMem.width) or (maskMem.height <> pictMem.height) then
alert ("Mask & Pict must have the same size!")
return
end if
w = maskMem.width
h = maskMem.height
Then we want to know how many pieces are in the mask.
We can determine this by scaning the mask pixel by pixel, counting the different colors and storing them in a list.
-- how many colors/pieces has the mask?
lstCol = []
repeat with y = 0 to h-1
repeat with x = 0 to w-1
mc = maskImg.getPixel(x,y) -- mask-color
-- is this color already in the list
pos = getPos(lstCol, mc)
-- if not -> append
if pos = 0 then
add lstCol, mc
end if
end repeat
end repeat
After that, we know how many colors are used and how many pieces we need, so we create empty bitmap members in the cast "Pieces".
-- the first color is for the border
put lstCol.count-1, lstCol
-- build for every color/piece an empty bitmap-image
repeat with n = 1 to lstCol.count
set newMem = new(#bitmap, castLib "Pieces")
newMem.image = image(w,h,24)
newMem.name = "P-" & n-1
end repeat
Finally, we scan the mask again pixel by pixel. We copy pixels from the source picture to a jigsaw piece image using the colors of the mask as a guide. The index of the color gives us the destination member.
-- now scan the mask ...
repeat with y = 0 to h-1
repeat with x = 0 to w-1
mc = maskImg.getPixel(x,y) -- mask-color
pos = getPos(lstCol, mc) -- index of the color-list
this = "P-" & pos-1
-- copy every pixel from the source-pict to one of the pieces
pc = pictImg.getPixel(x,y) -- picture-color
member(this).image.setPixel(x,y, pc)
end repeat
end repeat
end
That's all, now the cast "Pieces" holds all the jigsaw pieces.
Assembling the Game
All of the pieces have the same reg-point. So we can put them all to the stage and see the whole picture.
And because of the first member is the border, we can reduce the blend of its sprite and get a frame/background for the player.
For a full game, we shuffle the positions and need a behavior for moving the pieces.
You'll find that in the source of the movie.
Conclusion
This is another example about the wide possibilities of imaging Lingo. With imagination you can use this technique for other types of image processing as well.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.