Skip to content

Instantly share code, notes, and snippets.

@noonat
Created March 7, 2011 03:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save noonat/858031 to your computer and use it in GitHub Desktop.
Save noonat/858031 to your computer and use it in GitHub Desktop.
Nape addCbPreBegin bug
package {
import flash.Boot;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import nape.callbacks.Callback;
import nape.callbacks.CbType;
import nape.dynamics.Arbiter;
import nape.geom.AABB;
import nape.geom.Vec2;
import nape.phys.Body;
import nape.phys.Material;
import nape.phys.Properties;
import nape.shape.Circle;
import nape.space.Space;
import nape.space.UniformSleepSpace;
import nape.util.Tools;
// Bug repro for http://deltaluca.me.uk/forum/index.php/t/140/a66603e8954afca0313f04df0a532584/
// Flock should not collide with each other, but should collide with boxes.
[SWF(width="800", height="600", backgroundColor="#000000")]
public class Test extends Sprite {
static protected const BOX_TYPE:int = CbType.get();
static protected const FLOCK_TYPE:int = CbType.get();
static protected const FOLLOW_DISTANCE:Number = 16;
static protected const SEPARATION_DISTANCE:Number = 16;
protected var _flock:Array = [];
protected var _flockNeighbors:Array = [];
protected var _space:Space;
protected var _width:Number;
protected var _height:Number;
function Test() {
new Boot();
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
// Add a bunch of random boxes in the middle. These are static objects
// that the flock should collide with.
protected function addBoxes():void {
for (var i:int = 0; i < 16; ++i) {
var w:Number = 16 + Math.random() * 16;
var h:Number = 16 + Math.random() * 16;
var sprite:Sprite = new Sprite;
sprite.graphics.beginFill(0x666666);
sprite.graphics.drawRect(-w / 2, -h / 2, w, h);
sprite.graphics.endFill();
addChild(sprite);
var x:Number = Math.random() * _width;
var y:Number = (_height / 2) - 32 + Math.random() * 64;
var body:Body = Tools.createBox(
x, y, w, h, 0, 0, 0, false, Material.Steel, 0xffffffff, 0);
body.assignGraphic(sprite);
body.cbType = BOX_TYPE;
body.calcProperties();
body.update();
body.stopAll()
_space.addObject(body);
}
}
// Add some bodies for our flock. Members of the flock should not
// collide with one another, but use a sensor to detect their neighbors.
protected function addFlock():void {
var properties:Properties = new Properties(0.3, 0.3);
for (var i:uint = 0; i < 32; ++i) {
var sprite:Sprite = new Sprite;
sprite.graphics.lineStyle(2, 0xffffff);
sprite.graphics.drawCircle(0, 0, 3);
addChild(sprite);
var colliderShape:Circle = new Circle(
4, new Vec2(0, 0), Material.Wood, 0xffffffff, 0);
var neighborShape:Circle = new Circle(
32, new Vec2(0, 0), Material.Wood, 0, 1);
var x:Number = Math.random() * _width;
var y:Number = Math.random() * _height;
var body:Body = new Body(x, y, properties);
body.assignGraphic(sprite);
body.addShape(colliderShape);
body.addShape(neighborShape);
body.cbType = FLOCK_TYPE;
body.data = i;
body.calcProperties();
body.update();
_flock[i] = body;
_flockNeighbors[i] = [];
_space.addObject(body);
}
}
// Add a body to another's neighbor list.
protected function addFlockNeighbor(index1:uint, index2:uint):void {
var neighbor:Body = _flock[index2];
var neighborIndex:int = _flockNeighbors[index1].indexOf(neighbor);
if (neighborIndex === -1) {
_flockNeighbors[index1].push(neighbor);
}
}
// Remove a body from another's neighbor list.
protected function removeFlockNeighbor(index1:uint, index2:uint):void {
var neighbor:Body = _flock[index2];
var neighborIndex:int = _flockNeighbors[index1].indexOf(neighbor);
if (neighborIndex !== -1) {
_flockNeighbors[index1].splice(neighborIndex, 1);
}
}
protected function onAddedToStage(event:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.frameRate = 60;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.BEST;
stage.scaleMode = StageScaleMode.NO_SCALE;
_width = stage.stageWidth;
_height = stage.stageHeight;
graphics.beginFill(0);
graphics.drawRect(0, 0, _width, _height);
graphics.endFill();
// Setup the space
_space = new UniformSleepSpace(new AABB(-_width, -_height, _width * 2, _height * 2), 16);
addBoxes();
addFlock();
_space.addCbPreBegin(FLOCK_TYPE, FLOCK_TYPE, function(a:Arbiter):int {
trace('Ignoring flock collision');
return Callback.IGNORE;
});
_space.addCbSenseBegin(FLOCK_TYPE, FLOCK_TYPE);
_space.addCbSenseEnd(FLOCK_TYPE, FLOCK_TYPE);
}
protected function onEnterFrame(event:Event):void {
_space.step(1 / 60, 4, 4);
// Update the neighbor lists.
while (!_space.callbacks.empty()) {
var cb:Callback = _space.callbacks.front();
switch (cb.type) {
case Callback.SENSE_BEGIN:
if (cb.obj_arb) {
addFlockNeighbor(cb.obj_arb.p1.data, cb.obj_arb.p2.data);
}
break;
case Callback.SENSE_END:
if (cb.obj_arb) {
removeFlockNeighbor(cb.obj_arb.p1.data, cb.obj_arb.p2.data);
}
break;
}
_space.callbacks.pop();
}
graphics.clear();
graphics.beginFill(0);
graphics.drawRect(0, 0, _width, _height);
graphics.endFill();
graphics.lineStyle(1, 0xff0000);
// Update the body velocities.
for (var i:uint = 0; i < _flock.length; ++i) {
var body:Body = _flock[i];
var forceX:Number = stage.mouseX - body.px;
var forceY:Number = stage.mouseY - body.py;
var distance:Number = Math.sqrt(forceX * forceX + forceY * forceY);
if (distance > 0) {
forceX /= distance;
forceY /= distance;
}
var force:Number = distance / FOLLOW_DISTANCE;
if (force > 1) {
force = 1;
}
forceX *= force;
forceY *= force;
if (!body.live) _space.wakeObject(body);
body.applyRelativeForce(forceX * 1e6, forceY * 1e6, 0, 0);
for each (var neighbor:Body in _flockNeighbors[i]) {
graphics.moveTo(body.px, body.py);
graphics.lineTo(neighbor.px, neighbor.py);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment