Sunday, November 6, 2011

DDTe3 Hours 22 to 23 - A Distorted Game


Sorry for missing last week, but I was condo-sitting for my aunt. This is a continuation of my series of articles about the creation of the multi-game Dozen Days of Tiles episode 3 where I tried to create as many games as I could in 24 hours. This part concludes the development of the final (and my personal favorite) game in the episode.

In earlier games created this episode, the game data (model) was separate from the display (view) with the interaction between the two handled by the game (controller). Having three separate classes allowed for a lot more reuse as the model class was used in all seven of the other games and there were only two view classes shared by the seven games. As time is running out and there will not be any other games based of of the radically different model that this game uses for arranging the tiles, I am combining the controller and the model into a single game class. The entire game code is so small that it really doesn’t matter and if fact creating multiple classes to do things properly is overkill.  In fact, despite trying to cut back on the amount of code I post and instead try to focus more on the much more important theory, I am going to post all of the code in the game class.

The constructor stores the image and splitting information. It then sets up the root tile, which is the size of the whole puzzle and contains the whole image. This tile is what gets broken apart to form the final puzzle. An array to hold all the puzzle pieces is created and we call the routine to scramble the board. Since this routine is only ever called once, it could have been placed in the constructor but to make the code a bit more readable (as if such a small program has that problem) it is in a separate function.

PuzzleGallery.DistortionPuzzleGame = function(id, w, h, img, clip, splits)
{
    this.supr = new BGLayers.Layer(id, clip.width, clip.height);
    BGLayers.inheritProperties(this, this.supr);

    this.split = splits;
    this.image = img;
    this.clip = clip;
    this.rootTile = new PuzzleGallery.DistortionTile(id, img, clip, clip.width, clip.height, 10);
    this.rootTile.setTileListener(this);
    this.tileList = new Array();
    this.tileList.push(this.rootTile);
    this.selectedTile = null;
    this.addChild(this.rootTile, new BGLayers.Rectangle(0,0,w,h));
    this.scramble();
}

The heart of the game is handling clicking on tiles. This is very simple as all we do is see if a tile has been clicked on already. If it has not been, the tile gets marked as the selected tile and it’s highlight is turned on. If there is a selected tile then we swap the clipping region of both the tiles and un-highlight the selected tile then we clear the selected tile variable so a new selection can be made. That is all the logic needed to handle the game.

PuzzleGallery.DistortionPuzzleGame.prototype.onTileClick = function(t)
{
    if (this.selectedTile == null) {
    this.selectedTile = t;
    this.selectedTile.setHighlighted(true);
    } else {
    t.swapClips(this.selectedTile);
    this.selectedTile.setHighlighted(false);
    this.selectedTile = null;
    }
    this.addDirty(null);
}

The heart of the game is the scrambling as it also breaks apart the picture. The number of splits passed to the constructor is what controls the number of split passes that the scrambler goes through. In theory, each split doubles the number of tiles in the game, but as there are occasionally tiles that are too small to split further, this is not always the case. One the clips that make up the final puzzle are ready, we loop through the list of pieces and let it know that the true clipping region is it’s current clipping region. Finally, we swap the pieces around. The number of swaps is the split size times the number of tiles to make sure that the puzzle is not straightforward swapping of tiles.

PuzzleGallery.DistortionPuzzleGame.prototype.scramble = function()
{
    // breaking up picture
    var child, cntr, listLen, cntrList;// =    this.rootTile.split();
    for (cntr = 0; cntr < this.split; ++cntr) {
    listLen = this.tileList.length;
    for (cntrList = 0; cntrList < listLen; ++cntrList) {
    child = this.tileList[cntrList].split();
    if (child != null)
    this.tileList.push(child);
    }
    }

    // marking correct clips
    listLen = this.tileList.length;
    for (cntrList = 0; cntrList < listLen; ++cntrList) {
    this.tileList[cntrList].setTrueClip();
    }
   
    // scrambling puzzle
    var swap;
    for (cntr = 0; cntr < this.split; ++cntr) {
    for (cntrList = 0; cntrList < listLen; ++cntrList) {
    swap = Math.floor(Math.random() * listLen)
    this.tileList[cntrList].swapClips(this.tileList[swap]);
    }
    }
}

That is the entire game and with about half an hour left is where we end this episode. But that may not be the end of the puzzle gallery. Next week I will have one final article on the topic of this game where I discuss possible future plans.

No comments: