Now, you study how to use Box2D in Cocos2d-x. By default, Cocos2d-x is installed for users to use the library of Cocos2d-x + Chipmunk, if you want to use Box2D, you must do some task to import it into the compiler.
In this lesson, you study:
+ How to setup to use Box2D
+ An example of physic, applying Box2D physic
Bắt đầu chém nào!
Step 1 - Setup to use Box2D
1/ Open file CMakeLists.txt in Project ( using NotePad++ to display line number ). Find to line number 162, and add "Box2D" as below:
(Before)
(After adding box2d)
2/ Open file physics.sln ( physics is the name of Project ) by VS2012 as following path physics\proj.win32\physics.sln,
Do the following steps:
* FILE -> Add -> Existing Project
* Right click Project physics, choose References, it displays project Properties Page, Click the button Add New References, and tick Box2D, it's done now!
* Finally you must SAVE thisi Solution by Ctrl + S, check the last step: open file physics.vcxproj in the following path: physics\proj.win32\physics.vcxproj
If you see this following line, it means that Box2D is available in Project Physics, you search "Box2D"
When you need to import some library, you also do as the above way.
Step 2 - A small physics practice
Create a new Project named Box2Dtest, ( you shouldn't name project - Box2D, because you will not import Box2D into VS)
>cocos new Box2Dtest -p com.vn.box2dtest -l cpp -d E/:android/project
Open file HelloWorldScene.h, do the following tasks:
+ Add #include "Box2D/Box2D.h" in #include area
+ Add USING_NS_CC;
+ Add the following code block in Public area:
b2World *world; // World with physic
b2Body *ballBody ; // Body of the ball
b2BodyDef bodyDef; // Define the above Body
b2FixtureDef fixtureDef; // Define some static features: friction, restitution, density, etc.
b2CircleShape bodyShape; // the shape of body
Sprite *ball; // Ball shape
void addWall(float w,float h,float px,float py); // Create the Wall edge around the screen for the ball to collide with.
void update(float dt); // Update scene by time
// This block is the most important to apply body in Box2D
//---------------------physics body in BOX2D--------------------
//bodyDef
//ballBody
//-----------------------------------------------------------
scheduleUpdate(); // Update again the scene by time
Open file HelloWorldScene.cpp, do the following tasks:
+ Add #define SCALE_RATIO 32.0 ( because Box2D uses the unit "mm", so you must have the factor to convert from pixel to mm)
+ In init() function, delete from the line this->addChild(label, 1); to the line return true; then add the following block
b2Vec2 gravity = b2Vec2(0.0f,-10.0f); // Vector of acceleration ( the mark "-" is for down direction, because the y axis is upwards )
world = new b2World(gravity); // Create world with vector of acceleration
// Create a ball Sprite
ball = Sprite::create("ball.png");
// Set the position in the center of the screen
ball->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
//---------------------physics body in BOX2D--------------------
bodyShape.m_radius = 45 / SCALE_RATIO; // The radius of body
//fixtureDef
fixtureDef.density=10;
fixtureDef.friction=0.8;
fixtureDef.restitution=0.6;
fixtureDef.shape=&bodyShape; // point to bodyShape
bodyDef.type = b2_dynamicBody; // Dynamic collision
bodyDef.userData = ball; // Attach to Sprite ball
// Set position, and remember to convert the unit
bodyDef.position.Set(ball->getPosition().x/SCALE_RATIO,ball->getPosition().y/SCALE_RATIO);
ballBody = world->CreateBody(&bodyDef); // Create Body
ballBody->CreateFixture(&fixtureDef); // Create static features
ballBody->SetGravityScale(10); // Set the ratio for acceleration, more higher more faster to fall
// Place the ball into layer of Scene
this->addChild(ball, 0);
void HelloWorld::update(float dt){
int positionIterations = 10; // Location
int velocityIterations = 10; // Velocity
deltaTime = dt; // Time step
// Simulate the physical movement by time, study here http://www.box2d.org/manual.html and here http://www.iforce2d.net/b2dtut/worlds
// Each Step happens in dt seconds , this dt in file AppDelegate.cpp is defined by command director->setAnimationInterval(1.0 / 60); you try replacing 1/60 = 1/1 , it falls very slow
world->Step(dt, velocityIterations, positionIterations);
for (b2Body *body = world->GetBodyList(); body != NULL; body = body->GetNext())
// Consider which body is attached to Sprite
if (body->GetUserData())
{
// return the ball sprite
Sprite *sprite = (Sprite *) body->GetUserData();
// Set the position again for this Sprite follow the position of body ( body is gradually falling by time), remember to multiply with RATIO to convert into pixel
sprite->setPosition(Point(body->GetPosition().x * SCALE_RATIO,body->GetPosition().y * SCALE_RATIO));
// Set the rotation ability
sprite->setRotation(-1 * CC_RADIANS_TO_DEGREES(body->GetAngle()));
}
world->ClearForces(); // Clear forces of Body
world->DrawDebugData(); // Draw shapes to check collision in debug mode
}
Build and run, if you see the ball falls into the bottom of the screen, you are successful. Congratulation!
Notices in Box2D
+ There must be a function with input param that is time, here is update (float dt)
+ When attaching body into sprite, the position of sprite always depends on the position of body
+ The way to convert rate, here we have two coordinate system: the coordinate of the screen, and the coordinate of Box2D. Remember the following:
- When setting position, size for objects, or components of Box2D (body, shape) if the input param is the coordinate of screen, you must divide by the scale ratio ( "/SCALE_RATIO" ), i.e:
bodyDef.position.Set(ball->getPosition().x/SCALE_RATIO,ball->getPosition().y/SCALE_RATIO);
- On the contrary, when setting position, size for objects, or components of the screen ( sprite, label, etc.) if the input param is the coordinate of Box2D, you must multiply with the (*SCALE_RATIO),i.e:
sprite->setPosition(Point(body->GetPosition().x * SCALE_RATIO,body->GetPosition().y * SCALE_RATIO));
[ttaiit.blogspot.com translated]
0 comments:
Post a Comment