RSS

Tag Archives: one

How to implement one-way walls and platforms

How to implement one-way walls and platforms

In almost all the platforms, a situation arises where you have to implement a platform that is solid from one side. In this experiment, i will implement that platform. The first step is to get into the Box2d sources (b2Contact.cpp) and comment out this line:

m_flags |= e_enabledFlag;

Now we will control this flag and the behavior of the objects coming into contact. Next we take a look at our ContactListener class which in inherited from the b2ContactListener.

class CTContactListener : public b2ContactListener
{
private:
b2Fixture* m_platformFixture;


public:
void BeginContact(b2Contact* contact);
void EndContact(b2Contact* contact);
void setPlatformFixture(b2Fixture* aFixture);
};

We will be passing the reference of the platform that is to be made one-way. However, this information can also be embedded into the sprite by using a boolean (e.g. isOneWayPlatform). If this boolean is true, then the behavior can be applied. But for the sakes of an experiment, we just passed a weak reference and compare it when the collision takes place. This is how our beginContact function looks like:

void CTContactListener::BeginContact(b2Contact* contact) {

//get the fixtures
b2Fixture* fixtureA = contact->GetFixtureA();
b2Fixture* fixtureB = contact->GetFixtureB();

//check if one of the fixtures is the platform
b2Fixture* platformFixture = NULL;
b2Fixture* otherFixture = NULL;

//check if the fixture is a one way platform and also which fixture of the two is it.
if ( fixtureA == m_platformFixture ) {
platformFixture = fixtureA;
otherFixture = fixtureB;
}

else if ( fixtureB == m_platformFixture ) {
platformFixture = fixtureB;
otherFixture = fixtureA;
}


//safety check: no need to execute ahead if the contact was between some other object.
if ( !platformFixture )
return;


//get the platform body and the other body
b2Body* platformBody = platformFixture->GetBody();
b2Body* otherBody = otherFixture->GetBody();


int numPoints = contact->GetManifold()->pointCount;
b2WorldManifold worldManifold;
contact->GetWorldManifold( &worldManifold );

//check if contact points are moving into platform
for (int i = 0; i < numPoints; i++) {


//calcualte the relative velocity
b2Vec2 pointVelPlatform =
platformBody->GetLinearVelocityFromWorldPoint( worldManifold.points[i] );
b2Vec2 pointVelOther =
otherBody->GetLinearVelocityFromWorldPoint( worldManifold.points[i] );
b2Vec2 relativeVel = platformBody->GetLocalVector( pointVelOther - pointVelPlatform );

if ( relativeVel.y < -1 ) //if moving down faster than 1 m/s, handle as before
return;//point is moving into platform, leave contact solid and exit
else if ( relativeVel.y < 1 ) { //if moving slower than 1 m/s //borderline case, moving only slightly out of platform b2Vec2 relativePoint = platformBody->GetLocalPoint( worldManifold.points[i] );
float platformFaceY = 0.5f;//front of platform, from fixture definition :(
if ( relativePoint.y > platformFaceY - 0.05 )
return;//contact point is less than 5cm inside front face of platfrom
}
else
;//moving up faster than 1 m/s
}

//no points are moving into platform, contact should not be solid
contact->SetEnabled(false);
}

void CTContactListener::EndContact(b2Contact* contact) {
//reset the default state of the contact in case it comes back for more
contact->SetEnabled(true);
}

This slideshow requires JavaScript.

Link to source code

Links to the video samples:
LINK1, LINK2, LINK3

 
4 Comments

Posted by on April 8, 2012 in Box2d, cocos2d, Objective C, Xcode

 

Tags: , , , , , , , , , ,

 
Follow

Get every new post delivered to your Inbox.

Join 47 other followers

%d bloggers like this: