Brownian Motion + CollisionGrid
Posted on March 1, 2009
Filed Under Actionscript 3.0, experiments |
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:
-
package
-
{
-
import flash.display.BlendMode;
-
import flash.filters.BlurFilter;
-
import flash.display.Bitmap;
-
import flash.display.BitmapData;
-
import flash.events.Event;
-
import flash.display.StageScaleMode;
-
import flash.display.StageAlign;
-
import flash.display.DisplayObject;
-
import flash.display.Sprite;
-
-
public class CollisionDemo extends Sprite
-
{
-
private const GRID_SIZE:Number = 30;
-
private const RADIUS:Number = 15;
-
-
private var _screen:BitmapData = new BitmapData(800, 600, false, 0);
-
private var _balls:Vector.<DisplayObject>;
-
private var _grid:CollisionGrid;
-
private var _numBalls:int = 100;
-
private var _ballContainer:Sprite = new Sprite();
-
-
public function CollisionDemo()
-
{
-
stage.align = StageAlign.TOP_LEFT;
-
stage.scaleMode = StageScaleMode.NO_SCALE;
-
-
addChild(new Bitmap(_screen));
-
addChild(_ballContainer);
-
-
_grid = new CollisionGrid(stage.stageWidth, stage.stageHeight, GRID_SIZE);
-
_grid.drawGrid(graphics, 0, .1);
-
-
makeBalls();
-
-
addEventListener(Event.ENTER_FRAME, onEnterFrame);
-
}
-
-
function onEnterFrame(event:Event):void
-
{
-
updateBalls();
-
_grid.check(_balls);
-
-
var numChecks:int = _grid.checks.length;
-
for(var j:int = 0; j < numChecks; j += 2)
-
{
-
checkCollision(_grid.checks[j] as Circle, _grid.checks[j + 1] as Circle);
-
}
-
-
_screen.draw(_ballContainer);
-
}
-
-
private function makeBalls():void
-
{
-
_balls = new Vector.<DisplayObject>(_numBalls);
-
for(var i:int = 0; i < _numBalls; i++)
-
{
-
var circle:Circle = new Circle(RADIUS);
-
circle.x = Math.random() * stage.stageWidth;
-
circle.y = Math.random() * stage.stageHeight;
-
circle.vx = Math.random() * 10 - 5;
-
circle.vy = Math.random() * 10 - 5;
-
_ballContainer.addChild(circle);
-
_balls[i] = circle;
-
}
-
-
_ballContainer.visible = false;
-
}
-
-
private function updateBalls():void
-
{
-
for(var i:int = 0; i < _numBalls; i++)
-
{
-
var circle:Circle = _balls[i] as Circle;
-
circle.update();
-
-
circle.vx = Math.random() * 10 - 5;
-
circle.vy = Math.random() * 10 - 5;
-
-
if(circle.x < RADIUS)
-
{
-
circle.x = RADIUS;
-
circle.vx *= -1;
-
}
-
else if(circle.x > stage.stageWidth - RADIUS)
-
{
-
circle.x = stage.stageWidth - RADIUS;
-
circle.vx *= -1;
-
}
-
if(circle.y < RADIUS)
-
{
-
circle.y = RADIUS;
-
circle.vy *= -1;
-
}
-
else if(circle.y > stage.stageHeight - RADIUS)
-
{
-
circle.y = stage.stageHeight - RADIUS;
-
circle.vy *= -1;
-
}
-
circle.color = 0xffffff;
-
}
-
}
-
-
private function checkCollision(circleA:Circle, circleB:Circle):void
-
{
-
var dx:Number = circleB.x - circleA.x;
-
var dy:Number = circleB.y - circleA.y;
-
var dist:Number = Math.sqrt(dx * dx + dy * dy);
-
if(dist < circleA.radius + circleB.radius)
-
{
-
circleA.color = 0×7DC202;
-
circleB.color = 0×7DC202;
-
}
-
}
-
}
-
}
CollisionGrid Class:
-
package
-
{
-
import flash.display.DisplayObject;
-
import flash.display.Graphics;
-
import flash.events.EventDispatcher;
-
-
public class CollisionGrid extends EventDispatcher
-
{
-
private var _checks:Vector.<DisplayObject>;
-
private var _grid:Vector.<Vector.<DisplayObject>>;
-
private var _gridSize:Number;
-
private var _height:Number;
-
private var _width:Number;
-
private var _numCells:int;
-
private var _numCols:int;
-
private var _numRows:int;
-
-
public function CollisionGrid(width:Number, height:Number, gridSize:Number)
-
{
-
_width = width;
-
_height = height;
-
_gridSize = gridSize;
-
_numCols = Math.ceil(_width / _gridSize);
-
_numRows = Math.ceil(_height / _gridSize);
-
_numCells = _numCols * _numRows;
-
}
-
-
public function drawGrid(graphics:Graphics, color:int = 0×333333, alpha:Number = 1):void
-
{
-
graphics.lineStyle(0, color, alpha);
-
for (var i:int = 0; i < _width; i += _gridSize)
-
{
-
graphics.moveTo(i, 0);
-
graphics.lineTo(i, _height);
-
}
-
-
for (var j:int = 0; j < _height; j += _gridSize)
-
{
-
graphics.moveTo(0, j);
-
graphics.lineTo(_width, j);
-
}
-
}
-
-
public function check(objects:Vector.<DisplayObject>):void
-
{
-
var numObjects:int = objects.length;
-
_grid = new Vector.<Vector.<DisplayObject>>(_numCells);
-
_checks = new Vector.<DisplayObject>();
-
for(var i:int = 0; i < numObjects; i++)
-
{
-
var obj:DisplayObject = objects[i];
-
var index:int = Math.floor(obj.y / _gridSize) * _numCols + Math.floor(obj.x / _gridSize);
-
if(_grid[index] == null) _grid[index] = new Vector.<DisplayObject>;
-
_grid[index].push(obj);
-
}
-
-
checkGrid();
-
}
-
-
private function checkGrid():void
-
{
-
for (var i:int = 0; i <_numCols; i++)
-
{
-
for (var j:int = 0; j < _numRows; j++)
-
{
-
checkOneCell(i,j);
-
checkTwoCells(i, j, i + 1, j); // right
-
checkTwoCells(i, j, i - 1, j + 1); // lower left
-
checkTwoCells(i, j, i , j + 1); // lower
-
checkTwoCells(i, j, i + 1, j + 1); // lower right
-
}
-
}
-
}
-
-
private function checkOneCell(x:int, y:int):void
-
{
-
var cell:Vector.<DisplayObject> = _grid[y * _numCols + x];
-
if (cell == null) return;
-
-
var cellLength:int = cell.length;
-
for (var i:int = 0; i < cellLength - 1; i++)
-
{
-
var objA:DisplayObject = cell[i];
-
-
for (var j:int = i + 1; j < cellLength; j++)
-
{
-
var objB:DisplayObject = cell[j];
-
_checks.push(objA, objB);
-
}
-
}
-
}
-
-
private function checkTwoCells(x1:int, y1:int, x2:int, y2:int):void
-
{
-
// make sure cell exists
-
if (x2 >= _numCols || x2 < 0 || y2 >= _numRows) return;
-
-
var cellA:Vector.<DisplayObject> = _grid[y1 * _numCols + x1];
-
var cellB:Vector.<DisplayObject> = _grid[y2 * _numCols + x2];
-
if (cellA == null || cellB == null) return;
-
-
var cellALength:int = cellA.length;
-
var cellBLength:int = cellB.length;
-
-
for (var i:int = 0; i < cellALength; i++)
-
{
-
var objA:DisplayObject = cellA[i];
-
-
for(var j:int = 0; j < cellBLength; j++)
-
{
-
var objB:DisplayObject = cellB[j];
-
_checks.push(objA, objB);
-
}
-
}
-
}
-
-
public function get checks():Vector.<DisplayObject>
-
{
-
return _checks;
-
}
-
}
-
}
Comments
3 Responses to “Brownian Motion + CollisionGrid”
Leave a Reply
View experiment.
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.
I’m using CS4 by the way!
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.