#include "B2Component.h" // C and C++ headers // cocos2d-x headers // project headers USING_NS_CC; B2Component::B2Component(Node* owner,b2World** world) :_world(world) { setOwner(owner); } B2Component::~B2Component() { } void B2Component::onRemove() { if (_body && *_world) { if (!_owner->getParent()) _body->SetUserData(nullptr); (*_world)->DestroyBody(_body); _body = nullptr; } } B2Component* B2Component::createBody(Node* owner, b2World** world, std::string name) { B2Component* body = new (std::nothrow) B2Component(owner, world); if (body && body->init(name, "hitBox")) { body->autorelease(); return body; } CC_SAFE_DELETE(body); return nullptr; } B2Component* B2Component::createBody(Node* owner, b2World** world, std::string name, std::string fixtureId, Vec2 localPosition, float angle) { B2Component* body = new (std::nothrow) B2Component(owner, world); if (body && body->init(name, fixtureId, localPosition, angle)) { body->autorelease(); return body; } CC_SAFE_DELETE(body); return nullptr; } B2Component* B2Component::createCircleBody(Node* owner, b2World** world, std::string name) { B2Component* body = new (std::nothrow) B2Component(owner, world); if (body && body->initCircle(name)) { body->autorelease(); return body; } CC_SAFE_DELETE(body); return nullptr; } bool B2Component::init(std::string name, std::string fixtureId) { setName(name); b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.bullet = true; auto p = getOwner()->convertToWorldSpace(Vec2(_positionX,_positionY)); bodyDef.position.Set(p.x / PTM_RATIO, p.y / PTM_RATIO); bodyDef.userData = static_cast(getOwner()); _body = (*_world)->CreateBody(&bodyDef); //auto v = getOwner()->convertToWorldSpace(Vec2(_positionX, _positionY)); //_body->SetTransform(b2Vec2(v.x / PTM_RATIO, v.y / PTM_RATIO), CC_DEGREES_TO_RADIANS(-getOwner()->getRotation() + _angle)); b2PolygonShape polygonShape; b2CircleShape circleShape; const ValueMap &map = static_cast(getOwner())->_map->at("physics").asValueMap(); auto plist = map.at("plist").asString(); auto gm = GameManager::getInstance(); const ValueMap &physicsMap = gm->physicsDataMap.at(plist).asValueMap(); auto nameOfBody = map.at(name).asString(); // temp float scale; if (name!="body") scale = map.at(name + "Scale").asFloat(); else scale = map.at("scale").asFloat(); b2FixtureDef fixtureDef = getFixtureDefsFromPhysicsEditor(physicsMap, nameOfBody, fixtureId, scale, polygonShape, circleShape); fixtureDef.filter.categoryBits = uint16(categoryBitsMap.at(map.at("collisionType").asString()).asInt()); fixtureDef.filter.maskBits = uint16(maskBitsMap.at(map.at("collisionType").asString()).asInt()); fixtureDef.isSensor = true; _body->CreateFixture(&fixtureDef); return true; } bool B2Component::init(std::string name, std::string fixtureId, Vec2 localPosition, float angle) { setBodyTransForm(localPosition.x, localPosition.y, angle); return init(name, fixtureId); } bool B2Component::initCircle(std::string name) { setName(name); b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.bullet = true; auto p = getOwner()->convertToWorldSpace(Vec2(_positionX, _positionY)); bodyDef.position.Set(p.x / PTM_RATIO, p.y / PTM_RATIO); bodyDef.userData = static_cast(getOwner()); _body = (*_world)->CreateBody(&bodyDef); b2CircleShape circleShape; const ValueMap &map = static_cast(getOwner())->_map->at("physics").asValueMap(); auto radius = map.at(name + "Radius").asFloat(); auto type = map.at("collisionType").asString(); circleShape.m_radius = radius / PTM_RATIO; b2FixtureDef fixtureDef; fixtureDef.shape = &circleShape; fixtureDef.friction = 0.0f; fixtureDef.restitution = 0.0f; fixtureDef.isSensor = true; fixtureDef.filter.categoryBits = uint16(categoryBitsMap.at(type).asInt()); fixtureDef.filter.maskBits = uint16(maskBitsMap.at(type).asInt()); _body->CreateFixture(&fixtureDef); return true; } void B2Component::update(float dt) { if (!_body) return; auto v = getOwner()->convertToWorldSpace(Vec2(_positionX, _positionY)); _body->SetTransform(b2Vec2(v.x / PTM_RATIO, v.y / PTM_RATIO), CC_DEGREES_TO_RADIANS(-getOwner()->getRotation() + _angle)); } b2FixtureDef B2Component::getFixtureDefsFromPhysicsEditor(const ValueMap &dict, const std::string &bodyName, std::string fixtureId, float scaleFactor, b2PolygonShape& ps, b2CircleShape& cs) { const ValueMap &bodies = dict.at("bodies").asValueMap(); const ValueMap &body = bodies.at(bodyName).asValueMap(); const ValueVector &fixtureList = body.at("fixtures").asValueVector(); b2FixtureDef fd; for (auto &fixtureitem : fixtureList) { const ValueMap &fixturedata = fixtureitem.asValueMap(); if (fixturedata.at("id").asString() == fixtureId) { fd.density = fixturedata.at("density").asFloat(); fd.friction = fixturedata.at("friction").asFloat(); fd.restitution = fixturedata.at("restitution").asFloat(); fd.isSensor = fixturedata.at("isSensor").asBool(); std::string fixtureType = fixturedata.at("fixture_type").asString(); if (fixtureType == "POLYGON") { const ValueVector &polygonsArray = fixturedata.at("polygons").asValueVector(); for (auto &polygonitem : polygonsArray) { auto &polygonArray = polygonitem.asValueVector(); int numVertices = (int)polygonArray.size(); b2Vec2 *vertices = new b2Vec2[numVertices]; int vindex = 0; for (auto &pointString : polygonArray) { auto offset = PointFromString(pointString.asString()); vertices[vindex].Set(offset.x * scaleFactor /PTM_RATIO, offset.y * scaleFactor / PTM_RATIO); vindex++; } ps.Set(vertices, numVertices); fd.shape = &ps; delete[] vertices; } } else if (fixtureType == "CIRCLE") { const ValueMap &circleData = fixturedata.at("circle").asValueMap(); cs.m_radius = circleData.at("radius").asFloat() * scaleFactor / PTM_RATIO; Point p = PointFromString(circleData.at("position").asString()) * scaleFactor / PTM_RATIO; cs.m_p = b2Vec2(p.x, p.y); fd.shape = &cs; } } } return fd; } void B2Component::beginContact(GameObject* otherObject, b2Contact* contact) { if (otherObject->getPositionX() < GAME_WIDTH) { auto owner = static_cast(getOwner()); if (otherObject->getObjectDamageType() == e_nuke) { owner->setObjectHp(owner->getObjectHp() - otherObject->getObjectDamage()); } else if (otherObject->getObjectDamageType() == e_dot) { } } }