2010-09-14 14:47:12 +08:00
|
|
|
#include "Box2dTest.h"
|
|
|
|
#include "../testResource.h"
|
|
|
|
|
|
|
|
#define PTM_RATIO 32
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
kTagTileMap = 1,
|
|
|
|
kTagSpriteManager = 1,
|
|
|
|
kTagAnimation1 = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
Box2DTestLayer::Box2DTestLayer()
|
|
|
|
{
|
|
|
|
setIsTouchEnabled( true );
|
|
|
|
setIsAccelerometerEnabled( true );
|
|
|
|
|
|
|
|
CGSize screenSize = CCDirector::getSharedDirector()->getWinSize();
|
|
|
|
//UXLOG(L"Screen width %0.2f screen height %0.2f",screenSize.width,screenSize.height);
|
|
|
|
|
|
|
|
// Define the gravity vector.
|
|
|
|
b2Vec2 gravity;
|
|
|
|
gravity.Set(0.0f, -10.0f);
|
|
|
|
|
|
|
|
// Do we want to let bodies sleep?
|
|
|
|
bool doSleep = true;
|
|
|
|
|
|
|
|
// Construct a world object, which will hold and simulate the rigid bodies.
|
|
|
|
world = new b2World(gravity, doSleep);
|
|
|
|
|
|
|
|
world->SetContinuousPhysics(true);
|
|
|
|
|
|
|
|
/*
|
|
|
|
m_debugDraw = new GLESDebugDraw( PTM_RATIO );
|
|
|
|
world->SetDebugDraw(m_debugDraw);
|
|
|
|
|
2010-10-12 17:15:07 +08:00
|
|
|
uint flags = 0;
|
2010-09-14 14:47:12 +08:00
|
|
|
flags += b2DebugDraw::e_shapeBit;
|
|
|
|
flags += b2DebugDraw::e_jointBit;
|
|
|
|
flags += b2DebugDraw::e_aabbBit;
|
|
|
|
flags += b2DebugDraw::e_pairBit;
|
|
|
|
flags += b2DebugDraw::e_centerOfMassBit;
|
|
|
|
m_debugDraw->SetFlags(flags);
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Define the ground body.
|
|
|
|
b2BodyDef groundBodyDef;
|
|
|
|
groundBodyDef.position.Set(0, 0); // bottom-left corner
|
|
|
|
|
|
|
|
// Call the body factory which allocates memory for the ground body
|
|
|
|
// from a pool and creates the ground box shape (also from a pool).
|
|
|
|
// The body is also added to the world.
|
|
|
|
b2Body* groundBody = world->CreateBody(&groundBodyDef);
|
|
|
|
|
|
|
|
// Define the ground box shape.
|
|
|
|
b2PolygonShape groundBox;
|
|
|
|
|
|
|
|
// bottom
|
|
|
|
groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(screenSize.width/PTM_RATIO,0));
|
|
|
|
groundBody->CreateFixture(&groundBox, 0);
|
|
|
|
|
|
|
|
// top
|
|
|
|
groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO));
|
|
|
|
groundBody->CreateFixture(&groundBox, 0);
|
|
|
|
|
|
|
|
// left
|
|
|
|
groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(0,0));
|
|
|
|
groundBody->CreateFixture(&groundBox, 0);
|
|
|
|
|
|
|
|
// right
|
|
|
|
groundBox.SetAsEdge(b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,0));
|
|
|
|
groundBody->CreateFixture(&groundBox, 0);
|
|
|
|
|
|
|
|
|
|
|
|
//Set up sprite
|
|
|
|
|
|
|
|
CCSpriteSheet *mgr = CCSpriteSheet::spriteSheetWithFile(s_pPathBlock, 150);
|
|
|
|
addChild(mgr, 0, kTagSpriteManager);
|
|
|
|
|
|
|
|
addNewSpriteWithCoords( CGPointMake(screenSize.width/2, screenSize.height/2) );
|
|
|
|
|
|
|
|
CCLabel *label = CCLabel::labelWithString("Tap screen", "Marker Felt", 32);
|
|
|
|
addChild(label, 0);
|
|
|
|
label->setColor( ccc3(0,0,255) );
|
|
|
|
label->setPosition( CGPointMake( screenSize.width/2, screenSize.height-50) );
|
|
|
|
|
|
|
|
schedule( schedule_selector(Box2DTestLayer::tick) );
|
|
|
|
}
|
|
|
|
|
|
|
|
Box2DTestLayer::~Box2DTestLayer()
|
|
|
|
{
|
|
|
|
delete world;
|
|
|
|
world = NULL;
|
|
|
|
|
|
|
|
//delete m_debugDraw;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Box2DTestLayer::draw()
|
|
|
|
{
|
|
|
|
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
|
|
|
|
// Needed states: GL_VERTEX_ARRAY,
|
|
|
|
// Unneeded states: GL_TEXTURE_2D, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
|
|
|
|
//world->DrawDebugData();
|
|
|
|
|
|
|
|
// restore default GL states
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Box2DTestLayer::addNewSpriteWithCoords(CGPoint p)
|
|
|
|
{
|
|
|
|
//UXLOG(L"Add sprite %0.2f x %02.f",p.x,p.y);
|
|
|
|
CCSpriteSheet* sheet = (CCSpriteSheet*)getChildByTag(kTagSpriteManager);
|
|
|
|
|
|
|
|
//We have a 64x64 sprite sheet with 4 different 32x32 images. The following code is
|
|
|
|
//just randomly picking one of the images
|
|
|
|
int idx = (CCRANDOM_0_1() > .5 ? 0:1);
|
|
|
|
int idy = (CCRANDOM_0_1() > .5 ? 0:1);
|
|
|
|
CCSprite *sprite = sheet->createSpriteWithRect( CGRectMake(32 * idx,32 * idy,32,32));
|
|
|
|
(CCNode*)(sheet)->addChild(sprite);
|
|
|
|
|
|
|
|
sprite->setPosition( CGPointMake( p.x, p.y) );
|
|
|
|
|
|
|
|
// Define the dynamic body.
|
|
|
|
//Set up a 1m squared box in the physics world
|
|
|
|
b2BodyDef bodyDef;
|
|
|
|
bodyDef.type = b2_dynamicBody;
|
|
|
|
bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
|
|
|
|
bodyDef.userData = sprite;
|
|
|
|
b2Body *body = world->CreateBody(&bodyDef);
|
|
|
|
|
|
|
|
// Define another box shape for our dynamic body.
|
|
|
|
b2PolygonShape dynamicBox;
|
|
|
|
dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box
|
|
|
|
|
|
|
|
// Define the dynamic body fixture.
|
|
|
|
b2FixtureDef fixtureDef;
|
|
|
|
fixtureDef.shape = &dynamicBox;
|
|
|
|
fixtureDef.density = 1.0f;
|
|
|
|
fixtureDef.friction = 0.3f;
|
|
|
|
body->CreateFixture(&fixtureDef);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Box2DTestLayer::tick(ccTime dt)
|
|
|
|
{
|
|
|
|
//It is recommended that a fixed time step is used with Box2D for stability
|
|
|
|
//of the simulation, however, we are using a variable time step here.
|
|
|
|
//You need to make an informed choice, the following URL is useful
|
|
|
|
//http://gafferongames.com/game-physics/fix-your-timestep/
|
|
|
|
|
2010-10-12 17:15:07 +08:00
|
|
|
int velocityIterations = 8;
|
|
|
|
int positionIterations = 1;
|
2010-09-14 14:47:12 +08:00
|
|
|
|
|
|
|
// Instruct the world to perform a single step of simulation. It is
|
|
|
|
// generally best to keep the time step and iterations fixed.
|
|
|
|
world->Step(dt, velocityIterations, positionIterations);
|
|
|
|
|
|
|
|
//Iterate over the bodies in the physics world
|
|
|
|
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
|
|
|
|
{
|
|
|
|
if (b->GetUserData() != NULL) {
|
|
|
|
//Synchronize the AtlasSprites position and rotation with the corresponding body
|
|
|
|
CCSprite* myActor = (CCSprite*)b->GetUserData();
|
|
|
|
myActor->setPosition( CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO) );
|
|
|
|
myActor->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Box2DTestLayer::ccTouchesEnded(NSSet* touches, UIEvent* event)
|
|
|
|
{
|
|
|
|
//Add a new body/atlas sprite at the touched location
|
|
|
|
NSSetIterator it;
|
|
|
|
CCTouch* touch;
|
|
|
|
|
|
|
|
for( it = touches->begin(); it != touches->end(); it++)
|
|
|
|
{
|
|
|
|
touch = (CCTouch*)(*it);
|
|
|
|
|
|
|
|
if(!touch)
|
|
|
|
break;
|
|
|
|
|
|
|
|
CGPoint location = touch->locationInView(touch->view());
|
|
|
|
|
|
|
|
location = CCDirector::getSharedDirector()->convertToGL(location);
|
|
|
|
|
|
|
|
addNewSpriteWithCoords( location );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
void Box2DTestLayer::accelerometer(UIAccelerometer* accelerometer, CCAcceleration* acceleration)
|
|
|
|
{
|
|
|
|
static float prevX=0, prevY=0;
|
|
|
|
|
|
|
|
//#define kFilterFactor 0.05f
|
|
|
|
#define kFilterFactor 1.0f // don't use filter. the code is here just as an example
|
|
|
|
|
|
|
|
float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX;
|
|
|
|
float accelY = (float) acceleration.y * kFilterFactor + (1- kFilterFactor)*prevY;
|
|
|
|
|
|
|
|
prevX = accelX;
|
|
|
|
prevY = accelY;
|
|
|
|
|
|
|
|
// accelerometer values are in "Portrait" mode. Change them to Landscape left
|
|
|
|
// multiply the gravity by 10
|
|
|
|
b2Vec2 gravity( -accelY * 10, accelX * 10);
|
|
|
|
|
|
|
|
world->SetGravity( gravity );
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
void Box2DTestScene::runThisTest()
|
|
|
|
{
|
|
|
|
CCLayer* pLayer = new Box2DTestLayer();
|
|
|
|
addChild(pLayer);
|
|
|
|
pLayer->release();
|
|
|
|
|
|
|
|
CCDirector::getSharedDirector()->replaceScene(this);
|
|
|
|
}
|
|
|
|
|