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?
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?
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);
@Meir_yanovich and @atuan1989
Thank you so much. Will try it! 
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