diff --git a/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id b/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id index e32180792f..ac519a56c8 100644 --- a/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -8c640bf1e2f1cd0a489e6169c930234b809636f2 \ No newline at end of file +5a0361664f33af4303065c98da4b8d8e4efe48b4 \ No newline at end of file diff --git a/cocos/2d/Android.mk b/cocos/2d/Android.mk index 75ff000786..6d36b83b55 100644 --- a/cocos/2d/Android.mk +++ b/cocos/2d/Android.mk @@ -149,16 +149,16 @@ platform/CCThread.cpp \ ../physics/CCPhysicsJoint.cpp \ ../physics/CCPhysicsShape.cpp \ ../physics/CCPhysicsWorld.cpp \ -../physics/box2d/CCPhysicsBodyInfo.cpp \ -../physics/box2d/CCPhysicsContactInfo.cpp \ -../physics/box2d/CCPhysicsJointInfo.cpp \ -../physics/box2d/CCPhysicsShapeInfo.cpp \ -../physics/box2d/CCPhysicsWorldInfo.cpp \ -../physics/chipmunk/CCPhysicsBodyInfo.cpp \ -../physics/chipmunk/CCPhysicsContactInfo.cpp \ -../physics/chipmunk/CCPhysicsJointInfo.cpp \ -../physics/chipmunk/CCPhysicsShapeInfo.cpp \ -../physics/chipmunk/CCPhysicsWorldInfo.cpp \ +../physics/box2d/CCPhysicsBodyInfo_box2d.cpp \ +../physics/box2d/CCPhysicsContactInfo_box2d.cpp \ +../physics/box2d/CCPhysicsJointInfo_box2d.cpp \ +../physics/box2d/CCPhysicsShapeInfo_box2d.cpp \ +../physics/box2d/CCPhysicsWorldInfo_box2d.cpp \ +../physics/chipmunk/CCPhysicsBodyInfo_chipmunk.cpp \ +../physics/chipmunk/CCPhysicsContactInfo_chipmunk.cpp \ +../physics/chipmunk/CCPhysicsJointInfo_chipmunk.cpp \ +../physics/chipmunk/CCPhysicsShapeInfo_chipmunk.cpp \ +../physics/chipmunk/CCPhysicsWorldInfo_chipmunk.cpp \ ../../external/tinyxml2/tinyxml2.cpp \ ../../external/unzip/ioapi.cpp \ ../../external/unzip/unzip.cpp diff --git a/cocos/2d/CCLayer.cpp b/cocos/2d/CCLayer.cpp index 127261efd5..2556a98dda 100644 --- a/cocos/2d/CCLayer.cpp +++ b/cocos/2d/CCLayer.cpp @@ -87,29 +87,6 @@ Layer *Layer::create() } } -#ifdef CC_USE_PHYSICS -void Layer::addChild(Node* child) -{ - Node::addChild(child); -} - -void Layer::addChild(Node* child, int zOrder) -{ - Node::addChild(child, zOrder); -} - -void Layer::addChild(Node* child, int zOrder, int tag) -{ - Node::addChild(child, zOrder, tag); - - if (this->getParent() && - dynamic_cast(this->getParent()) != nullptr) - { - dynamic_cast(this->getParent())->addChildToPhysicsWorld(child); - } -} -#endif - // LayerRGBA LayerRGBA::LayerRGBA() : _displayedOpacity(255) diff --git a/cocos/2d/CCLayer.h b/cocos/2d/CCLayer.h index e94224b580..2aafa9a895 100644 --- a/cocos/2d/CCLayer.h +++ b/cocos/2d/CCLayer.h @@ -112,12 +112,6 @@ public: // // Overrides // - -#ifdef CC_USE_PHYSICS - virtual void addChild(Node* child) override; - virtual void addChild(Node* child, int zOrder) override; - virtual void addChild(Node* child, int zOrder, int tag) override; -#endif // CC_USE_PHYSICS }; #ifdef __apple__ diff --git a/cocos/2d/CCNode.cpp b/cocos/2d/CCNode.cpp index 5302648923..cb1fb62f6c 100644 --- a/cocos/2d/CCNode.cpp +++ b/cocos/2d/CCNode.cpp @@ -43,6 +43,7 @@ THE SOFTWARE. #include "CCEventDispatcher.h" #include "CCEvent.h" #include "CCEventTouch.h" +#include "CCScene.h" #ifdef CC_USE_PHYSICS #include "CCPhysicsBody.h" @@ -629,6 +630,17 @@ void Node::addChild(Node *child, int zOrder, int tag) } this->insertChild(child, zOrder); + +#ifdef CC_USE_PHYSICS + for (Node* node = this->getParent(); node != nullptr; node = node->getParent()) + { + if (dynamic_cast(node) != nullptr) + { + (dynamic_cast(node))->addChildToPhysicsWorld(child); + break; + } + } +#endif child->_tag = tag; @@ -752,6 +764,14 @@ void Node::detachChild(Node *child, int childIndex, bool doCleanup) child->onExitTransitionDidStart(); child->onExit(); } + +#ifdef CC_USE_PHYSICS + if (child->_physicsBody != nullptr) + { + child->_physicsBody->removeFromWorld(); + } + +#endif // If you don't do cleanup, the child's actions will not get removed and the // its scheduledSelectors_ dict will not get released! @@ -1369,10 +1389,12 @@ void Node::setPhysicsBody(PhysicsBody* body) { if (_physicsBody != nullptr) { + _physicsBody->_node = nullptr; _physicsBody->release(); } _physicsBody = body; + _physicsBody->_node = this; _physicsBody->retain(); _physicsBody->setPosition(getPosition()); _physicsBody->setRotation(getRotation()); diff --git a/cocos/2d/CCScene.cpp b/cocos/2d/CCScene.cpp index cc8654204b..3f05e43c83 100644 --- a/cocos/2d/CCScene.cpp +++ b/cocos/2d/CCScene.cpp @@ -102,8 +102,7 @@ bool Scene::initWithPhysics() Director * pDirector; CC_BREAK_IF( ! (pDirector = Director::getInstance()) ); this->setContentSize(pDirector->getWinSize()); - CC_BREAK_IF(! (_physicsWorld = PhysicsWorld::create())); - _physicsWorld->setScene(this); + CC_BREAK_IF(! (_physicsWorld = PhysicsWorld::create(*this))); this->scheduleUpdate(); // success @@ -136,14 +135,8 @@ void Scene::addChildToPhysicsWorld(Node* child) std::function addToPhysicsWorldFunc = nullptr; addToPhysicsWorldFunc = [this, &addToPhysicsWorldFunc](Object* child) -> void { - if (dynamic_cast(child) != nullptr) - { - Object* subChild = nullptr; - CCARRAY_FOREACH((dynamic_cast(child))->getChildren(), subChild) - { - addToPhysicsWorldFunc(subChild); - } - }else if (dynamic_cast(child) != nullptr) + + if (dynamic_cast(child) != nullptr) { Node* node = dynamic_cast(child); @@ -151,20 +144,16 @@ void Scene::addChildToPhysicsWorld(Node* child) { _physicsWorld->addBody(node->getPhysicsBody()); } + + Object* subChild = nullptr; + CCARRAY_FOREACH(node->getChildren(), subChild) + { + addToPhysicsWorldFunc(subChild); + } } }; - if(dynamic_cast(child) != nullptr) - { - Object* subChild = nullptr; - CCARRAY_FOREACH(child->getChildren(), subChild) - { - addToPhysicsWorldFunc(subChild); - } - }else - { - addToPhysicsWorldFunc(child); - } + addToPhysicsWorldFunc(child); } } diff --git a/cocos/2d/CCScene.h b/cocos/2d/CCScene.h index 11e3e0fbb5..e0f69edd82 100644 --- a/cocos/2d/CCScene.h +++ b/cocos/2d/CCScene.h @@ -87,7 +87,7 @@ protected: PhysicsWorld* _physicsWorld; #endif // CC_USE_PHYSICS - friend class Layer; + friend class Node; friend class SpriteBatchNode; }; diff --git a/cocos/2d/CCSpriteBatchNode.cpp b/cocos/2d/CCSpriteBatchNode.cpp index 195b5fa8eb..d531a571dd 100644 --- a/cocos/2d/CCSpriteBatchNode.cpp +++ b/cocos/2d/CCSpriteBatchNode.cpp @@ -181,17 +181,6 @@ void SpriteBatchNode::addChild(Node *child, int zOrder, int tag) Node::addChild(child, zOrder, tag); appendChild(sprite); - - - if (this->getParent() && - dynamic_cast(this->getParent()) != nullptr) - { - if (this->getParent()->getParent() && - dynamic_cast(this->getParent()->getParent())) - { - dynamic_cast(this->getParent()->getParent())->addChildToPhysicsWorld(child); - } - } } // override reorderChild diff --git a/cocos/2d/Makefile b/cocos/2d/Makefile index 6b89961f42..3e711d5d20 100644 --- a/cocos/2d/Makefile +++ b/cocos/2d/Makefile @@ -75,16 +75,16 @@ CCParticleExamples.cpp \ CCParticleSystem.cpp \ CCParticleSystemQuad.cpp \ CCParticleBatchNode.cpp \ -../physics/box2d/CCPhysicsContactInfo.cpp \ -../physics/box2d/CCPhysicsJointInfo.cpp \ -../physics/box2d/CCPhysicsShapeInfo.cpp \ -../physics/box2d/CCPhysicsBodyInfo.cpp \ -../physics/box2d/CCPhysicsWorldInfo.cpp \ -../physics/chipmunk/CCPhysicsContactInfo.cpp \ -../physics/chipmunk/CCPhysicsJointInfo.cpp \ -../physics/chipmunk/CCPhysicsShapeInfo.cpp \ -../physics/chipmunk/CCPhysicsBodyInfo.cpp \ -../physics/chipmunk/CCPhysicsWorldInfo.cpp \ +../physics/box2d/CCPhysicsContactInfo_box2d.cpp \ +../physics/box2d/CCPhysicsJointInfo_box2d.cpp \ +../physics/box2d/CCPhysicsShapeInfo_box2d.cpp \ +../physics/box2d/CCPhysicsBodyInfo_box2d.cpp \ +../physics/box2d/CCPhysicsWorldInfo_box2d.cpp \ +../physics/chipmunk/CCPhysicsContactInfo_chipmunk.cpp \ +../physics/chipmunk/CCPhysicsJointInfo_chipmunk.cpp \ +../physics/chipmunk/CCPhysicsShapeInfo_chipmunk.cpp \ +../physics/chipmunk/CCPhysicsBodyInfo_chipmunk.cpp \ +../physics/chipmunk/CCPhysicsWorldInfo_chipmunk.cpp \ ../physics/CCPhysicsBody.cpp \ ../physics/CCPhysicsContact.cpp \ ../physics/CCPhysicsShape.cpp \ diff --git a/cocos/2d/cocos2d.vcxproj b/cocos/2d/cocos2d.vcxproj index a59611bc90..5180e1a6f9 100644 --- a/cocos/2d/cocos2d.vcxproj +++ b/cocos/2d/cocos2d.vcxproj @@ -192,21 +192,21 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou - - - - - + + + + + - - - - - + + + + + @@ -361,24 +361,24 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou - - - - - - + + + + + + - - - - - - + + + + + + diff --git a/cocos/2d/cocos2d.vcxproj.filters b/cocos/2d/cocos2d.vcxproj.filters index 493e1dc747..9055db96e4 100644 --- a/cocos/2d/cocos2d.vcxproj.filters +++ b/cocos/2d/cocos2d.vcxproj.filters @@ -129,36 +129,6 @@ physics - - physics\chipmunk - - - physics\chipmunk - - - physics\chipmunk - - - physics\chipmunk - - - physics\chipmunk - - - physics\Box2D - - - physics\Box2D - - - physics\Box2D - - - physics\Box2D - - - physics\Box2D - base_nodes @@ -578,6 +548,36 @@ event_dispatcher + + physics\Box2D + + + physics\Box2D + + + physics\Box2D + + + physics\Box2D + + + physics\Box2D + + + physics\chipmunk + + + physics\chipmunk + + + physics\chipmunk + + + physics\chipmunk + + + physics\chipmunk + @@ -598,42 +598,6 @@ physics - - physics\chipmunk - - - physics\chipmunk - - - physics\chipmunk - - - physics\chipmunk - - - physics\chipmunk - - - physics\chipmunk - - - physics\Box2D - - - physics\Box2D - - - physics\Box2D - - - physics\Box2D - - - physics\Box2D - - - physics\Box2D - base_nodes @@ -1164,5 +1128,41 @@ event_dispatcher + + physics\Box2D + + + physics\Box2D + + + physics\Box2D + + + physics\Box2D + + + physics\Box2D + + + physics\Box2D + + + physics\chipmunk + + + physics\chipmunk + + + physics\chipmunk + + + physics\chipmunk + + + physics\chipmunk + + + physics\chipmunk + - \ No newline at end of file + diff --git a/cocos/base/CCObject.h b/cocos/base/CCObject.h index 3c3e6c5321..dc1a6adfd2 100644 --- a/cocos/base/CCObject.h +++ b/cocos/base/CCObject.h @@ -207,6 +207,7 @@ typedef int (Object::*SEL_Compare)(Object*); #define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__) #define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__) #define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__) +#define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3 ##__VA_ARGS__) // end of base_nodes group /// @} diff --git a/cocos/physics/CCPhysicsBody.cpp b/cocos/physics/CCPhysicsBody.cpp index f1eb18e754..1922ee59d4 100644 --- a/cocos/physics/CCPhysicsBody.cpp +++ b/cocos/physics/CCPhysicsBody.cpp @@ -37,17 +37,16 @@ #include "CCPhysicsJoint.h" #include "CCPhysicsWorld.h" -#include "chipmunk/CCPhysicsBodyInfo.h" -#include "box2d/CCPhysicsBodyInfo.h" -#include "chipmunk/CCPhysicsJointInfo.h" -#include "box2d/CCPhysicsJointInfo.h" -#include "chipmunk/CCPhysicsWorldInfo.h" -#include "box2d/CCPhysicsWorldInfo.h" -#include "chipmunk/CCPhysicsShapeInfo.h" -#include "box2d/CCPhysicsShapeInfo.h" - -#include "chipmunk/CCPhysicsHelper.h" -#include "box2d/CCPhysicsHelper.h" +#include "chipmunk/CCPhysicsBodyInfo_chipmunk.h" +#include "box2d/CCPhysicsBodyInfo_box2d.h" +#include "chipmunk/CCPhysicsJointInfo_chipmunk.h" +#include "box2d/CCPhysicsJointInfo_box2d.h" +#include "chipmunk/CCPhysicsWorldInfo_chipmunk.h" +#include "box2d/CCPhysicsWorldInfo_box2d.h" +#include "chipmunk/CCPhysicsShapeInfo_chipmunk.h" +#include "box2d/CCPhysicsShapeInfo_box2d.h" +#include "chipmunk/CCPhysicsHelper_chipmunk.h" +#include "box2d/CCPhysicsHelper_box2d.h" NS_CC_BEGIN @@ -58,11 +57,11 @@ namespace { static const float MASS_DEFAULT = 1.0; static const float MOMENT_DEFAULT = 200; - static float GROUP_INDEX = 0; } PhysicsBody::PhysicsBody() -: _owner(nullptr) +: _node(nullptr) +, _shapes(nullptr) , _world(nullptr) , _info(nullptr) , _dynamic(true) @@ -81,23 +80,29 @@ PhysicsBody::PhysicsBody() , _categoryBitmask(UINT_MAX) , _collisionBitmask(UINT_MAX) , _contactTestBitmask(0) +, _group(0) { } PhysicsBody::~PhysicsBody() { - CC_SAFE_DELETE(_info); + if (_world) + { + removeFromWorld(); + } removeAllShapes(); for (auto it = _joints.begin(); it != _joints.end(); ++it) { PhysicsJoint* joint = *it; - PhysicsBody* other = joint->getBodyA() == this ? joint->getBodyA() : joint->getBodyB(); + PhysicsBody* other = joint->getBodyA() == this ? joint->getBodyB() : joint->getBodyA(); other->_joints.erase(std::find(other->_joints.begin(), other->_joints.end(), joint)); + delete joint; } + CC_SAFE_DELETE(_info); } PhysicsBody* PhysicsBody::create() @@ -113,6 +118,45 @@ PhysicsBody* PhysicsBody::create() return nullptr; } +PhysicsBody* PhysicsBody::create(float mass) +{ + PhysicsBody* body = new PhysicsBody(); + if (body) + { + body->_mass = mass; + body->_massDefault = false; + if (body->init()) + { + body->autorelease(); + return body; + } + } + + CC_SAFE_DELETE(body); + return nullptr; +} + +PhysicsBody* PhysicsBody::create(float mass, float moment) +{ + PhysicsBody* body = new PhysicsBody(); + if (body) + { + body->_mass = mass; + body->_massDefault = false; + body->_moment = moment; + body->_momentDefault = false; + if (body->init()) + { + body->autorelease(); + return body; + } + } + + CC_SAFE_DELETE(body); + return nullptr; + +} + PhysicsBody* PhysicsBody::createCircle(float radius, PhysicsMaterial material) { PhysicsBody* body = new PhysicsBody(); @@ -224,9 +268,11 @@ bool PhysicsBody::init() { _info = new PhysicsBodyInfo(); CC_BREAK_IF(_info == nullptr); + _shapes = Array::create(); + CC_BREAK_IF(_shapes == nullptr); + _shapes->retain(); _info->body = cpBodyNew(PhysicsHelper::float2cpfloat(_mass), PhysicsHelper::float2cpfloat(_moment)); - _info->group = ++GROUP_INDEX; CC_BREAK_IF(_info->body == nullptr); @@ -274,10 +320,10 @@ void PhysicsBody::setGravityEnable(bool enable) { if (enable) { - applyForce(_world->getGravity()); + applyForce(_world->getGravity() * _mass); }else { - applyForce(-_world->getGravity()); + applyForce(-_world->getGravity() * _mass); } } } @@ -304,15 +350,14 @@ float PhysicsBody::getRotation() const return -PhysicsHelper::cpfloat2float(cpBodyGetAngle(_info->body) / 3.14f * 180.0f); } -void PhysicsBody::addShape(PhysicsShape* shape) +PhysicsShape* PhysicsBody::addShape(PhysicsShape* shape) { - if (shape == nullptr) return; + if (shape == nullptr) return nullptr; // add shape to body - if (std::find(_shapes.begin(), _shapes.end(), shape) == _shapes.end()) + if (_shapes->getIndexOfObject(shape) == UINT_MAX) { shape->setBody(this); - _shapes.push_back(shape); // calculate the area, mass, and desity // area must update before mass, because the density changes depend on it. @@ -325,8 +370,15 @@ void PhysicsBody::addShape(PhysicsShape* shape) _world->addShape(shape); } - shape->retain(); + _shapes->addObject(shape); + + if (_group != CP_NO_GROUP && shape->getGroup() == CP_NO_GROUP) + { + shape->setGroup(_group); + } } + + return shape; } void PhysicsBody::applyForce(Point force) @@ -518,10 +570,11 @@ void PhysicsBody::setMoment(float moment) } } -PhysicsShape* PhysicsBody::getShapeByTag(int tag) +PhysicsShape* PhysicsBody::getShapeByTag(int tag) const { - for (auto shape : _shapes) + for (auto child : *_shapes) { + PhysicsShape* shape = dynamic_cast(child); if (shape->getTag() == tag) { return shape; @@ -533,8 +586,9 @@ PhysicsShape* PhysicsBody::getShapeByTag(int tag) void PhysicsBody::removeShapeByTag(int tag) { - for (auto shape : _shapes) + for (auto child : *_shapes) { + PhysicsShape* shape = dynamic_cast(child); if (shape->getTag() == tag) { removeShape(shape); @@ -545,9 +599,7 @@ void PhysicsBody::removeShapeByTag(int tag) void PhysicsBody::removeShape(PhysicsShape* shape) { - auto it = std::find(_shapes.begin(), _shapes.end(), shape); - - if (it != _shapes.end()) + if (_shapes->getIndexOfObject(shape) == UINT_MAX) { // deduce the area, mass and moment // area must update before mass, because the density changes depend on it. @@ -560,25 +612,39 @@ void PhysicsBody::removeShape(PhysicsShape* shape) { _world->removeShape(shape); } - _shapes.erase(it); shape->setBody(nullptr); - shape->release(); + _shapes->removeObject(shape); } } void PhysicsBody::removeAllShapes() { - for (auto shape : _shapes) + for (auto child : *_shapes) { + PhysicsShape* shape = dynamic_cast(child); + + // deduce the area, mass and moment + // area must update before mass, because the density changes depend on it. + _area -= shape->getArea(); + addMass(-shape->getMass()); + addMoment(-shape->getMoment()); + if (_world) { _world->removeShape(shape); } - - delete shape; + shape->setBody(nullptr); } - _shapes.clear(); + _shapes->removeAllObjects(); +} + +void PhysicsBody::removeFromWorld() +{ + if (_world) + { + _world->removeBody(this); + } } void PhysicsBody::setEnable(bool enable) @@ -600,7 +666,7 @@ void PhysicsBody::setEnable(bool enable) } } -bool PhysicsBody::isResting() +bool PhysicsBody::isResting() const { return cpBodyIsSleeping(_info->body) == cpTrue; } @@ -616,14 +682,53 @@ void PhysicsBody::update(float delta) } } -//Clonable* PhysicsBody::clone() const -//{ -// PhysicsBody* body = new PhysicsBody(); -// -// body->autorelease(); -// -// return body; -//} +void PhysicsBody::setCategoryBitmask(int bitmask) +{ + _categoryBitmask = bitmask; + + for (auto shape : *_shapes) + { + ((PhysicsShape*)shape)->setCategoryBitmask(bitmask); + } +} + +void PhysicsBody::setContactTestBitmask(int bitmask) +{ + _contactTestBitmask = bitmask; + + for (auto shape : *_shapes) + { + ((PhysicsShape*)shape)->setContactTestBitmask(bitmask); + } +} + +void PhysicsBody::setCollisionBitmask(int bitmask) +{ + _collisionBitmask = bitmask; + + for (auto shape : *_shapes) + { + ((PhysicsShape*)shape)->setCollisionBitmask(bitmask); + } +} + +void PhysicsBody::setGroup(int group) +{ + for (auto shape : *_shapes) + { + ((PhysicsShape*)shape)->setGroup(group); + } +} + +Point PhysicsBody::world2Local(const Point& point) +{ + return PhysicsHelper::cpv2point(cpBodyWorld2Local(_info->body, PhysicsHelper::point2cpv(point))); +} + +Point PhysicsBody::local2World(const Point& point) +{ + return PhysicsHelper::cpv2point(cpBodyLocal2World(_info->body, PhysicsHelper::point2cpv(point))); +} #elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) diff --git a/cocos/physics/CCPhysicsBody.h b/cocos/physics/CCPhysicsBody.h index f1715b0f1a..a4bad406b8 100644 --- a/cocos/physics/CCPhysicsBody.h +++ b/cocos/physics/CCPhysicsBody.h @@ -30,6 +30,7 @@ #include "CCObject.h" #include "CCGeometry.h" +#include "CCArray.h" #include "CCPhysicsShape.h" @@ -43,7 +44,7 @@ class PhysicsJoint; class PhysicsBodyInfo; -const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT(1.0f, 1.0f, 1.0f); +const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT(0.1f, 0.5f, 0.5f); /** * A body affect by physics. @@ -53,6 +54,8 @@ class PhysicsBody : public Object//, public Clonable { public: static PhysicsBody* create(); + static PhysicsBody* create(float mass); + static PhysicsBody* create(float mass, float moment); /** * @brief Create a body contains a circle shape. */ @@ -84,7 +87,7 @@ public: */ static PhysicsBody* createEdgeChain(Point* points, int count, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT, float border = 1); - virtual void addShape(PhysicsShape* shape); + virtual PhysicsShape* addShape(PhysicsShape* shape); /** * @brief Applies a immediate force to body. @@ -119,12 +122,12 @@ public: /* * @brief get the body shapes. */ - inline std::vector& getShapes() { return _shapes; } + inline Array* getShapes() const { return _shapes; } /* * @brief get the first body shapes. */ - inline PhysicsShape* getShape() { return _shapes.size() >= 1 ? _shapes.front() : nullptr; } - PhysicsShape* getShapeByTag(int tag); + inline PhysicsShape* getShape() const { return _shapes->count() >= 1 ? dynamic_cast(_shapes->getObjectAtIndex(0)) : nullptr; } + PhysicsShape* getShapeByTag(int tag) const; /* * @brief remove a shape from body */ @@ -135,6 +138,8 @@ public: */ void removeAllShapes(); + void removeFromWorld(); + /* * @brief get the world body added to. */ @@ -142,20 +147,23 @@ public: /* * @brief get all joints the body have */ - inline const std::vector* getJoints() const { return &_joints; } + inline const std::vector& getJoints() const { return _joints; } /* * @brief get the sprite the body set to. */ - inline Sprite* getOwner() const { return _owner; } + inline Node* getNode() const { return _node; } - inline void setCategoryBitmask(int bitmask) { _categoryBitmask = bitmask; } + void setCategoryBitmask(int bitmask); + void setContactTestBitmask(int bitmask); + void setCollisionBitmask(int bitmask); inline int getCategoryBitmask() const { return _categoryBitmask; } - inline void setContactTestBitmask(int bitmask) { _contactTestBitmask = bitmask; } inline int getContactTestBitmask() const { return _contactTestBitmask; } - inline void setCollisionBitmask(int bitmask) { _collisionBitmask = bitmask; } inline int getCollisionBitmask() const { return _collisionBitmask; } + void setGroup(int group); + inline int getGroup() const { return _group; } + /* * @brief get the body position. */ @@ -169,7 +177,7 @@ public: * @brief test the body is dynamic or not. * a dynamic body will effect with gravity. */ - inline bool isDynamic() { return _dynamic; } + inline bool isDynamic() const { return _dynamic; } /* * @brief set dynamic to body. * a dynamic body will effect with gravity. @@ -184,7 +192,7 @@ public: /* * @brief get the body mass. */ - inline float getMass() { return _mass; } + inline float getMass() const { return _mass; } /* * @brief add mass to body. * if _mass(mass of the body) == PHYSICS_INFINITY, it remains. @@ -203,7 +211,7 @@ public: /* * @brief get the body moment of inertia. */ - inline float getMoment(float moment) { return _moment; } + inline float getMoment(float moment) const { return _moment; } /* * @brief add moment of inertia to body. * if _moment(moment of the body) == PHYSICS_INFINITY, it remains. @@ -220,27 +228,29 @@ public: /* * @brief get angular damping. */ - inline float getLinearDamping() { return _linearDamping; } + inline float getLinearDamping() const { return _linearDamping; } inline void setLinearDamping(float damping) { _linearDamping = damping; } - inline float getAngularDamping() { return _angularDamping; } + inline float getAngularDamping() const { return _angularDamping; } inline void setAngularDamping(float damping) { _angularDamping = damping; } //virtual Clonable* clone() const override; - bool isResting(); - inline bool isEnable() { return _enable; } + bool isResting() const; + inline bool isEnable() const { return _enable; } void setEnable(bool enable); - inline bool isRotationEnable() { return _rotationEnable; } + inline bool isRotationEnable() const { return _rotationEnable; } void setRotationEnable(bool enable); - inline bool isGravityEnable() { return _gravityEnable; } + inline bool isGravityEnable() const { return _gravityEnable; } void setGravityEnable(bool enable); - inline int getTag() { return _tag; } + inline int getTag() const { return _tag; } inline void setTag(int tag) { _tag = tag; } + Point world2Local(const Point& point); + Point local2World(const Point& point); protected: @@ -256,9 +266,9 @@ protected: virtual ~PhysicsBody(); protected: - Sprite* _owner; + Node* _node; std::vector _joints; - std::vector _shapes; + Array* _shapes; PhysicsWorld* _world; PhysicsBodyInfo* _info; bool _dynamic; @@ -275,9 +285,10 @@ protected: float _angularDamping; int _tag; - int _categoryBitmask; - int _collisionBitmask; - int _contactTestBitmask; + int _categoryBitmask; + int _collisionBitmask; + int _contactTestBitmask; + int _group; friend class PhysicsWorld; friend class PhysicsShape; diff --git a/cocos/physics/CCPhysicsContact.cpp b/cocos/physics/CCPhysicsContact.cpp index 1ec9667d6f..1d0cfd8bdd 100644 --- a/cocos/physics/CCPhysicsContact.cpp +++ b/cocos/physics/CCPhysicsContact.cpp @@ -30,16 +30,32 @@ #include "Box2D.h" #endif -#include "chipmunk/CCPhysicsContactInfo.h" -#include "box2d/CCPhysicsContactInfo.h" +#include "CCPhysicsBody.h" + +#include "chipmunk/CCPhysicsContactInfo_chipmunk.h" +#include "box2d/CCPhysicsContactInfo_box2d.h" +#include "chipmunk/CCPhysicsHelper_chipmunk.h" +#include "box2d/CCPhysicsHelper_box2d.h" + +#include "CCEventCustom.h" NS_CC_BEGIN +const char* PHYSICSCONTACT_EVENT_NAME = "PhysicsContactEvent"; + PhysicsContact::PhysicsContact() -: _shapeA(nullptr) +: Event(Event::Type::CUSTOM) +, _world(nullptr) +, _shapeA(nullptr) , _shapeB(nullptr) +, _eventCode(EventCode::NONE) , _info(nullptr) +, _notify(true) +, _begin(false) , _data(nullptr) +, _contactInfo(nullptr) +, _contactData(nullptr) +, _result(true) { } @@ -47,6 +63,7 @@ PhysicsContact::PhysicsContact() PhysicsContact::~PhysicsContact() { CC_SAFE_DELETE(_info); + CC_SAFE_DELETE(_contactData); } PhysicsContact* PhysicsContact::create(PhysicsShape* a, PhysicsShape* b) @@ -78,37 +95,69 @@ bool PhysicsContact::init(PhysicsShape* a, PhysicsShape* b) return false; } -// PhysicsContactPreSolve implementation -PhysicsContactPreSolve::PhysicsContactPreSolve() +void PhysicsContact::generateContactData() { + if (_contactInfo == nullptr) + { + return; + } + cpArbiter* arb = static_cast(_contactInfo); + _contactData = new PhysicsContactData(); + _contactData->count = cpArbiterGetCount(arb); + for (int i=0; i<_contactData->count; ++i) + { + _contactData->points[i] = PhysicsHelper::cpv2point(cpArbiterGetPoint(arb, i)); + } + + _contactData->normal = _contactData->count > 0 ? PhysicsHelper::cpv2point(cpArbiterGetNormal(arb, 0)) : Point::ZERO; +} + +// PhysicsContactPreSolve implementation +PhysicsContactPreSolve::PhysicsContactPreSolve(PhysicsContactData* data, void* contactInfo) +: _preContactData(data) +, _contactInfo(contactInfo) +{ +} + +float PhysicsContactPreSolve::getElasticity() const +{ + return static_cast(_contactInfo)->e; +} + +float PhysicsContactPreSolve::getFriciton() const +{ + return static_cast(_contactInfo)->u; +} + +Point PhysicsContactPreSolve::getSurfaceVelocity() const +{ + return PhysicsHelper::cpv2point(static_cast(_contactInfo)->surface_vr); +} + +void PhysicsContactPreSolve::setElasticity(float elasticity) +{ + static_cast(_contactInfo)->e = elasticity; +} + +void PhysicsContactPreSolve::setFriction(float friction) +{ + static_cast(_contactInfo)->u = friction; +} + +void PhysicsContactPreSolve::setSurfaceVelocity(Point surfaceVelocity) +{ + static_cast(_contactInfo)->surface_vr = PhysicsHelper::point2cpv(surfaceVelocity); } PhysicsContactPreSolve::~PhysicsContactPreSolve() { - + CC_SAFE_DELETE(_preContactData); } -PhysicsContactPreSolve* PhysicsContactPreSolve::create() -{ - PhysicsContactPreSolve * solve = new PhysicsContactPreSolve(); - if(solve && solve->init()) - { - return solve; - } - - CC_SAFE_DELETE(solve); - return nullptr; -} - -bool PhysicsContactPreSolve::init() -{ - return true; -} - - // PhysicsContactPostSolve implementation -PhysicsContactPostSolve::PhysicsContactPostSolve() +PhysicsContactPostSolve::PhysicsContactPostSolve(void* contactInfo) +: _contactInfo(contactInfo) { } @@ -118,36 +167,331 @@ PhysicsContactPostSolve::~PhysicsContactPostSolve() } -PhysicsContactPostSolve* PhysicsContactPostSolve::create() +float PhysicsContactPostSolve::getElasticity() const { - PhysicsContactPostSolve * solve = new PhysicsContactPostSolve(); - if(solve && solve->init()) - { - return solve; - } - - CC_SAFE_DELETE(solve); - return nullptr; + return static_cast(_contactInfo)->e; } -bool PhysicsContactPostSolve::init() +float PhysicsContactPostSolve::getFriciton() const { - return true; + return static_cast(_contactInfo)->u; } -PhysicsContactListener::PhysicsContactListener() +Point PhysicsContactPostSolve::getSurfaceVelocity() const +{ + return PhysicsHelper::cpv2point(static_cast(_contactInfo)->surface_vr); +} + +EventListenerPhysicsContact::EventListenerPhysicsContact() : onContactBegin(nullptr) , onContactPreSolve(nullptr) , onContactPostSolve(nullptr) -, onContactEnd(nullptr) +, onContactSeperate(nullptr) +{ +} + +bool EventListenerPhysicsContact::init() +{ + auto func = [this](EventCustom* event) -> void + { + return onEvent(event); + }; + + return EventListenerCustom::init(std::hash()(PHYSICSCONTACT_EVENT_NAME), func); +} + +void EventListenerPhysicsContact::onEvent(EventCustom* event) +{ + PhysicsContact& contact = *(PhysicsContact*)(event->getUserData()); + + switch (contact.getEventCode()) + { + case PhysicsContact::EventCode::BEGIN: + { + bool ret = true; + + if (onContactBegin != nullptr + && contact.getNotify() + && test(contact.getShapeA(), contact.getShapeB())) + { + contact._begin = true; + contact.generateContactData(); + + // the mask has high priority than _listener->onContactBegin. + // so if the mask test is false, the two bodies won't have collision. + if (ret) + { + ret = onContactBegin(event, contact); + }else + { + onContactBegin(event, contact); + } + } + + contact.setResult(ret); + break; + } + case PhysicsContact::EventCode::PRESOLVE: + { + bool ret = true; + + if (onContactPreSolve != nullptr + && test(contact.getShapeA(), contact.getShapeB())) + { + PhysicsContactPreSolve solve(contact._begin ? nullptr : contact._contactData, contact._contactInfo); + contact._begin = false; + contact.generateContactData(); + + ret = onContactPreSolve(event, contact, solve); + } + + contact.setResult(ret); + break; + } + case PhysicsContact::EventCode::POSTSOLVE: + { + if (onContactPreSolve != nullptr + && test(contact.getShapeA(), contact.getShapeB())) + { + PhysicsContactPostSolve solve(contact._contactInfo); + onContactPostSolve(event, contact, solve); + } + break; + } + case PhysicsContact::EventCode::SEPERATE: + { + if (onContactSeperate != nullptr + && test(contact.getShapeA(), contact.getShapeB())) + { + onContactSeperate(event, contact); + } + break; + } + default: + break; + } +} + +EventListenerPhysicsContact::~EventListenerPhysicsContact() { } -PhysicsContactListener::~PhysicsContactListener() +EventListenerPhysicsContact* EventListenerPhysicsContact::create() +{ + EventListenerPhysicsContact* obj = new EventListenerPhysicsContact(); + + if (obj != nullptr && obj->init()) + { + obj->autorelease(); + return obj; + } + + CC_SAFE_DELETE(obj); + return nullptr; +} + +bool EventListenerPhysicsContact::test(PhysicsShape* shapeA, PhysicsShape* shapeB) +{ + CC_UNUSED_PARAM(shapeA); + CC_UNUSED_PARAM(shapeB); + return true; +} + +bool EventListenerPhysicsContact::checkAvailable() +{ + if (onContactBegin == nullptr && onContactPreSolve == nullptr + && onContactPostSolve == nullptr && onContactSeperate == nullptr) + { + CCASSERT(false, "Invalid PhysicsContactListener."); + return false; + } + + return true; +} + +EventListenerPhysicsContact* EventListenerPhysicsContact::clone() +{ + EventListenerPhysicsContact* obj = EventListenerPhysicsContact::create(); + + if (obj != nullptr) + { + obj->onContactBegin = onContactBegin; + obj->onContactPreSolve = onContactPreSolve; + obj->onContactPostSolve = onContactPostSolve; + obj->onContactSeperate = onContactSeperate; + + return obj; + } + + CC_SAFE_DELETE(obj); + return nullptr; +} + +EventListenerPhysicsContactWithBodies* EventListenerPhysicsContactWithBodies::create(PhysicsBody* bodyA, PhysicsBody* bodyB) +{ + EventListenerPhysicsContactWithBodies* obj = new EventListenerPhysicsContactWithBodies(); + + if (obj != nullptr && obj->init()) + { + obj->_a = bodyA; + obj->_b = bodyB; + obj->autorelease(); + return obj; + } + + CC_SAFE_DELETE(obj); + return nullptr; +} + +EventListenerPhysicsContactWithBodies::EventListenerPhysicsContactWithBodies() +: _a(nullptr) +, _b(nullptr) { } +EventListenerPhysicsContactWithBodies::~EventListenerPhysicsContactWithBodies() +{ + +} + + +bool EventListenerPhysicsContactWithBodies::test(PhysicsShape* shapeA, PhysicsShape* shapeB) +{ + if ((shapeA->getBody() == _a && shapeB->getBody() == _b) + || (shapeA->getBody() == _b && shapeB->getBody() == _a)) + { + return true; + } + + return false; +} + +EventListenerPhysicsContactWithBodies* EventListenerPhysicsContactWithBodies::clone() +{ + EventListenerPhysicsContactWithBodies* obj = EventListenerPhysicsContactWithBodies::create(_a, _b); + + if (obj != nullptr) + { + obj->onContactBegin = onContactBegin; + obj->onContactPreSolve = onContactPreSolve; + obj->onContactPostSolve = onContactPostSolve; + obj->onContactSeperate = onContactSeperate; + + return obj; + } + + CC_SAFE_DELETE(obj); + return nullptr; +} + +EventListenerPhysicsContactWithShapes::EventListenerPhysicsContactWithShapes() +: _a(nullptr) +, _b(nullptr) +{ +} + +EventListenerPhysicsContactWithShapes::~EventListenerPhysicsContactWithShapes() +{ +} + +EventListenerPhysicsContactWithShapes* EventListenerPhysicsContactWithShapes::create(PhysicsShape* shapeA, PhysicsShape* shapeB) +{ + EventListenerPhysicsContactWithShapes* obj = new EventListenerPhysicsContactWithShapes(); + + if (obj != nullptr && obj->init()) + { + obj->_a = shapeA; + obj->_b = shapeB; + obj->autorelease(); + return obj; + } + + CC_SAFE_DELETE(obj); + return nullptr; +} + +bool EventListenerPhysicsContactWithShapes::test(PhysicsShape* shapeA, PhysicsShape* shapeB) +{ + if ((shapeA == _a && shapeB == _b) + || (shapeA == _b && shapeB == _a)) + { + return true; + } + + return false; +} + +EventListenerPhysicsContactWithShapes* EventListenerPhysicsContactWithShapes::clone() +{ + EventListenerPhysicsContactWithShapes* obj = EventListenerPhysicsContactWithShapes::create(_a, _b); + + if (obj != nullptr) + { + obj->onContactBegin = onContactBegin; + obj->onContactPreSolve = onContactPreSolve; + obj->onContactPostSolve = onContactPostSolve; + obj->onContactSeperate = onContactSeperate; + + return obj; + } + + CC_SAFE_DELETE(obj); + return nullptr; +} + +EventListenerPhysicsContactWithGroup::EventListenerPhysicsContactWithGroup() +: _group(CP_NO_GROUP) +{ +} + +EventListenerPhysicsContactWithGroup::~EventListenerPhysicsContactWithGroup() +{ +} + +EventListenerPhysicsContactWithGroup* EventListenerPhysicsContactWithGroup::create(int group) +{ + EventListenerPhysicsContactWithGroup* obj = new EventListenerPhysicsContactWithGroup(); + + if (obj != nullptr && obj->init()) + { + obj->_group = group; + obj->autorelease(); + return obj; + } + + CC_SAFE_DELETE(obj); + return nullptr; +} + +bool EventListenerPhysicsContactWithGroup::test(PhysicsShape* shapeA, PhysicsShape* shapeB) +{ + if (shapeA->getGroup() == _group || shapeB->getGroup() == _group) + { + return true; + } + + return false; +} + +EventListenerPhysicsContactWithGroup* EventListenerPhysicsContactWithGroup::clone() +{ + EventListenerPhysicsContactWithGroup* obj = EventListenerPhysicsContactWithGroup::create(_group); + + if (obj != nullptr) + { + obj->onContactBegin = onContactBegin; + obj->onContactPreSolve = onContactPreSolve; + obj->onContactPostSolve = onContactPostSolve; + obj->onContactSeperate = onContactSeperate; + + return obj; + } + + CC_SAFE_DELETE(obj); + return nullptr; +} + NS_CC_END #endif // CC_USE_PHYSICS diff --git a/cocos/physics/CCPhysicsContact.h b/cocos/physics/CCPhysicsContact.h index 9b9e3044c0..32127da7a5 100644 --- a/cocos/physics/CCPhysicsContact.h +++ b/cocos/physics/CCPhysicsContact.h @@ -30,20 +30,45 @@ #include "CCObject.h" #include "CCGeometry.h" +#include "CCEventListenerCustom.h" +#include "CCEvent.h" NS_CC_BEGIN class PhysicsShape; +class PhysicsBody; class PhysicsWorld; class PhysicsContactInfo; + +typedef struct PhysicsContactData +{ + Point points[PHYSICS_CONTACT_POINT_MAX]; + int count; + Point normal; + + PhysicsContactData() + : count(0) + {} +}PhysicsContactData; + /** * @brief Contact infomation. it will created automatically when two shape contact with each other. and it will destoried automatically when two shape separated. */ -class PhysicsContact +class PhysicsContact : Event { public: + + enum class EventCode + { + NONE, + BEGIN, + PRESOLVE, + POSTSOLVE, + SEPERATE + }; + /* * @brief get contact shape A. */ @@ -52,35 +77,53 @@ public: * @brief get contact shape B. */ inline PhysicsShape* getShapeB() const { return _shapeB; } + inline const PhysicsContactData* getContactData() const { return _contactData; } /* * @brief get data. */ - inline void* getData() { return _data; } + inline void* getData() const { return _data; } /* * @brief set data to contact. you must manage the memory yourself, Generally you can set data at contact begin, and distory it at contact end. */ inline void setData(void* data) { _data = data; } + EventCode getEventCode() const { return _eventCode; }; + private: static PhysicsContact* create(PhysicsShape* a, PhysicsShape* b); bool init(PhysicsShape* a, PhysicsShape* b); - inline bool getNotify() { return _notify; } + void setEventCode(EventCode eventCode) { _eventCode = eventCode; }; + inline bool getNotify() const { return _notify; } inline void setNotify(bool notify) { _notify = notify; } + inline PhysicsWorld* getWorld() const { return _world; } + inline void setWorld(PhysicsWorld* world) { _world = world; } + inline void setResult(bool result) { _result = result; } + inline bool resetResult() { bool ret = _result; _result = true; return ret; } + + void generateContactData(); private: PhysicsContact(); ~PhysicsContact(); private: + PhysicsWorld* _world; PhysicsShape* _shapeA; PhysicsShape* _shapeB; + EventCode _eventCode; PhysicsContactInfo* _info; - void* _data; bool _notify; + bool _begin; + bool _result; - friend class PhysicsWorld; + void* _data; + void* _contactInfo; + PhysicsContactData* _contactData; + + friend class EventListenerPhysicsContact; friend class PhysicsWorldCallback; + friend class PhysicsWorld; }; /* @@ -88,14 +131,27 @@ private: */ class PhysicsContactPreSolve { +public: + // getter/setter + float getElasticity() const; + float getFriciton() const; + Point getSurfaceVelocity() const; + void setElasticity(float elasticity); + void setFriction(float friction); + void setSurfaceVelocity(Point surfaceVelocity); + private: - PhysicsContactPreSolve(); + PhysicsContactPreSolve(PhysicsContactData* data, void* contactInfo); ~PhysicsContactPreSolve(); - static PhysicsContactPreSolve* create(); - bool init(); +private: + float _elasticity; + float _friction; + Point _surfaceVelocity; + PhysicsContactData* _preContactData; + void* _contactInfo; - friend class PhysicsWorldCallback; + friend class EventListenerPhysicsContact; }; /* @@ -103,43 +159,110 @@ private: */ class PhysicsContactPostSolve { +public: + // getter + float getElasticity() const; + float getFriciton() const; + Point getSurfaceVelocity() const; + private: - PhysicsContactPostSolve(); + PhysicsContactPostSolve(void* contactInfo); ~PhysicsContactPostSolve(); - static PhysicsContactPostSolve* create(); - bool init(); +private: + void* _contactInfo; - friend class PhysicsWorldCallback; + friend class EventListenerPhysicsContact; }; /* * @brief contact listener. */ -class PhysicsContactListener +class EventListenerPhysicsContact : public EventListenerCustom { public: - PhysicsContactListener(); - virtual ~PhysicsContactListener(); + static EventListenerPhysicsContact* create(); + + virtual bool test(PhysicsShape* shapeA, PhysicsShape* shapeB); + virtual bool checkAvailable() override; + virtual EventListenerPhysicsContact* clone() override; public: /* * @brief it will called at two shapes start to contact, and only call it once. */ - std::function onContactBegin; + std::function onContactBegin; /* * @brief Two shapes are touching during this step. Return false from the callback to make world ignore the collision this step or true to process it normally. Additionally, you may override collision values, elasticity, or surface velocity values. */ - std::function onContactPreSolve; + std::function onContactPreSolve; /* * @brief Two shapes are touching and their collision response has been processed. You can retrieve the collision impulse or kinetic energy at this time if you want to use it to calculate sound volumes or damage amounts. See cpArbiter for more info */ - std::function onContactPostSolve; + std::function onContactPostSolve; /* * @brief it will called at two shapes separated, and only call it once. - * onContactBegin and onContactEnd will called in pairs. + * onContactBegin and onContactSeperate will called in pairs. */ - std::function onContactEnd; + std::function onContactSeperate; + +protected: + bool init(); + void onEvent(EventCustom* event); + +protected: + EventListenerPhysicsContact(); + virtual ~EventListenerPhysicsContact(); +}; + +class EventListenerPhysicsContactWithBodies : public EventListenerPhysicsContact +{ +public: + static EventListenerPhysicsContactWithBodies* create(PhysicsBody* bodyA, PhysicsBody* bodyB); + + virtual bool test(PhysicsShape* shapeA, PhysicsShape* shapeB) override; + virtual EventListenerPhysicsContactWithBodies* clone() override; + +protected: + PhysicsBody* _a; + PhysicsBody* _b; + +protected: + EventListenerPhysicsContactWithBodies(); + virtual ~EventListenerPhysicsContactWithBodies(); +}; + +class EventListenerPhysicsContactWithShapes : public EventListenerPhysicsContact +{ +public: + static EventListenerPhysicsContactWithShapes* create(PhysicsShape* shapeA, PhysicsShape* shapeB); + + virtual bool test(PhysicsShape* shapeA, PhysicsShape* shapeB) override; + virtual EventListenerPhysicsContactWithShapes* clone() override; + +protected: + PhysicsShape* _a; + PhysicsShape* _b; + +protected: + EventListenerPhysicsContactWithShapes(); + virtual ~EventListenerPhysicsContactWithShapes(); +}; + +class EventListenerPhysicsContactWithGroup : public EventListenerPhysicsContact +{ +public: + static EventListenerPhysicsContactWithGroup* create(int group); + + virtual bool test(PhysicsShape* shapeA, PhysicsShape* shapeB) override; + virtual EventListenerPhysicsContactWithGroup* clone() override; + +protected: + int _group; + +protected: + EventListenerPhysicsContactWithGroup(); + virtual ~EventListenerPhysicsContactWithGroup(); }; NS_CC_END diff --git a/cocos/physics/CCPhysicsJoint.cpp b/cocos/physics/CCPhysicsJoint.cpp index 6cca90dd5b..694559264e 100644 --- a/cocos/physics/CCPhysicsJoint.cpp +++ b/cocos/physics/CCPhysicsJoint.cpp @@ -33,14 +33,15 @@ #include "CCPhysicsBody.h" -#include "chipmunk/CCPhysicsJointInfo.h" -#include "box2d/CCPhysicsJointInfo.h" -#include "chipmunk/CCPhysicsBodyInfo.h" -#include "box2d/CCPhysicsBodyInfo.h" -#include "chipmunk/CCPhysicsShapeInfo.h" -#include "box2d/CCPhysicsShapeInfo.h" -#include "chipmunk/CCPhysicsHelper.h" -#include "box2d/CCPhysicsHelper.h" +#include "chipmunk/CCPhysicsJointInfo_chipmunk.h" +#include "box2d/CCPhysicsJointInfo_box2d.h" +#include "chipmunk/CCPhysicsBodyInfo_chipmunk.h" +#include "box2d/CCPhysicsBodyInfo_box2d.h" +#include "chipmunk/CCPhysicsShapeInfo_chipmunk.h" +#include "box2d/CCPhysicsShapeInfo_box2d.h" +#include "chipmunk/CCPhysicsHelper_chipmunk.h" +#include "box2d/CCPhysicsHelper_box2d.h" +#include "CCNode.h" NS_CC_BEGIN @@ -61,9 +62,6 @@ PhysicsJoint::~PhysicsJoint() setCollisionEnable(true); CC_SAFE_DELETE(_info); - - CC_SAFE_RELEASE(_bodyA); - CC_SAFE_RELEASE(_bodyB); } bool PhysicsJoint::init(cocos2d::PhysicsBody *a, cocos2d::PhysicsBody *b) @@ -75,14 +73,12 @@ bool PhysicsJoint::init(cocos2d::PhysicsBody *a, cocos2d::PhysicsBody *b) if (a != nullptr) { _bodyA = a; - _bodyA->retain(); _bodyA->_joints.push_back(this); } if (b != nullptr) { _bodyB = b; - _bodyB->retain(); _bodyB->_joints.push_back(this); } @@ -148,23 +144,33 @@ PhysicsJointLimit::~PhysicsJointLimit() } +PhysicsJointDistance::PhysicsJointDistance() +{ + +} + +PhysicsJointDistance::~PhysicsJointDistance() +{ + +} + #if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) -PhysicsBodyInfo* PhysicsJoint::bodyInfo(PhysicsBody* body) const +PhysicsBodyInfo* PhysicsJoint::getBodyInfo(PhysicsBody* body) const { return body->_info; } +Node* PhysicsJoint::getBodyNode(PhysicsBody* body) const +{ + return body->_node; +} + void PhysicsJoint::setCollisionEnable(bool enable) { if (_collisionEnable != enable) { _collisionEnable = enable; - - for (auto shape : _bodyB->_shapes) - { - shape->_info->setGroup(enable ? _bodyB->_info->group : _bodyA->_info->group); - } } } @@ -174,7 +180,6 @@ PhysicsJointFixed* PhysicsJointFixed::create(PhysicsBody* a, PhysicsBody* b, con if (joint && joint->init(a, b, anchr)) { - joint->autorelease(); return joint; } @@ -188,15 +193,18 @@ bool PhysicsJointFixed::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr) { CC_BREAK_IF(!PhysicsJoint::init(a, b)); + getBodyNode(a)->setPosition(anchr); + getBodyNode(b)->setPosition(anchr); + // add a pivot joint to fixed two body together - cpConstraint* joint = cpPivotJointNew(bodyInfo(a)->body, bodyInfo(b)->body, + cpConstraint* joint = cpPivotJointNew(getBodyInfo(a)->body, getBodyInfo(b)->body, PhysicsHelper::point2cpv(anchr)); - CC_BREAK_IF(joint); + CC_BREAK_IF(joint == nullptr); _info->add(joint); // add a gear joint to make two body have the same rotation. - joint = cpGearJointNew(bodyInfo(a)->body, bodyInfo(b)->body, 0, 1); - CC_BREAK_IF(joint); + joint = cpGearJointNew(getBodyInfo(a)->body, getBodyInfo(b)->body, 0, 1); + CC_BREAK_IF(joint == nullptr); _info->add(joint); setCollisionEnable(false); @@ -213,7 +221,6 @@ PhysicsJointPin* PhysicsJointPin::create(PhysicsBody* a, PhysicsBody* b, const P if (joint && joint->init(a, b, anchr)) { - joint->autorelease(); return joint; } @@ -226,22 +233,29 @@ bool PhysicsJointPin::init(PhysicsBody *a, PhysicsBody *b, const Point& anchr) do { CC_BREAK_IF(!PhysicsJoint::init(a, b)); - - cpConstraint* joint = cpPivotJointNew(bodyInfo(a)->body, bodyInfo(b)->body, + cpConstraint* joint = cpPivotJointNew(getBodyInfo(a)->body, getBodyInfo(b)->body, PhysicsHelper::point2cpv(anchr)); - CC_BREAK_IF(joint); + CC_BREAK_IF(joint == nullptr); _info->add(joint); - setCollisionEnable(false); - return true; } while (false); return false; } +void PhysicsJointPin::setMaxForce(float force) +{ + _info->joints.front()->maxForce = PhysicsHelper::float2cpfloat(force); +} + +float PhysicsJointPin::getMaxForce() const +{ + return PhysicsHelper::cpfloat2float(_info->joints.front()->maxForce); +} + PhysicsJointSliding* PhysicsJointSliding::create(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr) { PhysicsJointSliding* joint = new PhysicsJointSliding(); @@ -261,12 +275,12 @@ bool PhysicsJointSliding::init(PhysicsBody* a, PhysicsBody* b, const Point& groo { CC_BREAK_IF(!PhysicsJoint::init(a, b)); - cpConstraint* joint = cpGrooveJointNew(bodyInfo(a)->body, bodyInfo(b)->body, + cpConstraint* joint = cpGrooveJointNew(getBodyInfo(a)->body, getBodyInfo(b)->body, PhysicsHelper::point2cpv(grooveA), PhysicsHelper::point2cpv(grooveB), PhysicsHelper::point2cpv(anchr)); - CC_BREAK_IF(joint); + CC_BREAK_IF(joint == nullptr); _info->add(joint); @@ -296,13 +310,13 @@ bool PhysicsJointLimit::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1 { CC_BREAK_IF(!PhysicsJoint::init(a, b)); - cpConstraint* joint = cpSlideJointNew(bodyInfo(a)->body, bodyInfo(b)->body, + cpConstraint* joint = cpSlideJointNew(getBodyInfo(a)->body, getBodyInfo(b)->body, PhysicsHelper::point2cpv(anchr1), PhysicsHelper::point2cpv(anchr2), 0, PhysicsHelper::float2cpfloat(anchr1.getDistance(anchr2))); - CC_BREAK_IF(joint); + CC_BREAK_IF(joint == nullptr); _info->add(joint); @@ -312,7 +326,7 @@ bool PhysicsJointLimit::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1 return false; } -float PhysicsJointLimit::getMin() +float PhysicsJointLimit::getMin() const { return PhysicsHelper::cpfloat2float(cpSlideJointGetMin(_info->joints.front())); } @@ -322,7 +336,7 @@ void PhysicsJointLimit::setMin(float min) cpSlideJointSetMin(_info->joints.front(), PhysicsHelper::float2cpfloat(min)); } -float PhysicsJointLimit::getMax() +float PhysicsJointLimit::getMax() const { return PhysicsHelper::cpfloat2float(cpSlideJointGetMax(_info->joints.front())); } @@ -332,6 +346,39 @@ void PhysicsJointLimit::setMax(float max) cpSlideJointSetMax(_info->joints.front(), PhysicsHelper::float2cpfloat(max)); } +PhysicsJointDistance* PhysicsJointDistance::create(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2) +{ + PhysicsJointDistance* joint = new PhysicsJointDistance(); + + if (joint && joint->init(a, b, anchr1, anchr2)) + { + return joint; + } + + CC_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointDistance::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2) +{ + do + { + CC_BREAK_IF(!PhysicsJoint::init(a, b)); + + cpConstraint* joint = cpPinJointNew(getBodyInfo(a)->body, + getBodyInfo(b)->body, + PhysicsHelper::point2cpv(anchr1), PhysicsHelper::point2cpv(anchr2)); + + CC_BREAK_IF(joint == nullptr); + + _info->add(joint); + + return true; + } while (false); + + return false; +} + #elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) #endif diff --git a/cocos/physics/CCPhysicsJoint.h b/cocos/physics/CCPhysicsJoint.h index 04f85d0d0c..2970d992d0 100644 --- a/cocos/physics/CCPhysicsJoint.h +++ b/cocos/physics/CCPhysicsJoint.h @@ -40,20 +40,20 @@ class PhysicsBodyInfo; /* * @brief An PhysicsJoint object connects two physics bodies together. */ -class PhysicsJoint : public Object +class PhysicsJoint { protected: PhysicsJoint(); virtual ~PhysicsJoint() = 0; public: - PhysicsBody* getBodyA() { return _bodyA; } - PhysicsBody* getBodyB() { return _bodyB; } - inline int getTag() { return _tag; } + PhysicsBody* getBodyA() const { return _bodyA; } + PhysicsBody* getBodyB() const { return _bodyB; } + inline int getTag() const { return _tag; } inline void setTag(int tag) { _tag = tag; } - inline bool isEnable() { return _enable; } + inline bool isEnable() const { return _enable; } void setEnable(bool enable); - inline bool isCollisionEnable() { return _collisionEnable; } + inline bool isCollisionEnable() const { return _collisionEnable; } void setCollisionEnable(bool enable); protected: @@ -62,7 +62,8 @@ protected: /** * PhysicsShape is PhysicsBody's friend class, but all the subclasses isn't. so this method is use for subclasses to catch the bodyInfo from PhysicsBody. */ - PhysicsBodyInfo* bodyInfo(PhysicsBody* body) const; + PhysicsBodyInfo* getBodyInfo(PhysicsBody* body) const; + Node* getBodyNode(PhysicsBody* body) const; protected: PhysicsBody* _bodyA; @@ -82,7 +83,7 @@ protected: class PhysicsJointFixed : public PhysicsJoint { public: - PhysicsJointFixed* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr); + static PhysicsJointFixed* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr); protected: bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr); @@ -98,7 +99,7 @@ protected: class PhysicsJointSliding : public PhysicsJoint { public: - PhysicsJointSliding* create(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr); + static PhysicsJointSliding* create(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr); protected: bool init(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr); @@ -132,9 +133,9 @@ class PhysicsJointLimit : public PhysicsJoint public: PhysicsJointLimit* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2); - float getMin(); + float getMin() const; void setMin(float min); - float getMax(); + float getMax() const; void setMax(float max); protected: @@ -153,6 +154,9 @@ class PhysicsJointPin : public PhysicsJoint public: static PhysicsJointPin* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr); + void setMaxForce(float force); + float getMaxForce() const; + protected: bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr); @@ -161,6 +165,20 @@ protected: virtual ~PhysicsJointPin(); }; +class PhysicsJointDistance : public PhysicsJoint +{ + +public: + static PhysicsJointDistance* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2); + +protected: + bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2); + +protected: + PhysicsJointDistance(); + virtual ~PhysicsJointDistance(); +}; + NS_CC_END #endif // __CCPHYSICS_JOINT_H__ diff --git a/cocos/physics/CCPhysicsSetting.h b/cocos/physics/CCPhysicsSetting.h index b29b12054d..ee3214bcd7 100644 --- a/cocos/physics/CCPhysicsSetting.h +++ b/cocos/physics/CCPhysicsSetting.h @@ -46,6 +46,11 @@ namespace cocos2d { extern const float PHYSICS_INFINITY; + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + static const int PHYSICS_CONTACT_POINT_MAX = 4; +#else +#endif } #endif // __CCPHYSICS_SETTING_H__ diff --git a/cocos/physics/CCPhysicsShape.cpp b/cocos/physics/CCPhysicsShape.cpp index 6ffd7d86aa..68ef1cf351 100644 --- a/cocos/physics/CCPhysicsShape.cpp +++ b/cocos/physics/CCPhysicsShape.cpp @@ -34,11 +34,11 @@ #include "CCPhysicsBody.h" #include "CCPhysicsWorld.h" -#include "chipmunk/CCPhysicsBodyInfo.h" -#include "box2d/CCPhysicsBodyInfo.h" -#include "chipmunk/CCPhysicsShapeInfo.h" -#include "box2d/CCPhysicsShapeInfo.h" -#include "chipmunk/CCPhysicsHelper.h" +#include "chipmunk/CCPhysicsBodyInfo_chipmunk.h" +#include "box2d/CCPhysicsBodyInfo_box2d.h" +#include "chipmunk/CCPhysicsShapeInfo_chipmunk.h" +#include "box2d/CCPhysicsShapeInfo_box2d.h" +#include "chipmunk/CCPhysicsHelper_chipmunk.h" NS_CC_BEGIN @@ -50,6 +50,10 @@ PhysicsShape::PhysicsShape() , _mass(0) , _moment(0) , _tag(0) +, _categoryBitmask(UINT_MAX) +, _collisionBitmask(UINT_MAX) +, _contactTestBitmask(0) +, _group(0) { } @@ -272,12 +276,12 @@ void PhysicsShape::setBody(PhysicsBody *body) if (body == nullptr) { _info->setBody(nullptr); - _info->setGroup(CP_NO_GROUP); + //_info->setGroup(CP_NO_GROUP); _body = nullptr; }else { _info->setBody(body->_info->body); - _info->setGroup(body->_info->group); + //_info->setGroup(body->_info->group); _body = body; } } @@ -349,7 +353,7 @@ float PhysicsShapeCircle::calculateDefaultMoment() cpCircleShapeGetOffset(shape))); } -float PhysicsShapeCircle::getRadius() +float PhysicsShapeCircle::getRadius() const { return PhysicsHelper::cpfloat2float(cpCircleShapeGetRadius(_info->shapes.front())); } @@ -401,12 +405,12 @@ bool PhysicsShapeEdgeSegment::init(Point a, Point b, PhysicsMaterial material/* return false; } -Point PhysicsShapeEdgeSegment::getPointA() +Point PhysicsShapeEdgeSegment::getPointA() const { return PhysicsHelper::cpv2point(((cpSegmentShape*)(_info->shapes.front()))->ta); } -Point PhysicsShapeEdgeSegment::getPointB() +Point PhysicsShapeEdgeSegment::getPointB() const { return PhysicsHelper::cpv2point(((cpSegmentShape*)(_info->shapes.front()))->tb); } @@ -499,7 +503,7 @@ float PhysicsShapeBox::calculateDefaultMoment() : PhysicsHelper::cpfloat2float(cpMomentForPoly(_mass, ((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts, cpvzero)); } -Point* PhysicsShapeBox::getPoints(Point* points) +Point* PhysicsShapeBox::getPoints(Point* points) const { cpShape* shape = _info->shapes.front(); return PhysicsHelper::cpvs2points(((cpPolyShape*)shape)->verts, points, ((cpPolyShape*)shape)->numVerts); @@ -507,7 +511,7 @@ Point* PhysicsShapeBox::getPoints(Point* points) return points; } -Size PhysicsShapeBox::getSize() +Size PhysicsShapeBox::getSize() const { cpShape* shape = _info->shapes.front(); return PhysicsHelper::cpv2size(cpv(cpvdist(cpPolyShapeGetVert(shape, 0), cpPolyShapeGetVert(shape, 1)), @@ -590,13 +594,13 @@ float PhysicsShapePolygon::calculateDefaultMoment() : PhysicsHelper::cpfloat2float(cpMomentForPoly(_mass, ((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts, cpvzero)); } -Point* PhysicsShapePolygon::getPoints(Point* points) +Point* PhysicsShapePolygon::getPoints(Point* points) const { cpShape* shape = _info->shapes.front(); return PhysicsHelper::cpvs2points(((cpPolyShape*)shape)->verts, points, ((cpPolyShape*)shape)->numVerts); } -int PhysicsShapePolygon::getPointsCount() +int PhysicsShapePolygon::getPointsCount() const { return ((cpPolyShape*)_info->shapes.front())->numVerts; } @@ -711,7 +715,7 @@ Point PhysicsShapeEdgePolygon::getCenter() return _center; } -int PhysicsShapeEdgePolygon::getPointsCount() +int PhysicsShapeEdgePolygon::getPointsCount() const { return _info->shapes.size() + 1; } @@ -772,11 +776,22 @@ Point PhysicsShapeEdgeChain::getCenter() return _center; } -int PhysicsShapeEdgeChain::getPointsCount() +int PhysicsShapeEdgeChain::getPointsCount() const { return _info->shapes.size() + 1; } +void PhysicsShape::setGroup(int group) +{ + if (group < 0) + { + for (auto shape : _info->shapes) + { + cpShapeSetGroup(shape, (cpGroup)group); + } + } +} + #elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) #endif diff --git a/cocos/physics/CCPhysicsShape.h b/cocos/physics/CCPhysicsShape.h index 6cd5329f6d..31497d14a2 100644 --- a/cocos/physics/CCPhysicsShape.h +++ b/cocos/physics/CCPhysicsShape.h @@ -57,7 +57,7 @@ typedef struct PhysicsMaterial {} }PhysicsMaterial; -const PhysicsMaterial PHYSICSSHAPE_MATERIAL_DEFAULT(0.0f, 1.0f, 1.0f); +const PhysicsMaterial PHYSICSSHAPE_MATERIAL_DEFAULT(0.0f, 0.5f, 0.5f); /** * @brief A shape for body. You do not create PhysicsWorld objects directly, instead, you can view PhysicsBody to see how to create it. @@ -102,6 +102,16 @@ public: static Point* recenterPoints(Point* points, int count, Point center = Point::ZERO); static Point getPolyonCenter(Point* points, int count); + inline void setCategoryBitmask(int bitmask) { _categoryBitmask = bitmask; } + inline int getCategoryBitmask() const { return _categoryBitmask; } + inline void setContactTestBitmask(int bitmask) { _contactTestBitmask = bitmask; } + inline int getContactTestBitmask() const { return _contactTestBitmask; } + inline void setCollisionBitmask(int bitmask) { _collisionBitmask = bitmask; } + inline int getCollisionBitmask() const { return _collisionBitmask; } + + void setGroup(int group); + inline int getGroup() { return _group; } + protected: bool init(Type type); @@ -125,6 +135,10 @@ protected: float _moment; PhysicsMaterial _material; int _tag; + int _categoryBitmask; + int _collisionBitmask; + int _contactTestBitmask; + int _group; friend class PhysicsWorld; friend class PhysicsBody; @@ -142,8 +156,8 @@ public: float calculateDefaultArea() override; float calculateDefaultMoment() override; - float getRadius(); - Point getOffset(); + float getRadius() const; + Point getOffset() override; protected: bool init(float radius, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0)); @@ -163,8 +177,8 @@ public: float calculateDefaultArea() override; float calculateDefaultMoment() override; - Point* getPoints(Point* points); - Size getSize(); + Point* getPoints(Point* points) const; + Size getSize() const; Point getOffset() override { return _offset; } protected: @@ -189,8 +203,8 @@ public: float calculateDefaultArea() override; float calculateDefaultMoment() override; - Point* getPoints(Point* points); - int getPointsCount(); + Point* getPoints(Point* points) const; + int getPointsCount() const; Point getCenter() override; protected: bool init(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0)); @@ -209,8 +223,8 @@ class PhysicsShapeEdgeSegment : public PhysicsShape public: static PhysicsShapeEdgeSegment* create(Point a, Point b, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1); - Point getPointA(); - Point getPointB(); + Point getPointA() const; + Point getPointB() const; Point getCenter() override; protected: @@ -232,8 +246,8 @@ class PhysicsShapeEdgeBox : public PhysicsShape public: static PhysicsShapeEdgeBox* create(Size size, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 0, Point offset = Point(0, 0)); Point getOffset() override { return _offset; } - Point* getPoints(Point* points); - int getPointsCount(); + Point* getPoints(Point* points) const; + int getPointsCount() const; protected: bool init(Size size, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1, Point offset = Point(0, 0)); @@ -254,8 +268,8 @@ class PhysicsShapeEdgePolygon : public PhysicsShape public: static PhysicsShapeEdgePolygon* create(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1); Point getCenter() override; - Point* getPoints(Point* points); - int getPointsCount(); + Point* getPoints(Point* points) const; + int getPointsCount() const; protected: bool init(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1); @@ -276,8 +290,8 @@ class PhysicsShapeEdgeChain : public PhysicsShape public: static PhysicsShapeEdgeChain* create(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1); Point getCenter() override; - Point* getPoints(Point* points); - int getPointsCount(); + Point* getPoints(Point* points) const; + int getPointsCount() const; protected: bool init(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1); diff --git a/cocos/physics/CCPhysicsWorld.cpp b/cocos/physics/CCPhysicsWorld.cpp index 9085805e1d..1cd2b936c5 100644 --- a/cocos/physics/CCPhysicsWorld.cpp +++ b/cocos/physics/CCPhysicsWorld.cpp @@ -37,29 +37,35 @@ #include "CCPhysicsJoint.h" #include "CCPhysicsContact.h" -#include "chipmunk/CCPhysicsWorldInfo.h" -#include "box2d/CCPhysicsWorldInfo.h" -#include "chipmunk/CCPhysicsBodyInfo.h" -#include "box2d/CCPhysicsBodyInfo.h" -#include "chipmunk/CCPhysicsShapeInfo.h" -#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 "chipmunk/CCPhysicsWorldInfo_chipmunk.h" +#include "box2d/CCPhysicsWorldInfo_box2d.h" +#include "chipmunk/CCPhysicsBodyInfo_chipmunk.h" +#include "box2d/CCPhysicsBodyInfo_box2d.h" +#include "chipmunk/CCPhysicsShapeInfo_chipmunk.h" +#include "box2d/CCPhysicsShapeInfo_box2d.h" +#include "chipmunk/CCPhysicsContactInfo_chipmunk.h" +#include "box2d/CCPhysicsContactInfo_box2d.h" +#include "chipmunk/CCPhysicsJointInfo_chipmunk.h" +#include "box2d/CCPhysicsJointInfo_box2d.h" +#include "chipmunk/CCPhysicsHelper_chipmunk.h" #include "CCDrawNode.h" #include "CCArray.h" #include "CCScene.h" #include "CCDirector.h" +#include "CCEventDispatcher.h" +#include "CCEventCustom.h" #include NS_CC_BEGIN +extern const char* PHYSICSCONTACT_EVENT_NAME; + #if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) +const float PHYSICS_INFINITY = INFINITY; + namespace { typedef struct RayCastCallbackInfo @@ -96,8 +102,6 @@ public: bool PhysicsWorldCallback::continues = true; -const float PHYSICS_INFINITY = INFINITY; - int PhysicsWorldCallback::collisionBeginCallbackFunc(cpArbiter *arb, struct cpSpace *space, PhysicsWorld *world) { CP_ARBITER_GET_SHAPES(arb, a, b); @@ -108,20 +112,19 @@ int PhysicsWorldCallback::collisionBeginCallbackFunc(cpArbiter *arb, struct cpSp PhysicsContact* contact = PhysicsContact::create(ita->second->shape, itb->second->shape); arb->data = contact; + contact->_contactInfo = arb; - return world->collisionBeginCallback(*static_cast(arb->data)); + return world->collisionBeginCallback(*contact); } int PhysicsWorldCallback::collisionPreSolveCallbackFunc(cpArbiter *arb, cpSpace *space, PhysicsWorld *world) { - return world->collisionPreSolveCallback(*static_cast(arb->data), - PhysicsContactPreSolve()); + return world->collisionPreSolveCallback(*static_cast(arb->data)); } void PhysicsWorldCallback::collisionPostSolveCallbackFunc(cpArbiter *arb, cpSpace *space, PhysicsWorld *world) { - world->collisionPostSolveCallback(*static_cast(arb->data), - PhysicsContactPostSolve()); + world->collisionPostSolveCallback(*static_cast(arb->data)); } void PhysicsWorldCallback::collisionSeparateCallbackFunc(cpArbiter *arb, cpSpace *space, PhysicsWorld *world) @@ -176,20 +179,31 @@ void PhysicsWorldCallback::nearestPointQueryFunc(cpShape *shape, cpFloat distanc arr->addObject(it->second->shape); } -bool PhysicsWorld::init() +bool PhysicsWorld::init(Scene& scene) { - _info = new PhysicsWorldInfo(); + do + { + _info = new PhysicsWorldInfo(); + CC_BREAK_IF(_info == nullptr); + _bodies = Array::create(); + CC_BREAK_IF(_bodies == nullptr); + _bodies->retain(); + + _scene = &scene; + + cpSpaceSetGravity(_info->space, PhysicsHelper::point2cpv(_gravity)); + + cpSpaceSetDefaultCollisionHandler(_info->space, + (cpCollisionBeginFunc)PhysicsWorldCallback::collisionBeginCallbackFunc, + (cpCollisionPreSolveFunc)PhysicsWorldCallback::collisionPreSolveCallbackFunc, + (cpCollisionPostSolveFunc)PhysicsWorldCallback::collisionPostSolveCallbackFunc, + (cpCollisionSeparateFunc)PhysicsWorldCallback::collisionSeparateCallbackFunc, + this); + + return true; + } while (false); - cpSpaceSetGravity(_info->space, PhysicsHelper::point2cpv(_gravity)); - - cpSpaceSetDefaultCollisionHandler(_info->space, - (cpCollisionBeginFunc)PhysicsWorldCallback::collisionBeginCallbackFunc, - (cpCollisionPreSolveFunc)PhysicsWorldCallback::collisionPreSolveCallbackFunc, - (cpCollisionPostSolveFunc)PhysicsWorldCallback::collisionPostSolveCallbackFunc, - (cpCollisionSeparateFunc)PhysicsWorldCallback::collisionSeparateCallbackFunc, - this); - - return true; + return false; } void PhysicsWorld::addJoint(PhysicsJoint* joint) @@ -198,8 +212,6 @@ void PhysicsWorld::addJoint(PhysicsJoint* joint) if (it == _joints.end()) { - _joints.push_back(joint); - for (auto subjoint : joint->_info->joints) { if (!cpSpaceContainsConstraint(_info->space, subjoint)) @@ -207,21 +219,47 @@ void PhysicsWorld::addJoint(PhysicsJoint* joint) cpSpaceAddConstraint(_info->space, subjoint); } } + + _joints.push_back(joint); } } void PhysicsWorld::removeJoint(PhysicsJoint* joint) { + auto it = std::find(_joints.begin(), _joints.end(), joint); + if (it != _joints.end()) + { + for (auto subjoint : joint->_info->joints) + { + if (cpSpaceContainsConstraint(_info->space, subjoint)) + { + cpSpaceRemoveConstraint(_info->space, subjoint); + } + } + + _joints.remove(joint); + } } void PhysicsWorld::removeAllJoints() { + for (auto joint : _joints) + { + for (auto subjoint : joint->_info->joints) + { + if (!cpSpaceContainsConstraint(_info->space, subjoint)) + { + cpSpaceRemoveConstraint(_info->space, subjoint); + } + } + } + _joints.clear(); } -void PhysicsWorld::addShape(PhysicsShape* shape) +PhysicsShape* PhysicsWorld::addShape(PhysicsShape* shape) { for (auto cps : shape->_info->shapes) { @@ -233,19 +271,29 @@ void PhysicsWorld::addShape(PhysicsShape* shape) if (cpBodyIsStatic(shape->getBody()->_info->body)) { cpSpaceAddStaticShape(_info->space, cps); - }else + } + else { cpSpaceAddShape(_info->space, cps); } } + + return shape; } -void PhysicsWorld::addBody(PhysicsBody* body) +PhysicsBody* PhysicsWorld::addBody(PhysicsBody* body) { CCASSERT(body != nullptr, "the body can not be nullptr"); + if (body->getWorld() != this && body->getWorld() != nullptr) + { + body->removeFromWorld(); + } + if (body->isEnable()) { + body->_world = this; + //is gravity enable if (!body->isGravityEnable()) { @@ -259,45 +307,42 @@ void PhysicsWorld::addBody(PhysicsBody* body) } // add shapes to space - for (auto shape : body->getShapes()) + for (auto shape : *body->getShapes()) { - addShape(shape); + addShape(dynamic_cast(shape)); } } - if (_bodys == nullptr) - { - _bodys = Array::create(body, NULL); - _bodys->retain(); - }else - { - _bodys->addObject(body); - } + _bodies->addObject(body); + + return body; } void PhysicsWorld::removeBody(PhysicsBody* body) { CCASSERT(body != nullptr, "the body can not be nullptr"); - if (body->getWorld() == this) + if (body->getWorld() != this) { - // reset the gravity - if (!body->isGravityEnable()) - { - body->applyForce(-_gravity); - } + return; + } + + // reset the gravity + if (!body->isGravityEnable()) + { + body->applyForce(-_gravity); + } + + // remove joints + for (auto joint : body->_joints) + { + removeJoint(joint); } // remove shaps - for (auto shape : body->getShapes()) + for (auto shape : *body->getShapes()) { - for (auto cps : shape->_info->shapes) - { - if (cpSpaceContainsShape(_info->space, cps)) - { - cpSpaceRemoveShape(_info->space, cps); - } - } + removeShape(dynamic_cast(shape)); } // remove body @@ -306,15 +351,13 @@ void PhysicsWorld::removeBody(PhysicsBody* body) cpSpaceRemoveBody(_info->space, body->_info->body); } - if (_bodys != nullptr) - { - _bodys->removeObject(body); - } + body->_world = nullptr; + _bodies->removeObject(body); } void PhysicsWorld::removeBodyByTag(int tag) { - for (Object* obj : *_bodys) + for (Object* obj : *_bodies) { PhysicsBody* body = dynamic_cast(obj); if (body->getTag() == tag) @@ -325,6 +368,43 @@ void PhysicsWorld::removeBodyByTag(int tag) } } +void PhysicsWorld::removeAllBodies() +{ + for (Object* obj : *_bodies) + { + PhysicsBody* body = dynamic_cast(obj); + + // reset the gravity + if (!body->isGravityEnable()) + { + body->applyForce(-_gravity); + } + + // remove joints + for (auto joint : body->_joints) + { + removeJoint(joint); + } + + // remove shaps + for (auto shape : *body->getShapes()) + { + removeShape(dynamic_cast(shape)); + } + + // remove body + if (cpSpaceContainsBody(_info->space, body->_info->body)) + { + cpSpaceRemoveBody(_info->space, body->_info->body); + } + + body->_world = nullptr; + } + + _bodies->removeAllObjects(); + CC_SAFE_RELEASE(_bodies); +} + void PhysicsWorld::removeShape(PhysicsShape* shape) { for (auto cps : shape->_info->shapes) @@ -338,7 +418,7 @@ void PhysicsWorld::removeShape(PhysicsShape* shape) void PhysicsWorld::update(float delta) { - for (auto body : *_bodys) + for (auto body : *_bodies) { body->update(delta); } @@ -359,22 +439,25 @@ void PhysicsWorld::update(float delta) void PhysicsWorld::debugDraw() { - if (_debugDraw && _bodys != nullptr) + if (_debugDraw && _bodies != nullptr) { _drawNode= DrawNode::create(); - for (Object* obj : *_bodys) + for (Object* obj : *_bodies) { PhysicsBody* body = dynamic_cast(obj); - std::vector shapes = body->getShapes(); - - for (auto shape : shapes) + for (auto shape : *body->getShapes()) { - drawWithShape(_drawNode, shape); + drawWithShape(_drawNode, dynamic_cast(shape)); } } + for (auto joint : _joints) + { + drawWithJoint(_drawNode, joint); + } + if (_scene) { _scene->addChild(_drawNode); @@ -382,9 +465,65 @@ void PhysicsWorld::debugDraw() } } -void PhysicsWorld::setScene(Scene *scene) +void PhysicsWorld::drawWithJoint(DrawNode* node, PhysicsJoint* joint) { - _scene = scene; + for (auto it = joint->_info->joints.begin(); it != joint->_info->joints.end(); ++it) + { + cpConstraint *constraint = *it; + + + cpBody *body_a = constraint->a; + cpBody *body_b = constraint->b; + + const cpConstraintClass *klass = constraint->klass_private; + if(klass == cpPinJointGetClass()) + { + cpPinJoint *joint = (cpPinJoint *)constraint; + + cpVect a = cpvadd(body_a->p, cpvrotate(joint->anchr1, body_a->rot)); + cpVect b = cpvadd(body_b->p, cpvrotate(joint->anchr2, body_b->rot)); + + node->drawSegment(PhysicsHelper::cpv2point(a), PhysicsHelper::cpv2point(b), 1, Color4F(0.0f, 0.0f, 1.0f, 1.0f)); + node->drawDot(PhysicsHelper::cpv2point(a), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + node->drawDot(PhysicsHelper::cpv2point(b), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + } + else if(klass == cpSlideJointGetClass()) + { + cpSlideJoint *joint = (cpSlideJoint *)constraint; + + cpVect a = cpvadd(body_a->p, cpvrotate(joint->anchr1, body_a->rot)); + cpVect b = cpvadd(body_b->p, cpvrotate(joint->anchr2, body_b->rot)); + + node->drawSegment(PhysicsHelper::cpv2point(a), PhysicsHelper::cpv2point(b), 1, Color4F(0.0f, 0.0f, 1.0f, 1.0f)); + node->drawDot(PhysicsHelper::cpv2point(a), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + node->drawDot(PhysicsHelper::cpv2point(b), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + } + else if(klass == cpPivotJointGetClass()) + { + cpPivotJoint *joint = (cpPivotJoint *)constraint; + + cpVect a = cpvadd(body_a->p, cpvrotate(joint->anchr1, body_a->rot)); + cpVect b = cpvadd(body_b->p, cpvrotate(joint->anchr2, body_b->rot)); + + node->drawDot(PhysicsHelper::cpv2point(a), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + node->drawDot(PhysicsHelper::cpv2point(b), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + } + else if(klass == cpGrooveJointGetClass()) + { + cpGrooveJoint *joint = (cpGrooveJoint *)constraint; + + cpVect a = cpvadd(body_a->p, cpvrotate(joint->grv_a, body_a->rot)); + cpVect b = cpvadd(body_a->p, cpvrotate(joint->grv_b, body_a->rot)); + cpVect c = cpvadd(body_b->p, cpvrotate(joint->anchr2, body_b->rot)); + + node->drawSegment(PhysicsHelper::cpv2point(a), PhysicsHelper::cpv2point(b), 1, Color4F(0.0f, 0.0f, 1.0f, 1.0f)); + node->drawDot(PhysicsHelper::cpv2point(c), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + } + else if(klass == cpDampedSpringGetClass()) + { + + } + } } void PhysicsWorld::drawWithShape(DrawNode* node, PhysicsShape* shape) @@ -443,63 +582,90 @@ void PhysicsWorld::drawWithShape(DrawNode* node, PhysicsShape* shape) int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact) { bool ret = true; - PhysicsBody* bodyA = contact.getShapeA()->getBody(); - PhysicsBody* bodyB = contact.getShapeB()->getBody(); - if ((bodyA->getCategoryBitmask() & bodyB->getContactTestBitmask()) == 0 - || (bodyB->getContactTestBitmask() & bodyA->getCategoryBitmask()) == 0) + PhysicsShape* shapeA = contact.getShapeA(); + PhysicsShape* shapeB = contact.getShapeB(); + PhysicsBody* bodyA = shapeA->getBody(); + PhysicsBody* bodyB = shapeB->getBody(); + std::vector jointsA = bodyA->getJoints(); + + // check the joint is collision enable or not + for (PhysicsJoint* joint : jointsA) + { + if (std::find(_joints.begin(), _joints.end(), joint) == _joints.end()) + { + continue; + } + + if (!joint->isCollisionEnable()) + { + PhysicsBody* body = joint->getBodyA() == bodyA ? joint->getBodyB() : joint->getBodyA(); + + if (body == bodyB) + { + contact.setNotify(false); + return false; + } + } + } + + // bitmask check + if ((shapeA->getCategoryBitmask() & shapeB->getContactTestBitmask()) == 0 + || (shapeB->getContactTestBitmask() & shapeA->getCategoryBitmask()) == 0) { contact.setNotify(false); } - if ((bodyA->getCategoryBitmask() & bodyB->getCollisionBitmask()) == 0 - || (bodyB->getCategoryBitmask() & bodyA->getCollisionBitmask()) == 0) + if (shapeA->getGroup() != 0 && shapeA->getGroup() == shapeB->getGroup()) { - ret = false; + ret = shapeA->getGroup() > 0; } - - if (contact.getNotify() && _listener && _listener->onContactBegin) + else { - // the mask has high priority than _listener->onContactBegin. - // so if the mask test is false, the two bodies won't have collision. - if (ret) + if ((shapeA->getCategoryBitmask() & shapeB->getCollisionBitmask()) == 0 + || (shapeB->getCategoryBitmask() & shapeA->getCollisionBitmask()) == 0) { - ret = _listener->onContactBegin(*this, contact); - }else - { - _listener->onContactBegin(*this, contact); + ret = false; } } - return ret; + contact.setEventCode(PhysicsContact::EventCode::BEGIN); + contact.setWorld(this); + EventCustom event(PHYSICSCONTACT_EVENT_NAME); + event.setUserData(&contact); + _scene->getEventDispatcher()->dispatchEvent(&event); + + return ret ? contact.resetResult() : false; } -int PhysicsWorld::collisionPreSolveCallback(PhysicsContact& contact, const PhysicsContactPreSolve& solve) +int PhysicsWorld::collisionPreSolveCallback(PhysicsContact& contact) { if (!contact.getNotify()) { return true; } - if (_listener && _listener->onContactPreSolve) - { - return _listener->onContactPreSolve(*this, contact, solve); - } + contact.setEventCode(PhysicsContact::EventCode::PRESOLVE); + contact.setWorld(this); + EventCustom event(PHYSICSCONTACT_EVENT_NAME); + event.setUserData(&contact); + _scene->getEventDispatcher()->dispatchEvent(&event); - return true; + return contact.resetResult(); } -void PhysicsWorld::collisionPostSolveCallback(PhysicsContact& contact, const PhysicsContactPostSolve& solve) +void PhysicsWorld::collisionPostSolveCallback(PhysicsContact& contact) { if (!contact.getNotify()) { return; } - if (_listener && _listener->onContactPreSolve) - { - _listener->onContactPostSolve(*this, contact, solve); - } + contact.setEventCode(PhysicsContact::EventCode::POSTSOLVE); + contact.setWorld(this); + EventCustom event(PHYSICSCONTACT_EVENT_NAME); + event.setUserData(&contact); + _scene->getEventDispatcher()->dispatchEvent(&event); } void PhysicsWorld::collisionSeparateCallback(PhysicsContact& contact) @@ -509,17 +675,18 @@ void PhysicsWorld::collisionSeparateCallback(PhysicsContact& contact) return; } - if (_listener && _listener->onContactEnd) - { - _listener->onContactEnd(*this, contact); - } + contact.setEventCode(PhysicsContact::EventCode::SEPERATE); + contact.setWorld(this); + EventCustom event(PHYSICSCONTACT_EVENT_NAME); + event.setUserData(&contact); + _scene->getEventDispatcher()->dispatchEvent(&event); } void PhysicsWorld::setGravity(Point gravity) { - if (_bodys != nullptr) + if (_bodies != nullptr) { - for (auto child : *_bodys) + for (auto child : *_bodies) { PhysicsBody* body = dynamic_cast(child); @@ -541,7 +708,7 @@ void PhysicsWorld::rayCast(PhysicsRayCastCallback& callback, Point point1, Point { if (callback.report != nullptr) { - RayCastCallbackInfo info = {this, &callback, point1, point2, data}; + RayCastCallbackInfo info = { this, &callback, point1, point2, data }; PhysicsWorldCallback::continues = true; cpSpaceSegmentQuery(this->_info->space, @@ -571,7 +738,7 @@ void PhysicsWorld::rectQuery(PhysicsRectQueryCallback& callback, Rect rect, void } } -Array* PhysicsWorld::getShapesAtPoint(Point point) +Array* PhysicsWorld::getShapesAtPoint(Point point) const { Array* arr = Array::create(); cpSpaceNearestPointQuery(this->_info->space, @@ -585,7 +752,7 @@ Array* PhysicsWorld::getShapesAtPoint(Point point) return arr; } -PhysicsShape* PhysicsWorld::getShapeAtPoint(Point point) +PhysicsShape* PhysicsWorld::getShapeAtPoint(Point point) const { cpShape* shape = cpSpaceNearestPointQueryNearest(this->_info->space, PhysicsHelper::point2cpv(point), @@ -597,19 +764,32 @@ PhysicsShape* PhysicsWorld::getShapeAtPoint(Point point) return shape == nullptr ? nullptr : PhysicsShapeInfo::map.find(shape)->second->shape; } -Array* PhysicsWorld::getAllBody() const +Array* PhysicsWorld::getAllBodies() const { - return _bodys; + return _bodies; +} + +PhysicsBody* PhysicsWorld::getBodyByTag(int tag) const +{ + for (auto body : *_bodies) + { + if (((PhysicsBody*)body)->getTag() == tag) + { + return (PhysicsBody*)body; + } + } + + return nullptr; } #elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) #endif -PhysicsWorld* PhysicsWorld::create() +PhysicsWorld* PhysicsWorld::create(Scene& scene) { PhysicsWorld * world = new PhysicsWorld(); - if(world && world->init()) + if(world && world->init(scene)) { return world; } @@ -622,8 +802,7 @@ PhysicsWorld::PhysicsWorld() : _gravity(Point(0.0f, -98.0f)) , _speed(1.0f) , _info(nullptr) -, _listener(nullptr) -, _bodys(nullptr) +, _bodies(nullptr) , _scene(nullptr) , _debugDraw(false) , _drawNode(nullptr) @@ -633,8 +812,9 @@ PhysicsWorld::PhysicsWorld() PhysicsWorld::~PhysicsWorld() { + removeAllBodies(); + removeAllJoints(); CC_SAFE_DELETE(_info); - CC_SAFE_RELEASE(_bodys); } NS_CC_END diff --git a/cocos/physics/CCPhysicsWorld.h b/cocos/physics/CCPhysicsWorld.h index 63c841cc93..e719dce2c4 100644 --- a/cocos/physics/CCPhysicsWorld.h +++ b/cocos/physics/CCPhysicsWorld.h @@ -40,9 +40,6 @@ class PhysicsJoint; class PhysicsWorldInfo; class PhysicsShape; class PhysicsContact; -class PhysicsContactPreSolve; -class PhysicsContactPostSolve; -class PhysicsContactListener; class Array; class Sprite; @@ -97,56 +94,57 @@ public: void rayCast(PhysicsRayCastCallback& callback, Point point1, Point point2, void* data); void rectQuery(PhysicsRectQueryCallback& callback, Rect rect, void* data); - Array* getShapesAtPoint(Point point); - PhysicsShape* getShapeAtPoint(Point point); - Array* getAllBody() const; + Array* getShapesAtPoint(Point point) const; + PhysicsShape* getShapeAtPoint(Point point) const; + Array* getAllBodies() const; + PhysicsBody* getBodyByTag(int tag) const; /** Register a listener to receive contact callbacks*/ - inline void registerContactListener(PhysicsContactListener* delegate) { _listener = delegate; } + //inline void registerContactListener(EventListenerPhysicsContact* delegate) { _listener = delegate; } /** Unregister a listener. */ - inline void unregisterContactListener() { _listener = nullptr; } + //inline void unregisterContactListener() { _listener = nullptr; } + inline Scene& getScene() const { return *_scene; } /** get the gravity value */ - inline Point getGravity() { return _gravity; } + inline Point getGravity() const { return _gravity; } /** set the gravity value */ void setGravity(Point gravity); /** test the debug draw is enabled */ - inline bool isDebugDraw() { return _debugDraw; } + inline bool isDebugDraw() const { return _debugDraw; } /** set the debug draw */ inline void setDebugDraw(bool debugDraw) { _debugDraw = debugDraw; } virtual void removeBody(PhysicsBody* body); virtual void removeBodyByTag(int tag); + virtual void removeAllBodies(); protected: - static PhysicsWorld* create(); - bool init(); + static PhysicsWorld* create(Scene& scene); + bool init(Scene& scene); - void setScene(Scene* scene); - - virtual void addBody(PhysicsBody* body); - virtual void addShape(PhysicsShape* shape); + virtual PhysicsBody* addBody(PhysicsBody* body); + virtual PhysicsShape* addShape(PhysicsShape* shape); virtual void removeShape(PhysicsShape* shape); virtual void update(float delta); virtual void debugDraw(); virtual void drawWithShape(DrawNode* node, PhysicsShape* shape); + virtual void drawWithJoint(DrawNode* node, PhysicsJoint* joint); virtual int collisionBeginCallback(PhysicsContact& contact); - virtual int collisionPreSolveCallback(PhysicsContact& contact, const PhysicsContactPreSolve& solve); - virtual void collisionPostSolveCallback(PhysicsContact& contact, const PhysicsContactPostSolve& solve); + virtual int collisionPreSolveCallback(PhysicsContact& contact); + virtual void collisionPostSolveCallback(PhysicsContact& contact); virtual void collisionSeparateCallback(PhysicsContact& contact); protected: Point _gravity; float _speed; PhysicsWorldInfo* _info; - PhysicsContactListener* _listener; + //EventListenerPhysicsContact* _listener; - - Array* _bodys; + Array* _bodies; std::list _joints; Scene* _scene; diff --git a/cocos/physics/box2d/CCPhysicsBodyInfo.cpp b/cocos/physics/box2d/CCPhysicsBodyInfo_box2d.cpp similarity index 97% rename from cocos/physics/box2d/CCPhysicsBodyInfo.cpp rename to cocos/physics/box2d/CCPhysicsBodyInfo_box2d.cpp index bfa20b616a..059619a264 100644 --- a/cocos/physics/box2d/CCPhysicsBodyInfo.cpp +++ b/cocos/physics/box2d/CCPhysicsBodyInfo_box2d.cpp @@ -22,7 +22,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "CCPhysicsBodyInfo.h" +#include "CCPhysicsBodyInfo_box2d.h" #if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) NS_CC_BEGIN diff --git a/cocos/physics/box2d/CCPhysicsBodyInfo.h b/cocos/physics/box2d/CCPhysicsBodyInfo_box2d.h similarity index 99% rename from cocos/physics/box2d/CCPhysicsBodyInfo.h rename to cocos/physics/box2d/CCPhysicsBodyInfo_box2d.h index 5c89ac5f19..ed5135bf36 100644 --- a/cocos/physics/box2d/CCPhysicsBodyInfo.h +++ b/cocos/physics/box2d/CCPhysicsBodyInfo_box2d.h @@ -27,7 +27,9 @@ #ifndef __CCPHYSICS_BODY_INFO_H__ #define __CCPHYSICS_BODY_INFO_H__ + #include "CCPlatformMacros.h" + NS_CC_BEGIN class PhysicsBodyInfo diff --git a/cocos/physics/box2d/CCPhysicsContactInfo.cpp b/cocos/physics/box2d/CCPhysicsContactInfo_box2d.cpp similarity index 97% rename from cocos/physics/box2d/CCPhysicsContactInfo.cpp rename to cocos/physics/box2d/CCPhysicsContactInfo_box2d.cpp index 41eaa4f831..4edb6ce3a2 100644 --- a/cocos/physics/box2d/CCPhysicsContactInfo.cpp +++ b/cocos/physics/box2d/CCPhysicsContactInfo_box2d.cpp @@ -22,7 +22,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "CCPhysicsContactInfo.h" +#include "CCPhysicsContactInfo_box2d.h" #if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) NS_CC_BEGIN diff --git a/cocos/physics/box2d/CCPhysicsContactInfo.h b/cocos/physics/box2d/CCPhysicsContactInfo_box2d.h similarity index 99% rename from cocos/physics/box2d/CCPhysicsContactInfo.h rename to cocos/physics/box2d/CCPhysicsContactInfo_box2d.h index f1e41ef572..c8d4a262d5 100644 --- a/cocos/physics/box2d/CCPhysicsContactInfo.h +++ b/cocos/physics/box2d/CCPhysicsContactInfo_box2d.h @@ -27,6 +27,7 @@ #ifndef __CCPHYSICS_CONTACT_INFO_H__ #define __CCPHYSICS_CONTACT_INFO_H__ + #include "CCPlatformMacros.h" NS_CC_BEGIN diff --git a/cocos/physics/box2d/CCPhysicsHelper.h b/cocos/physics/box2d/CCPhysicsHelper_box2d.h similarity index 99% rename from cocos/physics/box2d/CCPhysicsHelper.h rename to cocos/physics/box2d/CCPhysicsHelper_box2d.h index 61dd2b6e4c..01f156628d 100644 --- a/cocos/physics/box2d/CCPhysicsHelper.h +++ b/cocos/physics/box2d/CCPhysicsHelper_box2d.h @@ -27,7 +27,6 @@ #ifndef __CCPHYSICS_HELPER_H__ #define __CCPHYSICS_HELPER_H__ - #include "CCPlatformMacros.h" #include "CCGeometry.h" diff --git a/cocos/physics/box2d/CCPhysicsJointInfo.cpp b/cocos/physics/box2d/CCPhysicsJointInfo_box2d.cpp similarity index 97% rename from cocos/physics/box2d/CCPhysicsJointInfo.cpp rename to cocos/physics/box2d/CCPhysicsJointInfo_box2d.cpp index 753ba41534..a0b6363cde 100644 --- a/cocos/physics/box2d/CCPhysicsJointInfo.cpp +++ b/cocos/physics/box2d/CCPhysicsJointInfo_box2d.cpp @@ -22,7 +22,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "CCPhysicsJointInfo.h" +#include "CCPhysicsJointInfo_box2d.h" #if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) NS_CC_BEGIN diff --git a/cocos/physics/box2d/CCPhysicsJointInfo.h b/cocos/physics/box2d/CCPhysicsJointInfo_box2d.h similarity index 99% rename from cocos/physics/box2d/CCPhysicsJointInfo.h rename to cocos/physics/box2d/CCPhysicsJointInfo_box2d.h index a60ecdb97e..c8223b6f8c 100644 --- a/cocos/physics/box2d/CCPhysicsJointInfo.h +++ b/cocos/physics/box2d/CCPhysicsJointInfo_box2d.h @@ -27,6 +27,7 @@ #ifndef __CCPHYSICS_JOINT_INFO_H__ #define __CCPHYSICS_JOINT_INFO_H__ + #include "CCPlatformMacros.h" NS_CC_BEGIN diff --git a/cocos/physics/box2d/CCPhysicsShapeInfo.cpp b/cocos/physics/box2d/CCPhysicsShapeInfo_box2d.cpp similarity index 97% rename from cocos/physics/box2d/CCPhysicsShapeInfo.cpp rename to cocos/physics/box2d/CCPhysicsShapeInfo_box2d.cpp index a89ba7dae7..fc3aa61491 100644 --- a/cocos/physics/box2d/CCPhysicsShapeInfo.cpp +++ b/cocos/physics/box2d/CCPhysicsShapeInfo_box2d.cpp @@ -22,7 +22,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "CCPhysicsShapeInfo.h" +#include "CCPhysicsShapeInfo_box2d.h" #if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) NS_CC_BEGIN diff --git a/cocos/physics/box2d/CCPhysicsShapeInfo.h b/cocos/physics/box2d/CCPhysicsShapeInfo_box2d.h similarity index 99% rename from cocos/physics/box2d/CCPhysicsShapeInfo.h rename to cocos/physics/box2d/CCPhysicsShapeInfo_box2d.h index 8608f0bad1..cd1fc6abcc 100644 --- a/cocos/physics/box2d/CCPhysicsShapeInfo.h +++ b/cocos/physics/box2d/CCPhysicsShapeInfo_box2d.h @@ -27,6 +27,7 @@ #ifndef __CCPHYSICS_SHAPE_INFO_H__ #define __CCPHYSICS_SHAPE_INFO_H__ + #include "CCPlatformMacros.h" NS_CC_BEGIN diff --git a/cocos/physics/box2d/CCPhysicsWorldInfo.cpp b/cocos/physics/box2d/CCPhysicsWorldInfo_box2d.cpp similarity index 97% rename from cocos/physics/box2d/CCPhysicsWorldInfo.cpp rename to cocos/physics/box2d/CCPhysicsWorldInfo_box2d.cpp index 0de6c00d82..fbe3be06d4 100644 --- a/cocos/physics/box2d/CCPhysicsWorldInfo.cpp +++ b/cocos/physics/box2d/CCPhysicsWorldInfo_box2d.cpp @@ -22,7 +22,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "CCPhysicsWorldInfo.h" +#include "CCPhysicsWorldInfo_box2d.h" #if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) NS_CC_BEGIN diff --git a/cocos/physics/box2d/CCPhysicsWorldInfo.h b/cocos/physics/box2d/CCPhysicsWorldInfo_box2d.h similarity index 99% rename from cocos/physics/box2d/CCPhysicsWorldInfo.h rename to cocos/physics/box2d/CCPhysicsWorldInfo_box2d.h index 662fa19843..9df3ec46cd 100644 --- a/cocos/physics/box2d/CCPhysicsWorldInfo.h +++ b/cocos/physics/box2d/CCPhysicsWorldInfo_box2d.h @@ -27,6 +27,7 @@ #ifndef __CCPHYSICS_WORLD_INFO_H__ #define __CCPHYSICS_WORLD_INFO_H__ + #include "CCPlatformMacros.h" NS_CC_BEGIN diff --git a/cocos/physics/chipmunk/CCPhysicsBodyInfo.cpp b/cocos/physics/chipmunk/CCPhysicsBodyInfo_chipmunk.cpp similarity index 96% rename from cocos/physics/chipmunk/CCPhysicsBodyInfo.cpp rename to cocos/physics/chipmunk/CCPhysicsBodyInfo_chipmunk.cpp index 852dad1eeb..42ce5cc7ec 100644 --- a/cocos/physics/chipmunk/CCPhysicsBodyInfo.cpp +++ b/cocos/physics/chipmunk/CCPhysicsBodyInfo_chipmunk.cpp @@ -22,13 +22,12 @@ THE SOFTWARE. ****************************************************************************/ -#include "CCPhysicsBodyInfo.h" +#include "CCPhysicsBodyInfo_chipmunk.h" #if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) NS_CC_BEGIN PhysicsBodyInfo::PhysicsBodyInfo() : body(nullptr) -, group(CP_NO_GROUP) { } diff --git a/cocos/physics/chipmunk/CCPhysicsBodyInfo.h b/cocos/physics/chipmunk/CCPhysicsBodyInfo_chipmunk.h similarity index 98% rename from cocos/physics/chipmunk/CCPhysicsBodyInfo.h rename to cocos/physics/chipmunk/CCPhysicsBodyInfo_chipmunk.h index ec84526b59..19e43c23fb 100644 --- a/cocos/physics/chipmunk/CCPhysicsBodyInfo.h +++ b/cocos/physics/chipmunk/CCPhysicsBodyInfo_chipmunk.h @@ -27,6 +27,7 @@ #ifndef __CCPHYSICS_BODY_INFO_H__ #define __CCPHYSICS_BODY_INFO_H__ + #include "chipmunk.h" #include "CCPlatformMacros.h" #include "CCObject.h" @@ -37,7 +38,6 @@ class PhysicsBodyInfo : public Clonable { public: cpBody* body; - cpGroup group; private: PhysicsBodyInfo(); diff --git a/cocos/physics/chipmunk/CCPhysicsContactInfo.cpp b/cocos/physics/chipmunk/CCPhysicsContactInfo_chipmunk.cpp similarity index 97% rename from cocos/physics/chipmunk/CCPhysicsContactInfo.cpp rename to cocos/physics/chipmunk/CCPhysicsContactInfo_chipmunk.cpp index 53b4f29b14..283a4998ab 100644 --- a/cocos/physics/chipmunk/CCPhysicsContactInfo.cpp +++ b/cocos/physics/chipmunk/CCPhysicsContactInfo_chipmunk.cpp @@ -22,7 +22,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "CCPhysicsContactInfo.h" +#include "CCPhysicsContactInfo_chipmunk.h" #if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) NS_CC_BEGIN diff --git a/cocos/physics/chipmunk/CCPhysicsContactInfo.h b/cocos/physics/chipmunk/CCPhysicsContactInfo_chipmunk.h similarity index 99% rename from cocos/physics/chipmunk/CCPhysicsContactInfo.h rename to cocos/physics/chipmunk/CCPhysicsContactInfo_chipmunk.h index 6c302947b7..7dc6561fec 100644 --- a/cocos/physics/chipmunk/CCPhysicsContactInfo.h +++ b/cocos/physics/chipmunk/CCPhysicsContactInfo_chipmunk.h @@ -27,6 +27,7 @@ #ifndef __CCPHYSICS_CONTACT_INFO_H__ #define __CCPHYSICS_CONTACT_INFO_H__ + #include "chipmunk.h" #include "CCPlatformMacros.h" NS_CC_BEGIN diff --git a/cocos/physics/chipmunk/CCPhysicsHelper.h b/cocos/physics/chipmunk/CCPhysicsHelper_chipmunk.h similarity index 100% rename from cocos/physics/chipmunk/CCPhysicsHelper.h rename to cocos/physics/chipmunk/CCPhysicsHelper_chipmunk.h diff --git a/cocos/physics/chipmunk/CCPhysicsJointInfo.cpp b/cocos/physics/chipmunk/CCPhysicsJointInfo_chipmunk.cpp similarity index 98% rename from cocos/physics/chipmunk/CCPhysicsJointInfo.cpp rename to cocos/physics/chipmunk/CCPhysicsJointInfo_chipmunk.cpp index b3fc376710..82053ce4b1 100644 --- a/cocos/physics/chipmunk/CCPhysicsJointInfo.cpp +++ b/cocos/physics/chipmunk/CCPhysicsJointInfo_chipmunk.cpp @@ -22,7 +22,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "CCPhysicsJointInfo.h" +#include "CCPhysicsJointInfo_chipmunk.h" #if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) #include NS_CC_BEGIN diff --git a/cocos/physics/chipmunk/CCPhysicsJointInfo.h b/cocos/physics/chipmunk/CCPhysicsJointInfo_chipmunk.h similarity index 99% rename from cocos/physics/chipmunk/CCPhysicsJointInfo.h rename to cocos/physics/chipmunk/CCPhysicsJointInfo_chipmunk.h index 04a2c716bf..8116c48eae 100644 --- a/cocos/physics/chipmunk/CCPhysicsJointInfo.h +++ b/cocos/physics/chipmunk/CCPhysicsJointInfo_chipmunk.h @@ -27,6 +27,7 @@ #ifndef __CCPHYSICS_JOINT_INFO_H__ #define __CCPHYSICS_JOINT_INFO_H__ + #include "chipmunk.h" #include "CCPlatformMacros.h" #include diff --git a/cocos/physics/chipmunk/CCPhysicsShapeInfo.cpp b/cocos/physics/chipmunk/CCPhysicsShapeInfo_chipmunk.cpp similarity index 98% rename from cocos/physics/chipmunk/CCPhysicsShapeInfo.cpp rename to cocos/physics/chipmunk/CCPhysicsShapeInfo_chipmunk.cpp index 07e5c2f932..74abfc75f1 100644 --- a/cocos/physics/chipmunk/CCPhysicsShapeInfo.cpp +++ b/cocos/physics/chipmunk/CCPhysicsShapeInfo_chipmunk.cpp @@ -22,7 +22,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "CCPhysicsShapeInfo.h" +#include "CCPhysicsShapeInfo_chipmunk.h" #if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) #include NS_CC_BEGIN diff --git a/cocos/physics/chipmunk/CCPhysicsShapeInfo.h b/cocos/physics/chipmunk/CCPhysicsShapeInfo_chipmunk.h similarity index 100% rename from cocos/physics/chipmunk/CCPhysicsShapeInfo.h rename to cocos/physics/chipmunk/CCPhysicsShapeInfo_chipmunk.h diff --git a/cocos/physics/chipmunk/CCPhysicsWorldInfo.cpp b/cocos/physics/chipmunk/CCPhysicsWorldInfo_chipmunk.cpp similarity index 97% rename from cocos/physics/chipmunk/CCPhysicsWorldInfo.cpp rename to cocos/physics/chipmunk/CCPhysicsWorldInfo_chipmunk.cpp index 57f601ead7..f58eebadf2 100644 --- a/cocos/physics/chipmunk/CCPhysicsWorldInfo.cpp +++ b/cocos/physics/chipmunk/CCPhysicsWorldInfo_chipmunk.cpp @@ -22,7 +22,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "CCPhysicsWorldInfo.h" +#include "CCPhysicsWorldInfo_chipmunk.h" #if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) NS_CC_BEGIN diff --git a/cocos/physics/chipmunk/CCPhysicsWorldInfo.h b/cocos/physics/chipmunk/CCPhysicsWorldInfo_chipmunk.h similarity index 99% rename from cocos/physics/chipmunk/CCPhysicsWorldInfo.h rename to cocos/physics/chipmunk/CCPhysicsWorldInfo_chipmunk.h index 71d56f0a5b..158f074c77 100644 --- a/cocos/physics/chipmunk/CCPhysicsWorldInfo.h +++ b/cocos/physics/chipmunk/CCPhysicsWorldInfo_chipmunk.h @@ -27,6 +27,7 @@ #ifndef __CCPHYSICS_WORLD_INFO_H__ #define __CCPHYSICS_WORLD_INFO_H__ + #include "chipmunk.h" #include "CCPlatformMacros.h" NS_CC_BEGIN diff --git a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp index fab2a82437..db51829b3f 100644 --- a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp +++ b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp @@ -10,6 +10,10 @@ namespace CL(PhysicsDemoPlink), CL(PhysicsDemoClickAdd), CL(PhysicsDemoRayCast), + CL(PhysicsDemoJoints), + CL(PhysicsDemoActions), + CL(PhysicsDemoPump), + CL(PhysicsDemoOneWayPlatform), }; static int sceneIdx=-1; @@ -51,6 +55,7 @@ namespace } static const Color4F STATIC_COLOR(1.0f, 0.0f, 0.0f, 1.0f); + static const int DRAG_BODYS_TAG = 0x80; } @@ -92,7 +97,6 @@ PhysicsDemo::PhysicsDemo() : _scene(nullptr) , _ball(nullptr) , _spriteTexture(nullptr) -, _mouse(nullptr) { } @@ -160,7 +164,7 @@ void PhysicsDemo::onEnter() #endif } -void PhysicsDemo::addGrossiniAtPosition(Point p, float scale/* = 1.0*/) +Sprite* PhysicsDemo::addGrossiniAtPosition(Point p, float scale/* = 1.0*/) { #ifdef CC_USE_PHYSICS CCLOG("Add sprite %0.2f x %02.f",p.x,p.y); @@ -178,6 +182,8 @@ void PhysicsDemo::addGrossiniAtPosition(Point p, float scale/* = 1.0*/) sp->setPhysicsBody(PhysicsBody::createBox(Size(48.0f * scale, 108.0f * scale))); this->addChild(sp); sp->setPosition(p); + + return sp; #endif } @@ -198,8 +204,10 @@ void PhysicsDemoClickAdd::onEnter() #ifdef CC_USE_PHYSICS - auto touchListener = EventListenerTouchAllAtOnce::create(); - touchListener->onTouchesEnded = CC_CALLBACK_2(PhysicsDemoClickAdd::onTouchesEnded, this); + auto touchListener = EventListenerTouchOneByOne::create(); + touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsDemoClickAdd::onTouchBegan, this); + touchListener->onTouchMoved = CC_CALLBACK_2(PhysicsDemoClickAdd::onTouchMoved, this); + touchListener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoClickAdd::onTouchEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this); auto accListener = EventListenerAcceleration::create(CC_CALLBACK_2(PhysicsDemoClickAdd::onAcceleration, this)); @@ -316,7 +324,7 @@ namespace } } -Sprite* PhysicsDemo::makeBall(float x, float y, float radius, PhysicsMaterial material) +Sprite* PhysicsDemo::makeBall(Point point, float radius, PhysicsMaterial material) { Sprite* ball = nullptr; if (_ball != nullptr) @@ -331,12 +339,12 @@ Sprite* PhysicsDemo::makeBall(float x, float y, float radius, PhysicsMaterial ma auto body = PhysicsBody::createCircle(radius, material); ball->setPhysicsBody(body); - ball->setPosition(Point(x, y)); + ball->setPosition(Point(point.x, point.y)); return ball; } -Sprite* PhysicsDemo::makeBox(float x, float y, Size size, PhysicsMaterial material) +Sprite* PhysicsDemo::makeBox(Point point, Size size, PhysicsMaterial material) { auto box = CCRANDOM_0_1() > 0.5f ? Sprite::create("Images/YellowSquare.png") : Sprite::create("Images/CyanSquare.png"); @@ -345,12 +353,12 @@ Sprite* PhysicsDemo::makeBox(float x, float y, Size size, PhysicsMaterial materi auto body = PhysicsBody::createBox(size); box->setPhysicsBody(body); - box->setPosition(Point(x, y)); + box->setPosition(Point(point.x, point.y)); return box; } -Sprite* PhysicsDemo::makeTriangle(float x, float y, Size size, PhysicsMaterial material) +Sprite* PhysicsDemo::makeTriangle(Point point, Size size, PhysicsMaterial material) { auto triangle = CCRANDOM_0_1() > 0.5f ? Sprite::create("Images/YellowTriangle.png") : Sprite::create("Images/CyanTriangle.png"); @@ -367,33 +375,66 @@ Sprite* PhysicsDemo::makeTriangle(float x, float y, Size size, PhysicsMaterial m auto body = PhysicsBody::createPolygon(vers, 3); triangle->setPhysicsBody(body); - triangle->setPosition(Point(x, y)); + triangle->setPosition(Point(point.x, point.y)); return triangle; } -void PhysicsDemo::onTouchesBegan(const std::vector& touches, Event* event) +bool PhysicsDemo::onTouchBegan(Touch* touch, Event* event) { - for( auto &touch: touches) + auto location = touch->getLocation(); + Array* arr = _scene->getPhysicsWorld()->getShapesAtPoint(location); + + PhysicsShape* shape = nullptr; + for (Object* obj : *arr) { - auto location = touch->getLocation(); - Array* arr = _scene->getPhysicsWorld()->getShapesAtPoint(location); + shape = dynamic_cast(obj); - PhysicsShape* shape = nullptr; - for (Object* obj : *arr) + if ((shape->getTag() & DRAG_BODYS_TAG) != 0) { - + break; } } + + if (shape != nullptr) + { + + Node* mouse = Node::create(); + mouse->setPhysicsBody(PhysicsBody::create(PHYSICS_INFINITY, PHYSICS_INFINITY)); + mouse->getPhysicsBody()->setDynamic(false); + mouse->setPosition(location); + this->addChild(mouse); + PhysicsJointPin* joint = PhysicsJointPin::create(mouse->getPhysicsBody(), shape->getBody(), location); + joint->setMaxForce(5000.0f * shape->getBody()->getMass()); + _scene->getPhysicsWorld()->addJoint(joint); + _mouses.insert(std::make_pair(touch->getID(), mouse)); + + return true; + } + + return false; +} + +void PhysicsDemo::onTouchMoved(Touch* touch, Event* event) +{ + auto it = _mouses.find(touch->getID()); + + if (it != _mouses.end()) + { + it->second->getPhysicsBody()->setVelocity((touch->getLocation() - it->second->getPosition()) * 60.0f); + it->second->setPosition(touch->getLocation()); + } } -void PhysicsDemo::onTouchesMoved(const std::vector& touches, Event* event) +void PhysicsDemo::onTouchEnded(Touch* touch, Event* event) { + auto it = _mouses.find(touch->getID()); -} - -void PhysicsDemo::onTouchesEnded(const std::vector& touches, Event* event) -{ + if (it != _mouses.end()) + { + this->removeChild(it->second); + _mouses.erase(it); + } } @@ -414,9 +455,9 @@ void PhysicsDemoLogoSmash::onEnter() float x_jitter = 0.05*frand(); float y_jitter = 0.05*frand(); - Node* ball = makeBall(2*(x - logo_width/2 + x_jitter) + VisibleRect::getVisibleRect().size.width/2, - 2*(logo_height-y + y_jitter) + VisibleRect::getVisibleRect().size.height/2 - logo_height/2, - 0.95f, PhysicsMaterial(1.0f, 0.0f, 0.0f)); + Node* ball = makeBall(Point(2*(x - logo_width/2 + x_jitter) + VisibleRect::getVisibleRect().size.width/2, + 2*(logo_height-y + y_jitter) + VisibleRect::getVisibleRect().size.height/2 - logo_height/2), + 0.95f, PhysicsMaterial(0.01f, 0.0f, 0.0f)); ball->getPhysicsBody()->setMass(1.0); ball->getPhysicsBody()->setMoment(PHYSICS_INFINITY); @@ -428,7 +469,7 @@ void PhysicsDemoLogoSmash::onEnter() } - auto bullet = makeBall(400, 0, 10, PhysicsMaterial(PHYSICS_INFINITY, 0, 0)); + auto bullet = makeBall(Point(400, 0), 10, PhysicsMaterial(PHYSICS_INFINITY, 0, 0)); bullet->getPhysicsBody()->setVelocity(Point(400, 0)); bullet->setPosition(Point(-1000, VisibleRect::getVisibleRect().size.height/2)); @@ -445,6 +486,12 @@ void PhysicsDemoPyramidStack::onEnter() { PhysicsDemo::onEnter(); + auto touchListener = EventListenerTouchOneByOne::create(); + touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsDemoPyramidStack::onTouchBegan, this); + touchListener->onTouchMoved = CC_CALLBACK_2(PhysicsDemoPyramidStack::onTouchMoved, this); + touchListener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoPyramidStack::onTouchEnded, this); + _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this); + auto node = Node::create(); node->setPhysicsBody(PhysicsBody::createEdgeSegment(VisibleRect::leftBottom() + Point(0, 50), VisibleRect::rightBottom() + Point(0, 50))); this->addChild(node); @@ -459,7 +506,9 @@ void PhysicsDemoPyramidStack::onEnter() { for(int j=0; j<=i; j++) { - addGrossiniAtPosition(VisibleRect::bottom() + Point((i/2 - j) * 11, (14 - i) * 23 + 100), 0.2f); + auto sp = addGrossiniAtPosition(VisibleRect::bottom() + Point((i/2 - j) * 11, (14 - i) * 23 + 100), 0.2f); + + sp->getPhysicsBody()->setTag(DRAG_BODYS_TAG); } } } @@ -694,13 +743,13 @@ void PhysicsDemoRayCast::onTouchesEnded(const std::vector& touches, Even if (r < 1.0f/3.0f) { - addChild(makeBall(location.x, location.y, 5 + CCRANDOM_0_1()*10)); + addChild(makeBall(location, 5 + CCRANDOM_0_1()*10)); }else if(r < 2.0f/3.0f) { - addChild(makeBox(location.x, location.y, Size(10 + CCRANDOM_0_1()*15, 10 + CCRANDOM_0_1()*15))); + addChild(makeBox(location, Size(10 + CCRANDOM_0_1()*15, 10 + CCRANDOM_0_1()*15))); }else { - addChild(makeTriangle(location.x, location.y, Size(10 + CCRANDOM_0_1()*20, 10 + CCRANDOM_0_1()*20))); + addChild(makeTriangle(location, Size(10 + CCRANDOM_0_1()*20, 10 + CCRANDOM_0_1()*20))); } } } @@ -710,26 +759,307 @@ std::string PhysicsDemoRayCast::title() return "Ray Cast"; } - void PhysicsDemoJoints::onEnter() { PhysicsDemo::onEnter(); - auto listener = EventListenerTouchAllAtOnce::create(); - listener->onTouchesEnded = CC_CALLBACK_2(PhysicsDemoJoints::onTouchesEnded, this); + auto listener = EventListenerTouchOneByOne::create(); + listener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoJoints::onTouchEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - _scene->getPhysicsWorld()->setGravity(Point::ZERO); + //_scene->getPhysicsWorld()->setGravity(Point::ZERO); + float width = (VisibleRect::getVisibleRect().size.width - 10) / 4; + float height = (VisibleRect::getVisibleRect().size.height - 50) / 4; -} - -void PhysicsDemoJoints::onTouchesEnded(const std::vector& touches, Event* event) -{ + Node* node = Node::create(); + PhysicsBody* box = PhysicsBody::create(); + node->setPhysicsBody(box); + box->setDynamic(false); + node->setPosition(Point::ZERO); + this->addChild(node); + + for (int i = 0; i < 4; ++i) + { + for (int j = 0; j < 4; ++j) + { + Point offset(VisibleRect::leftBottom().x + 5 + j * width + width/2, VisibleRect::leftBottom().y + 50 + i * height + height/2); + box->addShape(PhysicsShapeEdgeBox::create(Size(width, height), PHYSICSSHAPE_MATERIAL_DEFAULT, 1, offset)); + + switch (i*4 + j) + { + case 0: + { + auto sp1 = makeBall(offset - Point(30, 0), 10); + sp1->getPhysicsBody()->setTag(DRAG_BODYS_TAG); + auto sp2 = makeBall(offset + Point(30, 0), 10); + sp2->getPhysicsBody()->setTag(DRAG_BODYS_TAG); + + PhysicsJointPin* joint = PhysicsJointPin::create(sp1->getPhysicsBody(), sp2->getPhysicsBody(), offset); + _scene->getPhysicsWorld()->addJoint(joint); + + this->addChild(sp1); + this->addChild(sp2); + break; + } + case 1: + { + + auto sp1 = makeBall(offset - Point(30, 0), 10); + sp1->getPhysicsBody()->setTag(DRAG_BODYS_TAG); + auto sp2 = makeBox(offset + Point(30, 0), Size(30, 10)); + sp2->getPhysicsBody()->setTag(DRAG_BODYS_TAG); + + PhysicsJointFixed* joint = PhysicsJointFixed::create(sp1->getPhysicsBody(), sp2->getPhysicsBody(), offset); + _scene->getPhysicsWorld()->addJoint(joint); + + this->addChild(sp1); + this->addChild(sp2); + break; + } + default: + break; + } + } + } } std::string PhysicsDemoJoints::title() { return "Joints"; +} + +void PhysicsDemoActions::onEnter() +{ + PhysicsDemo::onEnter(); + + auto touchListener = EventListenerTouchOneByOne::create(); + touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsDemoActions::onTouchBegan, this); + touchListener->onTouchMoved = CC_CALLBACK_2(PhysicsDemoActions::onTouchMoved, this); + touchListener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoActions::onTouchEnded, this); + _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this); + + auto node = Node::create(); + node->setPhysicsBody(PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size)); + node->setPosition(VisibleRect::center()); + this->addChild(node); + + Sprite* sp1 = addGrossiniAtPosition(VisibleRect::center()); + Sprite* sp2 = addGrossiniAtPosition(VisibleRect::left() + Point(50, 0)); + Sprite* sp3 = addGrossiniAtPosition(VisibleRect::right() - Point(20, 0)); + Sprite* sp4 = addGrossiniAtPosition(VisibleRect::leftTop() + Point(50, -50)); + sp4->getPhysicsBody()->setGravityEnable(false); + + + auto actionTo = JumpTo::create(2, Point(100,100), 50, 4); + auto actionBy = JumpBy::create(2, Point(300,0), 50, 4); + auto actionUp = JumpBy::create(2, Point(0,50), 80, 4); + auto actionByBack = actionBy->reverse(); + + sp1->runAction(RepeatForever::create(actionUp)); + sp2->runAction(RepeatForever::create(Sequence::create(actionBy, actionByBack, NULL))); + sp3->runAction(actionTo); + sp4->runAction(RepeatForever::create(Sequence::create(actionBy->clone(), actionByBack->clone(), NULL))); +} + +std::string PhysicsDemoActions::title() +{ + return "Actions"; +} + +void PhysicsDemoPump::onEnter() +{ + PhysicsDemo::onEnter(); + + _distance = 0.0f; + _rotationV = 0.0f; + auto touchListener = EventListenerTouchOneByOne::create(); + touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsDemoPump::onTouchBegan, this); + touchListener->onTouchMoved = CC_CALLBACK_2(PhysicsDemoPump::onTouchMoved, this); + touchListener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoPump::onTouchEnded, this); + _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this); + scheduleUpdate(); + + auto node = Node::create(); + auto body = PhysicsBody::create(); + body->setDynamic(false); + + PhysicsMaterial staticMaterial(PHYSICS_INFINITY, 0, 0.5f); + body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(50, 0), VisibleRect::leftTop() + Point(50, -130), staticMaterial, 2.0f)); + body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(190, 0), VisibleRect::leftTop() + Point(100, -50), staticMaterial, 2.0f)); + body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(100, -50), VisibleRect::leftTop() + Point(100, -90), staticMaterial, 2.0f)); + body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(50, -130), VisibleRect::leftTop() + Point(100, -145), staticMaterial, 2.0f)); + body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(100, -145), VisibleRect::leftBottom() + Point(100, 80), staticMaterial, 2.0f)); + body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(150, -80), VisibleRect::leftBottom() + Point(150, 80), staticMaterial, 2.0f)); + body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(150, -80), VisibleRect::rightTop() + Point(-100, -150), staticMaterial, 2.0f)); + + body->setCategoryBitmask(0x01); + + // balls + for (int i = 0; i < 6; ++i) + { + auto ball = makeBall(VisibleRect::leftTop() + Point(75 + CCRANDOM_0_1() * 90, 0), 22, PhysicsMaterial(0.05f, 0.0f, 0.1f)); + ball->getPhysicsBody()->setTag(DRAG_BODYS_TAG); + addChild(ball); + } + + node->setPhysicsBody(body); + this->addChild(node); + + Point vec[4] = + { + VisibleRect::leftTop() + Point(102, -148), + VisibleRect::leftTop() + Point(148, -161), + VisibleRect::leftBottom() + Point(148, 20), + VisibleRect::leftBottom() + Point(102, 20) + }; + + auto _world = _scene->getPhysicsWorld(); + + // small gear + auto sgear = Node::create(); + auto sgearB = PhysicsBody::createCircle(44); + sgear->setPhysicsBody(sgearB); + sgear->setPosition(VisibleRect::leftBottom() + Point(125, 0)); + this->addChild(sgear); + sgearB->setCategoryBitmask(0x04); + sgearB->setCollisionBitmask(0x04); + sgearB->setTag(1); + _world->addJoint(PhysicsJointPin::create(body, sgearB, sgearB->getPosition())); + + + // big gear + auto bgear = Node::create(); + auto bgearB = PhysicsBody::createCircle(100); + bgear->setPhysicsBody(bgearB); + bgear->setPosition(VisibleRect::leftBottom() + Point(275, 0)); + this->addChild(bgear); + bgearB->setCategoryBitmask(0x04); + _world->addJoint(PhysicsJointPin::create(body, bgearB, bgearB->getPosition())); + + + // pump + auto pump = Node::create(); + pump->setPosition(PhysicsShape::getPolyonCenter(vec, 4)); + auto pumpB = PhysicsBody::createPolygon(PhysicsShape::recenterPoints(vec, 4), 4); + pump->setPhysicsBody(pumpB); + this->addChild(pump); + pumpB->setCategoryBitmask(0x02); + pumpB->setGravityEnable(false); + _world->addJoint(PhysicsJointDistance::create(pumpB, sgearB, Point(0, 0), Point(0, -44))); + + // plugger + Point seg[] = {VisibleRect::leftTop() + Point(75, -120), VisibleRect::leftBottom() + Point(75, -100)}; + Point segCenter = (seg[1] + seg[0])/2; + seg[1] -= segCenter; + seg[0] -= segCenter; + auto plugger = Node::create(); + auto pluggerB = PhysicsBody::createEdgeSegment(seg[0], seg[1], PhysicsMaterial(0.01f, 0.0f, 0.5f), 20); + pluggerB->setDynamic(true); + pluggerB->setMass(30); + pluggerB->setMoment(100000); + plugger->setPhysicsBody(pluggerB); + plugger->setPosition(segCenter); + this->addChild(plugger); + pluggerB->setCategoryBitmask(0x02); + sgearB->setCollisionBitmask(0x04 | 0x01); + _world->addJoint(PhysicsJointPin::create(body, pluggerB, VisibleRect::leftBottom() + Point(75, -90))); + _world->addJoint(PhysicsJointDistance::create(pluggerB, sgearB, pluggerB->world2Local(VisibleRect::leftBottom() + Point(75, 0)), Point(44, 0))); +} + +void PhysicsDemoPump::update(float delta) +{ + for (auto obj : *_scene->getPhysicsWorld()->getAllBodies()) + { + PhysicsBody* body = dynamic_cast(obj); + if (body->getTag() == DRAG_BODYS_TAG && body->getPosition().y < 0.0f) + { + body->getNode()->setPosition(VisibleRect::leftTop() + Point(75 + CCRANDOM_0_1() * 90, 0)); + body->setVelocity(Point(0, 0)); + } + } + + PhysicsBody* gear = _scene->getPhysicsWorld()->getBodyByTag(1); + + if (gear != nullptr) + { + if (_distance != 0.0f) + { + _rotationV += _distance/2500.0f; + + if (_rotationV > 30) _rotationV = 30.0f; + if (_rotationV < -30) _rotationV = -30.0f; + } + + gear->setAngularVelocity(_rotationV); + _rotationV *= 0.995f; + } +} + +bool PhysicsDemoPump::onTouchBegan(Touch* touch, Event* event) +{ + PhysicsDemo::onTouchBegan(touch, event); + + _distance = touch->getLocation().x - VisibleRect::center().x; + + return true; +} + +void PhysicsDemoPump::onTouchMoved(Touch* touch, Event* event) +{ + PhysicsDemo::onTouchMoved(touch, event); + + _distance = touch->getLocation().x - VisibleRect::center().x; +} + +void PhysicsDemoPump::onTouchEnded(Touch* touch, Event* event) +{ + PhysicsDemo::onTouchEnded(touch, event); + + _distance = 0; +} + +std::string PhysicsDemoPump::title() +{ + return "Pump"; +} + +void PhysicsDemoOneWayPlatform::onEnter() +{ + PhysicsDemo::onEnter(); + + auto touchListener = EventListenerTouchOneByOne::create(); + touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsDemoOneWayPlatform::onTouchBegan, this); + touchListener->onTouchMoved = CC_CALLBACK_2(PhysicsDemoOneWayPlatform::onTouchMoved, this); + touchListener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoOneWayPlatform::onTouchEnded, this); + _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this); + + auto ground = Node::create(); + ground->setPhysicsBody(PhysicsBody::createEdgeSegment(VisibleRect::leftBottom() + Point(0, 50), VisibleRect::rightBottom() + Point(0, 50))); + this->addChild(ground); + + auto platform = Node::create(); + platform->setPhysicsBody(PhysicsBody::createBox(Size(200, 50))); + platform->getPhysicsBody()->setDynamic(false); + platform->setPosition(VisibleRect::center()); + this->addChild(platform); + + auto ball = makeBall(VisibleRect::center() - Point(0, 50), 5); + ball->getPhysicsBody()->setVelocity(Point(0, 200)); + this->addChild(ball); + + auto contactListener = EventListenerPhysicsContactWithBodies::create(platform->getPhysicsBody(), ball->getPhysicsBody()); + contactListener->onContactPreSolve = CC_CALLBACK_3(PhysicsDemoOneWayPlatform::onPreSolve, this); + _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this); +} + +bool PhysicsDemoOneWayPlatform::onPreSolve(EventCustom* event, const PhysicsContact& contact, const PhysicsContactPreSolve& solve) +{ + return true; +} + +std::string PhysicsDemoOneWayPlatform::title() +{ + return "One Way Platform"; } \ No newline at end of file diff --git a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h index bb737b497d..185c2a3e96 100644 --- a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h +++ b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h @@ -5,6 +5,8 @@ #include "../testBasic.h" #include "../BaseTest.h" +#include + class PhysicsTestScene : public TestScene { @@ -36,19 +38,19 @@ public: void backCallback(Object* sender); void toggleDebugCallback(Object* sender); - void addGrossiniAtPosition(Point p, float scale = 1.0); - Sprite* makeBall(float x, float y, float radius, PhysicsMaterial material = PhysicsMaterial(1.0f, 1.0f, 1.0f)); - Sprite* makeBox(float x, float y, Size size, PhysicsMaterial material = PhysicsMaterial(1.0f, 1.0f, 1.0f)); - Sprite* makeTriangle(float x, float y, Size size, PhysicsMaterial material = PhysicsMaterial(1.0f, 1.0f, 1.0f)); + Sprite* addGrossiniAtPosition(Point p, float scale = 1.0); + Sprite* makeBall(Point point, float radius, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT); + Sprite* makeBox(Point point, Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT); + Sprite* makeTriangle(Point point, Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT); - void onTouchesBegan(const std::vector& touches, Event* event); - void onTouchesMoved(const std::vector& touches, Event* event); - void onTouchesEnded(const std::vector& touches, Event* event); + bool onTouchBegan(Touch* touch, Event* event); + void onTouchMoved(Touch* touch, Event* event); + void onTouchEnded(Touch* touch, Event* event); protected: Texture2D* _spriteTexture; // weak ref SpriteBatchNode* _ball; - DrawNode* _mouse; + std::map _mouses; }; class PhysicsDemoClickAdd : public PhysicsDemo @@ -105,12 +107,40 @@ private: class PhysicsDemoJoints : public PhysicsDemo { public: - PhysicsDemoJoints(); - + void onEnter() override; + std::string title() override; +}; + +class PhysicsDemoActions : public PhysicsDemo +{ public: void onEnter() override; std::string title() override; - void onTouchesEnded(const std::vector& touches, Event* event); +}; + +class PhysicsDemoPump : public PhysicsDemo +{ +public: + void onEnter() override; + std::string title() override; + void update(float delta) override; + + bool onTouchBegan(Touch* touch, Event* event); + void onTouchMoved(Touch* touch, Event* event); + void onTouchEnded(Touch* touch, Event* event); + +private: + float _distance; + float _rotationV; +}; + +class PhysicsDemoOneWayPlatform : public PhysicsDemo +{ +public: + void onEnter() override; + std::string title() override; + + bool onPreSolve(EventCustom* event, const PhysicsContact& contact, const PhysicsContactPreSolve& solve); }; #endif