diff --git a/cocos/2d/CCLayer.cpp b/cocos/2d/CCLayer.cpp index 19346ea844..fe57da15fd 100644 --- a/cocos/2d/CCLayer.cpp +++ b/cocos/2d/CCLayer.cpp @@ -476,30 +476,6 @@ void Layer::onTouchesCancelled(const std::vector& pTouches, Event *pEven CC_UNUSED_PARAM(pEvent); } - -#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 0dad16ff21..9280bdc6aa 100644 --- a/cocos/2d/CCLayer.h +++ b/cocos/2d/CCLayer.h @@ -179,12 +179,6 @@ public: * @lua NA */ virtual void onEnterTransitionDidFinish() override; - -#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 protected: void addTouchListener(); diff --git a/cocos/2d/CCNode.cpp b/cocos/2d/CCNode.cpp index 99283b95a8..53ea8d3f18 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" @@ -626,6 +627,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; @@ -1392,10 +1404,12 @@ void Node::setPhysicsBody(PhysicsBody* body) { if (_physicsBody != nullptr) { + _physicsBody->_owner = nullptr; _physicsBody->release(); } _physicsBody = body; + _physicsBody->_owner = this; _physicsBody->retain(); _physicsBody->setPosition(getPosition()); _physicsBody->setRotation(getRotation()); diff --git a/cocos/2d/CCScene.cpp b/cocos/2d/CCScene.cpp index cc8654204b..5d0de936de 100644 --- a/cocos/2d/CCScene.cpp +++ b/cocos/2d/CCScene.cpp @@ -136,14 +136,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 +145,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 b4be9bd045..af41111808 100644 --- a/cocos/2d/CCSpriteBatchNode.cpp +++ b/cocos/2d/CCSpriteBatchNode.cpp @@ -182,17 +182,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/physics/CCPhysicsBody.h b/cocos/physics/CCPhysicsBody.h index c1a3d4b1a1..7d569075f8 100644 --- a/cocos/physics/CCPhysicsBody.h +++ b/cocos/physics/CCPhysicsBody.h @@ -44,7 +44,7 @@ class PhysicsJoint; class PhysicsBodyInfo; -const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT(1.0f, 1.0f, 1.0f); +const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT(0.01f, 0.5f, 0.5f); /** * A body affect by physics. @@ -152,7 +152,7 @@ public: /* * @brief get the sprite the body set to. */ - inline Sprite* getOwner() const { return _owner; } + inline Node* getOwner() const { return _owner; } inline void setCategoryBitmask(int bitmask) { _categoryBitmask = bitmask; } inline int getCategoryBitmask() const { return _categoryBitmask; } @@ -261,7 +261,7 @@ protected: virtual ~PhysicsBody(); protected: - Sprite* _owner; + Node* _owner; std::vector _joints; Array* _shapes; PhysicsWorld* _world; diff --git a/cocos/physics/CCPhysicsJoint.cpp b/cocos/physics/CCPhysicsJoint.cpp index c7ca4ef2f9..0abca9e9a4 100644 --- a/cocos/physics/CCPhysicsJoint.cpp +++ b/cocos/physics/CCPhysicsJoint.cpp @@ -41,6 +41,7 @@ #include "box2d/CCPhysicsShapeInfo.h" #include "chipmunk/CCPhysicsHelper.h" #include "box2d/CCPhysicsHelper.h" +#include "CCNode.h" NS_CC_BEGIN @@ -149,6 +150,11 @@ PhysicsBodyInfo* PhysicsJoint::bodyInfo(PhysicsBody* body) const return body->_info; } +Node* PhysicsJoint::bodyOwner(PhysicsBody* body) const +{ + return body->_owner; +} + void PhysicsJoint::setCollisionEnable(bool enable) { @@ -182,6 +188,9 @@ bool PhysicsJointFixed::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr) { CC_BREAK_IF(!PhysicsJoint::init(a, b)); + bodyOwner(a)->setPosition(anchr); + bodyOwner(b)->setPosition(anchr); + // add a pivot joint to fixed two body together cpConstraint* joint = cpPivotJointNew(bodyInfo(a)->body, bodyInfo(b)->body, PhysicsHelper::point2cpv(anchr)); @@ -219,7 +228,6 @@ 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, PhysicsHelper::point2cpv(anchr)); @@ -227,7 +235,7 @@ bool PhysicsJointPin::init(PhysicsBody *a, PhysicsBody *b, const Point& anchr) _info->add(joint); - setCollisionEnable(false); + //setCollisionEnable(false); return true; } while (false); @@ -235,6 +243,16 @@ bool PhysicsJointPin::init(PhysicsBody *a, PhysicsBody *b, const Point& anchr) return false; } +void PhysicsJointPin::setMaxForce(float force) +{ + _info->joints.front()->maxForce = PhysicsHelper::float2cpfloat(force); +} + +float PhysicsJointPin::getMaxForce() +{ + 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(); diff --git a/cocos/physics/CCPhysicsJoint.h b/cocos/physics/CCPhysicsJoint.h index 67e05cb858..d6c0d5df15 100644 --- a/cocos/physics/CCPhysicsJoint.h +++ b/cocos/physics/CCPhysicsJoint.h @@ -63,6 +63,7 @@ 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; + Node* bodyOwner(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); @@ -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(); + protected: bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr); diff --git a/cocos/physics/CCPhysicsShape.h b/cocos/physics/CCPhysicsShape.h index 6cd5329f6d..02e6f604c0 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. diff --git a/cocos/physics/CCPhysicsWorld.cpp b/cocos/physics/CCPhysicsWorld.cpp index 915daa040e..c01f9ac640 100644 --- a/cocos/physics/CCPhysicsWorld.cpp +++ b/cocos/physics/CCPhysicsWorld.cpp @@ -524,7 +524,7 @@ int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact) if (!joint->isCollisionEnable()) { - PhysicsBody* body = joint->getBodyA() == bodyA ? bodyB : bodyA; + PhysicsBody* body = joint->getBodyA() == bodyA ? joint->getBodyB() : joint->getBodyA(); if (body == bodyB) { diff --git a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp index 304981c448..51d5d3252c 100644 --- a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp +++ b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp @@ -10,6 +10,7 @@ namespace CL(PhysicsDemoPlink), CL(PhysicsDemoClickAdd), CL(PhysicsDemoRayCast), + CL(PhysicsDemoJoints), }; static int sceneIdx=-1; @@ -51,6 +52,7 @@ namespace } static const Color4F STATIC_COLOR(1.0f, 0.0f, 0.0f, 1.0f); + static const int DRAG_BODYS_TAG = 100; } @@ -378,7 +380,7 @@ bool PhysicsDemo::onTouchBegan(Touch* touch, Event* event) { shape = dynamic_cast(obj); - if (shape->getTag() == 1) + if (shape->getTag() == DRAG_BODYS_TAG) { break; } @@ -392,7 +394,8 @@ bool PhysicsDemo::onTouchBegan(Touch* touch, Event* event) mouse->getPhysicsBody()->setDynamic(false); mouse->setPosition(location); this->addChild(mouse); - PhysicsJoint* joint = PhysicsJointPin::create(mouse->getPhysicsBody(), shape->getBody(), location); + PhysicsJointPin* joint = PhysicsJointPin::create(mouse->getPhysicsBody(), shape->getBody(), location); + joint->setMaxForce(5000.0f); _scene->getPhysicsWorld()->addJoint(joint); _mouses.insert(std::make_pair(touch->getID(), mouse)); @@ -492,7 +495,7 @@ void PhysicsDemoPyramidStack::onEnter() { auto sp = addGrossiniAtPosition(VisibleRect::bottom() + Point((i/2 - j) * 11, (14 - i) * 23 + 100), 0.2f); - sp->getPhysicsBody()->setTag(1); + sp->getPhysicsBody()->setTag(DRAG_BODYS_TAG); } } } @@ -741,15 +744,74 @@ std::string PhysicsDemoRayCast::title() } +PhysicsDemoJoints::PhysicsDemoJoints() +{ + +} + void PhysicsDemoJoints::onEnter() { PhysicsDemo::onEnter(); setTouchEnabled(true); + setTouchMode(Touch::DispatchMode::ONE_BY_ONE); - _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; + 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.x - 30, offset.y, 10); + sp1->getPhysicsBody()->setTag(DRAG_BODYS_TAG); + auto sp2 = makeBall(offset.x + 30, offset.y, 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.x - 30, offset.y, 10); + sp1->getPhysicsBody()->setTag(DRAG_BODYS_TAG); + auto sp2 = makeBox(offset.x + 30, offset.y, 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() diff --git a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h index 736c71574a..fe58196372 100644 --- a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h +++ b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h @@ -39,9 +39,9 @@ public: void toggleDebugCallback(Object* sender); Sprite* 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* makeBall(float x, float y, float radius, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT); + Sprite* makeBox(float x, float y, Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT); + Sprite* makeTriangle(float x, float y, Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT); bool onTouchBegan(Touch* touch, Event* event) override; void onTouchMoved(Touch* touch, Event* event) override;