Introduction to box2d cocos2d 2.x Tutorial: fl

Source: Internet
Author: User

Address: http://www.raywenderlich.com/28602/intro-to-box2d-with-cocos2d-2-x-tutorial-bouncing-balls

Updated:

Update content:

    1. SetBodyUnified TranslationRigid Body
    2. SetFixtureUnified TranslationJigs

Updated on:

Update content: fully updated to cocos2d 2.1-beta4

Tutorial by Ray wenderlich

Tutorial update: Brian broom

This tutorial demonstrates a simple applicationProgramTo help you use box2d in cocos2d. The app shows a small ball, and the iPhone uses an accelerator to let the ball play on the screen.

The game is as follows:

The sample program used in this tutorial is based on a great example written by Kyle on the iPhone dev.net, updated to the latest version of cocos2d, and explained in detail how it works. The tutorial will also explain the working principles of some elements provided by The box2d Application Template of cocos2d in the sample project.

This tutorial assumes that you have learned how to create a simple iPhone game using cocos2d 2.x or have the same knowledge.

OK. Let's start learning about cocos2d 2. x box2d!

Create an empty project

First, create a new project in xcode, select cocos2d v2.x \ cocos2d IOS with box2d application template, and name the project box2d. If you compile and run this template, you will see a very cool example showing a lot of box2d content. However, for the purpose of this tutorial, we prepare to create everything from scratch so that we can understand how it works well.

Therefore, let's first clean up the template so that we have a good starting point. Use the followingCodeReplaceHelloworldlayer. hContent:

 
# Import "Cocos2d. h" # DefinePptm_ratio 32.0@ InterfaceHelloworldlayer: cclayer {}+ (ID) Scene;@ End

Use the following code to replaceHelloworldlayer. MmContent:

 #import  "   helloworldlayer. h   "  @ implementation   helloworldlayer  + ( id  ) scene {ccscene  * scene =  [ccscene node]; helloworldlayer  * layer =  [helloworldlayer node]; [scene addchild: layer];   return   scene ;} -( id  ) init {  If  (Self =  [Super init]) {}  return   Self ;}  @ end  

Compile and run again, and you will see a blank screen. Okay. Now let's start creating our own box2d scenario!

Box2d world Theory

Before proceeding, let's briefly introduce how it works in box2d.

The first thing to do when using cocos2d is to create a world for box2d (World) Object. The world object is the main object in cocos2d and is responsible for managing all objects and physical simulation.

After creating the world object, we need to add some rigid bodies to the world (Body). A rigid body can be an object that moves back and forth in a game, such as a ninja or monster, or a static rigid body, such as a platform or wall.

To create a rigid body, you need to do many things-create a rigid body definition, a rigid body object, a shape, a fixture definition, and a fixture object. Next we will explain what these crazy terms mean separately!

    • First, create a rigid body definition (Body DefinitionSpecifies the initial attributes of a rigid body, such as the position or speed.
    • After creating a rigid body definition, you can use the World object to create a rigid body object by specifying a rigid body definition (Body object).
    • Then create a geometric shape (Shape).
    • Then create a fixture definition (Fixture Definition), Set the shape defined by the fixture to the shape you created, and set other attributes, such as density or friction coefficient.
    • Finally, create a fixture object by specifying the fixture Definition (Fixture object).
    • Note that you can add any number of fixture objects to a single rigid body object. This feature is useful when creating complex objects.

After adding all required rigid bodies to the world, you only need to call the step function cyclically to let box2d take over the work and start physical simulation, so this takes a certain amount of processing time.

However, note that box2dOnlyUpdate the location of the internal model object. If you want the cocos2d genie to update the location of the physical simulation, you also need to periodically update the location of the genie.

OK. Now we have a basic understanding of the working mechanism of box2d. Next let's take a look at how it is implemented in the code!

Box2d world Drill

OK. First download a small ball image and its retina version. We are going to add this ball to the scenario. After the download, drag them to the resources folder in the project and make sure that the copy items into destination group's folder (if needed) Check is selected ).

Next, let's take a look at the code we previously added in helloworldlayer. h:

 
# DefinePptm_ratio 32.0

This line of code defines the ratio between a pixel and a "meter. When you specify the position of a rigid body in cocos2d, you must specify a unit. Although you may consider using pixels, this location is incorrect. According to the box2d reference manual, box2d has been optimized in length from 0.1 to 10 units. According to the length as long as possible, we usually tend to regard it as "meters", so 0.1 is about the size of a cup, and 10 is about the size of a box.

Therefore, we cannot directly transmit pixels, because even a very small object will have about 60x60 pixels, which is beyond the maximum value set by box2d optimization. Therefore, we need a method to convert pixels into "meters", so we have the above proportional definition. If we have a 64-pixel object divided by ptm_ratio, We can get 2 "meters", which is the length of a box2d physical simulation.

Now, you can try something interesting. InHelloworldlayer. hAdd the following code to the top:

# Import "Box2d. h"

Add the following member variables to the interface definition of the helloworldlayer class:

 
B2world *_ World; b2body*_ Body; ccsprite* _ Ball;

Then, add the following codeHelloworldlayer. MmInit method:

Cgsize winsize = [Ccdirector shareddire]. winsize;  //  Create Sprite and add it to the Layer _ Ball = [ccsprite spritewithfile: @"  Ball.png  " Rect: cgrectmake (0 , 0 , 52 , 52  )]; _ Ball. Position = CCP ( 100 , 300  ); [Self addchild: _ Ball];  //  Create a world B2vec2 gravity = b2vec2 ( 0.0f ,- 8.0f  ); _ World = New B2world (gravity );  //  Create ball body and shape  B2bodydef ballbodydef; ballbodydef. Type = B2_dynamicbody; ballbodydef. position. Set (  100 /Ptm_ratio, 300 / Ptm_ratio); ballbodydef. userdata = _ Ball; _ body = _ World-> createbody (& Ballbodydef); b2circleshape circle; circle. m_radius = 26.0 /Ptm_ratio; b2fixturedef ballshapedef; ballshapedef. Shape = & Circle; ballshapedef. Density = 1.0f  ; Ballshapedef. Friction = 0.2f  ; Ballshapedef. Restitution = 0.8f  ; _ Body -> Createfixture (& Ballshapedef); [self schedule: @ selector (tick :)]; 

Except for a few lines of code that are already familiar with the cocos2d tutorial, most of the code here is unfamiliar. Let's explain it at 1.1. I will repeat the above Code for a while, which should be clearer.

Cgsize winsize =[Ccdirector shareddire]. winsize;//Create Sprite and add it to the Layer_ Ball = [ccsprite spritewithfile:@"Ball.png"Rect: cgrectmake (0,0,52,52)]; _ Ball. Position= CCP (100,300); [Self addchild: _ Ball];

First, use cocos2d to add the genie to the scenario. If you have already learned the cocos2d tutorial, there should be no problem here.

//Create a worldB2vec2 gravity = b2vec2 (0.0f,-8.0f); _ World=NewB2world (gravity );

Next, create a world object. When creating this object, you must specify an initial Gravity Vector. We set it to a vector extending the Y axis to-8, so that the rigid body will fall to the bottom of the screen.

 //  Create ball body and shape  B2bodydef ballbodydef; ballbodydef. Type = B2_dynamicbody; ballbodydef. position. Set (  100 /Ptm_ratio, 300 / Ptm_ratio); ballbodydef. userdata =_ Ball; _ body = _ World-> createbody (& Ballbodydef); b2circleshape circle; circle. m_radius = 26.0 / Ptm_ratio; b2fixturedef ballshapedef; ballshapedef. Shape = & Circle; ballshapedef. Density = 1.0f  ; Ballshapedef. Friction = 0.2f  ; Ballshapedef. Restitution = 0.8f  ; _ Body -> Createfixture (& ballshapedef );

Next, we will create a ball rigid body.

    • Specify its type as a dynamic rigid body (Dynamic body). The default type of a rigid body is a static Rigid Body (Static body), Indicating that the rigid body cannot move or participate in simulation. Obviously, we want the ball to participate in the simulation!
    • Put user data (User Data. You can set the user data parameter on the rigid body to any object you want, but it is usually convenient to set it as a wizard so that you can access it elsewhere, for example, handling two rigid body collisions.
    • We must define a circular shape (Shape). Remember that box2d does not view the sprite's image. We must tell it the shape of the sprite so that it can correctly simulate the movements of the genie.
    • Finally, some fixture-defined parameters are set. The specific meanings of these parameters will be described later.
 
[Self schedule: @ selector (tick :)];

The last thing to do in the method is to schedule a method named tick to be called as frequently as possible. Please note that this is not the best processing method. A better way is to make the tick method be called at a fixed frequency, for example, 60 times per second. However, to ensure the simplicity of the tutorial content, let's proceed with this first.

Next, let's compile the tick method code! Add the following code after the init method:

-( Void  ) Tick :( cctime) dt {_ world -> Step (DT, 10 ,10  );  For (B2body * B = _ world-> getbodylist (); B; B = B-> Getnext ()){  If (B-> getuserdata ()! = Null) {ccsprite * Balldata = (ccsprite *) B-> Getuserdata (); balldata. Position = CCP (B-> getposition (). x * Ptm_ratio, B -> Getposition (). y * Ptm_ratio); balldata. Rotation =- 1 * Cc_radians_to_degrees (B->Getangle ());}}} 

The first thing we do in the method is to call the step function on the world object so that it can perform physical simulation. The two parameters are speed iteration and location iteration respectively. You should set them to 8 ~ A value between 10.

The next thing is to match the genie with the physical simulation. Therefore, we traverse all the rigid bodies in the world and find the rigid bodies with user data. After finding the data, convert the user data into an genie (previously set the genie as user data !), Then, update the location and angle of the genie to match the physical simulation.

The last thing-Clear the memory! Add the following code at the end of the file:

 
-(Void) Dealloc {Delete _ world; _ body=NULL; _ world=NULL; [_ ball release]; _ ball=Nil; [Super dealloc];}

Compile and run the application. You should be able to see the ball dropping out of the screen. Oh, we forgot to define a ground and then bounce the ball.

Recovery

To represent the ground, we create an invisible boundary at the bottom of the iPhone screen. Follow these steps.

    • Create a rigid body definition (Body DefinitionAnd specify that the rigid body is located in the lower left corner of the screen. Since the default type of the rigid body is the static rigid body we need, you do not need to set it.
    • Then, use the World object to create a rigid object (Body object).
    • Create a boundary shape (Edge Shape). This "shape" is actually a line. Note that the preceding conversion ratio must be used to convert pixels to "meters ".
    • Create a fixture definition (Fixture Definition) Specifies the border shape.
    • Create a fixture object for the shape using a rigid body object (Fixture object).
    • Note that a rigid body object can contain multiple fixture objects!

Add the following code to the code used to create a world object and define a ball in the init method.

  //   Create edges around the entire screen   b2bodydef groundbodydef; groundbodydef. position. set (  0 ,  0   ); b2body  * groundbody = _ world-> createbody (&  groundbodydef); b2edgeshape groundedge; b2fixturedef boxshapedef; boxshapedef. shape =&  groundedge;  ///   wall definitions  groundedge. set (b2vec2 ( 0 ,  0 ), b2vec2 (winsize. width/ptm_ratio,  0   )); groundbody -> createfixture (& boxshapedef); 

Compile and run the program again. After the ball falls on the ground, it will bounce back to the air. After several times, it will finally rest on the ground.

How to run horizontally?

Now that we have basic knowledge, let's do something more interesting-Let an invisible foot kick the ball every few seconds. InHelloworldlayer. hDefine a new method:

 
-(Void) Kick;

Then, add the implementation of this methodHelloworldlayer. Mm:

 
-(Void) Kick {b2vec2 force= B2vec2 (30,30); _ Body-> Applylinearimpulse (force, _ body->Getposition ());}

The applylinearimpulse method can act a force on the ball to move the ball. The distance of moving depends on the quality of the ball. We previously set its density when defining the ball (Density. You can try different density and Force values to find the values you think are good. The coordinate system is the same as cocos2d. The X direction is a forward extension to the right, and the Y direction is a forward extension.

Add the following code lines to the init method and run the kick method every 5 seconds.

[Self schedule: @ selector (kick) interval:5.0];

If a project is generated and run now, the ball will fly out of the screen after it is "kicked. Let's continue and define other walls. FindWall DefinitionsAnd add the following code lines. Note: two lines of code are required for each wall. One line sets the coordinates, and the other line adds the boundary as the fixture Rigid Body of the Ground Object.

Groundedge. Set (b2vec2 (0,0), B2vec2 (0, Winsize. Height/Ptm_ratio); groundbody-> Createfixture (&Boxshapedef); groundedge. Set (b2vec2 (0, Winsize. Height/Ptm_ratio), b2vec2 (winsize. Width/Ptm_ratio, winsize. Height/Ptm_ratio); groundbody-> Createfixture (&Boxshapedef); groundedge. Set (b2vec2 (winsize. Width/Ptm_ratio, winsize. Height/Ptm_ratio), b2vec2 (winsize. Width/Ptm_ratio,0); Groundbody-> Createfixture (& boxshapedef );

Now generate and run the project. Watch the ball and play it on the screen.

Integrated touch

Since helloworldlayer is still a cocos2d layer, we can use all the tools, including the touch events we have learned. To demonstrate how to interact with box2d, let's make some modifications to the program and play in the left when you touch the screen.

To enable the touch event, firstHelloworldlayer. MmAdd the following line of code to the init method:

 
[Self settouchenabled: Yes];

Then add the following method to handle touch events:

 
-(Void) Cctouchesbegan :( uitouch *) touch withevent :( uievent *)Event{B2vec2 force= B2vec2 (-30,30); _ Body-> Applylinearimpulse (force, _ body->Getposition ());}

Similarly, we use the applylinearimpulse method to exert a force on the ball. A negative value of X given by force will kick the ball on the left.

Comments about Simulation

As a commitment, let's introduce the functions of density, friction, and restitution set for the ball above.

    • Density (Density) Is the quality per unit volume. Therefore, the higher the density, the higher the quality, and the more difficult it is to move.
    • Friction Coefficient (FrictionIs a coefficient used to describe the difficulty of moving between objects. The range is between 0 and 1. 0 indicates no friction, while 1 indicates that the friction is very large.
    • Recovery coefficient (Restitution) Is also a coefficient used to describe how "Bullet" an object has ". The range is usually between 0 and 1. 0 indicates that the object will not rebound, while 1 indicates that the object is completely elastic, that is, the object will rebound at the same speed.

You can modify these values at will to see what will happen after modification. Try to see if it can make your ball fully scalable!

Ending

If we tilt the screen, it will be cool to let the ball play on the screen! One thing that can help us in the next experiment is that all the boundaries can work normally now! The rest is simple. Add the following code to the init method:

 
[Self setaccelerometerenabled: Yes];

Add a location in the file as follows:

-(Void) Accelerometer :( uiaccelerometer *) accelerometer didaccelerate :( uiacceleration *) Acceleration {//Landscape left valuesB2vec2 gravity (acceleration. y *30,-Acceleration. x *30); _ World->Setgravity (gravity );}

Finally, click the project at the top of the Project navigation sidebar. Select box2d under targets and select the summary tab. In the oriorted interface orientations section, click the landscape right button to deselect this button. At this time, the landscape left button should be the only selected button. This is because we do not want Ios to change the direction of the app when rotating the phone. As shown in:

What we do here is to set the Gravity Vector used for simulation to a multiple of the accelerator vector. Compile and run the application on the device. Now tilt the mobile phone should be able to let the ball play on the screen!

Note: only when a program runs on a physical device can accelerator data be obtained. This requires a paid developer account and a developer certificate installed. For more information, see Ios provisioning portal at pai.apple.com.

What to do next?

Click Download sample code for this tutorial.

If you want to learn more about box2d, please refer to the next tutorial how to create a breakout game with box2d and cocos2d!

 

Copyright Disclaimer: This article is translated by http://www.cnblogs.com/liufan9. you are welcome to enjoy the transfer. Please respect the work of the author. Keep this note and the author's blog link when reprinting. Thank you!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.