Brownian Motion + CollisionGrid

Posted on March 1, 2009
Filed Under Actionscript 3.0, experiments | 3 Comments

brownianmotionwithgridcollisionView experiment.

Started reading Advanced Actionscript 3 Animation written by Keith Peters & Seb Lee-DeLisle (technical reviewer) so here’s a little experiment with grid collision using the FP10 Vector class. Let it run for a while and it creates a nice weird image.

Brownian CollisionDemo:

  1. package
  2. {
  3.  import flash.display.BlendMode;
  4.  import flash.filters.BlurFilter;
  5.  import flash.display.Bitmap;
  6.  import flash.display.BitmapData;
  7.  import flash.events.Event;
  8.  import flash.display.StageScaleMode;
  9.  import flash.display.StageAlign;
  10.  import flash.display.DisplayObject;
  11.  import flash.display.Sprite;
  12.  
  13.  public class CollisionDemo extends Sprite
  14.  {
  15.   private const GRID_SIZE:Number = 30;
  16.   private const RADIUS:Number = 15;
  17.  
  18.   private var _screen:BitmapData = new BitmapData(800, 600, false, 0);
  19.   private var _balls:Vector.<DisplayObject>;
  20.   private var _grid:CollisionGrid;
  21.   private var _numBalls:int = 100;
  22.   private var _ballContainer:Sprite = new Sprite();
  23.  
  24.   public function CollisionDemo()
  25.   {
  26.    stage.align = StageAlign.TOP_LEFT;
  27.    stage.scaleMode = StageScaleMode.NO_SCALE;
  28.  
  29.    addChild(new Bitmap(_screen));
  30.    addChild(_ballContainer);
  31.  
  32.    _grid = new CollisionGrid(stage.stageWidth, stage.stageHeight, GRID_SIZE);
  33.    _grid.drawGrid(graphics, 0, .1);
  34.  
  35.    makeBalls();
  36.  
  37.    addEventListener(Event.ENTER_FRAME, onEnterFrame);
  38.   }
  39.  
  40.   function onEnterFrame(event:Event):void
  41.   {
  42.    updateBalls();
  43.    _grid.check(_balls);
  44.  
  45.    var numChecks:int = _grid.checks.length;
  46.    for(var j:int = 0; j < numChecks; j += 2)
  47.    {
  48.     checkCollision(_grid.checks[j] as Circle, _grid.checks[j + 1] as Circle);
  49.    }
  50.  
  51.    _screen.draw(_ballContainer);
  52.   }
  53.  
  54.   private function makeBalls():void
  55.   {
  56.    _balls = new Vector.<DisplayObject>(_numBalls);
  57.    for(var i:int = 0; i < _numBalls; i++)
  58.    {
  59.     var circle:Circle = new Circle(RADIUS);
  60.     circle.x = Math.random() * stage.stageWidth;
  61.     circle.y = Math.random() * stage.stageHeight;
  62.     circle.vx = Math.random() * 105;
  63.     circle.vy = Math.random() * 105;
  64.     _ballContainer.addChild(circle);
  65.     _balls[i] = circle;
  66.    }
  67.  
  68.    _ballContainer.visible = false;
  69.   }
  70.  
  71.   private function updateBalls():void
  72.   {
  73.    for(var i:int = 0; i < _numBalls; i++)
  74.    {
  75.     var circle:Circle = _balls[i] as Circle;
  76.     circle.update();
  77.  
  78.     circle.vx = Math.random() * 105;
  79.     circle.vy = Math.random() * 105;
  80.  
  81.     if(circle.x < RADIUS)
  82.     {
  83.      circle.x = RADIUS;
  84.      circle.vx *= -1;
  85.     }
  86.     else if(circle.x > stage.stageWidth – RADIUS)
  87.     {
  88.      circle.x = stage.stageWidth – RADIUS;
  89.      circle.vx *= -1;
  90.     }
  91.     if(circle.y < RADIUS)
  92.     {
  93.      circle.y = RADIUS;
  94.      circle.vy *= -1;
  95.     }
  96.     else if(circle.y > stage.stageHeight – RADIUS)
  97.     {
  98.      circle.y = stage.stageHeight – RADIUS;
  99.      circle.vy *= -1;
  100.     }
  101.     circle.color = 0xffffff;
  102.    }
  103.   }
  104.  
  105.   private function checkCollision(circleA:Circle, circleB:Circle):void
  106.   {
  107.    var dx:Number = circleB.x – circleA.x;
  108.    var dy:Number = circleB.y – circleA.y;
  109.    var dist:Number = Math.sqrt(dx * dx + dy * dy);
  110.    if(dist < circleA.radius + circleB.radius)
  111.    {
  112.     circleA.color = 0x7DC202;
  113.     circleB.color = 0x7DC202;
  114.    }
  115.   }
  116.  }
  117. }

CollisionGrid Class:

  1. package
  2. {
  3.  import flash.display.DisplayObject;
  4.  import flash.display.Graphics;
  5.  import flash.events.EventDispatcher;
  6.  
  7.  public class CollisionGrid extends EventDispatcher
  8.  {
  9.   private var _checks:Vector.<DisplayObject>;
  10.   private var _grid:Vector.<Vector.<DisplayObject>>;
  11.   private var _gridSize:Number;
  12.   private var _height:Number;
  13.   private var _width:Number;
  14.   private var _numCells:int;
  15.   private var _numCols:int;
  16.   private var _numRows:int;
  17.  
  18.   public function CollisionGrid(width:Number, height:Number, gridSize:Number)
  19.   {
  20.    _width = width;
  21.    _height = height;
  22.    _gridSize = gridSize;
  23.    _numCols = Math.ceil(_width / _gridSize);
  24.    _numRows = Math.ceil(_height / _gridSize);
  25.    _numCells = _numCols * _numRows;
  26.   }
  27.  
  28.   public function drawGrid(graphics:Graphics, color:int = 0×333333, alpha:Number = 1):void
  29.   {
  30.    graphics.lineStyle(0, color, alpha);
  31.    for (var i:int = 0; i < _width; i += _gridSize)
  32.    {
  33.     graphics.moveTo(i, 0);
  34.     graphics.lineTo(i, _height);
  35.    }
  36.  
  37.    for (var j:int = 0; j < _height; j += _gridSize)
  38.    {
  39.     graphics.moveTo(0, j);
  40.     graphics.lineTo(_width, j);
  41.    }
  42.   }
  43.  
  44.   public function check(objects:Vector.<DisplayObject>):void
  45.   {
  46.    var numObjects:int = objects.length;
  47.    _grid = new Vector.<Vector.<DisplayObject>>(_numCells);
  48.    _checks = new Vector.<DisplayObject>();
  49.    for(var i:int = 0; i < numObjects; i++)
  50.    {
  51.     var obj:DisplayObject = objects[i];
  52.     var index:int = Math.floor(obj.y / _gridSize) * _numCols + Math.floor(obj.x / _gridSize);
  53.     if(_grid[index] == null) _grid[index] = new Vector.<DisplayObject>;
  54.     _grid[index].push(obj);
  55.    }
  56.  
  57.    checkGrid();
  58.   }
  59.  
  60.   private function checkGrid():void
  61.   {
  62.    for (var i:int = 0; i <_numCols; i++)
  63.    {
  64.     for (var j:int = 0; j < _numRows; j++)
  65.     {
  66.      checkOneCell(i,j);
  67.      checkTwoCells(i, j, i + 1, j);  // right
  68.      checkTwoCells(i, j, i – 1, j + 1); // lower left
  69.      checkTwoCells(i, j, i    , j + 1); // lower
  70.      checkTwoCells(i, j, i + 1, j + 1);  // lower right
  71.     }
  72.    }
  73.   }
  74.  
  75.   private function checkOneCell(x:int, y:int):void
  76.   {
  77.    var cell:Vector.<DisplayObject> = _grid[y * _numCols + x];
  78.    if (cell == null) return;
  79.  
  80.    var cellLength:int = cell.length;
  81.    for (var i:int = 0; i < cellLength – 1; i++)
  82.    {
  83.     var objA:DisplayObject = cell[i];
  84.  
  85.     for (var j:int = i + 1; j < cellLength; j++)
  86.     {
  87.      var objB:DisplayObject = cell[j];
  88.      _checks.push(objA, objB);
  89.     }
  90.    }
  91.   }
  92.  
  93.   private function checkTwoCells(x1:int, y1:int, x2:int, y2:int):void
  94.   {
  95.    // make sure cell exists
  96.    if (x2 >= _numCols || x2 < 0 || y2 >= _numRows) return;
  97.  
  98.    var cellA:Vector.<DisplayObject> = _grid[y1 * _numCols + x1];
  99.    var cellB:Vector.<DisplayObject> = _grid[y2 * _numCols + x2];
  100.    if (cellA == null || cellB == null) return;
  101.  
  102.    var cellALength:int = cellA.length;
  103.    var cellBLength:int = cellB.length;
  104.  
  105.    for (var i:int = 0; i < cellALength; i++)
  106.    {
  107.     var objA:DisplayObject = cellA[i];
  108.  
  109.     for(var j:int = 0; j < cellBLength; j++)
  110.     {
  111.      var objB:DisplayObject = cellB[j];
  112.      _checks.push(objA, objB);
  113.     }
  114.    }
  115.   }
  116.  
  117.   public function get checks():Vector.<DisplayObject>
  118.   {
  119.    return _checks;
  120.   }
  121.  }
  122. }

Comments

3 Responses to “Brownian Motion + CollisionGrid”

  1. Lol on February 23rd, 2010 2:13 pm

    Hello, I am trying to get this fine Brownian Motion/Collision Grid to work, I have made the example work from the Keith Peters book, I am learning.

    I can’t get it to run – 1046: Type was not found or was not a compile-time constant: Circle.

    I know you must be really busy but would be very grateful if you could advise me.

  2. Lol on February 23rd, 2010 2:32 pm

    I’m using CS4 by the way!

  3. Lol on February 23rd, 2010 3:29 pm

    Ok so I see CollisionDemo wants a Circle, so I have made a Circle class for it, like in the Ball class in the ActionScript 3.0 Animation book. But now it complains there is no circle.update() method, which indeed there is not. I am very new at this, can you tell me what the circle.update() method should be please?

    Although I see you have not been active here for months. I do hope you are ok.

-->