#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); uint flags = 0; 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/ int velocityIterations = 8; int positionIterations = 1; // 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); }