Movieclip issues with Box2D collisions

Discuss issues specific to the Flash/AS3 port of Box2D
gramcracker
Posts: 21
Joined: Wed Feb 25, 2015 10:36 am

Movieclip issues with Box2D collisions

Postby gramcracker » Wed Feb 25, 2015 10:57 am

I've been trying to debug this for days now.

Here's the code (It relies on source files from Forumballs demo tutorial by sticks & stones)

It's basically a movable block on the bottom that catches objects.
You control it with the mouse.

When balls hit the player, a collision movieclip is played by calling the clip() method. I need the movieclip to stop and disappear after playing once. I've tried 12 or 13 solutions but no matter what the movieclip loops endlessly. If I use a stop(); function, it just plays the last frame of the movieclip. If I removeClass, the movieclip doesn't appear at all.


package
{
import Box2D.Dynamics.b2World;
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.b2BodyDef;
import Box2D.Dynamics.b2Body;
import Box2D.Collision.Shapes.b2PolygonShape;
import Box2D.Dynamics.b2Fixture;
import Box2D.Dynamics.b2FixtureDef;
import flash.display.MovieClip;
import Box2D.Dynamics.b2DebugDraw;
import flash.utils.*;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.display.Sprite;
import flash.events.Event;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Collision.b2AABB;
import Box2D.Collision.Shapes.b2Shape;
import Box2D.Collision.Shapes.b2CircleShape;
import General.Input;
import Box2D.Dynamics.Joints.b2MouseJoint;
import Box2D.Dynamics.Joints.b2MouseJointDef;
import Box2D.Dynamics.Contacts.*;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;



public class collision extends MovieClip
{
protected const PIXELS_TO_METRE:int = 30;
protected const SWF_WIDTH:int = 640;
protected const SWF_HALF_WIDTH:int = 320;
protected const SWF_HEIGHT:int = 960;
protected const SPAWNER:int = 80;
protected const UNIT:int = 64;
protected const COLS:int = 10;
protected const RADADJ:int = 32;

protected var _world:b2World;
protected var _mouseJoint:b2MouseJoint;
protected var _input:Input;
protected var _mouseXWorldPhys:Number;
protected var _mouseYWorldPhys:Number;
protected var _mouseXWorld:Number;
protected var _mouseYWorld:Number;
protected var _mousePVec:b2Vec2 = new b2Vec2();
protected var _playerBody:b2Body;
protected var _guttersensorBody:b2Body;
protected var time_count:Timer=new Timer(5000);
var t:int = 0;
public var m_isSensor:Boolean

protected const RELEASE_HEIGHT:Number = -300;

protected const BOUNDARY:Number = 0x0001;
protected const BALLS:Number = 0x0002;
protected const CEILING:Number = 0x0004;
protected const PLAYER:Number = 0x0008;

protected const MASK_BALLS:Number = BOUNDARY | PLAYER | BALLS;
protected const MASK_CUBES:Number = BOUNDARY | PLAYER | BALLS;

protected const MASK_BOUNDARY:Number = BOUNDARY | PLAYER;
protected const MASK_PLAYER:Number = BOUNDARY | BALLS | CEILING;

public const RADIANS_TO_DEGREES:Number = 57.2957795;
public const DEGREES_TO_RADIANS:Number = 0.0174532925;

// create array to hold balls
private var balls:Array = new Array();



public function collision()
{
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);

}



protected function onAddedToStage(e:Event):void
{
init();
setup();
}


// create player
protected function setup():void
{

createPlayer(SWF_HALF_WIDTH, SWF_HEIGHT-105, 48, 64);



// create userdata object to get player collisions
var groundObject:Object = new Object();
groundObject.bodyType = BodyType.GROUND;
_guttersensorBody.SetUserData(groundObject);

var playerObject:Object = new Object();
playerObject.bodyType = BodyType.PLAYER;
_playerBody.SetUserData(playerObject);



// create listener variable
var ballContactListener = new BallContactListener();
// create listener
_world.SetContactListener(ballContactListener);

//var redBall1 = createBall(225, 200, 50, RedBallTexture, BodyType.RED_BALL);
//var blueBall2 = createBall(350, 50, 50, BlueBallTexture, BodyType.BLUE_BALL);
//var redBall2 = createBall(475, 150, 50, RedBallTexture, BodyType.RED_BALL);

}


//public var contact_listener=new custom_contact_listener();

protected function init():void
{
_world = new b2World(new b2Vec2(0, 9.8), true);


//var fixtureDef:b2FixtureDef = new b2FixtureDef();

// ground definition
var groundBodyDef:b2BodyDef = new b2BodyDef();

groundBodyDef.position.Set(SWF_HALF_WIDTH / PIXELS_TO_METRE, SWF_HEIGHT / PIXELS_TO_METRE - 20 / PIXELS_TO_METRE);
var groundBody:b2Body = _world.CreateBody(groundBodyDef);

var groundBox:b2PolygonShape = new b2PolygonShape();
groundBox.SetAsBox(SWF_HALF_WIDTH / PIXELS_TO_METRE, 20 / PIXELS_TO_METRE);

var groundFixtureDef:b2FixtureDef = new b2FixtureDef();
groundFixtureDef.shape = groundBox;
groundFixtureDef.filter.categoryBits = 2;
groundFixtureDef.filter.maskBits = MASK_BOUNDARY;

groundFixtureDef.density = 1;

var groundBodyFixture:b2Fixture = groundBody.CreateFixture(groundFixtureDef);




// falling object destroyer sensor
var guttersensorBodyDef:b2BodyDef = new b2BodyDef();
guttersensorBodyDef.position.Set(SWF_HALF_WIDTH / PIXELS_TO_METRE, SWF_HEIGHT / PIXELS_TO_METRE - 2 / PIXELS_TO_METRE);
_guttersensorBody = _world.CreateBody(guttersensorBodyDef);
var guttersensorShape:b2PolygonShape = new b2PolygonShape();
guttersensorShape.SetAsBox(SWF_WIDTH / PIXELS_TO_METRE, 1 / PIXELS_TO_METRE);

var guttersensorFixtureDef:b2FixtureDef = new b2FixtureDef();
guttersensorFixtureDef.shape = guttersensorShape;
guttersensorFixtureDef.filter.maskBits = MASK_PLAYER;
//guttersensorFixtureDef.isSensor=true;

_guttersensorBody.CreateFixture(guttersensorFixtureDef);



// gutter
var spawnerBodyDef:b2BodyDef = new b2BodyDef();
spawnerBodyDef.position.Set(0,0);
var spawnerBody:b2Body = _world.CreateBody(spawnerBodyDef);
var spawnerShape:b2PolygonShape = new b2PolygonShape();
spawnerShape.SetAsBox(SWF_WIDTH / PIXELS_TO_METRE, SPAWNER / PIXELS_TO_METRE);
var spawnerFixtureDef:b2FixtureDef = new b2FixtureDef();
spawnerFixtureDef.filter.categoryBits = 4;
spawnerFixtureDef.shape = spawnerShape;
var spawnerFixture:b2Fixture = spawnerBody.CreateFixture(spawnerFixtureDef);



// user ceiling
var topwallBodyDef:b2BodyDef = new b2BodyDef();
topwallBodyDef.position.Set(SWF_HALF_WIDTH / PIXELS_TO_METRE, SWF_HEIGHT / PIXELS_TO_METRE - 172 / PIXELS_TO_METRE);
var topwallBody:b2Body = _world.CreateBody(topwallBodyDef);
var topwallShape:b2PolygonShape = new b2PolygonShape();
topwallShape.SetAsBox(SWF_WIDTH / PIXELS_TO_METRE, 2 / PIXELS_TO_METRE);


var topwallFixtureDef:b2FixtureDef = new b2FixtureDef();
topwallFixtureDef.shape = topwallShape;
topwallFixtureDef.density = 5.0;
topwallFixtureDef.friction = 1;

topwallFixtureDef.filter.categoryBits = 4;
var topwallFixture:b2Fixture = topwallBody.CreateFixture(topwallFixtureDef);


// left wall
var leftwallBodyDef:b2BodyDef = new b2BodyDef();
leftwallBodyDef.position.Set(0, SWF_HEIGHT / PIXELS_TO_METRE);
var leftwallBody:b2Body = _world.CreateBody(leftwallBodyDef);
var leftwallShape:b2PolygonShape = new b2PolygonShape();
leftwallShape.SetAsBox(1 / PIXELS_TO_METRE,SWF_HEIGHT / PIXELS_TO_METRE);
var leftwallFixtureDef:b2FixtureDef = new b2FixtureDef();
leftwallFixtureDef.shape = leftwallShape;
groundFixtureDef.filter.categoryBits = 2;
groundFixtureDef.filter.maskBits = MASK_BOUNDARY;
var leftwallFixture:b2Fixture = leftwallBody.CreateFixture(leftwallFixtureDef);

// right wall
var rightwallBodyDef:b2BodyDef = new b2BodyDef();
rightwallBodyDef.position.Set(SWF_WIDTH / PIXELS_TO_METRE, SWF_HEIGHT / PIXELS_TO_METRE);
var rightwallBody:b2Body = _world.CreateBody(rightwallBodyDef);
var rightwallShape:b2PolygonShape = new b2PolygonShape();
rightwallShape.SetAsBox(1 / PIXELS_TO_METRE, SWF_HEIGHT / PIXELS_TO_METRE);
var rightwallFixtureDef:b2FixtureDef = new b2FixtureDef();
rightwallFixtureDef.shape = rightwallShape;
groundFixtureDef.filter.categoryBits = 2;
groundFixtureDef.filter.maskBits = MASK_BOUNDARY;
var rightwallFixture:b2Fixture = rightwallBody.CreateFixture(rightwallFixtureDef);


var debugSprite:Sprite = new Sprite();
addChild(debugSprite);
var debugDraw:b2DebugDraw = new b2DebugDraw();
debugDraw.SetSprite(debugSprite);
debugDraw.SetDrawScale(PIXELS_TO_METRE);
debugDraw.SetLineThickness(1.0);
debugDraw.SetAlpha(1);
debugDraw.SetFillAlpha(0.4);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
_world.SetDebugDraw(debugDraw);

_input = new Input(stage);

addEventListener(Event.ENTER_FRAME, update);
time_count.addEventListener(TimerEvent.TIMER, on_time);
time_count.start();
}





public function createBall(x:Number, y:Number, radius:Number, texture:Class, clip:Class, bodyType:String):b2Body
{
var bodyDef:b2BodyDef = new b2BodyDef();
bodyDef.type = b2Body.b2_dynamicBody;
//bodyDef.fixedRotation = true;
bodyDef.position.Set(x / PIXELS_TO_METRE, y / PIXELS_TO_METRE);
bodyDef.angle = Math.random() * Math.PI;
var body:b2Body = _world.CreateBody(bodyDef);

var bodyShape:b2CircleShape = new b2CircleShape();
bodyShape.SetRadius(radius / PIXELS_TO_METRE);

var fixtureDef:b2FixtureDef = new b2FixtureDef();
fixtureDef.shape = bodyShape;
fixtureDef.density = 1.0;
fixtureDef.friction = 0.3;
fixtureDef.restitution = 0.1;

fixtureDef.filter.categoryBits = 2;
fixtureDef.filter.maskBits = MASK_BALLS;

body.CreateFixture(fixtureDef);


var ballTexture = new texture();
addChild(ballTexture);

var ballClip = new clip();
addChild(ballClip);

var ballObject:Object = new Object();
ballObject.body = body;
ballObject.texture = ballTexture;
ballObject.clip = ballClip;
ballObject.startX = x;
ballObject.startY = y;
ballObject.contact = false;
ballObject.ground = false;
ballObject.bodyType = bodyType;
ballObject.hitPlayer = false;

body.SetUserData(ballObject);
balls.push(ballObject);

return body;

}

public function createBox(x:Number, y:Number, radius, texture:Class, clip:Class, bodyType:String):b2Body
{
var bodyDef:b2BodyDef = new b2BodyDef();
bodyDef.type = b2Body.b2_dynamicBody;
//bodyDef.fixedRotation = true;
bodyDef.position.Set(x / PIXELS_TO_METRE, y / PIXELS_TO_METRE);
bodyDef.angle = Math.random() * Math.PI;
var body:b2Body = _world.CreateBody(bodyDef);

var dynamicBox:b2PolygonShape = new b2PolygonShape();
dynamicBox.SetAsBox((UNIT / 2) / PIXELS_TO_METRE, (UNIT / 2) / PIXELS_TO_METRE );

var fixtureDef:b2FixtureDef = new b2FixtureDef();
fixtureDef.shape = dynamicBox;
fixtureDef.density = 1.0;
fixtureDef.friction = 0.3;
fixtureDef.restitution = 0.1;

fixtureDef.filter.categoryBits = 2;
fixtureDef.filter.maskBits = MASK_BALLS;

body.CreateFixture(fixtureDef);


var ballTexture = new texture();
addChild(ballTexture);

var ballClip = new clip();
addChild(ballClip);

var ballObject:Object = new Object();
ballObject.body = body;
ballObject.texture = ballTexture;
ballObject.clip = ballClip;
ballObject.startX = x;
ballObject.startY = y;
ballObject.contact = false;
ballObject.ground = false;
ballObject.hitPlayer = false;

ballObject.bodyType = bodyType;

body.SetUserData(ballObject);
balls.push(ballObject);

return body;

}




protected function createPlayer(x:int,y:int,width:int,height:int):b2Body
{
var playerBodyDef:b2BodyDef = new b2BodyDef();

playerBodyDef.type = b2Body.b2_dynamicBody;

playerBodyDef.fixedRotation = true;

playerBodyDef.position.Set(x / PIXELS_TO_METRE, y / PIXELS_TO_METRE);

_playerBody = _world.CreateBody(playerBodyDef);

var dynamicBox:b2PolygonShape = new b2PolygonShape();


dynamicBox.SetAsBox(width / PIXELS_TO_METRE, height / PIXELS_TO_METRE);


var playerFixtureDef:b2FixtureDef = new b2FixtureDef();
playerFixtureDef.shape = dynamicBox;
playerFixtureDef.filter.maskBits = MASK_PLAYER;

playerFixtureDef.density = 1;
playerFixtureDef.friction = 0.3;
_playerBody.CreateFixture(playerFixtureDef);



return _playerBody;
}



public function on_time(e:Event) {


var i:int = 1 + int(Math.random() * Number(COLS + 1));
//var i:int = Math.floor(Math.random()*COLS);
trace("Random Number was:", i);
var radius:Number = UNIT / 2;
var x:Number = (UNIT * i) + RADADJ;
var y:Number = RELEASE_HEIGHT;


var redBall1 = createBox(x, y, radius, RedBallTexture, lightball, BodyType.RED_BALL);
var blueBall1 = createBall(x, y, radius, BlueBallTexture, lightball, BodyType.BLUE_BALL);
//var redBall1 = createBall(225, 200, 50, RedBallTexture, BodyType.RED_BALL);
//createBall(x, y, radius, BlueBallTexture, BodyType.BLUE_BALL);


t++;
}



protected function update(e:Event):void
{
var timeStep:Number = 1 / 30;
var velocityIterations:int = 8;
var positionIterations:int = 1;
var subSteps:int = 2;
var subdt:Number = timeStep / subSteps;

updateTextures();

for (var i:int = 0; i < subSteps; i++)
{
_world.Step(subdt, velocityIterations, positionIterations);

UpdateMouseWorld();
MouseDestroy();
MouseDrag();
_world.ClearForces();
trace("Cleared forces.");
checkCollisions();


// do your physics-related stuff inside here but leave any sprites manipulation outside this loop
}

//_world.Step(timeStep, velocityIterations, positionIterations);
_world.DrawDebugData();


General.Input.update();
trace("General.Input.update();.");

}


private function updateTextures():void
{
var i = balls.length;
while (i--)
{
trace("Update textures.");
var currentBallObject = balls[i];


currentBallObject.texture.x = currentBallObject.body.GetPosition().x * PIXELS_TO_METRE;
currentBallObject.texture.y = currentBallObject.body.GetPosition().y * PIXELS_TO_METRE;
currentBallObject.texture.rotation = currentBallObject.body.GetAngle() * RADIANS_TO_DEGREES;
//trace(currentBallObject.texture.rotation);

}
}



private function checkCollisions():void
{

trace("Check collisions.");

var i = balls.length;
while (i--)
{
var currentBallObject = balls[i];


if (currentBallObject.contact)
{

trace("Hit something.");


//condition hits ground
if (currentBallObject.ground)
{
trace("Hit ground.");

currentBallObject.body.SetPosition(new b2Vec2(currentBallObject.startX / PIXELS_TO_METRE, currentBallObject.startY / PIXELS_TO_METRE));
currentBallObject.body.SetLinearVelocity(new b2Vec2(0, 0));
currentBallObject.body.SetAngularVelocity(0);

//currentBallObject.texture.pop();
}
else // it hit player
{
//currentBallObject.clip.addFrameScript(13 - 1, remove(currentBallObject.clip);
trace("Hit player.");


// assign clip texture to current position
currentBallObject.clip.x = currentBallObject.body.GetPosition().x * PIXELS_TO_METRE;
currentBallObject.clip.y = currentBallObject.body.GetPosition().y * PIXELS_TO_METRE;

currentBallObject.hitPlayer = true;

// whisk old object away
currentBallObject.body.SetPosition(new b2Vec2(currentBallObject.startX / PIXELS_TO_METRE, currentBallObject.startY / PIXELS_TO_METRE));
currentBallObject.body.SetLinearVelocity(new b2Vec2(0, 0));
currentBallObject.body.SetAngularVelocity(0);
currentBallObject.contact = false;

//currentBallObject.texture.pop();


}
trace("Hit neither");
}
}
}



protected function GetBodyAtMouse(includeStatic:Boolean = false):b2Body
{
_mousePVec.Set(_mouseXWorldPhys, _mouseYWorldPhys);
var aabb:b2AABB = new b2AABB();
aabb.lowerBound.Set(_mouseXWorldPhys - 0.001, _mouseYWorldPhys - 0.001);
aabb.upperBound.Set(_mouseXWorldPhys + 0.001, _mouseYWorldPhys + 0.001);
var body:b2Body = null;
var fixture:b2Fixture;



// Query the world for overlapping shapes.
function GetBodyCallback(fixture:b2Fixture):Boolean
{
var shape:b2Shape = fixture.GetShape();
if (fixture.GetBody().GetType() != b2Body.b2_staticBody || includeStatic)
{
var inside:Boolean = shape.TestPoint(fixture.GetBody().GetTransform(), _mousePVec);
if (inside)
{
body = fixture.GetBody();
return false;
}
}
return true;
}
_world.QueryAABB(GetBodyCallback, aabb);
return body;
}

protected function MouseDestroy():void
{
if (!Input.mouseDown && Input.isKeyPressed(68/*D*/))
{
var body:b2Body = GetBodyAtMouse(true);

if (body)
{
_world.DestroyBody(body);
return;
}
}
}

protected function MouseDrag():void
{
if (Input.mouseDown && !_mouseJoint)
{
var body:b2Body = GetBodyAtMouse();

if (body)
{
var md:b2MouseJointDef = new b2MouseJointDef();

md.bodyA = _world.GetGroundBody();
md.bodyB = body;
md.target.Set(_mouseXWorldPhys, _mouseYWorldPhys);
md.collideConnected = true;
md.frequencyHz = 100;
md.dampingRatio = 0;
md.maxForce = 8000 * body.GetMass();
_mouseJoint = _world.CreateJoint(md) as b2MouseJoint;
body.SetAwake(true);
}
}

if (!Input.mouseDown)
{
if (_mouseJoint)
{
_world.DestroyJoint(_mouseJoint);
_mouseJoint = null;
}
}

if (_mouseJoint)
{
var p2:b2Vec2 = new b2Vec2(_mouseXWorldPhys, _mouseYWorldPhys);
_mouseJoint.SetTarget(p2);
}
}

protected function UpdateMouseWorld():void
{
_mouseXWorldPhys = (Input.mouseX) / PIXELS_TO_METRE;
_mouseYWorldPhys = (Input.mouseY) / PIXELS_TO_METRE;

_mouseXWorld = (Input.mouseX);
_mouseYWorld = (Input.mouseY);
}
}
}

gramcracker
Posts: 21
Joined: Wed Feb 25, 2015 10:36 am

Re: Movieclip issues with Box2D collisions

Postby gramcracker » Wed Feb 25, 2015 2:25 pm

Ok I got it working.

I added this code in the CheckCollision function just after the declaration var currentBallObject = balls[i]

Code: Select all

               if (currentBallObject.clip.currentFrame == currentBallObject.clip.totalFrames)
               {
                  trace("Kill it");
                  currentBallObject.clip.x = 0;
                  currentBallObject.clip.y = 0;
                  
                  
               }


What I don't understand is setting .x and .y to 0. I would have thought setting .clip to NULL would do it. But it works, so not going to question it.

Great library. Having fun learning it. Thanks for taking the time to make it.


Return to “Flash”



Who is online

Users browsing this forum: No registered users and 4 guests