[Cocos2dx game development box2d] 3. tmx blocking for reading tiledmap

Source: Internet
Author: User

To create a pixel game project, read the blocking area in the TMX file and generate the fixture of box2d to block the use of cocos2dx: 2.2.2

 

1. Create a "Physics" layer in the tmx file to store various blocks generated in the editor.

The editor mainly includes polygone, polyline, box and circle. in fact, box also belongs to polygone.

 

2. My tiled map Version 0.9.1

View the tmx file. The added layer belongs It will not be rendered, So adding multiple layers has no effect on efficiency. Here we call it Physics"

Corresponding to the four images in XML

Polyline reads an initial vertex x and y, and then reads the offset values of some columns relative to the initial vertex.

Box read x, y, width, height

The circle read start point x, y, plus the width (height) diameter is sufficient, because the b2Shape of the elliptic cannot be constructed, So we construct the circle

Polygon reads the starting point x and y, and then reads the offset values of some columns relative to the initial point, similar to the polyline

 

 

 

3. When the file is parsed in cocos2dx, CCTMXXMLParser. cpp is about 623 rows, but only polygon is parsed in the code, and the parsing code at polyline and circle is empty. We add complete

 

 

else if (elementName == "polygon")     {        // find parent object's dict and add polygon-points to it        ObjectGroup* objectGroup = (ObjectGroup*)m_pObjectGroups->lastObject();        CCDictionary* dict = (CCDictionary*)objectGroup->getObjects()->lastObject();        // get points value string        const char* value = valueForKey("points", attributeDict);        if(value)        {            CCArray* pPointsArray = new CCArray;            // parse points string into a space-separated set of points            stringstream pointsStream(value);            string pointPair;            while(std::getline(pointsStream, pointPair, ' '))            {                // parse each point combo into a comma-separated x,y point                stringstream pointStream(pointPair);                string xStr,yStr;                char buffer[32] = {0};                                CCDictionary* pPointDict = new CCDictionary;                // set x                if(std::getline(pointStream, xStr, ','))                {                    int x = atoi(xStr.c_str()) + (int)objectGroup->getPositionOffset().x;                    sprintf(buffer, "%d", x);                    CCString* pStr = new CCString(buffer);                    pStr->autorelease();                    pPointDict->setObject(pStr, "x");                }                // set y                if(std::getline(pointStream, yStr, ','))                {                    int y = atoi(yStr.c_str()) + (int)objectGroup->getPositionOffset().y;                    sprintf(buffer, "%d", y);                    CCString* pStr = new CCString(buffer);                    pStr->autorelease();                    pPointDict->setObject(pStr, "y");                }                                // add to points array                pPointsArray->addObject(pPointDict);                pPointDict->release();            }                        dict->setObject(pPointsArray, "points");            pPointsArray->release();                        dict->setObject(dict->objectForKey("points"), "polygonPoints");        }    }     else if (elementName == "polyline")    {        // find parent object's dict and add polyline-points to it        // ObjectGroup* objectGroup = (ObjectGroup*)m_pObjectGroups->lastObject();        // CCDictionary* dict = (CCDictionary*)objectGroup->getObjects()->lastObject();        // TODO: dict->setObject:[attributeDict objectForKey:@"points"] forKey:@"polylinePoints"];                // ------Added by Teng.start        // find parent object's dict and add polygon-points to it        ObjectGroup* objectGroup = (ObjectGroup*)m_pObjectGroups->lastObject();        CCDictionary* dict = (CCDictionary*)objectGroup->getObjects()->lastObject();                // get points value string        const char* value = valueForKey("points", attributeDict);        if(value)        {            CCArray* pPointsArray = new CCArray;                        // parse points string into a space-separated set of points            stringstream pointsStream(value);            string pointPair;            while(std::getline(pointsStream, pointPair, ' '))            {                // parse each point combo into a comma-separated x,y point                stringstream pointStream(pointPair);                string xStr,yStr;                char buffer[32] = {0};                                CCDictionary* pPointDict = new CCDictionary;                                // set x                if(std::getline(pointStream, xStr, ','))                {                    int x = atoi(xStr.c_str()) + (int)objectGroup->getPositionOffset().x;                    sprintf(buffer, "%d", x);                    CCString* pStr = new CCString(buffer);                    pStr->autorelease();                    pPointDict->setObject(pStr, "x");                }                                // set y                if(std::getline(pointStream, yStr, ','))                {                    int y = atoi(yStr.c_str()) + (int)objectGroup->getPositionOffset().y;                    sprintf(buffer, "%d", y);                    CCString* pStr = new CCString(buffer);                    pStr->autorelease();                    pPointDict->setObject(pStr, "y");                }                                // add to points array                pPointsArray->addObject(pPointDict);                pPointDict->release();            }                        dict->setObject(pPointsArray, "points");            pPointsArray->release();                        dict->setObject(dict->objectForKey("points"), "polylinePoints");        }                // ------Added by Teng.end    }    else if (elementName == "ellipse")    {        // ------Added by Teng.start        // Do nothing...        ObjectGroup* objectGroup = (ObjectGroup*)m_pObjectGroups->lastObject();        CCDictionary* dict = (CCDictionary*)objectGroup->getObjects()->lastObject();                CCObject *obj = new CCObject;        dict->setObject(obj, "ellipse");        obj->release();        // ------Added by Teng.end    }

 

4. The rest is that we get these blocking areas in the program.

 

Bool Map: createPhysical (b2World * world) {b2BodyDef body_def; body_def.type = b2_staticBody; body_def.position.SetZero (); mBody = world-> CreateBody (& body_def ); // find the ObjectGroup * group = mTiledMap-> objectGroupNamed ("Physics"); CCArray * array = group-> getObjects (); CCDictionary * dict; CCObject * pObj = NULL; CCARRAY_FOREACH (array, pObj) {dict = (CCDictionary *) pObj; if (! Dict) continue; b2FixtureDef fixture_def; StaticBlockObject * sb_obj = new StaticBlockObject (); sb_obj-> density = 1.0f; sb_obj-> friction = 0.2f; sb_obj-> restitution = 0.f; // read the starting point float x = (CCString *) dict-> objectForKey ("x")-> floatValue (); float y = (CCString *) dict-> objectForKey ("y")-> floatValue (); b2Shape * shape = NULL; // polygccobject * polygon = dict-> objectForKey ("polygonPoints"); if (polygon) {CCArray * polygon_points = (CCArray *) polygon; std: vector
 
  
Points; // all read points must be reversed, because after y is flipped, the order of the triangle points has been reversed. When b2PolygonShape is constructed, crash int c = polygon_points-> count (); points. resize (c); c --; CCDictionary * pt_dict; CCObject * obj = NULL; CCARRAY_FOREACH (polygon_points, obj) {pt_dict = (CCDictionary *) obj; if (! Pt_dict) {continue;} // offset float offx = (CCString *) pt_dict-> objectForKey ("x")-> floatValue (); float offy = (CCString *) pt_dict-> objectForKey ("y")-> floatValue (); points [c --] = (b2Vec2 (x + offx) /PTM_RATIO, (y-offy)/PTM_RATIO);} b2PolygonShape * ps = new b2PolygonShape (); ps-> Set (& points [0], points. size (); fixture_def.shape = ps; shape = ps; sb_obj-> shape = StaticBlockObject: ST_POLYGON;} else if (polygon = dict-> objectForKey ("polylinePoints ")) {CCArray * polyline_points = (CCArray *) polygon; std: vector
  
   
Points; CCDictionary * pt_dict; CCObject * obj = NULL; CCARRAY_FOREACH (polyline_points, obj) {pt_dict = (CCDictionary *) obj; if (! Pt_dict) {continue;} float offx = (CCString *) pt_dict-> objectForKey ("x")-> floatValue (); float offy = (CCString *) pt_dict-> objectForKey ("y")-> floatValue (); points. push_back (b2Vec2 (x + offx)/PTM_RATIO, (y-offy)/PTM_RATIO);} b2ChainShape * ps = new b2ChainShape (); ps-> CreateChain (& points [0], points. size (); fixture_def.shape = ps; shape = ps; sb_obj-> shape = StaticBlockObject: ST_POLYGON;} else if (dict-> objectForKey ("ellipse ")) {float width = (CCString *) dict-> objectForKey ("width")-> floatValue (); float height = (CCString *) dict-> objectForKey ("height")-> floatValue (); b2CircleShape * ps = new b2CircleShape; ps-> m_p.Set (x + width/2)/PTM_RATIO, (y + height/2)/PTM_RATIO); ps-> m_radius = width/2/PTM_RATIO; fixture_def.shape = ps; shape = ps; sb_obj-> shape = StaticBlockObject :: ST_CIRCLE;} else {float width = (CCString *) dict-> objectForKey ("width")-> floatValue (); float height = (CCString *) dict-> objectForKey ("height")-> floatValue (); b2PolygonShape * ps = new b2PolygonShape; ps-> SetAsBox (width/2/PTM_RATIO, height/2/PTM_RATIO, b2Vec2 (x + width/2)/PTM_RATIO, (y + height/2)/PTM_RATIO), 0); fixture_def.shape = ps; shape = ps; sb_obj-> shape = StaticBlockObject: ST_POLYGON;} member = sb_obj-> density; fixture_def.friction = sb_obj-> friction; fixture_def.restitution = sb_obj-> restitution; b2Fixture * fixture = mBody-> CreateFixture (& fixture_def); sb_obj-> fixture = fixture; if (shape) {delete shape; shape = NULL ;} // store the Static block object. mStaticBlockList. push_back (sb_obj);} return true ;}
  
 

Because it is directly copied from the code, but it does not implement the following functions:

 

1. Find the "Physics" layer in map

2. traverse the starting point for reading all images, analyze the images, and read the corresponding attributes.

3. Construct b2Shape with each read image and construct b2Fixture with the map body.

Note the following points:

1. Because Box2d is different from the unit used in the game, which is meter and pixel, The PTM_RATIO macro is used for conversion.

2. Construct b2PolygonShape by reading all vertices from polygon. This sequence must be the reverse list of all vertices to be read. Otherwise, a computing center assertion error will be reported.

This is because the vertex Coordinate System in tmx is the upper-left corner of the map, and the lower-left corner of the map in the game. When the starting point is resolved in CCTMXXMLParser. cpp, it automatically turns us into the coordinates in the game.

Therefore, the vertex sequence of 1, 2, 4 in tmx forms the interior of a convex polygon. After conversion, it becomes 4, 3, 2, and 1, which forms the exterior of a convex polygon.

Because polyline is not closed, there is no need to reverse it.

 

Std: vector
 
  
Points; // all read points must be reversed, because after y is flipped, the order of the triangle points has been reversed. When b2PolygonShape is constructed, crash int c = polygon_points-> count (); points. resize (c); c --; CCDictionary * pt_dict; CCObject * obj = NULL; CCARRAY_FOREACH (polygon_points, obj) {pt_dict = (CCDictionary *) obj; if (! Pt_dict) {continue;} // offset float offx = (CCString *) pt_dict-> objectForKey ("x")-> floatValue (); float offy = (CCString *) pt_dict-> objectForKey ("y")-> floatValue (); points [c --] = (b2Vec2 (x + offx) /PTM_RATIO, (y-offy)/PTM_RATIO);} b2PolygonShape * ps = new b2PolygonShape (); ps-> Set (& points [0], points. size (); fixture_def.shape = ps;
 


 

5. Upload:

 

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.