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: