topical media & game development

talk show tell print

#graphic-player-10-cube-be-nascom-flash-util-UnitGrid.ax

#graphic-player-10-cube-be-nascom-flash-util-UnitGrid.ax [swf] [flash] flex


  package be.nascom.flash.util{
          
          import flash.display.Shape;
          import flash.events.Event;
          import flash.events.EventDispatcher;
          import flash.geom.Point;
          import flash.geom.Rectangle;
          
          public class @ax-graphic-player-10-cube-be-nascom-flash-util-UnitGrid extends EventDispatcher{
                  
                  protected var _active_cells:Array;
                  protected var _grid_rectangle:Rectangle;
                  protected var _rows:uint=0;
                  public function get rows():uint{return _rows;}
                  protected var _cols:uint=0;
                  public function get cols():uint{return _cols;}
                  protected var _unit_size:uint=0;
                  public function get unit_size():uint{return _unit_size;}
                  
                  public function get width():uint{return _unit_size*_cols;}
                  public function get height():uint{return _unit_size*_rows;}
                          
                  protected var _test_shape:Shape;
                                  
                  public function get total_cells():uint{
                          return _cols*_rows;
                  }
                  
                  public function @ax-graphic-player-10-cube-be-nascom-flash-util-UnitGrid(){}
  
                  public function init(rows:uint,cols:uint,unit_size:uint,test_shape:Shape=null):void{
                          _test_shape=test_shape;
                          _rows=rows;
                          _cols=cols;
                          _unit_size=unit_size;
                          trace("@ax-graphic-player-10-cube-be-nascom-flash-util-UnitGrid.init() rows:"+_rows+",cols:"+_cols+",unit_size:"+_unit_size);
                          var tot:uint=total_cells;
                          _active_cells=new Array();
                          for(var i:uint=0;i<tot;i++){
                                  _active_cells[i]=true;
                          }
                          _grid_rectangle=new Rectangle(0,0,_cols*_unit_size,_rows*_unit_size);
                          dispatchEvent(new Event(Event.CHANGE));
                  }
                  
                  protected function showInTestShape(p:Point):void{
                          if(_test_shape==null)return;
                          var color:uint=Math.floor(Math.random()*0xDF)+100000;
                          _test_shape.graphics.beginFill(color);
                          _test_shape.graphics.drawCircle(p.x,p.y,3);
                          _test_shape.graphics.endFill();
                          
                  }
  
                  
                  protected function checkCellIndexBounds(index:int):void{
                          if(!isWithinCellIndexBounds(index))throw new Error("CellGrid out of bounds cell index Error");
                  }
                  
                  protected function isWithinCellIndexBounds(index:int):Boolean{
                          return index>=0 || index<total_cells;
                  }
                  
                  public function getCenterCellIndex():uint{
                          return Math.round(Math.round(_rows/2)*_cols+_cols/2);
                  }
                  
                  
                  public function getCellXYPointByIndex(cell_index:uint):Point{
                          checkCellIndexBounds(cell_index);
                          return new Point(getCellXByIndex(cell_index),getCellYByIndex(cell_index));
                  }
                  public function getCellXByIndex(cell_index:uint):uint{
                          checkCellIndexBounds(cell_index);
                          return getColumnIndex(cell_index)*this._unit_size;
                  }
                  public function getCellYByIndex(cell_index:uint):uint{
                          checkCellIndexBounds(cell_index);
                          return getRowIndex(cell_index)*this._unit_size;
                  }
                  
                  public function getRowIndex(cell_index:uint):uint{
                          return Math.floor(cell_index/_cols);
                  }
                  public function getColumnIndex(cell_index:uint):uint{
                          //trace("@ax-graphic-player-10-cube-be-nascom-flash-util-UnitGrid.getColumnIndex() rows:"+_rows+",cols:"+_cols+",cell_index:"+cell_index+",return:"+cell_index%_cols);
                          return cell_index%_cols;
                  }
                  
                  public function indexIsActive(cell_index:uint):Boolean{
                          checkCellIndexBounds(cell_index);//too much?
                          return _active_cells[cell_index];
                  }
                  
                  //LEFT SIDE
                  public function hasCellOnLeftSide(cell_index:uint):Boolean{
                          return getColumnIndex(cell_index) ? true : false;//if column index is 0, then it's the leftmost column
                  }
                  //use this like you use String.indexOf(), ex) if(getCellIndexToLeft(x)>-1)
                  public function getCellIndexToLeft(cell_index:uint):int{
                          checkCellIndexBounds(cell_index);
                          if(!hasCellOnLeftSide(cell_index))return -1;
                          return cell_index-1;
                  }
                  public function cellToLeftIsActive(cell_index:uint):Boolean{
                          if(!hasCellOnLeftSide(cell_index))return false;
                          return Boolean(_active_cells[getCellIndexToLeft(cell_index)]);
                  }
                  
  
                  //RIGHT SIDE                
                  public function hasCellOnRightSide(cell_index:uint):Boolean{
                          return getColumnIndex(cell_index)<_cols-1 ? true : false;
                  }
                  //use this like you use String.indexOf(), ex) if(getCellToRight(x)>-1)
                  public function getCellIndexToRight(cell_index:uint):int{
                          checkCellIndexBounds(cell_index);
                          if(!hasCellOnRightSide(cell_index))return -1;
                          return cell_index+1;
                  }
                  public function cellToRightIsActive(cell_index:uint):Boolean{
                          if(!hasCellOnRightSide(cell_index))return false;
                          return Boolean(_active_cells[getCellIndexToRight(cell_index)]);
                  }
                  
                  //ABOVE
                  public function hasCellAbove(cell_index:uint):Boolean{
                          return getRowIndex(cell_index) ? true : false;
                  }
                  public function getCellIndexAbove(cell_index:uint):int{
                          checkCellIndexBounds(cell_index);
                          if(!hasCellAbove(cell_index))return -1;
                          return cell_index-_cols;                
                  }
                  public function cellAboveIsActive(cell_index:uint):Boolean{
                          if(!hasCellAbove(cell_index))return false;
                          return Boolean(_active_cells[getCellIndexAbove(cell_index)]);
                  }
                  
                  //BELOW
                  public function hasCellBelow(cell_index:uint):Boolean{
                          return getRowIndex(cell_index)<_rows-1 ? true : false;
                  }
                  public function getCellIndexBelow(cell_index:uint):int{
                          checkCellIndexBounds(cell_index);
                          if(!hasCellBelow(cell_index))return -1;
                          return cell_index+_cols;                
                  }
                  
                  /*
                  public function getRectRight(from_rect:Rectangle,minimum_rect:Rectangle,max_rect:Rectangle):Rectangle{
                          //search for a rect of minimum size, if none found:
                          return null;
                          //else return found Rectangle of maximum size
                          var rect:Rectangle=new Rectangle();
                          disableCells(rect);
                          return rect;
                  }
                  
                  public function getRectUnder(from_rect:Rectangle,minimum_rect:Rectangle,max_rect:Rectangle):Rectangle{
                          return null;
                  }
                  
                  public function getRectLeft(from_rect:Rectangle,minimum_rect:Rectangle,max_rect:Rectangle):Rectangle{
                          return null;
                  }
                  
                  public function getSpaceOnTop(from_rect:Rectangle,minimum_rect:Rectangle,max_rect:Rectangle):Rectangle{
                          return null;
                  }
  		*/
                  
                  public function getCellIndexContainingPoint(p:Point):int{
                          if(!_grid_rectangle.containsPoint(p))return -1;
                          var _x:uint=Math.floor(p.x/unit_size);
                          var _y:uint=Math.floor(p.y/unit_size);
                          var index:uint=_y*_cols+_x;
                          return index;
                  }
                  
                  
                  //RIGHT
                  protected function findSeedToTheRight(rect:Rectangle):int{
                          var seed:int=getCellIndexContainingPoint(new Point(rect.right,rect.top));
                          trace("@ax-graphic-player-10-cube-be-nascom-flash-util-UnitGrid.findSeedToTheRight() seed:"+seed);
                          if(seed==-1)return -1;//failsafe
                          var current_index:uint=this.getCellIndexToRight(seed);
                          if(seed==-1)return -1;
                          if(indexIsActive(current_index))return current_index;
                          //set only after conditions are met
                          var max_iterations:uint=Math.ceil(rect.height/_unit_size);
                          var cur_iteration:uint=0;
                          while(hasCellBelow(current_index) && cur_iteration<max_iterations){
                                  current_index=getCellIndexBelow(current_index);
                                  if(_active_cells[current_index])return current_index;
                                  cur_iteration++;
                          }
                          return -1;                
                  }
                  
                  //finds first available "seed" starting from top right corner, going downwards
                  protected function findBiggestSquareRightDown(cell_index:uint,max_rect:Rectangle):Rectangle{
                          trace("CellGrid.findBiggestRectRightDown()");
                          var max_size:uint=Math.ceil(max_rect.width/this._unit_size);
                          var found:Rectangle=new Rectangle(0,0,_unit_size,_unit_size);
                          var down_check_cell:int=cell_index;
                          var right_check_cell:int=cell_index;
                          var check_cell:int;
                          var i:uint,j:uint,size:uint;
                          
                          main:for(i=1;i<max_size;i++){
                                  size=(i+1)*_unit_size;
                                  if(size>max_rect.width)break;//this should be redundant (see main loop)
                                  check_cell=down_check_cell=this.getCellIndexToRight(down_check_cell);
                                  if(down_check_cell==-1)break;
                                  //check new vertical line going down
                                  for(j=0;j<i;j++){
                                          if(check_cell==-1)break main;
                                          if(!_active_cells[check_cell])break main;
                                          check_cell=getCellIndexBelow(check_cell);
                                  }
                                  //check new horizontal line going right
                                  check_cell=right_check_cell=this.getCellIndexBelow(right_check_cell);
                                  for(j=0;j<i;j++){
                                          if(check_cell==-1)break main;
                                          if(!_active_cells[check_cell])break main;
                                          check_cell=this.getCellIndexToRight(check_cell);
                                  }
  
                                  found=new Rectangle(0,0,size,size);
                                  trace("\t"+found.toString());
                          }
                          return found;
                  }
                  
                  public function findRectangleToTheRight(source_rect:Rectangle,min_rect:Rectangle,max_rect:Rectangle):Rectangle{
                          var seed:int=findSeedToTheRight(source_rect);
                          if(seed==-1)return null;
                          var biggest:Rectangle=findBiggestSquareRightDown(seed,max_rect);
                          biggest.x=this.getCellXByIndex(seed);
                          biggest.y=this.getCellYByIndex(seed);
                          return biggest;
                  }
  
                  
                  //BELOW
                  protected function findSeedBelow(rect:Rectangle):int{
                          var seed:int=getCellIndexContainingPoint(rect.bottomRight);
                          trace("@ax-graphic-player-10-cube-be-nascom-flash-util-UnitGrid.findSeedBelow() seed:"+seed);
                          if(seed==-1)return -1;//failsafe
                          var current_index:uint=getCellIndexBelow(seed);
                          if(current_index==-1)return -1;
                          if(indexIsActive(current_index))return current_index;
                          //set only after conditions are met
                          var max_iterations:uint=Math.ceil(rect.height/_unit_size);
                          var cur_iteration:uint=0;
                          while(hasCellOnLeftSide(current_index) && cur_iteration<max_iterations){
                                  current_index=getCellIndexToLeft(current_index);
                                  if(_active_cells[current_index])return current_index;
                                  cur_iteration++;
                          }
                          return -1;                
                  }
                  
                  //finds first available "seed" starting from bottom right corner, going left
                  protected function findBiggestSquareBottomRight(cell_index:uint,max_rect:Rectangle):Rectangle{
                          trace("CellGrid.findBiggestRectBottomRight()");
                          var max_size:uint=Math.ceil(max_rect.width/this._unit_size);
                          var found:Rectangle=new Rectangle(0,0,_unit_size,_unit_size);
                          var down_check_cell:int=cell_index;
                          var left_check_cell:int=cell_index;
                          var check_cell:int;
                          var i:uint,j:uint,size:uint;
                          
                          main:for(i=1;i<max_size;i++){
                                  size=(i+1)*_unit_size;
                                  if(size>max_rect.width)break;//this should be redundant (see main loop)
                                  check_cell=down_check_cell=this.getCellIndexToLeft(down_check_cell);
                                  if(down_check_cell==-1)break;
                                  //check new vertical line going down
                                  for(j=0;j<i;j++){
                                          if(check_cell==-1)break main;
                                          if(!_active_cells[check_cell])break main;
                                          check_cell=getCellIndexBelow(check_cell);
                                  }
                                  //check new horizontal line going right
                                  check_cell=left_check_cell=this.getCellIndexBelow(left_check_cell);
                                  if(left_check_cell==-1)break;
                                  for(j=0;j<i;j++){
                                          if(check_cell==-1)break main;
                                          if(!_active_cells[check_cell])break main;
                                          check_cell=this.getCellIndexToLeft(check_cell);
                                  }
  
                                  found=new Rectangle(0,0,size,size);
                                  trace("\t"+found.toString());
                          }
                          return found;
                  }
  
                  public function findRectangleBelow(source_rect:Rectangle,min_rect:Rectangle,max_rect:Rectangle):Rectangle{
                          var seed:int=findSeedBelow(source_rect);
                          if(seed==-1)return null;
                          var biggest:Rectangle=findBiggestSquareBottomRight(seed,max_rect);
                          biggest.x=this.getCellXByIndex(seed)-biggest.width+_unit_size;//offset
                          //biggest.x=this.getCellXByIndex(seed);//offset
                          biggest.y=this.getCellYByIndex(seed);
                          return biggest;
                  }
                  
                  //LEFT
                  //Refactor to "findNextActiveBelow(index,max_units), findNExtActiveAbove(index,max_units)
                  protected function findSeedToTheLeft(rect:Rectangle):int{
                          var seed:int=getCellIndexContainingPoint(rect.topLeft);
                          trace("@ax-graphic-player-10-cube-be-nascom-flash-util-UnitGrid.findSeedToTheLeft() seed:"+seed);
                          if(seed==-1)return -1;//failsafe
                          var current_index:uint=this.getCellIndexToLeft(seed);
                          if(seed==-1)return -1;
                          if(indexIsActive(current_index))return current_index;
                          //set only after conditions are met
                          var max_iterations:uint=Math.ceil(rect.height/_unit_size);
                          var cur_iteration:uint=0;
                          while(hasCellBelow(current_index) && cur_iteration<max_iterations){
                                  current_index=getCellIndexBelow(current_index);
                                  if(_active_cells[current_index])return current_index;
                                  cur_iteration++;
                          }
                          return -1;                
                  }
                  
                  public function findRectangleToTheLeft(source_rect:Rectangle,min_rect:Rectangle,max_rect:Rectangle):Rectangle{
                          var seed:int=findSeedToTheLeft(source_rect);
                          if(seed==-1)return null;
                          var biggest:Rectangle=findBiggestSquareBottomRight(seed,max_rect);
                          biggest.x=this.getCellXByIndex(seed)-biggest.width+_unit_size;//offset
                          biggest.y=this.getCellYByIndex(seed);
                          return biggest;
                  }
  
                  //TOP
                  //Refactor to "findNextActiveAbove(index,max_units), 
                  protected function findSeedAbove(rect:Rectangle):int{
                          var seed:int=getCellIndexContainingPoint(rect.topLeft);
                          //trace("@ax-graphic-player-10-cube-be-nascom-flash-util-UnitGrid.findSeedAbove() seed:"+seed);
                          //showInTestShape(getCellXYPointByIndex(seed));
                          if(seed==-1)return -1;//failsafe
                          var current_index:uint=this.getCellIndexAbove(seed);
                          if(seed==-1)return -1;
                          if(indexIsActive(current_index))return current_index;
                          //set only after conditions are met
                          var max_iterations:uint=Math.ceil(rect.width/_unit_size);
                          var cur_iteration:uint=0;
                          while(this.hasCellOnRightSide(current_index) && cur_iteration<max_iterations){
                                  //trace("findSeedAbove() looping:"+cur_iteration);
                                  current_index=this.getCellIndexToRight(current_index);
                                  //showInTestShape(getCellXYPointByIndex(current_index));
                                  if(_active_cells[current_index])return current_index;
                                  cur_iteration++;
                          }
                          return -1;
                  }
  
                  //finds first available "seed" starting from bottom right corner, going left
                  protected function findBiggestSquareTopLeft(cell_index:uint,max_rect:Rectangle):Rectangle{
                          trace("CellGrid.findBiggestSquareTopLeft()");
                          var max_size:uint=Math.ceil(max_rect.width/this._unit_size);
                          var found:Rectangle=new Rectangle(0,0,_unit_size,_unit_size);
                          var up_check_cell:int,right_check_cell:int,check_cell:int;
                          up_check_cell=right_check_cell=check_cell=getCellIndexAbove(cell_index);
                          var i:uint,j:uint,size:uint;
                          
                          main:for(i=0;i<max_size;i++){
                                  size=(i+1)*_unit_size;
                                  if(size>max_rect.width)break;//this should be redundant (see main loop)
                                  if(up_check_cell==-1)break;
                                  check_cell=up_check_cell;
                                  //check new vertical line going up
                                  for(j=0;j<i;j++){
                                          if(check_cell==-1)break main;
                                          if(!_active_cells[check_cell])break main;
                                          //showInTestShape(getCellXYPointByIndex(check_cell));
                                          check_cell=getCellIndexAbove(check_cell);
                                  }
                                  //check new horizontal line going right
                                  check_cell=right_check_cell;
                                  if(right_check_cell==-1)break;
                                  for(j=0;j<i;j++){
                                          if(check_cell==-1)break main;
                                          if(!_active_cells[check_cell])break main;
                                          //showInTestShape(getCellXYPointByIndex(check_cell));
                                          check_cell=this.getCellIndexToRight(check_cell);
                                  }
                                  up_check_cell=getCellIndexToRight(up_check_cell);
                                  right_check_cell=getCellIndexAbove(right_check_cell);
                                  found=new Rectangle(0,0,size,size);
                                  //trace("\t"+found.toString());
                          }
                          return found;
                  }
                  
                  public function findRectangleAbove(source_rect:Rectangle,min_rect:Rectangle,max_rect:Rectangle):Rectangle{
                          var seed:int=findSeedAbove(source_rect);
                          trace("findRectangleAbove() source_rect:"+source_rect+" , seed:"+seed);
                          if(seed==-1)return null;
                          var biggest:Rectangle=findBiggestSquareTopLeft(seed,max_rect);
                          biggest.x=this.getCellXByIndex(seed);
                          biggest.y=this.getCellYByIndex(seed)-biggest.height;//y offset
                          return biggest;
                  }        
                  
                  public function disableCellsUnderRect(rect:Rectangle):void{
                          var top_left_index:uint=getCellIndexContainingPoint(rect.topLeft);
                          var bottom_right_index:uint=getCellIndexContainingPoint(rect.bottomRight);
                          var affected_cols:uint=getColumnIndex(bottom_right_index)-getColumnIndex(top_left_index);//plus one is a hack... 
                          var affected_rows:uint=getRowIndex(bottom_right_index)-getRowIndex(top_left_index);//plus one is a hack... 
                          trace("disableCellsUnderRect() affected_cols:"+affected_cols+",affected_rows"+affected_rows);
                          var i:uint,j:uint;
                          var current_index:uint=top_left_index;
                          var current_v_index:uint=top_left_index;
                          //var tot:uint=0;
                          for(i=0;i<=affected_rows;i++){
                                  for(j=0;j<=affected_cols;j++){
                                          _active_cells[current_index]=false;
                                          current_index++;
                                          //tot++;
                                          //checkCellIndexBounds(current_index);
                                  }
                                  current_v_index=current_index=this.getCellIndexBelow(current_v_index);
                          }
                          //trace("@ax-graphic-player-10-cube-be-nascom-flash-util-UnitGrid.disableCellsUnderRect() total flagged:"+tot);
                          dispatchEvent(new Event(Event.CHANGE));
                  }
  
          }
  }


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.