From dbfd05ef779bab1aa898ab1a7791998430b971e4 Mon Sep 17 00:00:00 2001 From: boyu0 Date: Sun, 29 Sep 2013 09:39:20 +0800 Subject: [PATCH] issue #2771: add tag and enable functions to physics classes --- .../CCScene.cpp | 2 +- cocos2dx/physics/CCPhysicsBody.cpp | 82 ++++++++++- cocos2dx/physics/CCPhysicsBody.h | 10 ++ cocos2dx/physics/CCPhysicsJoint.cpp | 17 +++ cocos2dx/physics/CCPhysicsJoint.h | 7 + cocos2dx/physics/CCPhysicsShape.cpp | 22 +++ cocos2dx/physics/CCPhysicsShape.h | 6 + cocos2dx/physics/CCPhysicsWorld.cpp | 127 +++++++++++++++--- cocos2dx/physics/CCPhysicsWorld.h | 10 +- .../physics/chipmunk/CCPhysicsShapeInfo.cpp | 8 +- 10 files changed, 260 insertions(+), 31 deletions(-) diff --git a/cocos2dx/layers_scenes_transitions_nodes/CCScene.cpp b/cocos2dx/layers_scenes_transitions_nodes/CCScene.cpp index 36f2947dc6..0950fcd0a8 100644 --- a/cocos2dx/layers_scenes_transitions_nodes/CCScene.cpp +++ b/cocos2dx/layers_scenes_transitions_nodes/CCScene.cpp @@ -137,7 +137,7 @@ void Scene::addChildToPhysicsWorld(Node* child) if (sp->getPhysicsBody()) { - _physicsWorld->addChild(sp->getPhysicsBody()); + _physicsWorld->addBody(sp->getPhysicsBody()); } } }; diff --git a/cocos2dx/physics/CCPhysicsBody.cpp b/cocos2dx/physics/CCPhysicsBody.cpp index 3fb5d485b1..2c190eefdd 100644 --- a/cocos2dx/physics/CCPhysicsBody.cpp +++ b/cocos2dx/physics/CCPhysicsBody.cpp @@ -63,12 +63,14 @@ PhysicsBody::PhysicsBody() , _world(nullptr) , _info(nullptr) , _dynamic(false) +, _enable(true) , _massDefault(true) , _angularDampingDefault(true) , _mass(MASS_DEFAULT) , _area(0.0) , _density(DENSITY_DEFAULT) , _angularDamping(ANGULARDAMPING_DEFAULT) +, _tag(0) { } @@ -76,10 +78,7 @@ PhysicsBody::~PhysicsBody() { CC_SAFE_DELETE(_info); - for (auto it = _shapes.begin(); it != _shapes.end(); ++it) - { - delete *it; - } + removeAllShapes(); for (auto it = _joints.begin(); it != _joints.end(); ++it) { @@ -375,6 +374,81 @@ void PhysicsBody::setAngularDamping(float angularDamping) cpBodySetMoment(_info->body, _angularDamping); } +PhysicsShape* PhysicsBody::getShapeByTag(int tag) +{ + for (auto shape : _shapes) + { + if (shape->getTag() == tag) + { + return shape; + } + } + + return nullptr; +} + +void PhysicsBody::removeShapeByTag(int tag) +{ + for (auto shape : _shapes) + { + if (shape->getTag() == tag) + { + removeShape(shape); + return; + } + } +} + +void PhysicsBody::removeShape(PhysicsShape* shape) +{ + auto it = std::find(_shapes.begin(), _shapes.end(), shape); + + if (it != _shapes.end()) + { + if (_world) + { + _world->removeShape(shape); + } + + _shapes.erase(it); + delete shape; + } +} + +void PhysicsBody::removeAllShapes() +{ + for (auto shape : _shapes) + { + if (_world) + { + _world->removeShape(shape); + } + + delete shape; + } + + _shapes.clear(); +} + +void PhysicsBody::setEnable(bool enable) +{ + if (_enable != enable) + { + _enable = enable; + + if (_world) + { + if (enable) + { + _world->addBody(this); + }else + { + _world->removeBody(this); + } + } + } +} + //Clonable* PhysicsBody::clone() const //{ // PhysicsBody* body = new PhysicsBody(); diff --git a/cocos2dx/physics/CCPhysicsBody.h b/cocos2dx/physics/CCPhysicsBody.h index 515366e64e..94d30f8b63 100644 --- a/cocos2dx/physics/CCPhysicsBody.h +++ b/cocos2dx/physics/CCPhysicsBody.h @@ -145,10 +145,12 @@ public: * @brief get the first body shapes. */ inline PhysicsShape* getShape() { return _shapes.size() >= 1 ? _shapes.front() : nullptr; } + PhysicsShape* getShapeByTag(int tag); /* * @brief remove a shape from body */ void removeShape(PhysicsShape* shape); + void removeShapeByTag(int tag); /* * @brief remove all shapes */ @@ -215,6 +217,12 @@ public: //virtual Clonable* clone() const override; + inline bool isEnable() { return _enable; } + void setEnable(bool enable); + + inline int getTag() { return _tag; } + inline void setTag(int tag) { _tag = tag; } + protected: bool init(); @@ -235,12 +243,14 @@ protected: PhysicsWorld* _world; PhysicsBodyInfo* _info; bool _dynamic; + bool _enable; bool _massDefault; bool _angularDampingDefault; float _mass; float _area; float _density; float _angularDamping; + int _tag; int _categoryBitmask; int _contactTestBitmask; diff --git a/cocos2dx/physics/CCPhysicsJoint.cpp b/cocos2dx/physics/CCPhysicsJoint.cpp index 3e60d246ab..63b6ac052e 100644 --- a/cocos2dx/physics/CCPhysicsJoint.cpp +++ b/cocos2dx/physics/CCPhysicsJoint.cpp @@ -46,6 +46,8 @@ PhysicsJoint::PhysicsJoint() : _bodyA(nullptr) , _bodyB(nullptr) , _info(nullptr) +, _enable(false) +, _tag(0) { } @@ -79,6 +81,21 @@ bool PhysicsJoint::init(cocos2d::PhysicsBody *a, cocos2d::PhysicsBody *b) return false; } +void PhysicsJoint::setEnable(bool enable) +{ + if (_enable != enable) + { + _enable = enable; + + if (enable) + { + + }else + { + + } + } +} PhysicsJointPin::PhysicsJointPin() { diff --git a/cocos2dx/physics/CCPhysicsJoint.h b/cocos2dx/physics/CCPhysicsJoint.h index 854963049d..73383c39b6 100644 --- a/cocos2dx/physics/CCPhysicsJoint.h +++ b/cocos2dx/physics/CCPhysicsJoint.h @@ -49,6 +49,10 @@ protected: public: PhysicsBody* getBodyA() { return _bodyA; } PhysicsBody* getBodyB() { return _bodyB; } + inline int getTag() { return _tag; } + inline void setTag(int tag) { _tag = tag; } + inline bool isEnable() { return _enable; } + void setEnable(bool enable); protected: bool init(PhysicsBody* a, PhysicsBody* b); @@ -62,8 +66,11 @@ protected: PhysicsBody* _bodyA; PhysicsBody* _bodyB; PhysicsJointInfo* _info; + bool _enable; + int _tag; friend class PhysicsBody; + friend class PhysicsWorld; }; /* diff --git a/cocos2dx/physics/CCPhysicsShape.cpp b/cocos2dx/physics/CCPhysicsShape.cpp index e98dff0b5c..1ce4cbb3b5 100644 --- a/cocos2dx/physics/CCPhysicsShape.cpp +++ b/cocos2dx/physics/CCPhysicsShape.cpp @@ -32,6 +32,7 @@ #endif #include "CCPhysicsBody.h" +#include "CCPhysicsWorld.h" #include "chipmunk/CCPhysicsBodyInfo.h" #include "Box2D/CCPhysicsBodyInfo.h" @@ -45,6 +46,8 @@ PhysicsShape::PhysicsShape() : _body(nullptr) , _info(nullptr) , _type(Type::UNKNOWN) +, _tag(0) +, _enable(true) { } @@ -68,6 +71,25 @@ bool PhysicsShape::init(PhysicsBody* body, Type type) return true; } +void PhysicsShape::setEnable(bool enable) +{ + if (_enable != enable) + { + _enable = enable; + + if (_body->getWorld() && _body->isEnable()) + { + if (enable) + { + _body->getWorld()->addShape(this); + }else + { + _body->getWorld()->removeShape(this); + } + } + } +} + void PhysicsShape::addToBody() { if(_body != nullptr) _body->addShape(this); diff --git a/cocos2dx/physics/CCPhysicsShape.h b/cocos2dx/physics/CCPhysicsShape.h index 79cda68e6d..4cc1da148b 100644 --- a/cocos2dx/physics/CCPhysicsShape.h +++ b/cocos2dx/physics/CCPhysicsShape.h @@ -58,6 +58,10 @@ public: public: inline PhysicsBody* getBody(){ return _body; } inline Type getType() { return _type; } + inline void setTag(int tag) { _tag = tag; } + inline int getTag() { return _tag; } + void setEnable(bool enable); + inline bool isEnable() { return _enable; } protected: bool init(PhysicsBody* body, Type type); @@ -77,6 +81,8 @@ protected: PhysicsBody* _body; PhysicsShapeInfo* _info; Type _type; + int _tag; + bool _enable; friend class PhysicsWorld; friend class PhysicsBody; diff --git a/cocos2dx/physics/CCPhysicsWorld.cpp b/cocos2dx/physics/CCPhysicsWorld.cpp index 08857de24b..17b866c6b7 100644 --- a/cocos2dx/physics/CCPhysicsWorld.cpp +++ b/cocos2dx/physics/CCPhysicsWorld.cpp @@ -34,6 +34,7 @@ #include "CCPhysicsBody.h" #include "CCPhysicsShape.h" #include "CCPhysicsContact.h" +#include "CCPhysicsJoint.h" #include "chipmunk/CCPhysicsWorldInfo.h" #include "Box2D/CCPhysicsWorldInfo.h" @@ -43,6 +44,8 @@ #include "Box2D/CCPhysicsShapeInfo.h" #include "chipmunk/CCPhysicsContactInfo.h" #include "Box2D/CCPhysicsContactInfo.h" +#include "chipmunk/CCPhysicsJointInfo.h" +#include "Box2D/CCPhysicsJointInfo.h" #include "chipmunk/CCPhysicsHelper.h" #include "draw_nodes/CCDrawNode.h" @@ -110,34 +113,69 @@ bool PhysicsWorld::init() return true; } +void PhysicsWorld::addJoint(PhysicsJoint* joint) +{ + auto it = std::find(_joints.begin(), _joints.end(), joint); + + if (it == _joints.end()) + { + _joints.push_back(joint); + + if (!cpSpaceContainsConstraint(_info->space, joint->_info->joint)) + { + cpSpaceAddConstraint(_info->space, joint->_info->joint); + } + } + +} + +void PhysicsWorld::removeJoint(PhysicsJoint* joint) +{ + +} + +void PhysicsWorld::removeAllJoints() +{ + +} + void PhysicsWorld::addShape(PhysicsShape* shape) { - for (auto it = shape->_info->shapes.begin(); it != shape->_info->shapes.end(); it++) + for (auto cps : shape->_info->shapes) { + if (cpSpaceContainsShape(_info->space, cps)) + { + continue; + } + if (cpBodyIsStatic(shape->getBody()->_info->body)) { - cpSpaceAddStaticShape(_info->space, *it); + cpSpaceAddStaticShape(_info->space, cps); }else { - cpSpaceAddShape(_info->space, *it); + cpSpaceAddShape(_info->space, cps); } } } -void PhysicsWorld::addChild(PhysicsBody* body) +void PhysicsWorld::addBody(PhysicsBody* body) { - auto shapes = body->getShapes(); - - // add body to space - if (body->isDynamic()) + if (body->isEnable()) { - cpSpaceAddBody(_info->space, body->_info->body); - } - - // add shapes to space - for (auto it = shapes.begin(); it != shapes.end(); it++) - { - addShape(*it); + // add body to space + if (body->isDynamic()) + { + cpSpaceAddBody(_info->space, body->_info->body); + } + + // add shapes to space + for (auto shape : body->getShapes()) + { + if (shape->isEnable()) + { + addShape(shape); + } + } } if (_bodys == nullptr) @@ -150,6 +188,54 @@ void PhysicsWorld::addChild(PhysicsBody* body) } } +void PhysicsWorld::removeBody(PhysicsBody* body) +{ + for (auto shape : body->getShapes()) + { + for (auto cps : shape->_info->shapes) + { + if (cpSpaceContainsShape(_info->space, cps)) + { + cpSpaceRemoveShape(_info->space, cps); + } + } + } + + if (cpSpaceContainsBody(_info->space, body->_info->body)) + { + cpSpaceRemoveBody(_info->space, body->_info->body); + } + + if (_bodys != nullptr) + { + _bodys->removeObject(body); + } +} + +void PhysicsWorld::removeBodyByTag(int tag) +{ + for (Object* obj : *_bodys) + { + PhysicsBody* body = dynamic_cast(obj); + if (body->getTag() == tag) + { + removeBody(body); + return; + } + } +} + +void PhysicsWorld::removeShape(PhysicsShape* shape) +{ + for (auto cps : shape->_info->shapes) + { + if (cpSpaceContainsShape(_info->space, cps)) + { + cpSpaceRemoveShape(_info->space, cps); + } + } +} + void PhysicsWorld::update(float delta) { cpSpaceStep(_info->space, delta); @@ -171,17 +257,16 @@ void PhysicsWorld::debugDraw() if (_debugDraw && _bodys != nullptr) { _drawNode= DrawNode::create(); - - Object* child = nullptr; - CCARRAY_FOREACH(_bodys, child) + + for (Object* obj : *_bodys) { - PhysicsBody* body = dynamic_cast(child); + PhysicsBody* body = dynamic_cast(obj); std::vector shapes = body->getShapes(); - for (auto it = shapes.begin(); it != shapes.end(); ++it) + for (auto shape : shapes) { - drawWithShape(_drawNode, *it); + drawWithShape(_drawNode, shape); } } diff --git a/cocos2dx/physics/CCPhysicsWorld.h b/cocos2dx/physics/CCPhysicsWorld.h index bd06fdf661..d7a30f37cf 100644 --- a/cocos2dx/physics/CCPhysicsWorld.h +++ b/cocos2dx/physics/CCPhysicsWorld.h @@ -28,6 +28,8 @@ #ifndef __CCPHYSICS_WORLD_H__ #define __CCPHYSICS_WORLD_H__ +#include + #include "cocoa/CCObject.h" #include "cocoa/CCGeometry.h" @@ -86,14 +88,18 @@ public: /** set the debug draw */ inline void setDebugDraw(bool debugDraw) { _debugDraw = debugDraw; } + virtual void removeBody(PhysicsBody* body); + virtual void removeBodyByTag(int tag); + protected: static PhysicsWorld* create(); bool init(); void setScene(Scene* scene); - virtual void addChild(PhysicsBody* body); + virtual void addBody(PhysicsBody* body); virtual void addShape(PhysicsShape* shape); + virtual void removeShape(PhysicsShape* shape); virtual void update(float delta); virtual void debugDraw(); @@ -120,6 +126,7 @@ protected: Array* _bodys; + std::list _joints; Scene* _scene; bool _debugDraw; @@ -132,6 +139,7 @@ protected: friend class Sprite; friend class Scene; friend class PhysicsBody; + friend class PhysicsShape; }; NS_CC_END diff --git a/cocos2dx/physics/chipmunk/CCPhysicsShapeInfo.cpp b/cocos2dx/physics/chipmunk/CCPhysicsShapeInfo.cpp index 0734bf6e49..0e660792ad 100644 --- a/cocos2dx/physics/chipmunk/CCPhysicsShapeInfo.cpp +++ b/cocos2dx/physics/chipmunk/CCPhysicsShapeInfo.cpp @@ -36,12 +36,12 @@ PhysicsShapeInfo::PhysicsShapeInfo(PhysicsShape* shape) PhysicsShapeInfo::~PhysicsShapeInfo() { - for (auto it = shapes.begin(); it != shapes.end(); it++) + for (auto shape : shapes) { - cpShapeFree(*it); + auto it = map.find(shape); + if (it != map.end()) map.erase(shape); - auto mit = map.find(*it); - if (mit != map.end()) map.erase(*it); + cpShapeFree(shape); } }