Build A Video Jigsaw Puzzle in Flash

Suppose you could convince your visitors to give their undivided attention to your company logo and message for one to two full minutes. And then watch your commercial. And then give you their email address. Sound too good to be true? Well, there is one catch: you have to be willing to chop your message up into little pieces.

In this tutorial, we’ll work through the process of building a jigsaw puzzle, based on either a still image or a video. In the process, we’ll cover some useful Flash techniques for loading and masking images, and for responding to user actions.

For a sneak preview of what we’re building, unzip the download files and fire up sitePointPuzzle.swf. If you look in the .fla, you’ll find a couple of functions not described here: randomize scatters the puzzle pieces across the Stage, and displayTime shows a running timer. We’ll focus on the key features of the jigsaw puzzle application: cutting the loaded .jpg or .swf into puzzle pieces, and putting those pieces back together.

Make a Reusable Puzzle Template

First, you need to decide on the dimensions of your puzzle, in order to make the puzzle template — the collection of shapes that fit together in the complete puzzle. The example template I’ve used here is 550 x 230 pixels. If you go much bigger than that, or if you use more than about 20 pieces, you risk bogging down slower machines. The actual JPG or SWF that provides the visible content will be loaded in at run-time, so we can get a lot of mileage out of a single template, reusing it with many different images.

In Frame 1 of a new Flash document, use the rectangle tool to draw a rectangle with no border, using any fill color. The color will not be visible in the final product. In the property inspector, set the width and height of the rectangle, and set its x and y position to 0. Insert an empty keyframe in Frame 2 of the timeline.

Build A Video Jigsaw Puzzle in Flash

Now select the lasso tool, and use it to cut out a puzzle piece from one corner of the rectangle.

Build A Video Jigsaw Puzzle in Flash

Choose Modify > Shape > Optimize, and find a setting that seems to work well. Optimizing the shapes will speed up the performance of the final movie, but over-optimizing will distort the shapes of your puzzle pieces. Press F8 to open the Convert to Symbol dialogue window. Give the piece the name piece0, select Movie clip, set the registration point in the upper left corner, and check Export for Actionscript. Press OK to close the window.

Build A Video Jigsaw Puzzle in Flash

Your freshly-minted puzzle piece is selected. Use the property inspector to give the shape the instance name a0. Cut it (Control-X), and Paste-in-Place (Control-Shift-V) into Frame 2 of the timeline. This instance serves to record the position of this piece in the final puzzle. When the Flash movie is published, a script will use this information to make a real picture-bearing puzzle piece, and then will delete this instance.

Repeat the cutting-out process until you’ve dissected the entire rectangle into movie clips with clip names piece0 through piece17 and instance names a0 through a17. Of course, replace 17 with the appropriate number for your own puzzle. Finally, delete the now-empty Frame 1. That completes most of the graphical interaction in this project–the rest is done with Actionscript code. If you’re impatient, you can skip this stage for now, and use the puzzle template in the file puzzleTemplate300x150.fla.

Preload the Image

We need a copy of the image for each puzzle piece. If we were to issue a loadMovie call for each puzzle piece at the start, the Flash player would start multiple processes to retrieve the movie from the server. Instead, we will load the visible content once, using Flash’s MovieClipLoader class. Once this first load completes, we will create the individual puzzle pieces. Because we wait for the loading to complete, the Flash player will use the cached copy of the image for all the puzzle pieces.

The MovieClipLoader class dispatches several events to any registered listeners. In this application, we create an object called loadListener, and give it onLoadProgress and onLoadComplete event handlers. These are used to update a preloader display, and to call the makePuzzle function when loading is complete. The preloader is a movie clip that contains another clip called, and we simply change the width of the bar to show progress.

var p : MovieClip = _root.createEmptyMovieClip("picture", 1);  var h = p.createEmptyMovieClip("holder", 1); 

var loadListener : Object = new Object();  loadListener.onLoadProgress = function(target, loaded, total) { = 100 * loaded / total;  }  loadListener.onLoadComplete = function() {    preloader._visible = false;    makePuzzle();    randomizeInt = setInterval(randomize, 3000);  } 

var loader:MovieClipLoader = new MovieClipLoader();  loader.addListener(loadListener);  loader.loadClip(puzzleContent, h);

Cut the Image According to the Puzzle Template

The code for this step is in the aptly-named makePuzzle function. Here’s the code for this function. (We’ll examine it in more detail momentarily.)

function makePuzzle() : Void {    // initialize the class array "pieces," that holds references to all puzzle pieces    PuzzlePiece.pieces = new Array();    PuzzlePiece.puzzleContent = puzzleContent;    var piece : MovieClip; 

for(var i : Number = 0; i < numPieces; i++){      piece = _root.attachMovie("PuzzlePieceSymbol", "piece" + i, 100 + i);      piece.init(_root["a" + i], i);    }   

// Now that we have all the puzzle pieces, we dim the original image    p._alpha = 10; 

/* We start loading the main content, which will be displayed after       the puzzle is completed.  This can be a much larger      file, but since it loads while the user is solving the puzzle,      it won't slow things down. */    loadListener.onLoadComplete = null;    loadListener.onLoadProgress = null;    loader.loadClip(mainContent, h);  }

First, we initialize the class array PuzzlePiece.pieces, which will hold references to all the puzzle pieces. We also store the name of the .swf or .jpg to load as a class property, for convenience.

  PuzzlePiece.pieces = new Array();    PuzzlePiece.puzzleContent = puzzleContent;

Here’s the key step: we run through a loop that creates the individual puzzle pieces. Because the class PuzzlePiece is an extension of the MovieClip class, we do not use the new operator; instead, we use attachMovie to put on stage an instance of PuzzlePieceSymbol. This movie clip has no visible content, but it is linked to the custom class PuzzlePiece, as we can see in the properties window.

Build A Video Jigsaw Puzzle in Flash

When an instance of PuzzlePieceSymbol is created, the constructor function for the class PuzzlePiece is called automatically. This creates an instance of PuzzlePiece, but there is one problem: because we are not calling the constructor directly from Actionscript code, we have no way to pass any parameters to the constructor.

The solution is to give PuzzlePiece a public initialization function, which we can call explicitly with the needed parameters. So the loop that creates the puzzle pieces also calls the init() function of each piece, passing as parameters a reference to the original puzzle piece on the stage, and an index number:

  for(var i : Number = 0; i < numPieces; i++){      piece = _root.attachMovie("PuzzlePieceSymbol", "piece" + i, 100 + i);      piece.init(_root["a" + i], i);    }     We'll examine this init() function in a moment, after finishing with the makePuzzle function.  The last thing makePuzzle does is to start loading the mainContent swf into the same movieclip that we used to preload the puzzleContent.  This can be a much larger file (in this example, it has music and sound effects included) without causing any delays: it will be preloaded while the user is assembling the puzzle pieces, and doesn't need to be displayed until the puzzle is finished.
  loadListener.onLoadComplete = null;    loadListener.onLoadProgress = null;    loader.loadClip(mainContent, h);
 Create the Puzzle Pieces Here's where the magic happens!  We need to create a copy of puzzleContent, but mask it so that only the portion corresponding to a given puzzle piece is visible.   This is done by the function PuzzlePiece.init():
  function init(templatePiece : MovieClip, index : Number) : Void {      _index = index;
 We save the index (which will also serve as a depth), and then load the puzzleContent into a holder subclip.  This is a wise practice in general, since loadMovie() obliterates various movieclip properties, including masking and event handlers.  By loading content into a subclip, we avoid wrecking properties of the main puzzle piece clip.
    holder = this.createEmptyMovieClip("holder", 1);      holder.loadMovie(puzzleContent);
 Now, for the all-important mask.    
  Flash allows us to use one movie clip as a mask for another.  The masked clip will be visible only in places where the masking clip has some visible content.  In this application, we use an empty movie clip as a mask, and then attach a puzzle piece to the mask.  When the movie is published, only the portion of the image that overlaps the puzzle piece will be visible.   Build A Video Jigsaw Puzzle in Flash
Note that we do not use the puzzle piece itself as a mask, but instead attach a copy of the puzzle piece to an initially empty mask. We'll see in a moment that this approach will give us a convenient way to join puzzle pieces together.
  //create a mask, and attach the puzzle piece to the mask     createEmptyMovieClip("mask", 2);     mask.attachMovie("piece" + index, "piece" + index,  index);     maskPiece = mask["piece" + index];  // reference to the mask piece     maskPiece.number = index;    // the piece knows its own number     setMask(mask);
 Now we need to place the masking puzzle piece in its proper position.  For this, we refer to the original puzzle piece on the Stage.  We set the mask piece to have the same _x and _y values as the original piece, then remove the original piece.
  this.maskPiece._x = templatePiece._x;     this.maskPiece._y = templatePiece._y;  

templatePiece.swapDepths(99);     templatePiece.removeMovieClip();

 Movie clips created in the authoring tool, like our original puzzle pieces, are placed at negative depths.  The method removeMovieClip() can only be used on movie clips at positive depths.  So we need to send each puzzle piece to a positive depth, using swapDepths(), before we can remove it. Finally, we add our new puzzle piece to the master list of puzzle pieces, update the maxDepth variable, and assign functions to fire when the puzzle piece is pressed or released.
    pieces.push(this);       maxDepth = Math.max(maxDepth, this.getDepth());  

this.onPress = pressFunction;        this.onRelease = this.onReleaseOutside = releaseFunction;     }      Make the Pieces Movable    It's all very well to have a bunch of puzzle pieces, but without some way to move them around, it won't be much fun!  Here is the function that fires when a puzzle piece is pressed.  This function does four things.  First, it moves the puzzle piece we've selected to a depth above all the other movie clips, to prevent the piece sliding under other pieces as it moves.  Then it emits a click sound, by calling the start() method of the sound object downClick.  Then, it calls the startDrag() method of the puzzle piece, causing it to follow the mouse.  Finally, it cancels the onEnterFrame function.  This will cancel the piece's desire to move to a random spot on the Stage, in case the user clicks on it during the randomization process.
    private function pressFunction() {     if(!draggable) return;    // do nothing if puzzle not yet active     this.swapDepths(++maxDepth);   // bring piece above other pieces     downClick.start();      // emit click sound     this.startDrag();      // start dragging the piece     delete this.onEnterFrame;    // cancel randomization       }
 Take Action When a Piece is Released When a puzzle piece is released, we have to do several things.  Of course, we need to stop dragging, and emit a click sound so the user can tell something happened.
    private function releaseFunction() {     if(!draggable) return;     upClick.start();    // emit a lower-pitched click     this.stopDrag();    // stop dragging
 But we also need to check whether the piece is adjacent to any of its neighboring pieces.  If so, these pieces will snap together, and effectively become a single piece.   Because we've set up all the pieces with the same reference point, it is easy to check whether two pieces are in the correct relative position.  We need only check whether the differences between their _x and _y coordinates are sufficiently close to zero.  We need to set some tolerance around how close to their proper alignment pieces must be in order to be counted as correctly aligned.  I've used a relatively large value of 16 pixels in this example, but larger or smaller values may work better for other puzzles.   Again, we use a loop that runs through all the elements of the pieces array.
  for(var j in pieces) {       otherPiece = pieces[j];
 Following the programming principle of putting shorter actions first, we skip over a piece if any one of several conditions occurs: We will not join a piece to itself::
    if(otherPiece == this) continue;
 If the puzzle pieces are not touching, we will not join them:
    if( !this.mask.hitTest(otherPiece .mask) ) continue;
 And if the pieces are out of alignment by more than the tolerance, in either the x or the y direction, we will not join them:
    if( Math.abs(this._x - otherPiece._x) > tol ||    Math.abs(this._y - otherPiece._y) > tol ) continue;
 If we make it through all these tests, we know that the piece we've just released is aligned with another piece, and should be joined to it.  In fact, we take the puzzle piece (or pieces, if a piece is already the result of previous joining) from the aligned movie clip, and add it to the mask layer of the released clip.
    for(var m in otherPiece.mask) {         maskPiece = otherPiece.mask[m];         var n = this.mask.attachMovie("piece" + maskPiece.number,            "piece" + maskPiece.number, maskPiece.number);         n.number = maskPiece.number;         n._x = maskPiece._x;         n._y = maskPiece._y;       }
  Then we delete the other piece from the array of puzzle pieces, and remove it from the stage:
    pieces.splice(parseInt(j), 1);       otherPiece.removeMovieClip();     }
 Finally, we check to see whether the puzzle has been completed.  Here's the full release function:
    private function releaseFunction() {     if(!draggable) return;     upClick.start();        // emit a lower-pitched click     this.stopDrag();        // stop dragging  

// check for connection to neighboring pieces     var otherPiece : MovieClip;     var maskPiece : MovieClip;     for(var j in pieces) {       otherPiece = pieces[j];       if(otherPiece == this) continue;           if( !this.mask.hitTest(otherPiece.mask) ) continue;          if( Math.abs(this._x - otherPiece._x) > tol ||          Math.abs(this._y - otherPiece._y) > tol ) continue;       for(var m in otherPiece.mask) {         maskPiece = otherPiece.mask[m];         var n = this.mask.attachMovie("piece" + maskPiece.number,            "piece" + maskPiece.number, maskPiece.number);         n.number = maskPiece.number;         n._x = maskPiece._x;         n._y = maskPiece._y;       }       pieces.splice(parseInt(j), 1);       otherPiece.removeMovieClip();     }     _root.checkForCompletion();       }
 Respond When the Puzzle is Completed Because we merge any aligned puzzle pieces into a single piece, it is very easy to check whether the puzzle is finished: we just check whether the array of pieces has been reduced to a single element!  If more than one element remains, we'll continue with the puzzle.  Otherwise, we'll reward the user for successfully completing the puzzle.  In this example, we remove the one remaining puzzle piece, and show a version of the movie that includes sound. The sound-enhanced version of the movie has a stop() command on frame 1, so that we can preload it while the user is working on the puzzle, without having it launch immediately upon loading.  So when the puzzle is done, we issue a gotoAndPlay(2) command to start the movie rolling.
function checkForCompletion() {     if(pieces.length > 1) return;     clearInterval(timerInt);  // stop the timer  

// show the movie with sound     p._alpha = 100;     p.holder.gotoAndPlay(2);     pieces[0].removeMovieClip();   }
 Further Developments On completion, we stop the timer, to record how long the user took to complete the puzzle.  On a commercial Website, one could offer the user various rewards for having completed the puzzle.  A free sample, or a lottery entry to win a prize, could be made available to those who complete the puzzle in less than one minute, for instance.  Having accomplished a task requiring some effort, your visitor will likely feel that they have earned whatever prize you offer, and be more willing to give their contact information than they would for a free offer.  And the user who misses the time cutoff may return to your site to try again. A video jigsaw puzzle can be an enticing -- even addictive -- entertainment. See what you can do with it!


Category: software Time: 2005-05-19 Views: 1

Related post

  • Solving a Jigsaw Puzzle! 2015-04-13

    I've just bought a new jigsaw puzzle but, as a programmer, I'm too lazy to do it by myself. So I've devised a way to encode the pieces, and now I need a way to solve the puzzle itself. Challenge A puzzle piece will have from 2 to 4 connecting corners

  • Building a video wall with devices 2011-06-30

    I am entertaining building a video wall made out of many android devices. But I have to say I have no clue about how to go about it? The fact that these are android devices is not very important I am curious about the general approach to doing video

  • How can I calculate a jigsaw puzzle cut path? 2012-06-12

    I want to generate a path to cut an arbitrary shape into a set of jigsaw puzzle pieces. All pieces must be unique to preclude placing a piece in the wrong spot. Pieces must be interlocking such that each piece is held by adjacent pieces. It must be p

  • Identifying corners in a jigsaw puzzle 2014-04-20

    I've spent the last few days trying to figure out a solution to this but haven't come up with anything that works. I'm trying create/find an algorithm that can identify the 4 corners in jigsaw puzzles. I have a 2-D array (x and y positions) that make

  • Configure error with pkgsrc trying to build xf86-video-intel 2014-10-04

    I am trying to build xf86-video-intel driver on NetBSD 64bit, and I have this problem: checking whether to build Xorg PCI functions... checking for PCIACCESS... no configure: error: Package requirements (pciaccess >= 0.12.901) were not met: Requested

  • Video compression artifacts in Flash 2010-05-10

    This only started happening in the past two days, which seems very odd to me. Everything worked flawlessly up until now, and I use my my computer as my primary TV. Flash video from Hulu and Amazon, for no apparent reason, now have lots of artifacts i

  • What do I need to know when building a Video Editing Workstation? 2010-08-20

    I want a new workstation with some super duper hardware. I'm planning for this to be a purpose-built video editing station, and I don't know quite where to start! What should I look for when building in this system? --------------Solutions-----------

  • How to (re)enable YouTube videos on Safari with Flash plugin 10.2? 2011-02-20

    Possible Duplicate: The browser doesn't show videos on Youtube Youtube videos appear as a black box only in safari 5.0.3, since flash payer has been updated to 10.2. They work if I change the User Agent to Safari 4.0.3 using the Developer menu, but t

  • Should I use XNA or Unity to build a video game? 2012-08-20

    My friend and I are planning to make a video game (like Slender) where the character is stuck in a building, when lightning strikes, and the lights go out and your objective is to find the back-up generators and turn the lights back on. The game will

  • Youtube - why are some videos html5 and some flash - and how do I force html5? 2012-11-23

    When I watch this youtube video - it's in flash. But when I click on - that video is in html5. Why are some videos in flash a

  • Whenever I watch videos, my screen gets flashes of snow 2013-07-10

    I'm using a 15 inch mid 2010 macbook with 10.8.4. It happens both on my cinema display and laptop display. It happens sporadically and had me questioning whether I was actually seeing it for a while. I notice mostly on youtube videos, but I think it'

  • How can I enhance my jigsaw puzzle solver function? 2014-05-31

    I'm working on writing code which gets several pieces of an image, and reconstructs them to one whole picture. The images are represented by matrices, and two pieces should be "glued" if the right column of one matrix is the same as the left col

  • how to automatically record a video response after the video stops playing using flash 2016-02-11

    Using Mediaelementjs, i have successfully implemented a videoplayer, and triggered an end event which immediately pops up a flash recorder of adobe. Listing the website in Website Privacy Settings panel gives the direct access to microphone and camer

  • how to pull video files from a flash player 2010-02-11

    I am trying to download a Flash video, so I can try to convert it to a normal DVD. (FYI: this is a religious video.) Is it possible to download this video? If so, how could I do this? --------------Solutions------------- If you have Firefox, install

  • Determining whether or not a youtube video is playing using Flash Objects in C# 2016-02-07

    I am creating a multimedia slideshow maker in C# and have to integrate YouTube videos dynamically into slides. However, I dont know how to tell my program to wait the duration of the video before moving onto the next picture/video in the slideshow. I

  • Building RIAs with the Adobe Flash Platform 2009-01-14

    The Flash that you thought you knew has changed. It's grown up. In this article, I'll explain some of the technologies that make up the Flash Platform, how they fit together, and how you can use them to build RIAs. Pay attention, because there will b

  • Building custom pages with a video player 2012-03-05

    Hey i am trying to learn wordpress developement on my own, I'm building a celebrity gossip blog and i need help. I want to build a video page. Does anyone know of a plugin or anything that i can use that allows me to have a flash video player that al

  • Build Your Own Video Community With Lighttpd And FlowPlayer (Debian Lenny) 2014-02-05

    Build Your Own Video Community With Lighttpd And FlowPlayer (Debian Lenny) Version 1.0 Author: Falko Timme Follow me on Twitter This article shows how you can build your own video community using lighttpd with its mod_flv_streaming module (for stream

  • Build Your Own Video Community With Lighttpd And FlowPlayer (Ubuntu 9.10) 2014-09-05

    Build Your Own Video Community With Lighttpd And FlowPlayer (Ubuntu 9.10) Version 1.0 Author: Falko Timme Follow me on Twitter This article shows how you can build your own video community using lighttpd with its mod_flv_streaming module (for streami

iOS development

Android development

Python development

JAVA development

Development language

PHP development

Ruby development


Front-end development


development tools

Open Platform

Javascript development

.NET development

cloud computing


Copyright (C), All Rights Reserved.

processed in 2.386 (s). 13 q(s)