Get the full commented source code of

HTML5 Suika Watermelon Game

Talking about Jigsaw Game game, Game development, HTML5, Javascript and Users contributions.

Five years ago I blogged about a Jigsaw game prototype made with KineticJS which is no longer maintained. Some time later, a blog reader called Ami Hanya ported the script to AS3, but a working and maintained HTML5 version of the game is still missing. Five years later, Ami strikes back with a HTML5 version of the game made with ZIM. ZIM is an open source JavaScript Framework for the HTML Canvas powered by CreateJS. Have a look at the game:
Drag the pieces in their correct places. The source code has some comments and it’s quite easy to understand, have a look:
<!doctype html>
<html>

<head>
    <meta charset="utf-8" />
    <title>Jigsaw Puzzle - ZIM Frame</title>

    <!-- Welcome to ZIM at http://zimjs.com - Code Interactive Media Pizzazz! 	        -->
    <!-- ZIM runs on the HTML Canvas powered by JavaScript and CreateJS http://createjs.com -->
    <!-- Founded by Inventor Dan Zen - http://danzen.com - Canadian New Media Award Winner 	-->
    <!-- ZIM is free to use. You can donate to help improve ZIM at http://zimjs.com/donate 	-->

    <script src="https://d309knd7es5f10.cloudfront.net/createjs_1.1_min.js"></script>
    <script>
        var zon = true; // set to false to turn off console messages from zim
        var zns = false; // set to true to require zim namespace - eg. new zim.Frame()
    </script>
    <script src="https://d309knd7es5f10.cloudfront.net/zim_6.9.0.js"></script>
    <!-- use zimjs.com/distill for minified individual functions! -->

    <script>
        // SCALING OPTIONS
        // scaling can have values as follows with full being the default
        // "fit"	sets canvas and stage to dimensions and scales to fit inside window size
        // "outside"	sets canvas and stage to dimensions and scales to fit outside window size
        // "full"	sets stage to window size with no scaling
        // "tagID"	add canvas to HTML tag of ID - set to dimensions if provided - no scaling

        var scaling = "fit"; // this will resize to fit inside the screen dimensions
        var width = 1024;
        var height = 768;
        var countPieces = 0;
        var totalPieces = 0;
        // as of ZIM 5.5.0 you do not need to put zim before ZIM functions and classes
        var frame = new Frame(scaling, width, height);
        frame.on("ready", function()
        {
            zog("ready from ZIM Frame"); // logs in console (F12 - choose console)

            var stage = frame.stage;
            var stageW = frame.width;
            var stageH = frame.height;

            var puzzleX;
            var puzzleY;
            frame.outerColor = "#444";
            frame.color = "#ddd";

            var con = new Container

            // with chaining - can also assign to a variable for later access
            var imageObj = [];
            var piecesArrayObj = [];
            frame.loadAssets(["brave.jpg"], "assets/");

            var label = new Label({
               text:"CLICK",
               size:60,
               font:"courier",
               color:"orange",
               rollColor:"red",
               fontOptions:"italic bold"
            });
            stage.addChild(label);
            label.x = label.y = 20;
            label.on("click", function(){zog("clicking");});


            frame.on("complete", function() {


                imageObj = frame.asset("brave.jpg").clone();
                imageObj.addTo(con);
                imageObj.alpha = 0.2;

                var piecesArray = new Array();
                var horizontalPieces = 5;
                var verticalPieces = 4;
                var obj = getQueryString();
                zog(obj)
                if(obj)
                {
                   horizontalPieces = obj.row;
                   verticalPieces = obj.column;
                }
                var imageWidth = imageObj.width;
                var imageHeight = imageObj.height;
                var pieceWidth = Math.round(imageWidth / horizontalPieces);
                var pieceHeight = Math.round(imageHeight / verticalPieces);
                var gap = 40;
                totalPieces = horizontalPieces*verticalPieces;

                puzzleX = frame.width/2-imageWidth/2;
                puzzleY = frame.height/2-imageHeight/2;
                imageObj.pos(puzzleX,puzzleY);
                zog(puzzleX,puzzleY);

                label.text = "Jigsaw Puzzle "+countPieces+"/"+totalPieces;


                for (j = 0; j < verticalPieces; j++) {
                    piecesArrayObj[j] = [];
                    for (i = 0; i < horizontalPieces; i++) {
                        var n = j + i * verticalPieces;

                        var offsetX = pieceWidth * i;
                        var offsetY = pieceHeight * j;


                        var x8 = Math.round(pieceWidth / 8);
                        var y8 = Math.round(pieceHeight / 8);

                        piecesArrayObj[j][i] = new Object();
                        piecesArrayObj[j][i].right = Math.floor(Math.random() * 2);
                        piecesArrayObj[j][i].down = Math.floor(Math.random() * 2);

                        if (j > 0) {
                            piecesArrayObj[j][i].up = 1 - piecesArrayObj[j - 1][i].down;
                        }
                        if (i > 0) {
                            piecesArrayObj[j][i].left = 1 - piecesArrayObj[j][i - 1].right;
                        }

                        piecesArray[n] = new Rectangle({
                            width: pieceWidth,
                            height: pieceHeight,

                        });



                        var tileObj = piecesArrayObj[j][i];
                        var s = new Shape

                        var context = s.graphics;
                        s.drag();
                        s.mouseChildren = false;
                        s.addEventListener("pressup", function(e) {
                            var mc = e.currentTarget;

                            var xx = Math.round(mc.x);
                            var yy = Math.round(mc.y);

                            if (xx < puzzleX+gap / 2 && xx > puzzleX-gap / 2 && yy < puzzleX+gap / 2 && yy > puzzleY-gap / 2) {
                                 mc.x = puzzleX;
                                mc.y = puzzleY;
                                mc.noDrag();
                                mc.addTo(mc.parent,0);
                                mc.mouseChildren = false;
                                mc.mouseEnabled = false;
                                mc.hint.visible = false;
                                countPieces++;
                                label.text = "Jigsaw Puzzle "+countPieces+"/"+totalPieces;
                                zog("countPieces",countPieces);
                                if(countPieces == totalPieces)
                                {
                                    var pane = new Pane({width:600,label:"VERY NICE!", height:250, modal:false, displayClose:false});

                                    var confirm = new Button(120, 50, "ON", "green").center(pane).mov(0,70);

                                    confirm.on("click", function() {
                                        pane.hide();
                                        window.location.replace(window.location.pathname + window.location.search + window.location.hash);

                                    });
                                    pane.show();
                                }
                                stage.update();

                            }

                        });
                        context.setStrokeStyle(3,"round");
                        var commandi1 = context.beginStroke(createjs.Graphics.getRGB(0, 0, 0)).command;
                        //
                        var commandi = context.beginBitmapFill(imageObj.image).command;


                        context.moveTo(offsetX, offsetY);




                        if (j != 0) {
                            context.lineTo(offsetX + 3 * x8, offsetY);
                            if (tileObj.up == 1) {
                                context.curveTo(offsetX + 2 * x8, offsetY - 2 * y8, offsetX + 4 * x8, offsetY - 2 * y8);
                                context.curveTo(offsetX + 6 * x8, offsetY - 2 * y8, offsetX + 5 * x8, offsetY);
                            } else {
                                context.curveTo(offsetX + 2 * x8, offsetY + 2 * y8, offsetX + 4 * x8, offsetY + 2 * y8);
                                context.curveTo(offsetX + 6 * x8, offsetY + 2 * y8, offsetX + 5 * x8, offsetY);
                            }
                        }
                        context.lineTo(offsetX + 8 * x8, offsetY);
                        if (i != horizontalPieces - 1) {
                            context.lineTo(offsetX + 8 * x8, offsetY + 3 * y8);
                            if (tileObj.right == 1) {
                                context.curveTo(offsetX + 10 * x8, offsetY + 2 * y8, offsetX + 10 * x8, offsetY + 4 * y8);
                                context.curveTo(offsetX + 10 * x8, offsetY + 6 * y8, offsetX + 8 * x8, offsetY + 5 * y8);
                            } else {
                                context.curveTo(offsetX + 6 * x8, offsetY + 2 * y8, offsetX + 6 * x8, offsetY + 4 * y8);
                                context.curveTo(offsetX + 6 * x8, offsetY + 6 * y8, offsetX + 8 * x8, offsetY + 5 * y8);
                            }
                        }
                        context.lineTo(offsetX + 8 * x8, offsetY + 8 * y8);
                        if (j != verticalPieces - 1) {
                            context.lineTo(offsetX + 5 * x8, offsetY + 8 * y8);
                            if (tileObj.down == 1) {
                                context.curveTo(offsetX + 6 * x8, offsetY + 10 * y8, offsetX + 4 * x8, offsetY + 10 * y8);
                                context.curveTo(offsetX + 2 * x8, offsetY + 10 * y8, offsetX + 3 * x8, offsetY + 8 * y8);
                            } else {
                                context.curveTo(offsetX + 6 * x8, offsetY + 6 * y8, offsetX + 4 * x8, offsetY + 6 * y8);
                                context.curveTo(offsetX + 2 * x8, offsetY + 6 * y8, offsetX + 3 * x8, offsetY + 8 * y8);
                            }
                        }
                        context.lineTo(offsetX, offsetY + 8 * y8);
                        if (i != 0) {
                            context.lineTo(offsetX, offsetY + 5 * y8);
                            if (tileObj.left == 1) {
                                context.curveTo(offsetX - 2 * x8, offsetY + 6 * y8, offsetX - 2 * x8, offsetY + 4 * y8);
                                context.curveTo(offsetX - 2 * x8, offsetY + 2 * y8, offsetX, offsetY + 3 * y8);
                            } else {
                                context.curveTo(offsetX + 2 * x8, offsetY + 6 * y8, offsetX + 2 * x8, offsetY + 4 * y8);
                                context.curveTo(offsetX + 2 * x8, offsetY + 2 * y8, offsetX, offsetY + 3 * y8);
                            }
                        }
                        context.lineTo(offsetX, offsetY);
                        s.addTo(con);

                        var fill = new createjs.Graphics.Fill("red");

                        //var newGra = context.append(fill);
                        var hint = new Shape();//s.clone(true);
                        hint.mouseChildren = false;
                        hint.mouseEnabled = false;
                        s.hint = hint;
                        hint.graphics = context.clone(true);
                        hint.pos(puzzleX,puzzleY);
                       // newGra.graphics = newGra;
                        hint.graphics._fill = fill;
                        hint.graphics._fill.style = null;

                        hint.addTo(con,0);
                        //s.animate({obj:{x:frame.width-offsetX-pieceWidth,y:frame.height-offsetY-pieceHeight}, time:700});
                        //s.animate({obj:{x:-offsetX,y:-offsetY}, time:700});
                        s.animate({obj:{x:rand(-offsetX,frame.width-offsetX-pieceWidth),y:rand(-offsetY,frame.height-offsetY-pieceHeight)}, time:700});

                    }
                }


                con.addTo(stage);
                /*con.x -= imageWidth/2;
                con.y -= imageHeight/2;*/
                stage.update();



            }); // end asset complete


            stage.update(); // this is needed to show any changes

        }); // end of ready
    </script>

    <meta name="viewport" content="width=device-width, user-scalable=no" />

</head>

<body>
    <!-- canvas with id="myCanvas" is made by zim Frame -->
</body>

</html>
Did you already know ZIM? Want to play with it? Download the source code of the entire project.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.