Custom Physics Body

I’m using cocos2dx v3.4 and box2d.

Is there a way to use custom physics bodies in box2d?
I know we can add multiple fixtures to create a custom shape but Is there any other way to trace out the outline of sprite and create a physics body?

try it. https://code.google.com/p/box2d-editor/

Is there a Parser class for box2d?

this is my code parser. you can use it.

	rapidjson::Document document;
	document.Parse<0>("physicFile");
	if (document.HasParseError())
	{
		return;
	}
	__Array* arrayMap = JSONLoad::loadArray(document, "rigidBodies");
	__Dictionary*  mapInfo = (__Dictionary*)arrayMap->getObjectAtIndex(0);
	__Array* arrayPolygon = (__Array*)mapInfo->objectForKey("polygons");

	Ref* obj;
	CCARRAY_FOREACH(arrayPolygon, obj)
	{
		__Array* key = static_cast<__Array*>(obj);

		Ref* objPos;
		Path path;
		CCARRAY_FOREACH(key, objPos)
		{
			__Dictionary* keyPos  = static_cast<__Dictionary*>(objPos);

			__Float* posXObject = (__Float *)keyPos->objectForKey("x");
			__Float* posYObject = (__Float *) keyPos->objectForKey("y");

			int realPosX = (int)(posXObject->getValue() * sprBomb->getContentSize().width);
			int realPosY = (int)(posYObject->getValue() * sprBomb->getContentSize().width);
			
			//You can use realPosX realPosY to create polygon for physic body
			
		}
	}

here is parser that is modified by me to support circle also from :

here is my version
MyBodyParser.cpp

//
//  MyBodyParser.cpp
//
//  Created by Jason Xu.
// modified by meir yanovich
//

#include "MyBodyParser.h"
#include "Config.h"


MyBodyParser* MyBodyParser::getInstance()
{
    static MyBodyParser* sg_ptr = nullptr;
    if (nullptr == sg_ptr)
    {
        sg_ptr = new MyBodyParser;
    }
    return sg_ptr;
}

bool MyBodyParser::parse(unsigned char *buffer, long length)
{
    bool result = false;
    std::string js((const char*)buffer, length);
    doc.Parse<0>(js.c_str());
    if(!doc.HasParseError())
    {
        result = true;
    }
    return result;
}

void MyBodyParser::clearCache()
{
    doc.SetNull();
}

bool MyBodyParser::parseJsonFile(const std::string& pFile)
{
    auto content = FileUtils::getInstance()->getDataFromFile(pFile);
    bool result = parse(content.getBytes(), content.getSize());
    return result;
}

 
void MyBodyParser::bodyFormJson(cocos2d::Node *pNode
								   ,const std::string& name 
								   ,b2FixtureDef* _fd,
								   b2Body *_Body)
{
    
    rapidjson::Value &bodies = doc["rigidBodies"];
    if (bodies.IsArray())
    {
       
        for (int i=0; i<bodies.Size(); ++i)
        {
            
            if (0 == strcmp(name.c_str(), bodies[i]["name"].GetString()))
            {
                rapidjson::Value &bd = bodies[i];
                if (bd.IsObject())
                {
               
                    
                    float width = pNode->getContentSize().width;
                    float offx = - pNode->getAnchorPoint().x*pNode->getContentSize().width;
                    float offy = - pNode->getAnchorPoint().y*pNode->getContentSize().height;

                    Point origin( bd["origin"]["x"].GetDouble(), bd["origin"]["y"].GetDouble());
                    rapidjson::Value &polygons = bd["polygons"];
					
                    for (int i = 0; i<polygons.Size(); ++i)
                    {
                        int pcount = polygons[i].Size();
                        Point* points = new Point[pcount];
						b2Vec2 *vertices = new b2Vec2[pcount];
                        for (int pi = 0; pi<pcount; ++pi)
                        {
                            points[pi].x = offx + width * polygons[i][pcount-1-pi]["x"].GetDouble();
                            points[pi].y = offy + width * polygons[i][pcount-1-pi]["y"].GetDouble();
							vertices[pi].Set(points[pi].x/PIXEL_TO_METER_RATIO_DEFAULT ,points[pi].y/PIXEL_TO_METER_RATIO_DEFAULT );
                        }
					 
						b2PolygonShape* polygonShape = new b2PolygonShape();
						polygonShape->Set(vertices,pcount);
						_fd->shape = polygonShape;
						_Body->CreateFixture(_fd);
                        
                        delete [] points;
						delete[] vertices;
                    }

                    rapidjson::Value &circles = bd["circles"];
                    int sz = circles.Size();
                    for (int i = 0; i<circles.Size(); ++i)
                    {
                        int pcount = circles.Size();
                        Point* points = new Point[pcount];
						b2Vec3 *vertices = new b2Vec3[pcount];
                        
                        for (int pi = 0; pi<pcount; ++pi)
                        {
                            points[pi].x = offx + width * circles[pcount-1-pi]["cx"].GetDouble();
                            points[pi].y = offy + width * circles[pcount-1-pi]["cy"].GetDouble();
                            float radius =  (width * circles[pcount-1-pi]["r"].GetDouble()) /PIXEL_TO_METER_RATIO_DEFAULT ;
							vertices[pi].Set(points[pi].x/PIXEL_TO_METER_RATIO_DEFAULT ,points[pi].y/PIXEL_TO_METER_RATIO_DEFAULT ,radius);
                        }
					 
						b2CircleShape* pcircleShape =  new b2CircleShape();
                        pcircleShape->m_radius = vertices[0].z;
						_fd->shape = pcircleShape;
						_Body->CreateFixture(_fd);
                         
                        delete [] points;
						delete[] vertices;
                    }

                }
                else
                {
                    CCLOGWARN("body: %s not found!", name.c_str());
                }
                break;
            }

           

        }
    }
    
} 

MyBodyParser.h

//
//  MyBodyParser.h
//
//  Created by Jason Xu.
// modified by meir yanovich
//

#pragma once

#include <string>
#include "cocos2d.h"
USING_NS_CC;
#include "json/document.h"
#include "GLES-Render.h"
class MyBodyParser {
    MyBodyParser(){}
    rapidjson::Document doc;
public:
    static MyBodyParser* getInstance();
    bool parseJsonFile(const std::string& pFile);
    bool parse(unsigned char* buffer, long length);
    void clearCache();
    void bodyFormJson(Node* pNode,
						const std::string& name,
						b2FixtureDef* _fd,
						b2Body *_Body);
};

Example :

// parse the file 
MyBodyParser::getInstance()->parseJsonFile(car_config_file);

 // Crate the body of the Truck.
	b2BodyDef bd;
	bd.type = wheel_bd_type;
	bd.position.Set(pos.x / PIXEL_TO_METER_RATIO_DEFAULT , pos.y / PIXEL_TO_METER_RATIO_DEFAULT );
	bd.angularDamping = car_bd_angularDamping;
	bd.linearDamping = car_bd_linearDamping;
 	truckBody = _world->CreateBody(&bd);
	b2MassData  massData;	 
	massData.center = truckBody->GetLocalCenter();
 	// the main body    
	b2FixtureDef fd;
	fd.density = car_fd_density;
	fd.friction = car_fd_friction;
	fd.restitution = car_fd_restitution;
	fd.filter.groupIndex = car_fd_filter_groupIndex;
 

	MyBodyParser::getInstance()->bodyFormJson(truckBody,
		pCarSprite,
		fd,
		std::string("car_body"),
		Box2dTags::CAR_BODY_SPRITE);
1 Like

@Meir_yanovich and @atuan1989
Thank you so much. Will try it! :slight_smile:

@Meir_yanovich

My game crashes when executing this line in MyBodyParser.cpp
_Body->CreateFixture(_fd);

more code please

This is Cop.cpp…

MyBodyParser::getInstance()->parseJsonFile("Cop.json");

copSprite->setPosition(Vec2(visibleSize.width*0.1 + origin.x, 2*visibleSize.height + origin.y));
copSprite->setTag(1);

copBodyDef.type = b2_dynamicBody;
copBodyDef.userData = copSprite;
pworld->CreateBody(&copBodyDef);

copBodyFixture.density = 0.0f;
copBodyFixture.userData = copSprite;
copBodyFixture.friction = 0.0f;
copBodyFixture.restitution = 0.0f;

MyBodyParser::getInstance()->bodyFormJson(copSprite,"Cop",&copBodyFixture,copBody);

i dont see you are defining copBodyFixture but i guess you did some where in the code ,
also dont pass it by reference
also i have 5 arguments in the function you have only 4 you missed the b2Body and then the sprite

The bodyFromJson method accepts only 4 arguments
First is Sprite
Second is Name
Third is Fixture
Fourth is Body

This is how I created Fixture
b2FixtureDef copBodyFixture

I passed the reference because the bodyFromJson method accepts Fixture pointer.

i will write tutorial soon