Shuffle Grid Demo

Drag & Drop the images to shuffle them around…

A friend of mine, Dale Sattler over at No Ponies recently posted a grid sorting class. He said it was based on my old dynamic stacking menu; but that was pure modesty as his script is based on a 2D grid and much more sophisticated.

Anyway – it inspired me to create a grid sorting / shuffling algorithm of my own. It behaves differently to Dales but I think it works pretty well.

The basic logic of the algorithm works by determining how far a dragged item travels along the grid (rows and columns) and then shuffling the surrounding items in the opposite direction by these values, therefore creating space for the dragged item to slot into when released.

It currently only works for grids which are fully populated, but adding more flexibility for incomplete grids will only be a matter of adding a few conditions – functionality which I’ll add when I get a moment.

You can extend the ShuffleGridItem class to add the functionality you need. In the demo I’ve made a simple image class which grabs a photo from Flickr.

Creating a ShuffleGrid is very simple, and can be done like so:

var grid:ShuffleGrid = new ShuffleGrid(4,7,40,40,1);

for (var i : int = 0; i < grid.numCells; i++)
{
	grid.addItem (new ShuffleGridItem());
}

addChild (grid);

The constructor takes the following arguments:

new ShuffleGrid(rows, cols, cellWidth, cellHeight, spacing);

Feel free to download the class and a simple demo and have a play around. I can imagine many uses for it, so hopefully it will come in handy.

Download: Shuffle Grid Class & Demo
Posted on 04 Mar 2009
48 Comments
7 Trackbacks

Meta

AS3 Shuffle Grid Class was posted on March 4th 2009 in the category Code / Actionscript 3.0, Code, Flash, Lab, Open Source and tagged; , , , , , , .

You can Leave a comment.

Twitter <follow>

September 9th 2010 - 8:43am

A few possible uses for old floppy disks » http://is.gd/f281S

Discussion

55 Responses to AS3 Shuffle Grid Class

Leave a Reply

Pingbacks / Trackbacks

  1. 1 year ago Bookmarks for March 5th from 15:03 to 15:06 « what i say // jon burger

    [...] AS3 Drag and Drop Shuffle Grid Menu Interface – [...]

  2. 1 year ago My First Game | PUBLIC SERVICE

    [...] soulwire’s Shufle Grid Class we present you PUZZLE NO [...]

  3. 1 year ago AntScript » 一个不错的效果收藏

    [...] 原文地址:http://blog.soulwire.co.uk/flash/flash-interfaces/as3-drag-drop-shuffle-grid-menu/#more-311 [...]

  4. 1 year ago Adobe — наш верный друг » AS3 Shuffle Grid Class — блог о air, flash, flex и других технологиях Adobe

    [...] делится своим видением области применения данной штуки. Можете поддержать [...]

  5. 7 months ago [Actionscript 3] Menu tipo iPhone con icone spostabili

    [...] ricerca.. ecco dove l’avevo visto noponies AS3 Drag Sort Grid Experiment e qui ce n’

  6. 3 months ago AnthemGDA » Blog Archive » 15 Detailed Expert Tutorials for ActionScript 3

    [...] 4. AS3 Shuffle Grid Class [...]

  1. wilma j. hancock 10 months ago

    Hi just figured i would let you know i also had a problem with this blog appearing blank also. Might be monkeys in the system.

    Reply to this comment

  2. Rasterstudios 9 months ago

    Hey Soulwire , This site is awesome and you show a great programming stuff!! I can see a Pattern based oops in it..

    nJoy Coding!!

    To drewm ,

    It is not a bug, it does what he programmed… When you click and drag quickly, you may not know where your mouse pointer is.. If the mouse pointer is not pointing the SWF window, obviously the “Tile will be dropped”

    Reply to this comment

  3. jessicatv 9 months ago

    Thanks for this code, it’s very usefull

    Reply to this comment

  4. shifla 9 months ago

    hi mate, amazing work you have donde here! seriously!.
    hey, i was wondering how coul i put images inside each block, i really dunno how to do it, so any help would be great!!
    anyway,, congrats, great work mate.

    shif.

    Reply to this comment

  5. sabee 6 months ago

    Thank you very much for your script!
    I’ve made a adjustment for the grid to work irregulary. It’s probably not the best optimized but works perfect for me and could work for others.

    Here is what I do:

    1) I declare an empty grid at start:
    this.grid = new ShuffleGrid(0, 0, ThumbGiftZone.WIDTH, ThumbGiftZone.HEIGHT, paddingGrid);
    addChild(grid)

    2) I add (in a loop or not) items to the grid with:

    var maxCols:uint = Math.floor(stage.stageWidth / (ThumbGiftZone.WIDTH + padding));
    grid.updateIndexArray(1, maxCols);

    var thumb:ThumbGiftZone = new ThumbGiftZone();
    grid.addItem(thumb);

    You can see I added a new function inside ShuffleGrid.as, here it is:

    public function updateIndexArray(numToAdd:int, maxCols:int):void
    		{
    			var tempNumItems:uint = numItems + numToAdd;
    			var i:int;
    			var j:int;
    			var cols:int;
    			var dif:int;
    
    			var rows:int = Math.ceil(tempNumItems / maxCols);
    
    			for (i = 0; i < rows; i++)
    			{
    				if(_index.length < rows)
    				{
    					_index.push(new Array());
    				}
    
    				// Pour chaque row on détermine le nombre de col. Tous sauf la dernière auront le maxCols
    				cols = (i < rows-1)?maxCols:tempNumItems - (i * maxCols);
    
    				if(_index[i].length < cols)
    				{
    					dif = cols - _index[i].length;
    					for (j = 0; j  1)?maxCols:cols;
    		}
    

    Then I did chane shuffelItems:

    private function shuffleItems() : void
    		{
    			var itemVO : ShuffleGridItemVO = _dictionary[_currentItem];
    			var cell : Point = getCell(_currentItem.x, _currentItem.y);
    
    			var col : int = cell.x;
    			var row : int = (getItemAtPosition(cell.y, cell.x) != null)?cell.y: itemVO.row;
    
    			if(col == itemVO.col && row == itemVO.row)
    			{
    				return;
    			}
    
    			var hMove : int = col - itemVO.col;
    			var vMove : int = (row == itemVO.row)?0:row - itemVO.row;
    
    			var i : int;
    			var item : ShuffleGridItemVO;
    			var move : Array = [];
    
    			if(hMove = itemVO.col + hMove; i--)
    				{
    					if(_index[itemVO.row][i])
    					{
    						item = _index[itemVO.row][i];
    						item.col++;
    
    						_index[item.row][item.col] = item;
    						move.push(item);
    					}
    				}
    			}
    			else
    			{
    				for (i = itemVO.col + 1;i <= itemVO.col + hMove; i++)
    				{
    					if(_index[itemVO.row][i])
    					{
    						item = _index[itemVO.row][i];
    						item.col--;
    
    						_index[item.row][item.col] = item;
    						move.push(item);
    					}
    				}
    			}
    
    			if(vMove = itemVO.row + vMove; i--)
    				{
    					if(_index[i][itemVO.col + hMove])
    					{
    						item = _index[i][itemVO.col + hMove];
    						item.row++;
    
    						if(item.col >= _index[item.row].length)
    						{
    							item.col = _index[item.row].length - 1;
    						}
    
    						_index[item.row][item.col] = item;
    						move.push(item);
    					}
    				}
    			}
    			else
    			{
    				for (i = itemVO.row + 1;i <= itemVO.row + vMove; i++)
    				{
    
    					if(_index[i][itemVO.col + hMove])
    					{
    						item = _index[i][itemVO.col + hMove];
    						item.row--;
    
    						_index[item.row][item.col] = item;
    						move.push(item);
    					}
    				}
    			}
    
    			for (i = 0;i  col)
    			{
    				itemVO.col = col;
    			}
    
    			_index[row][itemVO.col] = itemVO;
    		}
    

    AND getItemAtPosition

    public function getItemAtPosition(row : int, col : int) : ShuffleGridItemVO
    		{
    			var item:ShuffleGridItemVO;
    
    			if(_index[row] != null && _index[row].length > col)
    			{
    				item = _index[row][col];
    			}else
    			{
    				item = null;
    			}
    			return item;
    		}
    

    The whole idea I use is that, even though there is a grid of 6 x 2 for example, if there no “thumb” at row 2, col 3 then I don’t allow the move and don’t update the v move during the shuffleItems()

    Reply to this comment

  6. Arindam 3 months ago

    simply awesome friend.

    Reply to this comment

  7. Fred 3 months ago

    This code is really great ! but I have no idea how to connect the grids to an url of images, or images from a local folder.
    An expert could explain how to proceed ?

    Thanks.

    Fred.

    Reply to this comment

    1. Tyler Madison 3 weeks ago

      You would want to load the images in first using the flash.display.Loader class. You can do this manually or you could probably just extend the ShuffleItem class and through composition create a flash.display.Loader instance as a class instance variable. Then just add a load method for clients to call, and pass it a URL as the load() methods parameter here is a sample of what you’d want to do:

      package {

      import ShuffleItem;
      import flash.display.Loader;
      import flash.events.Event;
      import flash.net.URLRequest;

      public class ShuffleLoaderItem extends ShuffleItem {

      protected var _loader:Loader;

      public function ShuffleLoaderItem(){
      _loader = new Loader();
      _loader.contentLoaderInfo.addEventListener(Event.COMPLETE , handleLoadComplete);
      }

      protected function handleLoadComplete(e:Event):void{
      addChild(_loader);
      }

      /**
      * Method to call when you want to load the image from a URL
      */
      public function load(url:String):void{
      _loader.load(new URLRequest(url));
      }

      }

      }

  8. strony internetowe 3 months ago

    Nice posting. This article has been really useful to me. Thx.

    Reply to this comment

  9. Murdoch 4 weeks ago

    Very nice solution. Thanks.

    Reply to this comment

  10. Rich 2 weeks ago

    Hi Soulwire,

    Thank you so much for sharing this! Sabee posted some code for irregular grids but it seems to have some bits missing. Did you ever find time to figure this out?

    Cheers
    Rich

    Reply to this comment

  11. Rich 2 weeks ago

    Hi,

    I couldn’t quite get Sabee’s exact code to work but the following is working for me for grids that are not full

    change these two functions:

    public function getItemAtPosition(row : int, col : int) : ShuffleGridItemVO
    {
    var item:ShuffleGridItemVO;

    if(_index[row] != null && _index[row].length > col)
    {
    item = _index[row][col];
    }else
    {
    item = null;
    }
    return item;
    }

    and

    private function shuffleItems() : void
    {
    var itemVO : ShuffleGridItemVO = _dictionary[_currentItem];
    var cell : Point = getCell(_currentItem.x, _currentItem.y);

    var col : int = (getItemAtPosition(cell.y, cell.x) != null)?cell.x: itemVO.col;
    var row : int = (getItemAtPosition(cell.y, cell.x) != null)?cell.y: itemVO.row;

    var colFound:Boolean = false;

    if(col == itemVO.col && row == itemVO.row)
    {
    return;
    }

    var hMove : int = (col == itemVO.col)?0:col – itemVO.col;
    var vMove : int = (row == itemVO.row)?0:row – itemVO.row;

    var i : int;
    var item : ShuffleGridItemVO;
    var move : Array = [];

    if(hMove = itemVO.col + hMove; i–)
    {
    if(_index[itemVO.row][i])
    {
    item = _index[itemVO.row][i];
    item.col++;

    _index[item.row][item.col] = item;
    move.push(item);
    }
    }
    }
    else
    {
    for (i = itemVO.col + 1;i <= itemVO.col + hMove; i++)
    {
    if(_index[itemVO.row][i])
    {
    item = _index[itemVO.row][i];
    item.col–;

    _index[item.row][item.col] = item;
    move.push(item);
    }
    }
    }

    if(vMove = itemVO.row + vMove; i–)
    {
    if(_index[i][itemVO.col + hMove])
    {
    item = _index[i][itemVO.col + hMove];
    item.row++;

    while(!colFound){
    if (getItemAtPosition(item.row, item.col)) {
    colFound = true;
    }else {
    item.col–;
    }
    }

    _index[item.row][item.col] = item;
    move.push(item);

    }
    }
    }
    else
    {
    for (i = itemVO.row + 1;i <= itemVO.row + vMove; i++)
    {
    if(_index[i][itemVO.col + hMove])
    {
    item = _index[i][itemVO.col + hMove];
    item.row–;

    _index[item.row][item.col] = item;
    move.push(item);
    }
    }
    }

    for (i = 0;i < move.length; i++)
    {
    snapToGrid(move[i]);
    }

    itemVO.row = row;
    itemVO.col = col;

    _index[row][col] = itemVO;
    }

    Reply to this comment