Box2DTestBed for iOS

iPhoneTestEntries.mm

*

* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com

*

* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com

*

* This software is provided 'as-is', without any express or implied

* warranty.  In no event will the authors be held liable for any damages

* arising from the use of this software.

* Permission is granted to anyone to use this software for any purpose,

* including commercial applications, and to alter it and redistribute it

* freely, subject to the following restrictions:

* 1. The origin of this software must not be misrepresented; you must not

* claim that you wrote the original software. If you use this software

* in a product, an acknowledgment in the product documentation would be

* appreciated but is not required.

* 2. Altered source versions must be plainly marked as such, and must not be

* misrepresented as being the original software.

* 3. This notice may not be removed or altered from any source distribution.

*/


//

// File modified for cocos2d integration

// http://www.cocos2d-iphone.org

//


#include "iPhoneTest.h"

//#include "GLES-Render.h"


#include "AddPair.h"

#include "ApplyForce.h"

#include "BodyTypes.h"

#include "Breakable.h"

#include "Bridge.h"

#include "BulletTest.h"

#include "Cantilever.h"

#include "Car.h"

#include "ContinuousTest.h"

#include "Chain.h"

#include "CharacterCollision.h"

#include "CollisionFiltering.h"

#include "CollisionProcessing.h"

#include "CompoundShapes.h"

#include "Confined.h"

#include "DistanceTest.h"

#include "Dominos.h"

#include "DynamicTreeTest.h"

#include "EdgeShapes.h"

#include "EdgeTest.h"

#include "Gears.h"

#include "OneSidedPlatform.h"

#include "Pinball.h"

#include "PolyCollision.h"

#include "PolyShapes.h"

#include "Prismatic.h"

#include "Pulleys.h"

#include "Pyramid.h"

#include "RayCast.h"

#include "Revolute.h"

//#include "Rope.h"

#include "RopeJoint.h"

#include "SensorTest.h"

#include "ShapeEditing.h"

#include "SliderCrank.h"

#include "SphereStack.h"

#include "TheoJansen.h"

#include "Tiles.h"

#include "TimeOfImpact.h"

#include "VaryingFriction.h"

#include "VaryingRestitution.h"

#include "VerticalStack.h"

#include "Web.h"


TestEntry g_testEntries[] =

{

{"Gears", Gears::Create},

{"Character Collision",CharacterCollision::Create},

{"Edge Test",EdgeTest::Create},

{"Body Types",BodyTypes::Create},

{"Shape Editing",ShapeEditing::Create},

{"Tiles", Tiles::Create},

{"Car", Car::Create},

{"Apply Force",ApplyForce::Create},

{"Prismatic",Prismatic::Create},

{"Vertical Stack",VerticalStack::Create},

{"SphereStack",SphereStack::Create},

{"Revolute", Revolute::Create},

{"Pulleys", Pulleys::Create},

{"Polygon Shapes",PolyShapes::Create},

//{"Rope", Rope::Create},

{"Web", Web::Create},

{"RopeJoint",RopeJoint::Create},

{"One-Sided Platform",OneSidedPlatform::Create},

{"Pinball", Pinball::Create},

{"Bullet Test",BulletTest::Create},

{"Continuous Test",ContinuousTest::Create},

{"Time of Impact",TimeOfImpact::Create},

{"Ray-Cast", RayCast::Create},

{"Confined", Confined::Create},

{"Pyramid", Pyramid::Create},

{"Varying Restitution",VaryingRestitution::Create},

{"Theo Jansen's Walker",TheoJansen::Create},

{"Edge Shapes",EdgeShapes::Create},

{"PolyCollision",PolyCollision::Create},

{"Cantilever",Cantilever::Create},

{"Bridge", Bridge::Create},

{"Breakable",Breakable::Create},

{"Chain", Chain::Create},

{"Collision Filtering",CollisionFiltering::Create},

{"Collision Processing",CollisionProcessing::Create},

{"Compound Shapes",CompoundShapes::Create},

{"Distance Test",DistanceTest::Create},

{"Dominos", Dominos::Create},

{"Dynamic Tree",DynamicTreeTest::Create},

{"Sensor Test",SensorTest::Create},

{"Slider Crank",SliderCrank::Create},

{"Varying Friction",VaryingFriction::Create},

{"Add Pair Stress Test",AddPair::Create},

// {NULL, NULL}

};


int g_totalEntries = sizeof(g_testEntries) /sizeof(g_testEntries[0]);


iPhoneTest.h

/*

* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com

*

* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com

*

* This software is provided 'as-is', without any express or implied

* warranty.  In no event will the authors be held liable for any damages

* arising from the use of this software.

* Permission is granted to anyone to use this software for any purpose,

* including commercial applications, and to alter it and redistribute it

* freely, subject to the following restrictions:

* 1. The origin of this software must not be misrepresented; you must not

* claim that you wrote the original software. If you use this software

* in a product, an acknowledgment in the product documentation would be

* appreciated but is not required.

* 2. Altered source versions must be plainly marked as such, and must not be

* misrepresented as being the original software.

* 3. This notice may not be removed or altered from any source distribution.

*/


//

// File modified for cocos2d integration

// http://www.cocos2d-iphone.org

//



#ifndef TEST_H

#define TEST_H


#import <UIKit/UIKit.h>

#include <Box2D/Box2D.h>

#include "GLES-Render.h"


#include <cstdlib>


class Test;

struct Settings;


typedef Test* TestCreateFcn();


#define RAND_LIMIT 32767


/// Random number in range [-1,1]

inline float32 RandomFloat()

{

float32 r = (float32)(rand() & (RAND_LIMIT));

r /= RAND_LIMIT;

r = 2.0f * r - 1.0f;

return r;

}


/// Random floating point number in range [lo, hi]

inline float32 RandomFloat(float32 lo,float32 hi)

{

float32 r = (float32)(rand() & (RAND_LIMIT));

r /= RAND_LIMIT;

r = (hi - lo) * r + lo;

return r;

}


/// Test settings. Some can be controlled in the GUI.

/// Test settings. Some can be controlled in the GUI.

struct Settings

{

Settings() :

viewCenter(0.0f,20.0f),

hz(60.0f),

velocityIterations(8),

positionIterations(3),

drawShapes(1),

drawJoints(1),

drawAABBs(0),

drawPairs(0),

drawContactPoints(0),

drawContactNormals(0),

drawContactForces(0),

drawFrictionForces(0),

drawCOMs(0),

drawStats(0),

drawProfile(0),

enableWarmStarting(1),

enableContinuous(1),

enableSubStepping(0),

pause(0),

singleStep(0)

{}


b2Vec2 viewCenter;

float32 hz;

int32 velocityIterations;

int32 positionIterations;

int32 drawShapes;

int32 drawJoints;

int32 drawAABBs;

int32 drawPairs;

int32 drawContactPoints;

int32 drawContactNormals;

int32 drawContactForces;

int32 drawFrictionForces;

int32 drawCOMs;

int32 drawStats;

int32 drawProfile;

int32 enableWarmStarting;

int32 enableContinuous;

int32 enableSubStepping;

int32 pause;

int32 singleStep;

};


struct TestEntry

{

const char *name;

TestCreateFcn *createFcn;

};


extern TestEntry g_testEntries[];

// This is called when a joint in the world is implicitly destroyed

// because an attached body is destroyed. This gives us a chance to

// nullify the mouse joint.

class DestructionListener : public b2DestructionListener

{

public:

void SayGoodbye(b2Fixture* fixture) {B2_NOT_USED(fixture); }

void SayGoodbye(b2Joint* joint);


Test* test;

};


const int32 k_maxContactPoints =2048;


struct ContactPoint

{

b2Fixture* fixtureA;

b2Fixture* fixtureB;

b2Vec2 normal;

b2Vec2 position;

b2PointState state;

};


class Test : publicb2ContactListener

{

public:


Test();

virtual ~Test();


void SetGravity(float x,float y);// iPhone specific


void SetTextLine(int32 line) {m_textLine = line; }

void DrawTitle(int x,int y, const char *string);

virtual void Step(Settings* settings);

virtual void Keyboard(unsigned char key) {B2_NOT_USED(key); }

void ShiftMouseDown(constb2Vec2& p);

virtualbool MouseDown(constb2Vec2& p); // cocos2d modifications

virtual void MouseUp(const b2Vec2& p);

void MouseMove(constb2Vec2& p);

void LaunchBomb();

void LaunchBomb(constb2Vec2& position, const b2Vec2& velocity);


void SpawnBomb(constb2Vec2& worldPt);

void CompleteBombSpawn(constb2Vec2& p);


// Let derived tests know that a joint was destroyed.

virtual void JointDestroyed(b2Joint* joint) { B2_NOT_USED(joint); }


// Callbacks for derived classes.

virtual void BeginContact(b2Contact* contact) { B2_NOT_USED(contact); }

virtual void EndContact(b2Contact* contact) { B2_NOT_USED(contact); }

virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);

virtual void PostSolve(const b2Contact* contact,const b2ContactImpulse* impulse)

{

B2_NOT_USED(contact);

B2_NOT_USED(impulse);

}


b2World* m_world;// cocos2d specific


protected:

friend class DestructionListener;

friend class BoundaryListener;

friend class ContactListener;


b2Body* m_groundBody;

b2AABB m_worldAABB;

ContactPoint m_points[k_maxContactPoints];

int32 m_pointCount;

DestructionListener m_destructionListener;

GLESDebugDraw m_debugDraw;

int32 m_textLine;

b2Body* m_bomb;

b2MouseJoint* m_mouseJoint;

b2Vec2 m_bombSpawnPoint;

bool m_bombSpawning;

b2Vec2 m_mouseWorld;

int32 m_stepCount;

};


#endif


iPhoneTest.mm

/*

* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com

*

* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com

*

* This software is provided 'as-is', without any express or implied

* warranty.  In no event will the authors be held liable for any damages

* arising from the use of this software.

* Permission is granted to anyone to use this software for any purpose,

* including commercial applications, and to alter it and redistribute it

* freely, subject to the following restrictions:

* 1. The origin of this software must not be misrepresented; you must not

* claim that you wrote the original software. If you use this software

* in a product, an acknowledgment in the product documentation would be

* appreciated but is not required.

* 2. Altered source versions must be plainly marked as such, and must not be

* misrepresented as being the original software.

* 3. This notice may not be removed or altered from any source distribution.

*/


//

// File modified for cocos2d integration

// http://www.cocos2d-iphone.org

//


#include "iPhoneTest.h"

#include "GLES-Render.h"


#include <cstdio>


void DestructionListener::SayGoodbye(b2Joint* joint)

{

if (test->m_mouseJoint == joint)

{

test->m_mouseJoint =NULL;

}

else

{

test->JointDestroyed(joint);

}

}


Test::Test()

{

b2Vec2 gravity;

gravity.Set(0.0f, -10.0f);

m_world = newb2World(gravity);


m_bomb = NULL;

m_textLine = 30;

m_mouseJoint = NULL;

m_pointCount = 0;


m_destructionListener.test =this;

m_world->SetDestructionListener(&m_destructionListener);

m_world->SetContactListener(this);

m_world->SetDebugDraw(&m_debugDraw);


m_bombSpawning = false;


m_stepCount = 0;


b2BodyDef bodyDef;

m_groundBody = m_world->CreateBody(&bodyDef);

}


Test::~Test()

{

// By deleting the world, we delete the bomb, mouse joint, etc.

deletem_world;

m_world = NULL;

}


void Test::SetGravity(float x, float y)

{

float tVectorLength=sqrtf(x*x+y*y);

float newGravityX=9.81f*x/tVectorLength;

float newGravityY=9.81f*y/tVectorLength;

m_world->SetGravity(b2Vec2(newGravityX,newGravityY));

}


void Test::PreSolve(b2Contact* contact,const b2Manifold* oldManifold)

{

const b2Manifold* manifold = contact->GetManifold();


if (manifold->pointCount ==0)

{

return;

}


b2Fixture* fixtureA = contact->GetFixtureA();

b2Fixture* fixtureB = contact->GetFixtureB();


b2PointState state1[b2_maxManifoldPoints], state2[b2_maxManifoldPoints];

b2GetPointStates(state1, state2, oldManifold, manifold);


b2WorldManifold worldManifold;

contact->GetWorldManifold(&worldManifold);


for (int32 i =0; i < manifold->pointCount &&m_pointCount < k_maxContactPoints; ++i)

{

ContactPoint* cp =m_points + m_pointCount;

cp->fixtureA = fixtureA;

cp->fixtureB = fixtureB;

cp->position = worldManifold.points[i];

cp->normal = worldManifold.normal;

cp->state = state2[i];

++m_pointCount;

}

}


void Test::DrawTitle(int x,int y, const char *string)

{

    m_debugDraw.DrawString(x, y, string);

}


class QueryCallback : publicb2QueryCallback

{

public:

QueryCallback(constb2Vec2& point)

{

m_point = point;

m_fixture =NULL;

}


bool ReportFixture(b2Fixture* fixture)

{

b2Body* body = fixture->GetBody();

if (body->GetType() ==b2_dynamicBody)

{

bool inside = fixture->TestPoint(m_point);

if (inside)

{

m_fixture = fixture;


// We are done, terminate the query.

returnfalse;

}

}


// Continue the query.

returntrue;

}


b2Vec2 m_point;

b2Fixture* m_fixture;

};


bool Test::MouseDown(constb2Vec2& p)

{

m_mouseWorld = p;


if (m_mouseJoint !=NULL)

{

returnfalse;

}


// Make a small box.

b2AABB aabb;

b2Vec2 d;

d.Set(0.001f,0.001f);

aabb.lowerBound = p - d;

aabb.upperBound = p + d;


// Query the world for overlapping shapes.

QueryCallback callback(p);

m_world->QueryAABB(&callback, aabb);


if (callback.m_fixture)

{

b2Body* body = callback.m_fixture->GetBody();

b2MouseJointDef md;

md.bodyA =m_groundBody;

md.bodyB = body;

md.target = p;

md.maxForce = 1000.0f * body->GetMass();


m_mouseJoint = (b2MouseJoint*)m_world->CreateJoint(&md);

body->SetAwake(true);


returntrue;

}


return false;

}


void Test::SpawnBomb(constb2Vec2& worldPt)

{

m_bombSpawnPoint = worldPt;

m_bombSpawning = true;

}


void Test::CompleteBombSpawn(constb2Vec2& p)

{

if (m_bombSpawning ==false)

{

return;

}


const float multiplier =30.0f;

b2Vec2 vel = m_bombSpawnPoint - p;

vel *= multiplier;

LaunchBomb(m_bombSpawnPoint,vel);

m_bombSpawning = false;

}


void Test::ShiftMouseDown(constb2Vec2& p)

{

m_mouseWorld = p;


if (m_mouseJoint !=NULL)

{

return;

}


SpawnBomb(p);

}


void Test::MouseUp(constb2Vec2& p)

{

if (m_mouseJoint)

{

m_world->DestroyJoint(m_mouseJoint);

m_mouseJoint =NULL;

}


if (m_bombSpawning)

{

CompleteBombSpawn(p);

}

}


void Test::MouseMove(constb2Vec2& p)

{

m_mouseWorld = p;


if (m_mouseJoint)

{

m_mouseJoint->SetTarget(p);

}

}


void Test::LaunchBomb()

{

b2Vec2 p(RandomFloat(-15.0f,15.0f), 30.0f);

b2Vec2 v = -5.0f * p;

LaunchBomb(p, v);

}


void Test::LaunchBomb(constb2Vec2& position, const b2Vec2& velocity)

{

if (m_bomb)

{

m_world->DestroyBody(m_bomb);

m_bomb = NULL;

}


b2BodyDef bd;

bd.type =b2_dynamicBody;

bd.position = position;

bd.bullet = true;

m_bomb = m_world->CreateBody(&bd);

m_bomb->SetLinearVelocity(velocity);


b2CircleShape circle;

circle.m_radius = 0.3f;


b2FixtureDef fd;

fd.shape = &circle;

fd.density = 20.0f;

fd.restitution =0.0f;



b2Vec2 minV = position - b2Vec2(0.3f,0.3f);

b2Vec2 maxV = position + b2Vec2(0.3f,0.3f);


b2AABB aabb;

aabb.lowerBound = minV;

aabb.upperBound = maxV;


m_bomb->CreateFixture(&fd);

}


void Test::Step(Settings* settings)

{

float32 timeStep = settings->hz >0.0f ? 1.0f / settings->hz :float32(0.0f);


if (settings->pause)

{

if (settings->singleStep)

{

settings->singleStep =0;

}

else

{

timeStep = 0.0f;

}


m_debugDraw.DrawString(5,m_textLine, "****PAUSED****");

m_textLine +=15;

}


uint32 flags = 0;

flags += settings->drawShapes* b2Draw::e_shapeBit;

flags += settings->drawJoints* b2Draw::e_jointBit;

flags += settings->drawAABBs* b2Draw::e_aabbBit;

flags += settings->drawPairs* b2Draw::e_pairBit;

flags += settings->drawCOMs* b2Draw::e_centerOfMassBit;

m_debugDraw.SetFlags(flags);


m_world->SetWarmStarting(settings->enableWarmStarting >0);

m_world->SetContinuousPhysics(settings->enableContinuous >0);


m_pointCount = 0;


m_world->Step(timeStep, settings->velocityIterations, settings->positionIterations);


// m_world->DrawDebugData();


if (timeStep > 0.0f)

{

++m_stepCount;

}


if (settings->drawStats)

{

m_debugDraw.DrawString(5,m_textLine, "bodies/contacts/joints/proxies = %d/%d/%d",

 m_world->GetBodyCount(),m_world->GetContactCount(),m_world->GetJointCount(),m_world->GetProxyCount());

m_textLine +=15;

}


if (m_mouseJoint)

{

// b2Body* body = m_mouseJoint->GetBodyB();

// b2Vec2 p1 = body->GetWorldPoint(m_mouseJoint->m_localAnchor);

// b2Vec2 p2 = m_mouseJoint->m_target;

//

// glPointSize(4.0f);

// glColor3f(0.0f, 1.0f, 0.0f);

// glBegin(GL_POINTS);

// glVertex2f(p1.x, p1.y);

// glVertex2f(p2.x, p2.y);

// glEnd();

// glPointSize(1.0f);

//

// glColor3f(0.8f, 0.8f, 0.8f);

// glBegin(GL_LINES);

// glVertex2f(p1.x, p1.y);

// glVertex2f(p2.x, p2.y);

// glEnd();

}


if (m_bombSpawning)

{

// glPointSize(4.0f);

// glColor3f(0.0f, 0.0f, 1.0f);

// glBegin(GL_POINTS);

// glColor3f(0.0f, 0.0f, 1.0f);

// glVertex2f(m_bombSpawnPoint.x, m_bombSpawnPoint.y);

// glEnd();

//

// glColor3f(0.8f, 0.8f, 0.8f);

// glBegin(GL_LINES);

// glVertex2f(m_mouseWorld.x, m_mouseWorld.y);

// glVertex2f(m_bombSpawnPoint.x, m_bombSpawnPoint.y);

// glEnd();

}


if (settings->drawContactPoints)

{

//const float32 k_impulseScale = 0.1f;

const float32 k_axisScale = 0.3f;


for (int32 i =0; i < m_pointCount; ++i)

{

ContactPoint* point =m_points + i;


if (point->state ==b2_addState)

{

// Add

m_debugDraw.DrawPoint(point->position,10.0f, b2Color(0.3f,0.95f, 0.3f));

}

elseif (point->state == b2_persistState)

{

// Persist

m_debugDraw.DrawPoint(point->position,5.0f, b2Color(0.3f,0.3f, 0.95f));

}


if (settings->drawContactNormals ==1)

{

b2Vec2 p1 = point->position;

b2Vec2 p2 = p1 + k_axisScale * point->normal;

m_debugDraw.DrawSegment(p1, p2,b2Color(0.4f, 0.9f,0.4f));

}

elseif (settings->drawContactForces ==1)

{

//b2Vec2 p1 = point->position;

//b2Vec2 p2 = p1 + k_forceScale * point->normalForce * point->normal;

//DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f));

}


if (settings->drawFrictionForces ==1)

{

//b2Vec2 tangent = b2Cross(point->normal, 1.0f);

//b2Vec2 p1 = point->position;

//b2Vec2 p2 = p1 + k_forceScale * point->tangentForce * tangent;

//DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f));

}

}

}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值