Instance introduction Box2D physical engine in Cocos2d-x: HelloBox2D
Let's take an example to introduce how to use the Box2D physical engine in Cocos2d-x 3. x and get familiar with the use of these Apis. In the scenario after this instance is run, after the scenario is started, the player can touch and click the screen. Each time the screen is touched, a new genie will be generated at the touch point, and the running of the genie will be moved freely.
The HelloBox2D instance uses the Box2D engine for development, as shown in 12-15. Next we will follow this step to introduce the code section. First, let's take a look at the HelloWorldScene. h file. Its code is as follows:
#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include cocos2d.h#include Box2D/Box2D.h①#define PTM_RATIO 32②class HelloWorld : public cocos2d::Layer{b2World* world;③public: static cocos2d::Scene* createScene(); virtual bool init(); virtual void update(float dt);④virtual bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event); ⑤ CREATE_FUNC(HelloWorld);void initPhysics();⑥void addNewSpriteAtPosition(cocos2d::Vec2 p);⑦};#endif // __HELLOWORLD_SCENE_H__
The above line code # include Box2D/Box2D. h is the header file required to use the Box2D engine. Line ② Code # define PTM_RATIO 32 is the definition macro PTM_RATIO, PTM_RATIO is the number of pixels on the screen is 1 meter, 32 represents the screen 32 pixels represents 1 meter, in Box2D, The MKS metric system is used, that is, the unit of length is meter, the unit of quality is kg, and the unit of time is second.
Line 3 of the Code indicates the b2World member variable of the physical world. The fourth line of code is the game loop function. The fifth line of code is the touch click response function. Line 6 of Code declares the initialization of the physical engine function initPhysics. Line 7 declares the addNewSpriteAtPosition function, which is used to create a Sprite object on the touch point.
The HelloWorld: init () function code in HelloWorldScene. cpp is as follows:
Bool HelloWorld: init () {if (! Layer: init () {return false;} Size visibleSize = Director: getInstance ()-> getVisibleSize (); Vec2 origin = Director: getInstance () -> getVisibleOrigin (); // initialize the physical engine this-> initPhysics (); ① setTouchEnabled (true); // set it to single-Touch setTouchMode (Touch: DispatchMode :: ONE_BY_ONE); // start the game loop scheduleUpdate (); ② return true ;}
The first line of the above Code calls the initPhysics () function to initialize the physical engine. Line ② code scheduleUpdate () is used to start the game loop. Once the game loop is enabled, the HelloWorld: update (float dt) function is called back.
The code for initializing the physical engine HelloWorld: initPhysics () in HelloWorldScene. cpp is as follows:
Void HelloWorld: initPhysics () {Size s = Director: getInstance ()-> getVisibleSize (); // gravity parameter b2Vec2 gravity; ① gravity. set (0.0f,-10.0f); ② // create world = new b2World (gravity); ③ // allow the object to sleep world-> SetAllowSleeping (true ); ④ // enable the continuous physical test world-> SetContinuousPhysics (true); ⑤ // The Ground Object defines b2BodyDef groundBodyDef; ⑥ // groundBodyDef in the lower left corner. position. set (0, 0); 7 // create a Ground Object b2Body * groundBody = world-> CreateBody (& groundBodyDef); then // define Edge Shape b2EdgeShape groundBox; border // bottom groundBox. set (b2Vec2 (0, 0), b2Vec2 (s. width/PTM_RATIO, 0); returns // uses the jigs to fix the shape of groundBody-> CreateFixture (& groundBox, 0 );? // Top groundBox. set (b2Vec2 (0, s. height/PTM_RATIO), b2Vec2 (s. width/PTM_RATIO, s. height/PTM_RATIO); groundBody-> CreateFixture (& groundBox, 0); // groundBox on the left. set (b2Vec2 (0, s. height/PTM_RATIO), b2Vec2 (0, 0); groundBody-> CreateFixture (& groundBox, 0); // groundBox on the right. set (b2Vec2 (s. width/PTM_RATIO, s. height/PTM_RATIO), b2Vec2 (s. width/PTM_RATIO, 0); groundBody-> CreateFixture (& groundBox, 0 );}
Line ① Of the code b2Vec2 gravity is the declared gravity variable. b2Vec2 is a two-dimensional vector. Its two attributes are floating point numbers x and y, representing the vectors in the x and y axes. The code line ② gravity. Set (0.0f,-10.0f) is to Set the vector value. (0.0f,-10.0f) indicates that only gravity is applied to the object, and-10.0f indicates downward along the Y axis.
Line ③ code world = new b2World (gravity) is used to create a b2World object in the physical world. Here we use new to create a physical world object and allocate memory with the new keyword in C ++, releasing memory is the delete keyword. World is a member variable and you need to release it yourself. Generally, it is released in the destructor. The Code is as follows:
HelloWorld ::~ HelloWorld ()
{
CC_SAFE_DELETE (world );
}
Among them, CC_SAFE_DELETE (world) is the safe release of the world variable, and the CC_SAFE_DELETE macro represents the safe release of memory.
Line ④ code world-> SetAllowSleeping (true) indicates whether to allow an object to sleep. If sleep is allowed, the processing efficiency of the object in the physical world can be improved, this object is awakened only when a collision occurs.
The fifth line of code world-> SetContinuousPhysics (true) is to enable the continuous physical test [enable the continuous physical test, because the computer can only divide the continuous time into many discrete time points, the behavior between each time point is calculated. If the time point is not detailed enough, a fast collision between two objects may produce a "penetration" phenomenon, enabling continuous physics will enable special algorithms to avoid this phenomenon.].
Line 6 of Code declares the Shape Definition (b2BodyDef) variable. Line 7 Code groundBodyDef. position. Set (0, 0) is to Set the shape position. The first line of code b2Body * groundBody = world-> CreateBody (& groundBodyDef) is used to create a ground object through the Shape Definition variable groundBodyDef.
The first line of code declares a variable with an edge shape defining b2EdgeShape, and the second line of code groundBox. set (b2Vec2 (0, 0), b2Vec2 (s. width/PTM_RATIO, 0) is the start position (0, 0) and end position (s. width/PTM_RATIO, 0), s. width/PTM_RATIO converts pixels into meters. Number? The line of code uses a jigs to fix the shape of the object. Use similar functions to define objects on the top, left, and right.
The code for creating the HelloWorld: addNewSpriteAtPosition function in HelloWorldScene. cpp is as follows:
Void HelloWorld: addNewSpriteAtPosition (Vec2 p) {log (Add sprite % 0.2f x % 02.f, p. x, p. y); // create the physical engine sprite object auto Sprite = sprite: create(BoxA2.png); ① sprite-> setPosition (Vec2 (p. x, p. y); this-> addChild (sprite); // The object definition b2BodyDef bodyDef; ② bodyDef. type = b2_dynamicBody; ③ bodyDef. position. set (p. x/PTM_RATIO, p. y/PTM_RATIO); ④ b2Body * body = world-> CreateBody (& bodyDef); ⑤ body-> SetUserData (sprite); ⑥ // defines the 2-meter square-shaped box b2Poly GonShape dynamicBox; 7dynamicbox. setAsBox (1, 1); done // The fixture defines b2FixtureDef fixtureDef; done // sets the shape of the fixture fixtureDef. shape = & dynamicBox; Specify // set the density fixtureDef. density = 1.0f ;? // Set the friction coefficient fixtureDef. friction = 0.3f ;? // Use the jigs to fix the shape of the Object body-> CreateFixture (& fixtureDef );?}
The first line of the above Code is to create a Sprite object. The Sprite object has nothing to do with the physical engine object. We need to update it in the game loop function.
Line ② Of the Code declares the dynamic object definition variables. Line ③ of the Code bodyDef. type = b2_dynamicBody is used to set the object type to dynamic objects, which are divided into static and dynamic objects. Line 4 of the Code sets the object position, in meters. Line ⑤ code b2Body * body = world-> CreateBody (& bodyDef) is used to create an object. Line 6 code body-> SetUserData (sprite) is to place the sprite in the UserData attribute of the object, so that we can obtain the associated object from the object.
Line 7 Code b2PolygonShape dynamicBox declares a Polygon Shape Definition variable. The first line of code dynamicBox. setAsBox (1, 1) is to set the polygon to the shape of a rectangular box. Because the coordinate origin is in the lower left corner of the box, SetAsBox is to set the center of the box ), the size of the box is 2 meters.
The first line of code is b2FixtureDef fixtureDef, which declares the fixture definition variable. The first line of code is to set the shape of the fixture. Number? The line code fixtureDef. density = 1.0f is used to set the shape density. Number? The row code fixtureDef. friction = 0.3f is used to set the friction coefficient. The range is 0.0 ~ In the range of 1.0. Number? The line code body-> CreateFixture (& fixtureDef) uses a clamp to fix the shape of the object, so that the object has a shape.
In HelloWorldScene. cpp, the game loop function HelloWorld: update code is as follows:
void HelloWorld::update(float dt){float timeStep = 0.03f; int32 velocityIterations = 8;int32 positionIterations = 1;world->Step(timeStep, velocityIterations, positionIterations);for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())①{if (b->GetUserData() != nullptr) {Sprite* sprite = (Sprite*)b->GetUserData();sprite->setPosition( Vec2( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO) );sprite->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );}}②}
Code ① ~ ② This code can synchronize the location and status of objects and genie in the physical engine.