From 2c66f1b95e25d4bc787a9f83a16cba77127c7ff7 Mon Sep 17 00:00:00 2001 From: boyu0 Date: Mon, 16 Sep 2013 21:22:22 +0800 Subject: [PATCH] issue #2771: Implement the minimum set of physical API. Improve the PhysicsTest --- .../project.pbxproj.REMOVED.git-id | 2 +- cocos2dx/include/cocos2d.h | 4 +- .../CCLayer.cpp | 25 + .../layers_scenes_transitions_nodes/CCLayer.h | 7 + .../CCScene.cpp | 25 +- .../layers_scenes_transitions_nodes/CCScene.h | 18 +- .../CCPhysicsBodyInfo.cpp} | 16 + cocos2dx/physics/Box2D/CCPhysicsBodyInfo.h | 43 ++ .../physics/Box2D/CCPhysicsContactInfo.cpp | 39 ++ cocos2dx/physics/Box2D/CCPhysicsContactInfo.h | 43 ++ .../CCPhysicsHelper.h} | 36 +- .../CCPhysicsJointInfo.cpp} | 16 + cocos2dx/physics/Box2D/CCPhysicsJointInfo.h | 43 ++ cocos2dx/physics/Box2D/CCPhysicsShapeInfo.cpp | 39 ++ cocos2dx/physics/Box2D/CCPhysicsShapeInfo.h | 43 ++ cocos2dx/physics/Box2D/CCPhysicsWorldInfo.cpp | 39 ++ cocos2dx/physics/Box2D/CCPhysicsWorldInfo.h | 43 ++ cocos2dx/physics/CCPhysicsBody.cpp | 346 ++++++++++++-- cocos2dx/physics/CCPhysicsBody.h | 96 ++-- cocos2dx/physics/CCPhysicsContact.cpp | 137 ++++++ cocos2dx/physics/CCPhysicsContact.h | 136 ++++++ cocos2dx/physics/CCPhysicsJoint.cpp | 195 ++++++++ cocos2dx/physics/CCPhysicsJoint.h | 49 +- cocos2dx/physics/CCPhysicsSetting.h | 8 + cocos2dx/physics/CCPhysicsShape.cpp | 426 +++++++++++++++++ cocos2dx/physics/CCPhysicsShape.h | 182 +++++++ cocos2dx/physics/CCPhysicsWorld.cpp | 275 ++++++++++- cocos2dx/physics/CCPhysicsWorld.h | 53 ++- .../physics/chipmunk/CCPhysicsBodyInfo.cpp | 45 ++ .../CCPhysicsBodyInfo.h} | 32 +- .../physics/chipmunk/CCPhysicsContactInfo.cpp | 39 ++ .../physics/chipmunk/CCPhysicsContactInfo.h | 49 ++ cocos2dx/physics/chipmunk/CCPhysicsHelper.h | 68 +++ .../physics/chipmunk/CCPhysicsJointInfo.cpp | 43 ++ .../physics/chipmunk/CCPhysicsJointInfo.h | 50 ++ .../physics/chipmunk/CCPhysicsShapeInfo.cpp | 70 +++ .../physics/chipmunk/CCPhysicsShapeInfo.h | 61 +++ .../physics/chipmunk/CCPhysicsWorldInfo.cpp | 40 ++ .../physics/chipmunk/CCPhysicsWorldInfo.h | 48 ++ cocos2dx/physics/chipmunk/ChipmunkDebugDraw.c | 446 ++++++++++++++++++ cocos2dx/physics/chipmunk/ChipmunkDebugDraw.h | 50 ++ cocos2dx/sprite_nodes/CCSprite.cpp | 61 ++- cocos2dx/sprite_nodes/CCSprite.h | 2 + .../Classes/PhysicsTest/PhysicsTest.cpp | 114 +++-- .../TestCpp/Classes/PhysicsTest/PhysicsTest.h | 4 +- 45 files changed, 3379 insertions(+), 227 deletions(-) rename cocos2dx/physics/{CCPhysicsContactDelegate.cpp => Box2D/CCPhysicsBodyInfo.cpp} (84%) create mode 100644 cocos2dx/physics/Box2D/CCPhysicsBodyInfo.h create mode 100644 cocos2dx/physics/Box2D/CCPhysicsContactInfo.cpp create mode 100644 cocos2dx/physics/Box2D/CCPhysicsContactInfo.h rename cocos2dx/physics/{CCPhysicsFixture.h => Box2D/CCPhysicsHelper.h} (60%) rename cocos2dx/physics/{CCPhysicsFixture.cpp => Box2D/CCPhysicsJointInfo.cpp} (84%) create mode 100644 cocos2dx/physics/Box2D/CCPhysicsJointInfo.h create mode 100644 cocos2dx/physics/Box2D/CCPhysicsShapeInfo.cpp create mode 100644 cocos2dx/physics/Box2D/CCPhysicsShapeInfo.h create mode 100644 cocos2dx/physics/Box2D/CCPhysicsWorldInfo.cpp create mode 100644 cocos2dx/physics/Box2D/CCPhysicsWorldInfo.h create mode 100644 cocos2dx/physics/CCPhysicsContact.cpp create mode 100644 cocos2dx/physics/CCPhysicsContact.h create mode 100644 cocos2dx/physics/CCPhysicsShape.cpp create mode 100644 cocos2dx/physics/CCPhysicsShape.h create mode 100644 cocos2dx/physics/chipmunk/CCPhysicsBodyInfo.cpp rename cocos2dx/physics/{CCPhysicsContactDelegate.h => chipmunk/CCPhysicsBodyInfo.h} (69%) create mode 100644 cocos2dx/physics/chipmunk/CCPhysicsContactInfo.cpp create mode 100644 cocos2dx/physics/chipmunk/CCPhysicsContactInfo.h create mode 100644 cocos2dx/physics/chipmunk/CCPhysicsHelper.h create mode 100644 cocos2dx/physics/chipmunk/CCPhysicsJointInfo.cpp create mode 100644 cocos2dx/physics/chipmunk/CCPhysicsJointInfo.h create mode 100644 cocos2dx/physics/chipmunk/CCPhysicsShapeInfo.cpp create mode 100644 cocos2dx/physics/chipmunk/CCPhysicsShapeInfo.h create mode 100644 cocos2dx/physics/chipmunk/CCPhysicsWorldInfo.cpp create mode 100644 cocos2dx/physics/chipmunk/CCPhysicsWorldInfo.h create mode 100644 cocos2dx/physics/chipmunk/ChipmunkDebugDraw.c create mode 100644 cocos2dx/physics/chipmunk/ChipmunkDebugDraw.h diff --git a/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id b/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id index 1eaf467207..ac85a298cf 100644 --- a/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -cbb5290ea17f6020e0249818c08c9d94a17dd073 \ No newline at end of file +f64b17366179be63ab250b6a65922b95efbd9712 \ No newline at end of file diff --git a/cocos2dx/include/cocos2d.h b/cocos2dx/include/cocos2d.h index d8ee1e9099..a841f7fa5c 100755 --- a/cocos2dx/include/cocos2d.h +++ b/cocos2dx/include/cocos2d.h @@ -126,8 +126,8 @@ THE SOFTWARE. // physics #include "physics/CCPhysicsBody.h" -#include "physics/CCPhysicsContactDelegate.h" -#include "physics/CCPhysicsFixture.h" +#include "physics/CCPhysicsContact.h" +#include "physics/CCPhysicsShape.h" #include "physics/CCPhysicsJoint.h" #include "physics/CCPhysicsWorld.h" diff --git a/cocos2dx/layers_scenes_transitions_nodes/CCLayer.cpp b/cocos2dx/layers_scenes_transitions_nodes/CCLayer.cpp index c00cf03903..04043c332e 100644 --- a/cocos2dx/layers_scenes_transitions_nodes/CCLayer.cpp +++ b/cocos2dx/layers_scenes_transitions_nodes/CCLayer.cpp @@ -38,6 +38,7 @@ THE SOFTWARE. // extern #include "kazmath/GL/matrix.h" #include "keyboard_dispatcher/CCKeyboardDispatcher.h" +#include "CCScene.h" NS_CC_BEGIN @@ -499,6 +500,30 @@ void Layer::ccTouchesCancelled(Set *pTouches, Event *pEvent) 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/cocos2dx/layers_scenes_transitions_nodes/CCLayer.h b/cocos2dx/layers_scenes_transitions_nodes/CCLayer.h index 32e8991b75..1c7792a29a 100644 --- a/cocos2dx/layers_scenes_transitions_nodes/CCLayer.h +++ b/cocos2dx/layers_scenes_transitions_nodes/CCLayer.h @@ -36,6 +36,7 @@ THE SOFTWARE. #ifdef EMSCRIPTEN #include "base_nodes/CCGLBufferedNode.h" #endif // EMSCRIPTEN +#include "physics/CCPhysicsSetting.h" NS_CC_BEGIN @@ -138,6 +139,12 @@ public: virtual void onEnter() override; virtual void onExit() override; 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: bool _touchEnabled; diff --git a/cocos2dx/layers_scenes_transitions_nodes/CCScene.cpp b/cocos2dx/layers_scenes_transitions_nodes/CCScene.cpp index 589a77d60b..36f2947dc6 100644 --- a/cocos2dx/layers_scenes_transitions_nodes/CCScene.cpp +++ b/cocos2dx/layers_scenes_transitions_nodes/CCScene.cpp @@ -99,12 +99,14 @@ bool Scene::initWithPhysics() CC_BREAK_IF( ! (pDirector = Director::getInstance()) ); this->setContentSize(pDirector->getWinSize()); CC_BREAK_IF(! (_physicsWorld = PhysicsWorld::create())); + _physicsWorld->setScene(this); + + this->scheduleUpdate(); // success bRet = true; } while (0); return bRet; } -#endif void Scene::addChild(Node* child) { @@ -120,23 +122,27 @@ void Scene::addChild(Node* child, int zOrder, int tag) { Node::addChild(child, zOrder, tag); -#ifdef CC_USE_PHYSICS + addChildToPhysicsWorld(child); +} + +void Scene::addChildToPhysicsWorld(Node* child) +{ if (_physicsWorld) { auto addToPhysicsWorldFunc = [this](Object* node) -> void { - if (typeid(Sprite).hash_code() == typeid(node).hash_code()) + if (dynamic_cast(node) != nullptr) { Sprite* sp = dynamic_cast(node); - if (sp && sp->getPhysicsBody()) + if (sp->getPhysicsBody()) { _physicsWorld->addChild(sp->getPhysicsBody()); } } }; - if(typeid(Layer).hash_code() == typeid(child).hash_code()) + if(dynamic_cast(child) != nullptr) { Object* subChild = nullptr; CCARRAY_FOREACH(child->getChildren(), subChild) @@ -148,8 +154,15 @@ void Scene::addChild(Node* child, int zOrder, int tag) addToPhysicsWorldFunc(child); } } -#endif } +void Scene::update(float delta) +{ + Node::update(delta); + + _physicsWorld->update(delta); +} +#endif + NS_CC_END diff --git a/cocos2dx/layers_scenes_transitions_nodes/CCScene.h b/cocos2dx/layers_scenes_transitions_nodes/CCScene.h index 4b5b27f4a4..217d01c756 100644 --- a/cocos2dx/layers_scenes_transitions_nodes/CCScene.h +++ b/cocos2dx/layers_scenes_transitions_nodes/CCScene.h @@ -60,22 +60,30 @@ public: virtual ~Scene(); bool init(); + #ifdef CC_USE_PHYSICS +public: bool initWithPhysics(); -#endif virtual void addChild(Node* child) override; virtual void addChild(Node* child, int zOrder) override; virtual void addChild(Node* child, int zOrder, int tag) override; -#ifdef CC_USE_PHYSICS + /* + * Update method will be called automatically every frame if "scheduleUpdate" is called, and the node is "live" + */ + virtual void update(float delta) override; + inline PhysicsWorld* getPhysicsWorld() { return _physicsWorld; } -#endif protected: -#ifdef CC_USE_PHYSICS + virtual void addChildToPhysicsWorld(Node* child); + +protected: PhysicsWorld* _physicsWorld; -#endif +#endif // CC_USE_PHYSICS + + friend class Layer; }; // end of scene group diff --git a/cocos2dx/physics/CCPhysicsContactDelegate.cpp b/cocos2dx/physics/Box2D/CCPhysicsBodyInfo.cpp similarity index 84% rename from cocos2dx/physics/CCPhysicsContactDelegate.cpp rename to cocos2dx/physics/Box2D/CCPhysicsBodyInfo.cpp index 39b3eedbc5..bfa20b616a 100644 --- a/cocos2dx/physics/CCPhysicsContactDelegate.cpp +++ b/cocos2dx/physics/Box2D/CCPhysicsBodyInfo.cpp @@ -21,3 +21,19 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ + +#include "CCPhysicsBodyInfo.h" + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) +NS_CC_BEGIN + +PhysicsBodyInfo::PhysicsBodyInfo() +{ +} + +PhysicsBodyInfo::~PhysicsBodyInfo() +{ +} + +NS_CC_END +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D diff --git a/cocos2dx/physics/Box2D/CCPhysicsBodyInfo.h b/cocos2dx/physics/Box2D/CCPhysicsBodyInfo.h new file mode 100644 index 0000000000..730837ed9d --- /dev/null +++ b/cocos2dx/physics/Box2D/CCPhysicsBodyInfo.h @@ -0,0 +1,43 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "../CCPhysicsSetting.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) + +#ifndef __CCPHYSICS_BODY_INFO_H__ +#define __CCPHYSICS_BODY_INFO_H__ +#include "platform/CCPlatformMacros.h" +NS_CC_BEGIN + +class PhysicsBodyInfo +{ +public: + PhysicsBodyInfo(); + ~PhysicsBodyInfo(); +}; + +NS_CC_END +#endif // __CCPHYSICS_BODY_INFO_H__ + +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D diff --git a/cocos2dx/physics/Box2D/CCPhysicsContactInfo.cpp b/cocos2dx/physics/Box2D/CCPhysicsContactInfo.cpp new file mode 100644 index 0000000000..41eaa4f831 --- /dev/null +++ b/cocos2dx/physics/Box2D/CCPhysicsContactInfo.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCPhysicsContactInfo.h" + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) +NS_CC_BEGIN + +PhysicsContactInfo::PhysicsContactInfo() +{ +} + +PhysicsContactInfo::~PhysicsContactInfo() +{ +} + +NS_CC_END +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D diff --git a/cocos2dx/physics/Box2D/CCPhysicsContactInfo.h b/cocos2dx/physics/Box2D/CCPhysicsContactInfo.h new file mode 100644 index 0000000000..b592caa0af --- /dev/null +++ b/cocos2dx/physics/Box2D/CCPhysicsContactInfo.h @@ -0,0 +1,43 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "../CCPhysicsSetting.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) + +#ifndef __CCPHYSICS_CONTACT_INFO_H__ +#define __CCPHYSICS_CONTACT_INFO_H__ +#include "platform/CCPlatformMacros.h" +NS_CC_BEGIN + +class PhysicsContactInfo +{ +public: + PhysicsContactInfo(); + ~PhysicsContactInfo(); +}; + +NS_CC_END +#endif // __CCPHYSICS_CONTACT_INFO_H__ + +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D diff --git a/cocos2dx/physics/CCPhysicsFixture.h b/cocos2dx/physics/Box2D/CCPhysicsHelper.h similarity index 60% rename from cocos2dx/physics/CCPhysicsFixture.h rename to cocos2dx/physics/Box2D/CCPhysicsHelper.h index e743ab3c44..86ef7d74ee 100644 --- a/cocos2dx/physics/CCPhysicsFixture.h +++ b/cocos2dx/physics/Box2D/CCPhysicsHelper.h @@ -22,42 +22,22 @@ THE SOFTWARE. ****************************************************************************/ -#include "CCPhysicsSetting.h" -#ifdef CC_USE_PHYSICS +#include "../CCPhysicsSetting.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) -#ifndef __CCPHYSICS_FIXTURE_H__ -#define __CCPHYSICS_FIXTURE_H__ +#ifndef __CCPHYSICS_HELPER_H__ +#define __CCPHYSICS_HELPER_H__ -#include "cocoa/CCObject.h" +#include "platform/CCPlatformMacros.h" #include "cocoa/CCGeometry.h" NS_CC_BEGIN -class PhysicsFixture : public Object +class PhysicsHelper { -public: - static PhysicsFixture* createCircle(Point centre, float radius); - static PhysicsFixture* createRectangle(Rect rect); - static PhysicsFixture* createPolygon(Array* points); - - static PhysicsFixture* createEdgeSegment(Point x, Point y); - static PhysicsFixture* createEdgeCircle(Point centre, float radius); - static PhysicsFixture* createEdgeRectangle(Rect rect); - static PhysicsFixture* createEdgePolygon(Array* points); - -protected: - bool init(); - -protected: - PhysicsFixture(); - virtual ~PhysicsFixture(); - -protected: - float _density; - float _friction; }; NS_CC_END -#endif // __CCPHYSICS_FIXTURE_H__ +#endif // __CCPHYSICS_HELPER_H__ -#endif // CC_USE_PHYSICS +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D diff --git a/cocos2dx/physics/CCPhysicsFixture.cpp b/cocos2dx/physics/Box2D/CCPhysicsJointInfo.cpp similarity index 84% rename from cocos2dx/physics/CCPhysicsFixture.cpp rename to cocos2dx/physics/Box2D/CCPhysicsJointInfo.cpp index 39b3eedbc5..753ba41534 100644 --- a/cocos2dx/physics/CCPhysicsFixture.cpp +++ b/cocos2dx/physics/Box2D/CCPhysicsJointInfo.cpp @@ -21,3 +21,19 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ + +#include "CCPhysicsJointInfo.h" + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) +NS_CC_BEGIN + +PhysicsJointInfo::PhysicsJointInfo() +{ +} + +PhysicsJointInfo::~PhysicsJointInfo() +{ +} + +NS_CC_END +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D diff --git a/cocos2dx/physics/Box2D/CCPhysicsJointInfo.h b/cocos2dx/physics/Box2D/CCPhysicsJointInfo.h new file mode 100644 index 0000000000..abcf089387 --- /dev/null +++ b/cocos2dx/physics/Box2D/CCPhysicsJointInfo.h @@ -0,0 +1,43 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "../CCPhysicsSetting.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) + +#ifndef __CCPHYSICS_JOINT_INFO_H__ +#define __CCPHYSICS_JOINT_INFO_H__ +#include "platform/CCPlatformMacros.h" +NS_CC_BEGIN + +class PhysicsJointInfo +{ +public: + PhysicsJointInfo(); + ~PhysicsJointInfo(); +}; + +NS_CC_END +#endif // __CCPHYSICS_JOINT_INFO_H__ + +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D diff --git a/cocos2dx/physics/Box2D/CCPhysicsShapeInfo.cpp b/cocos2dx/physics/Box2D/CCPhysicsShapeInfo.cpp new file mode 100644 index 0000000000..a89ba7dae7 --- /dev/null +++ b/cocos2dx/physics/Box2D/CCPhysicsShapeInfo.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCPhysicsShapeInfo.h" + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) +NS_CC_BEGIN + +PhysicsShapeInfo::PhysicsShapeInfo() +{ +} + +PhysicsShapeInfo::~PhysicsShapeInfo() +{ +} + +NS_CC_END +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D diff --git a/cocos2dx/physics/Box2D/CCPhysicsShapeInfo.h b/cocos2dx/physics/Box2D/CCPhysicsShapeInfo.h new file mode 100644 index 0000000000..9091001887 --- /dev/null +++ b/cocos2dx/physics/Box2D/CCPhysicsShapeInfo.h @@ -0,0 +1,43 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "../CCPhysicsSetting.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) + +#ifndef __CCPHYSICS_SHAPE_INFO_H__ +#define __CCPHYSICS_SHAPE_INFO_H__ +#include "platform/CCPlatformMacros.h" +NS_CC_BEGIN + +class PhysicsShapeInfo +{ +public: + PhysicsShapeInfo(); + ~PhysicsShapeInfo(); +}; + +NS_CC_END +#endif // __CCPHYSICS_SHAPE_INFO_H__ + +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D diff --git a/cocos2dx/physics/Box2D/CCPhysicsWorldInfo.cpp b/cocos2dx/physics/Box2D/CCPhysicsWorldInfo.cpp new file mode 100644 index 0000000000..0de6c00d82 --- /dev/null +++ b/cocos2dx/physics/Box2D/CCPhysicsWorldInfo.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCPhysicsWorldInfo.h" + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) +NS_CC_BEGIN + +PhysicsWorldInfo::PhysicsWorldInfo() +{ +} + +PhysicsWorldInfo::~PhysicsWorldInfo() +{ +} + +NS_CC_END +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D diff --git a/cocos2dx/physics/Box2D/CCPhysicsWorldInfo.h b/cocos2dx/physics/Box2D/CCPhysicsWorldInfo.h new file mode 100644 index 0000000000..bcc09124db --- /dev/null +++ b/cocos2dx/physics/Box2D/CCPhysicsWorldInfo.h @@ -0,0 +1,43 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "../CCPhysicsSetting.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) + +#ifndef __CCPHYSICS_WORLD_INFO_H__ +#define __CCPHYSICS_WORLD_INFO_H__ +#include "platform/CCPlatformMacros.h" +NS_CC_BEGIN + +class PhysicsWorldInfo +{ +public: + PhysicsWorldInfo(); + ~PhysicsWorldInfo(); +}; + +NS_CC_END +#endif // __CCPHYSICS_WORLD_INFO_H__ + +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D diff --git a/cocos2dx/physics/CCPhysicsBody.cpp b/cocos2dx/physics/CCPhysicsBody.cpp index 0b2309a1c1..588586dded 100644 --- a/cocos2dx/physics/CCPhysicsBody.cpp +++ b/cocos2dx/physics/CCPhysicsBody.cpp @@ -22,51 +22,74 @@ THE SOFTWARE. ****************************************************************************/ #include "CCPhysicsBody.h" - #ifdef CC_USE_PHYSICS +#include "CCPhysicsShape.h" +#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/CCPhysicsHelper.h" +#include "Box2D/CCPhysicsHelper.h" + NS_CC_BEGIN #if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) -class PhysicsBodyInfo +namespace { -public: - PhysicsBodyInfo(); - ~PhysicsBodyInfo(); - -public: - cpBody* body; - cpShape* shape; -}; - -PhysicsBodyInfo::PhysicsBodyInfo() -: body(nullptr) -, shape(nullptr) -{ -} - -PhysicsBodyInfo::~PhysicsBodyInfo() -{ - if (body) cpBodyFree(body); - if (shape) cpShapeFree(shape); + static const float MASS_DEFAULT = 1.0; + static const float DENSITY_DEFAULT = 1.0; + static const float ANGULARDAMPING_DEFAULT = 200; } PhysicsBody::PhysicsBody() +: _owner(nullptr) +, _world(nullptr) +, _info(nullptr) +, _dynamic(false) +, _massDefault(true) +, _angularDampingDefault(true) +, _mass(MASS_DEFAULT) +, _area(0.0) +, _density(DENSITY_DEFAULT) +, _angularDamping(ANGULARDAMPING_DEFAULT) { } PhysicsBody::~PhysicsBody() { CC_SAFE_DELETE(_info); + + for (auto it = _shapes.begin(); it != _shapes.end(); ++it) + { + delete *it; + } + + for (auto it = _joints.begin(); it != _joints.end(); ++it) + { + PhysicsJoint* joint = *it; + PhysicsBody* other = joint->getBodyA() == this ? joint->getBodyA() : joint->getBodyB(); + + other->_joints.erase(std::find(other->_joints.begin(), other->_joints.end(), joint)); + delete joint; + } } -PhysicsBody* PhysicsBody::create() +PhysicsBody* PhysicsBody::createCircle(float radius) { - PhysicsBody * body = new PhysicsBody(); - if(body && body->init()) + PhysicsBody* body = new PhysicsBody(); + if (body && body->init()) { + body->addCircle(radius); + body->autorelease(); return body; } @@ -74,6 +97,156 @@ PhysicsBody* PhysicsBody::create() return nullptr; } +PhysicsBody* PhysicsBody::createBox(Size size) +{ + PhysicsBody* body = new PhysicsBody(); + if (body && body->init()) + { + body->addBox(size); + body->autorelease(); + return body; + } + + CC_SAFE_DELETE(body); + return nullptr; +} + +PhysicsBody* PhysicsBody::createPolygon(Point* points, int count) +{ + PhysicsBody* body = new PhysicsBody(); + if (body && body->init()) + { + body->addPolygon(points, count); + body->autorelease(); + return body; + } + + CC_SAFE_DELETE(body); + return nullptr; +} + +PhysicsBody* PhysicsBody::createEdgeSegment(Point a, Point b, float border/* = 1*/) +{ + PhysicsBody* body = new PhysicsBody(); + if (body && body->initStatic()) + { + body->addEdgeSegment(a, b, border); + body->autorelease(); + return body; + } + + CC_SAFE_DELETE(body); + return nullptr; +} + +PhysicsBody* PhysicsBody::createEdgeBox(Size size, float border/* = 1*/) +{ + PhysicsBody* body = new PhysicsBody(); + if (body && body->initStatic()) + { + body->addEdgeBox(size, border); + body->autorelease(); + return body; + } + + CC_SAFE_DELETE(body); + + return nullptr; +} + +PhysicsBody* PhysicsBody::createEdgePolygon(Point* points, int count, float border/* = 1*/) +{ + PhysicsBody* body = new PhysicsBody(); + if (body && body->initStatic()) + { + body->addEdgePolygon(points, count, border); + body->autorelease(); + return body; + } + + CC_SAFE_DELETE(body); + + return nullptr; +} + +PhysicsBody* PhysicsBody::createEdgeChain(Point* points, int count, float border/* = 1*/) +{ + PhysicsBody* body = new PhysicsBody(); + if (body && body->initStatic()) + { + body->addEdgeChain(points, count); + body->autorelease(); + return body; + } + + CC_SAFE_DELETE(body); + + return nullptr; +} + +PhysicsShapeCircle* PhysicsBody::addCircle(float radius, Point offset/* = Point(0, 0)*/) +{ + _area = PhysicsHelper::cpfloat2float(cpAreaForCircle(0, radius)); + setMass((_massDefault ? 0 : getMass()) + _area * _density); + + setAngularDamping((_angularDampingDefault ? 0 : getAngularDamping()) + + PhysicsHelper::cpfloat2float(cpMomentForCircle(getMass(), 0, radius, PhysicsHelper::point2cpv(offset)))); + + return PhysicsShapeCircle::create(this, radius, offset); +} + +PhysicsShapeBox* PhysicsBody::addBox(Size size, Point offset/* = Point(0, 0)*/) +{ + cpVect cpOffset = PhysicsHelper::size2cpv(size); + cpVect vec[4] = {}; + vec[0] = cpv(0, 0); + vec[1] = cpv(0, cpOffset.y); + vec[2] = cpv(cpOffset.x, cpOffset.y); + vec[3] = cpv(cpOffset.x, 0); + + _area = PhysicsHelper::cpfloat2float(cpAreaForPoly(4, vec)); + setMass((_massDefault ? 0 : getMass()) + _area * _density); + + setAngularDamping((_angularDampingDefault ? 0 : getAngularDamping()) + + PhysicsHelper::cpfloat2float(cpMomentForBox(getMass(), PhysicsHelper::float2cpfloat(size.width), PhysicsHelper::float2cpfloat(size.height)))); + + return PhysicsShapeBox::create(this, size, offset); +} + +PhysicsShapePolygon* PhysicsBody::addPolygon(Point* points, int count, Point offset/* = Point(0, 0)*/) +{ + cpVect* vec = new cpVect[count]; + PhysicsHelper::points2cpvs(points, vec, count); + _area = PhysicsHelper::cpfloat2float(cpAreaForPoly(count, vec)); + + setAngularDamping((_angularDampingDefault ? 0 : getAngularDamping()) + + PhysicsHelper::cpfloat2float(cpMomentForPoly(getMass(), count, vec, PhysicsHelper::point2cpv(offset)))); + + delete[] vec; + + return PhysicsShapePolygon::create(this, points, count, offset); +} + +PhysicsShapeEdgeSegment* PhysicsBody::addEdgeSegment(Point a, Point b, float border/* = 1*/) +{ + return PhysicsShapeEdgeSegment::create(this, a, b, border); +} + +PhysicsShapeEdgeBox* PhysicsBody::addEdgeBox(Size size, float border/* = 1*/, Point offset/* = Point(0, 0)*/) +{ + return PhysicsShapeEdgeBox::create(this, size, border, offset); +} + +PhysicsShapeEdgePolygon* PhysicsBody::addEdgePolygon(Point* points, int count, float border/* = 1*/) +{ + return PhysicsShapeEdgePolygon::create(this, points, count); +} + +PhysicsShapeEdgeChain* PhysicsBody::addEdgeChain(Point* points, int count, float border/* = 1*/) +{ + return PhysicsShapeEdgeChain::create(this, points, count, border); +} + bool PhysicsBody::init() { do @@ -81,8 +254,9 @@ bool PhysicsBody::init() _info = new PhysicsBodyInfo(); CC_BREAK_IF(_info == nullptr); - _info->body = cpBodyNew(1.0, 1.0); + _info->body = cpBodyNew(PhysicsHelper::float2cpfloat(_mass), PhysicsHelper::float2cpfloat(_angularDamping)); CC_BREAK_IF(_info->body == nullptr); + _dynamic = true; return true; } while (false); @@ -90,26 +264,118 @@ bool PhysicsBody::init() return false; } -PhysicsBody* PhysicsBody::createCircle(Point centre, float radius) +void PhysicsBody::setDynamic(bool dynamic) { - PhysicsBody* body = PhysicsBody::create(); - - if (body == nullptr) + _dynamic = dynamic; + if (_world != nullptr && cpBodyIsStatic(_info->body) == (cpBool)_dynamic) { - return nullptr; + if (dynamic) + { + cpSpaceConvertBodyToDynamic(_world->_info->space, _info->body, _mass, _angularDamping); + }else + { + cpSpaceConvertBodyToStatic(_world->_info->space, _info->body); + } } - - cpBodySetPos(body->_info->body, cpv(centre.x, centre.y)); - body->_info->shape = cpCircleShapeNew(body->_info->body, radius, cpvzero); - - if (body->_info->shape == nullptr) - { - return nullptr; - } - - return body; } +bool PhysicsBody::initStatic() +{ + do + { + _info = new PhysicsBodyInfo(); + CC_BREAK_IF(_info == nullptr); + + _info->body = cpBodyNewStatic(); + CC_BREAK_IF(_info->body == nullptr); + _dynamic = false; + + return true; + } while (false); + + return false; +} + +void PhysicsBody::setPosition(Point position) +{ + cpBodySetPos(_info->body, PhysicsHelper::point2cpv(position)); +} + +void PhysicsBody::setRotation(float rotation) +{ + cpBodySetAngle(_info->body, PhysicsHelper::float2cpfloat(rotation)); +} + +Point PhysicsBody::getPosition() const +{ + cpVect vec = cpBodyGetPos(_info->body); + return PhysicsHelper::cpv2point(vec); +} + +float PhysicsBody::getRotation() const +{ + return -PhysicsHelper::cpfloat2float(cpBodyGetAngle(_info->body) / 3.14f * 180.0f); +} + +void PhysicsBody::addShape(PhysicsShape* shape) +{ + if (shape == nullptr) return; + + _shapes.push_back(shape); + + if (_world != nullptr) _world->addShape(shape); +} + +void PhysicsBody::applyForce(Point force) +{ + applyForce(force, Point()); +} + +void PhysicsBody::applyForce(Point force, Point offset) +{ + cpBodyApplyForce(_info->body, PhysicsHelper::point2cpv(force), PhysicsHelper::point2cpv(offset)); +} + +void PhysicsBody::applyImpulse(Point impulse) +{ + applyImpulse(impulse, Point()); +} + +void PhysicsBody::applyImpulse(Point impulse, Point offset) +{ + cpBodyApplyImpulse(_info->body, PhysicsHelper::point2cpv(impulse), PhysicsHelper::point2cpv(offset)); +} + +void PhysicsBody::applyTorque(float torque) +{ + cpBodySetTorque(_info->body, PhysicsHelper::float2cpfloat(torque)); +} + +void PhysicsBody::setMass(float mass) +{ + _mass = mass; + _massDefault = false; + + cpBodySetMass(_info->body, PhysicsHelper::float2cpfloat(_mass)); +} + +void PhysicsBody::setAngularDamping(float angularDamping) +{ + _angularDamping = angularDamping; + _angularDampingDefault = false; + + cpBodySetMoment(_info->body, _angularDamping); +} + +//Clonable* PhysicsBody::clone() const +//{ +// PhysicsBody* body = new PhysicsBody(); +// +// body->autorelease(); +// +// return body; +//} + #elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) diff --git a/cocos2dx/physics/CCPhysicsBody.h b/cocos2dx/physics/CCPhysicsBody.h index 64df98ec3f..08fffb8722 100644 --- a/cocos2dx/physics/CCPhysicsBody.h +++ b/cocos2dx/physics/CCPhysicsBody.h @@ -36,33 +36,48 @@ NS_CC_BEGIN class Sprite; class PhysicsWorld; class PhysicsJoint; -class PhysicsFixture; +class PhysicsShape; +class PhysicsShapeCircle; +class PhysicsShapeBox; +class PhysicsShapePolygon; +class PhysicsShapeEdgeSegment; +class PhysicsShapeEdgeBox; +class PhysicsShapeEdgePolygon; +class PhysicsShapeEdgeChain; + class PhysicsBodyInfo; -class PhysicsBody : public Object, public Clonable +class PhysicsBody : public Object//, public Clonable { public: - static PhysicsBody* createCircle(Point centre, float radius); - static PhysicsBody* createRectangle(Rect rect); - static PhysicsBody* createPolygon(Array* points); + static PhysicsBody* createCircle(float radius); + static PhysicsBody* createBox(Size size); + static PhysicsBody* createPolygon(Point* points, int count); - static PhysicsBody* createEdgeSegment(Point x, Point y); - static PhysicsBody* createEdgeCircle(Point centre, float radius); - static PhysicsBody* createEdgeRectangle(Rect rect); - static PhysicsBody* createEdgePolygon(Array* points); - static PhysicsBody* createEdgeChain(Array* points); + static PhysicsBody* createEdgeSegment(Point a, Point b, float border = 1); + static PhysicsBody* createEdgeBox(Size size, float border = 1); + static PhysicsBody* createEdgePolygon(Point* points, int count, float border = 1); + static PhysicsBody* createEdgeChain(Point* points, int count, float border = 1); + + virtual PhysicsShapeCircle* addCircle(float radius, Point offset = Point(0, 0)); + virtual PhysicsShapeBox* addBox(Size size, Point offset = Point(0, 0)); + virtual PhysicsShapePolygon* addPolygon(Point* points, int count, Point offset = Point(0, 0)); + + virtual PhysicsShapeEdgeSegment* addEdgeSegment(Point a, Point b, float border = 1); + virtual PhysicsShapeEdgeBox* addEdgeBox(Size size, float border = 1, Point offset = Point(0, 0)); + virtual PhysicsShapeEdgePolygon* addEdgePolygon(Point* points, int count, float border = 1); + virtual PhysicsShapeEdgeChain* addEdgeChain(Point* points, int count, float border = 1); virtual void applyForce(Point force); - virtual void applyForce(Point force, Point point); + virtual void applyForce(Point force, Point offset); virtual void applyImpulse(Point impulse); - virtual void applyImpulse(Point impulse, Point point); + virtual void applyImpulse(Point impulse, Point offset); virtual void applyTorque(float torque); - virtual void applyAngularImpulse(float impulse); - void addFixture(PhysicsFixture* fixture); - inline Array* getFixtures() const { return _fixtures; } - void removeFixture(PhysicsFixture* fixture); - void removeAllFixtures(); + inline std::vector& getShapes() { return _shapes; } + inline PhysicsShape* getShape() { return _shapes.size() >= 1 ? _shapes.front() : nullptr; } + void removeShape(PhysicsShape* shape); + void removeAllShapes(); inline PhysicsWorld* getWorld() const { return _world; } inline const std::vector* getJoints() const { return &_joints; } @@ -76,34 +91,55 @@ public: void setCollisionBitmask(int bitmask); inline int getCollisionBitmask() const { return _collisionBitmask; } - virtual Clonable* clone() const override; + Point getPosition() const; + float getRotation() const; + + inline bool isDynamic() { return _dynamic; } + void setDynamic(bool dynamic); + + void setMass(float mass); + inline float getMass() { return _mass; } + + void setAngularDamping(float angularDamping); + inline float getAngularDamping() { return _angularDamping; } + + //virtual Clonable* clone() const override; protected: - static PhysicsBody* create(); + bool init(); + bool initStatic(); + + virtual void setPosition(Point position); + virtual void setRotation(float rotation); + virtual void addShape(PhysicsShape* shape); protected: PhysicsBody(); virtual ~PhysicsBody(); protected: - float _mass; - float _density; - float _area; - float _friction; Sprite* _owner; - Point _velocity; - float _angularVelocity; - bool _resting; + std::vector _joints; + std::vector _shapes; + PhysicsWorld* _world; + PhysicsBodyInfo* _info; + bool _dynamic; + bool _massDefault; + bool _angularDampingDefault; + float _mass; + float _area; + float _density; + float _angularDamping; int _categoryBitmask; int _contactTestBitmask; int _collisionBitmask; - std::vector _joints; - Array* _fixtures; - PhysicsWorld* _world; - PhysicsBodyInfo* _info; + friend class PhysicsWorld; + friend class PhysicsShape; + friend class PhysicsJoint; + friend class Sprite; }; NS_CC_END diff --git a/cocos2dx/physics/CCPhysicsContact.cpp b/cocos2dx/physics/CCPhysicsContact.cpp new file mode 100644 index 0000000000..d76b93f9d8 --- /dev/null +++ b/cocos2dx/physics/CCPhysicsContact.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "CCPhysicsContact.h" +#ifdef CC_USE_PHYSICS +#include "chipmunk/CCPhysicsContactInfo.h" +#include "Box2D/CCPhysicsContactInfo.h" + +NS_CC_BEGIN + +PhysicsContact::PhysicsContact() +: _shapeA(nullptr) +, _shapeB(nullptr) +, _info(nullptr) +, _data(nullptr) +{ + +} + +PhysicsContact::~PhysicsContact() +{ + CC_SAFE_DELETE(_info); +} + +PhysicsContact* PhysicsContact::create(PhysicsShape* a, PhysicsShape* b) +{ + PhysicsContact * contact = new PhysicsContact(); + if(contact && contact->init(a, b)) + { + return contact; + } + + CC_SAFE_DELETE(contact); + return nullptr; +} + +bool PhysicsContact::init(PhysicsShape* a, PhysicsShape* b) +{ + do + { + CC_BREAK_IF(a == nullptr || b == nullptr); + + CC_BREAK_IF(!(_info = new PhysicsContactInfo(this))); + + _shapeA = a; + _shapeB = b; + + return true; + } while(false); + + return false; +} + +// PhysicsContactPreSolve implementation +PhysicsContactPreSolve::PhysicsContactPreSolve() +{ + +} + +PhysicsContactPreSolve::~PhysicsContactPreSolve() +{ + +} + +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() +{ + +} + +PhysicsContactPostSolve* PhysicsContactPostSolve::create() +{ + PhysicsContactPostSolve * solve = new PhysicsContactPostSolve(); + if(solve && solve->init()) + { + return solve; + } + + CC_SAFE_DELETE(solve); + return nullptr; +} + +bool PhysicsContactPostSolve::init() +{ + return true; +} + + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) +#elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) +#endif + +NS_CC_END +#endif // CC_USE_PHYSICS diff --git a/cocos2dx/physics/CCPhysicsContact.h b/cocos2dx/physics/CCPhysicsContact.h new file mode 100644 index 0000000000..6db1fd47f7 --- /dev/null +++ b/cocos2dx/physics/CCPhysicsContact.h @@ -0,0 +1,136 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCPhysicsSetting.h" +#ifdef CC_USE_PHYSICS + +#ifndef __CCPHYSICS_CONTACT_H__ +#define __CCPHYSICS_CONTACT_H__ + +#include "cocoa/CCObject.h" +#include "cocoa/CCGeometry.h" + +NS_CC_BEGIN + +class PhysicsShape; +class PhysicsWorld; + +namespace PhysicsInnerCallbackFunctions +{ +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + int collisionBeginCallbackFunc(cpArbiter *arb, struct cpSpace *space, void *data); + int collisionPreSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); + void collisionPostSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); + void collisionSeparateCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); +#endif +} + +class PhysicsContactInfo; + +class PhysicsContact +{ +public: + inline PhysicsShape* getShapeA() { return _shapeA; } + inline PhysicsShape* getShapeB() { return _shapeB; } + inline void* getData() { return _data; } + +private: + static PhysicsContact* create(PhysicsShape* a, PhysicsShape* b); + bool init(PhysicsShape* a, PhysicsShape* b); + +private: + PhysicsContact(); + ~PhysicsContact(); + +private: + PhysicsShape* _shapeA; + PhysicsShape* _shapeB; + PhysicsContactInfo* _info; + void* _data; + + friend class PhysicsWorld; + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + friend int PhysicsInnerCallbackFunctions::collisionBeginCallbackFunc(cpArbiter *arb, struct cpSpace *space, void *data); + friend int PhysicsInnerCallbackFunctions::collisionPreSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); + friend void PhysicsInnerCallbackFunctions::collisionPostSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); + friend void PhysicsInnerCallbackFunctions::collisionSeparateCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); +#endif +}; + +class PhysicsContactPreSolve +{ +private: + PhysicsContactPreSolve(); + ~PhysicsContactPreSolve(); + + static PhysicsContactPreSolve* create(); + bool init(); + + friend class PhysicsWorld; + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + friend int PhysicsInnerCallbackFunctions::collisionBeginCallbackFunc(cpArbiter *arb, struct cpSpace *space, void *data); + friend int PhysicsInnerCallbackFunctions::collisionPreSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); + friend void PhysicsInnerCallbackFunctions::collisionPostSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); + friend void PhysicsInnerCallbackFunctions::collisionSeparateCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); +#endif +}; + +class PhysicsContactPostSolve +{ +private: + PhysicsContactPostSolve(); + ~PhysicsContactPostSolve(); + + static PhysicsContactPostSolve* create(); + bool init(); + + friend class PhysicsWorld; + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + friend int PhysicsInnerCallbackFunctions::collisionBeginCallbackFunc(cpArbiter *arb, struct cpSpace *space, void *data); + friend int PhysicsInnerCallbackFunctions::collisionPreSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); + friend void PhysicsInnerCallbackFunctions::collisionPostSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); + friend void PhysicsInnerCallbackFunctions::collisionSeparateCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); +#endif +}; + +class PhysicsContactDelegate +{ +public: + PhysicsContactDelegate(); + virtual ~PhysicsContactDelegate(); + +public: + virtual bool onContactBegin(const PhysicsContact& contact) = 0; + virtual bool onContactPreSolve(const PhysicsContact& contact, const PhysicsContactPreSolve& solve) = 0; + virtual void onContactPostSove(const PhysicsContact& contact, const PhysicsContactPostSolve& solve)= 0; + virtual void onContactEnd(const PhysicsContact& contact) = 0; +}; + +NS_CC_END +#endif //__CCPHYSICS_CONTACT_H__ + +#endif // CC_USE_PHYSICS diff --git a/cocos2dx/physics/CCPhysicsJoint.cpp b/cocos2dx/physics/CCPhysicsJoint.cpp index 39b3eedbc5..572e682fa8 100644 --- a/cocos2dx/physics/CCPhysicsJoint.cpp +++ b/cocos2dx/physics/CCPhysicsJoint.cpp @@ -21,3 +21,198 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ + +#include "CCPhysicsJoint.h" +#ifdef CC_USE_PHYSICS +#include "CCPhysicsBody.h" + +#include "chipmunk/CCPhysicsJointInfo.h" +#include "Box2D/CCPhysicsJointInfo.h" +#include "chipmunk/CCPhysicsBodyInfo.h" +#include "Box2D/CCPhysicsBodyInfo.h" +#include "chipmunk/CCPhysicsHelper.h" +#include "Box2D/CCPhysicsHelper.h" + +NS_CC_BEGIN + +PhysicsJoint::PhysicsJoint() +: _bodyA(nullptr) +, _bodyB(nullptr) +, _info(nullptr) +{ + +} + +PhysicsJoint::~PhysicsJoint() +{ + CC_SAFE_DELETE(_info); + + CC_SAFE_RELEASE(_bodyA); + CC_SAFE_RELEASE(_bodyB); +} + +bool PhysicsJoint::init(cocos2d::PhysicsBody *a, cocos2d::PhysicsBody *b) +{ + do + { + CC_BREAK_IF(a == nullptr || b == nullptr); + + CC_BREAK_IF(!(_info = new PhysicsJointInfo())); + + _bodyA = a; + _bodyA->retain(); + _bodyA->_joints.push_back(this); + _bodyB = b; + _bodyB->retain(); + _bodyB->_joints.push_back(this); + + return true; + } while (false); + + return false; +} + + +PhysicsJointPin::PhysicsJointPin() +{ + +} + +PhysicsJointPin::~PhysicsJointPin() +{ + +} + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) +PhysicsBodyInfo* PhysicsJoint::bodyInfo(PhysicsBody* body) const +{ + return body->_info; +} + + + +PhysicsJointFixed* PhysicsJointFixed::create(PhysicsBody* a, PhysicsBody* b, const Point& anchr) +{ + PhysicsJointFixed* joint = new PhysicsJointFixed(); + + if (joint && joint->init(a, b, anchr)) + { + joint->autorelease(); + return joint; + } + + CC_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointFixed::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr) +{ + do + { + CC_BREAK_IF(!PhysicsJoint::init(a, b)); + + _info->joint = cpPivotJointNew(bodyInfo(a)->body, bodyInfo(b)->body, + PhysicsHelper::point2cpv(anchr)); + + return true; + } while (false); + + return false; +} + +PhysicsJointPin* PhysicsJointPin::create(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2) +{ + PhysicsJointPin* joint = new PhysicsJointPin(); + + if (joint && joint->init(a, b, anchr1, anchr2)) + { + joint->autorelease(); + return joint; + } + + CC_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointPin::init(PhysicsBody *a, PhysicsBody *b, const Point& anchr1, const Point& anchr2) +{ + do + { + CC_BREAK_IF(!PhysicsJoint::init(a, b)); + + _info->joint = cpPinJointNew(bodyInfo(a)->body, bodyInfo(b)->body, PhysicsHelper::point2cpv(anchr1), PhysicsHelper::point2cpv(anchr2)); + + return true; + } while (false); + + return false; +} + +PhysicsJointSliding* PhysicsJointSliding::create(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr) +{ + PhysicsJointSliding* joint = new PhysicsJointSliding(); + + if (joint && joint->init(a, b, grooveA, grooveB, anchr)) + { + return joint; + } + + CC_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointSliding::init(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr) +{ + do + { + CC_BREAK_IF(!PhysicsJoint::init(a, b)); + + _info->joint = cpGrooveJointNew(bodyInfo(a)->body, bodyInfo(b)->body, + PhysicsHelper::point2cpv(grooveA), + PhysicsHelper::point2cpv(grooveB), + PhysicsHelper::point2cpv(anchr)); + + return true; + } while (false); + + return false; +} + + +PhysicsJointLimit* PhysicsJointLimit::create(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2, float min, float max) +{ + PhysicsJointLimit* joint = new PhysicsJointLimit(); + + if (joint && joint->init(a, b, anchr1, anchr2, min, max)) + { + return joint; + } + + CC_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointLimit::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2, float min, float max) +{ + do + { + CC_BREAK_IF(!PhysicsJoint::init(a, b)); + + _info->joint = cpSlideJointNew(bodyInfo(a)->body, bodyInfo(b)->body, + PhysicsHelper::point2cpv(anchr1), + PhysicsHelper::point2cpv(anchr2), + PhysicsHelper::float2cpfloat(min), + PhysicsHelper::float2cpfloat(max)); + + return true; + } while (false); + + return false; +} + +#elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) + +#endif + +NS_CC_END +#endif // CC_USE_PHYSICS diff --git a/cocos2dx/physics/CCPhysicsJoint.h b/cocos2dx/physics/CCPhysicsJoint.h index c7e659ab75..ab0315d690 100644 --- a/cocos2dx/physics/CCPhysicsJoint.h +++ b/cocos2dx/physics/CCPhysicsJoint.h @@ -34,42 +34,59 @@ NS_CC_BEGIN class PhysicsBody; +class PhysicsJointInfo; +class PhysicsBodyInfo; -class PhysicsJoint +class PhysicsJoint : public Object { protected: PhysicsJoint(); - virtual ~PhysicsJoint(); + virtual ~PhysicsJoint() = 0; + +public: + PhysicsBody* getBodyA() { return _bodyA; } + PhysicsBody* getBodyB() { return _bodyB; } -private: +protected: + bool init(PhysicsBody* a, PhysicsBody* b); + + /** + * 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; + +protected: PhysicsBody* _bodyA; PhysicsBody* _bodyB; + PhysicsJointInfo* _info; + + friend class PhysicsBody; }; class PhysicsJointFixed : public PhysicsJoint { public: - PhysicsJointFixed* create(); + PhysicsJointFixed* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr); protected: - bool init(); + bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr); protected: PhysicsJointFixed(); - ~PhysicsJointFixed(); + virtual ~PhysicsJointFixed(); }; class PhysicsJointSliding : public PhysicsJoint { public: - PhysicsJointSliding* create(); + PhysicsJointSliding* create(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr); protected: - bool init(); + bool init(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr); protected: PhysicsJointSliding(); - ~PhysicsJointSliding(); + virtual ~PhysicsJointSliding(); }; class PhysicsJointSpring : public PhysicsJoint @@ -82,33 +99,33 @@ protected: protected: PhysicsJointSpring(); - ~PhysicsJointSpring(); + virtual ~PhysicsJointSpring(); }; class PhysicsJointLimit : public PhysicsJoint { public: - PhysicsJointLimit* create(); + PhysicsJointLimit* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2, float min, float max); protected: - bool init(); + bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2, float min, float max); protected: PhysicsJointLimit(); - ~PhysicsJointLimit(); + virtual ~PhysicsJointLimit(); }; class PhysicsJointPin : public PhysicsJoint { public: - PhysicsJointPin* create(); + static PhysicsJointPin* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2); protected: - bool init(); + bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2); protected: PhysicsJointPin(); - ~PhysicsJointPin(); + virtual ~PhysicsJointPin(); }; NS_CC_END diff --git a/cocos2dx/physics/CCPhysicsSetting.h b/cocos2dx/physics/CCPhysicsSetting.h index b68da7cf93..3d3aaaaf55 100644 --- a/cocos2dx/physics/CCPhysicsSetting.h +++ b/cocos2dx/physics/CCPhysicsSetting.h @@ -29,7 +29,15 @@ #define CC_PHYSICS_BOX2D 1 #define CC_PHYSICS_CHIPMUNK 2 +#define CC_USE_CHIPMUNK + +#ifdef CC_USE_BOX2D +#define CC_PHYSICS_ENGINE CC_PHYSICS_BOX2D +#elif defined(CC_USE_CHIPMUNK) #define CC_PHYSICS_ENGINE CC_PHYSICS_CHIPMUNK +#else +#define CC_PHYSICS_ENGINE CC_PHYSICS_UNKNOWN +#endif #if (CC_PHYSICS_ENGINE != CC_PHYSICS_UNKNOWN) #define CC_USE_PHYSICS diff --git a/cocos2dx/physics/CCPhysicsShape.cpp b/cocos2dx/physics/CCPhysicsShape.cpp new file mode 100644 index 0000000000..002c848eff --- /dev/null +++ b/cocos2dx/physics/CCPhysicsShape.cpp @@ -0,0 +1,426 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCPhysicsShape.h" +#ifdef CC_USE_PHYSICS + +#include "CCPhysicsBody.h" + +#include "chipmunk/CCPhysicsBodyInfo.h" +#include "Box2D/CCPhysicsBodyInfo.h" +#include "chipmunk/CCPhysicsShapeInfo.h" +#include "Box2D/CCPhysicsShapeInfo.h" +#include "chipmunk/CCPhysicsHelper.h" + +NS_CC_BEGIN + +PhysicsShape::PhysicsShape() +: _body(nullptr) +, _info(nullptr) +, _type(Type::UNKNOWN) +{ + +} + +PhysicsShape::~PhysicsShape() +{ + CC_SAFE_DELETE(_info); +} + +bool PhysicsShape::init(PhysicsBody* body, Type type) +{ + if (body == nullptr) return false; + + _body = body; + + _info = new PhysicsShapeInfo(this); + if (_info == nullptr) return false; + + _type = type; + + return true; +} + +void PhysicsShape::addToBody() +{ + if(_body != nullptr) _body->addShape(this); +} + +PhysicsBodyInfo* PhysicsShape::bodyInfo() const +{ + return _body->_info; +} + +PhysicsShapeCircle::PhysicsShapeCircle() +{ + +} + +PhysicsShapeCircle::~PhysicsShapeCircle() +{ + +} + +PhysicsShapeBox::PhysicsShapeBox() +{ + +} + +PhysicsShapeBox::~PhysicsShapeBox() +{ + +} + +PhysicsShapePolygon::PhysicsShapePolygon() +{ + +} + +PhysicsShapePolygon::~PhysicsShapePolygon() +{ + +} + +PhysicsShapeEdgeBox::PhysicsShapeEdgeBox() +{ + +} + +PhysicsShapeEdgeBox::~PhysicsShapeEdgeBox() +{ + +} + +PhysicsShapeEdgeChain::PhysicsShapeEdgeChain() +{ + +} + +PhysicsShapeEdgeChain::~PhysicsShapeEdgeChain() +{ + +} + +PhysicsShapeEdgePolygon::PhysicsShapeEdgePolygon() +{ + +} + +PhysicsShapeEdgePolygon::~PhysicsShapeEdgePolygon() +{ + +} + +PhysicsShapeEdgeSegment::PhysicsShapeEdgeSegment() +{ + +} + +PhysicsShapeEdgeSegment::~PhysicsShapeEdgeSegment() +{ + +} + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + +// PhysicsShapeCircle +PhysicsShapeCircle* PhysicsShapeCircle::create(PhysicsBody* body, float radius, Point offset/* = Point(0, 0)*/) +{ + PhysicsShapeCircle* shape = new PhysicsShapeCircle(); + if (shape && shape->init(body, radius, offset)) + { + return shape; + } + + CC_SAFE_DELETE(shape); + return nullptr; +} + +bool PhysicsShapeCircle::init(PhysicsBody* body, float radius, Point offset /*= Point(0, 0)*/) +{ + do + { + CC_BREAK_IF(!PhysicsShape::init(body, Type::CIRCLE)); + + cpShape* shape = cpCircleShapeNew(bodyInfo()->body, radius, PhysicsHelper::point2cpv(offset)); + + CC_BREAK_IF(shape == nullptr); + + _info->add(shape); + addToBody(); + + return true; + } while (false); + + return false; +} + +// PhysicsShapeEdgeSegment +PhysicsShapeEdgeSegment* PhysicsShapeEdgeSegment::create(PhysicsBody* body, Point a, Point b, float border/* = 1*/) +{ + PhysicsShapeEdgeSegment* shape = new PhysicsShapeEdgeSegment(); + if (shape && shape->init(body, a, b, border)) + { + return shape; + } + + CC_SAFE_DELETE(shape); + return nullptr; +} + +bool PhysicsShapeEdgeSegment::init(PhysicsBody* body, Point a, Point b, float border/* = 1*/) +{ + do + { + CC_BREAK_IF(!PhysicsShape::init(body, Type::EDGESEGMENT)); + + cpShape* shape = cpSegmentShapeNew(bodyInfo()->body, + PhysicsHelper::point2cpv(a), + PhysicsHelper::point2cpv(b), + PhysicsHelper::float2cpfloat(border)); + + CC_BREAK_IF(shape == nullptr); + + _info->add(shape); + addToBody(); + + return true; + } while (false); + + return false; +} + +// PhysicsShapeBox +PhysicsShapeBox* PhysicsShapeBox::create(PhysicsBody* body, Size size, Point offset/* = Point(0, 0)*/) +{ + PhysicsShapeBox* shape = new PhysicsShapeBox(); + if (shape && shape->init(body, size, offset)) + { + return shape; + } + + CC_SAFE_DELETE(shape); + return nullptr; +} + +bool PhysicsShapeBox::init(PhysicsBody* body, Size size, Point offset /*= Point(0, 0)*/) +{ + do + { + CC_BREAK_IF(!PhysicsShape::init(body, Type::BOX)); + + cpShape* shape = cpBoxShapeNew(bodyInfo()->body, PhysicsHelper::float2cpfloat(size.width), PhysicsHelper::float2cpfloat(size.height)); + + CC_BREAK_IF(shape == nullptr); + + _info->add(shape); + addToBody(); + + return true; + } while (false); + + return false; +} + +// PhysicsShapeCircle +PhysicsShapePolygon* PhysicsShapePolygon::create(PhysicsBody* body, Point* points, int count, Point offset/* = Point(0, 0)*/) +{ + PhysicsShapePolygon* shape = new PhysicsShapePolygon(); + if (shape && shape->init(body, points, count, offset)) + { + return shape; + } + + CC_SAFE_DELETE(shape); + return nullptr; +} + +bool PhysicsShapePolygon::init(PhysicsBody* body, Point* points, int count, Point offset /*= Point(0, 0)*/) +{ + do + { + CC_BREAK_IF(!PhysicsShape::init(body, Type::POLYGEN)); + + cpVect* vecs = new cpVect[count]; + PhysicsHelper::points2cpvs(points, vecs, count); + cpShape* shape = cpPolyShapeNew(bodyInfo()->body, count, vecs, PhysicsHelper::point2cpv(offset)); + + CC_BREAK_IF(shape == nullptr); + + _info->add(shape); + addToBody(); + + return true; + } while (false); + + return false; +} + +// PhysicsShapeEdgeBox +PhysicsShapeEdgeBox* PhysicsShapeEdgeBox::create(PhysicsBody* body, Size size, float border/* = 1*/, Point offset/* = Point(0, 0)*/) +{ + PhysicsShapeEdgeBox* shape = new PhysicsShapeEdgeBox(); + if (shape && shape->init(body, size, border, offset)) + { + return shape; + } + + CC_SAFE_DELETE(shape); + return nullptr; +} + +bool PhysicsShapeEdgeBox::init(PhysicsBody* body, Size size, float border/* = 1*/, Point offset/*= Point(0, 0)*/) +{ + do + { + CC_BREAK_IF(!PhysicsShape::init(body, Type::EDGEBOX)); + + Point bodyPos = body->getPosition(); + + cpVect vec[4] = {}; + vec[0] = PhysicsHelper::point2cpv(Point(bodyPos.x-size.width/2+offset.x, bodyPos.y-size.height/2+offset.y)); + vec[1] = PhysicsHelper::point2cpv(Point(bodyPos.x+size.width/2+offset.x, bodyPos.y-size.height/2+offset.y)); + vec[2] = PhysicsHelper::point2cpv(Point(bodyPos.x+size.width/2+offset.x, bodyPos.y+size.height/2+offset.y)); + vec[3] = PhysicsHelper::point2cpv(Point(bodyPos.x-size.width/2+offset.x, bodyPos.y+size.height/2+offset.y)); + + int i = 0; + for (; i < 4; ++i) + { + cpShape* shape = cpSegmentShapeNew(bodyInfo()->body, vec[i], vec[(i+1)%4], + PhysicsHelper::float2cpfloat(border)); + CC_BREAK_IF(shape == nullptr); + cpShapeSetElasticity(shape, 1.0f); + cpShapeSetFriction(shape, 1.0f); + _info->add(shape); + } + CC_BREAK_IF(i < 4); + + addToBody(); + + return true; + } while (false); + + return false; +} + +// PhysicsShapeEdgeBox +PhysicsShapeEdgePolygon* PhysicsShapeEdgePolygon::create(PhysicsBody* body, Point* points, int count, float border/* = 1*/) +{ + PhysicsShapeEdgePolygon* shape = new PhysicsShapeEdgePolygon(); + if (shape && shape->init(body, points, count, border)) + { + return shape; + } + + CC_SAFE_DELETE(shape); + return nullptr; +} + +bool PhysicsShapeEdgePolygon::init(PhysicsBody* body, Point* points, int count, float border/* = 1*/) +{ + cpVect* vec = nullptr; + do + { + CC_BREAK_IF(!PhysicsShape::init(body, Type::EDGEPOLYGEN)); + + vec = new cpVect[count]; + PhysicsHelper::points2cpvs(points, vec, count); + + int i = 0; + for (; i < count; ++i) + { + cpShape* shape = cpSegmentShapeNew(bodyInfo()->body, vec[i], vec[(i+1)%count], + PhysicsHelper::float2cpfloat(border)); + CC_BREAK_IF(shape == nullptr); + cpShapeSetElasticity(shape, 1.0f); + cpShapeSetFriction(shape, 1.0f); + _info->add(shape); + } + CC_BREAK_IF(i < count); + + addToBody(); + + if (vec != nullptr) delete[] vec; + return true; + } while (false); + + if (vec != nullptr) delete[] vec; + + return false; +} + +// PhysicsShapeEdgeChain +PhysicsShapeEdgeChain* PhysicsShapeEdgeChain::create(PhysicsBody* body, Point* points, int count, float border/* = 1*/) +{ + PhysicsShapeEdgeChain* shape = new PhysicsShapeEdgeChain(); + if (shape && shape->init(body, points, count, border)) + { + return shape; + } + + CC_SAFE_DELETE(shape); + return nullptr; +} + +bool PhysicsShapeEdgeChain::init(PhysicsBody* body, Point* points, int count, float border/* = 1*/) +{ + cpVect* vec = nullptr; + do + { + CC_BREAK_IF(!PhysicsShape::init(body, Type::EDGECHAIN)); + + vec = new cpVect[count]; + PhysicsHelper::points2cpvs(points, vec, count); + + int i = 0; + for (; i < count - 1; ++i) + { + cpShape* shape = cpSegmentShapeNew(bodyInfo()->body, vec[i], vec[i+1], + PhysicsHelper::float2cpfloat(border)); + CC_BREAK_IF(shape == nullptr); + cpShapeSetElasticity(shape, 1.0f); + cpShapeSetFriction(shape, 1.0f); + _info->add(shape); + } + CC_BREAK_IF(i < count); + + addToBody(); + + if (vec != nullptr) delete[] vec; + return true; + } while (false); + + if (vec != nullptr) delete[] vec; + + return false; +} + + +#elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) + +#endif + +NS_CC_END + +#endif // CC_USE_PHYSICS \ No newline at end of file diff --git a/cocos2dx/physics/CCPhysicsShape.h b/cocos2dx/physics/CCPhysicsShape.h new file mode 100644 index 0000000000..64049c2947 --- /dev/null +++ b/cocos2dx/physics/CCPhysicsShape.h @@ -0,0 +1,182 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCPhysicsSetting.h" +#ifdef CC_USE_PHYSICS + +#ifndef __CCPHYSICS_SHAPE_H__ +#define __CCPHYSICS_SHAPE_H__ + +#include "cocoa/CCObject.h" +#include "cocoa/CCGeometry.h" + +NS_CC_BEGIN + +class PhysicsShapeInfo; +class PhysicsBody; +class PhysicsBodyInfo; + +class PhysicsShape : public Object +{ +public: + enum class Type + { + UNKNOWN, + CIRCLE, + BOX, + POLYGEN, + EDGESEGMENT, + EDGEBOX, + EDGEPOLYGEN, + EDGECHAIN, + }; + +public: + inline PhysicsBody* getBody(){ return _body; } + inline Type getType() { return _type; } + +protected: + bool init(PhysicsBody* body, Type type); + + /** + * 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() const; + + void addToBody(); + +protected: + PhysicsShape(); + virtual ~PhysicsShape(); + +protected: + PhysicsBody* _body; + PhysicsShapeInfo* _info; + Type _type; + + friend class PhysicsWorld; + friend class PhysicsBody; +}; + +class PhysicsShapeCircle : public PhysicsShape +{ +protected: + static PhysicsShapeCircle* create(PhysicsBody* body, float radius, Point offset = Point(0, 0)); + bool init(PhysicsBody* body, float radius, Point offset = Point(0, 0)); + +protected: + PhysicsShapeCircle(); + virtual ~PhysicsShapeCircle(); + + friend class PhysicsBody; +}; + +class PhysicsShapeBox : public PhysicsShape +{ +protected: + static PhysicsShapeBox* create(PhysicsBody* body, Size size, Point offset = Point(0, 0)); + bool init(PhysicsBody* body, Size size, Point offset = Point(0, 0)); + +protected: + PhysicsShapeBox(); + virtual ~PhysicsShapeBox(); + + friend class PhysicsBody; +}; + +class PhysicsShapePolygon : public PhysicsShape +{ +protected: + static PhysicsShapePolygon* create(PhysicsBody* body, Point* points, int count, Point offset = Point(0, 0)); + bool init(PhysicsBody* body, Point* points, int count, Point offset = Point(0, 0)); + +protected: + PhysicsShapePolygon(); + virtual ~PhysicsShapePolygon(); + + friend class PhysicsBody; +}; + +class PhysicsShapeEdgeSegment : public PhysicsShape +{ +protected: + static PhysicsShapeEdgeSegment* create(PhysicsBody* body, Point a, Point b, float border = 1); + bool init(PhysicsBody* body, Point a, Point b, float border = 1); + +protected: + PhysicsShapeEdgeSegment(); + virtual ~PhysicsShapeEdgeSegment(); + + friend class PhysicsBody; +}; + +class PhysicsShapeEdgeBox : public PhysicsShape +{ +public: + static PhysicsShapeEdgeBox* create(PhysicsBody* body, Size size, float border = 0, Point offset = Point(0, 0)); + +protected: + bool init(PhysicsBody* body, Size size, float border = 1, Point offset = Point(0, 0)); + +protected: + PhysicsShapeEdgeBox(); + virtual ~PhysicsShapeEdgeBox(); + + friend class PhysicsBody; +}; + +class PhysicsShapeEdgePolygon : public PhysicsShape +{ +public: + static PhysicsShapeEdgePolygon* create(PhysicsBody* body, Point* points, int count, float border = 1); + +protected: + bool init(PhysicsBody* body, Point* points, int count, float border = 1); + +protected: + PhysicsShapeEdgePolygon(); + virtual ~PhysicsShapeEdgePolygon(); + + friend class PhysicsBody; +}; + +class PhysicsShapeEdgeChain : public PhysicsShape +{ +public: + static PhysicsShapeEdgeChain* create(PhysicsBody* body, Point* points, int count, float border = 1); + +protected: + bool init(PhysicsBody* body, Point* points, int count, float border = 1); + +protected: + PhysicsShapeEdgeChain(); + virtual ~PhysicsShapeEdgeChain(); + + friend class PhysicsBody; +}; + +NS_CC_END +#endif // __CCPHYSICS_FIXTURE_H__ + +#endif // CC_USE_PHYSICS diff --git a/cocos2dx/physics/CCPhysicsWorld.cpp b/cocos2dx/physics/CCPhysicsWorld.cpp index ccfc1ea788..78a6f3b806 100644 --- a/cocos2dx/physics/CCPhysicsWorld.cpp +++ b/cocos2dx/physics/CCPhysicsWorld.cpp @@ -23,51 +23,265 @@ ****************************************************************************/ #include "CCPhysicsWorld.h" +#ifdef CC_USE_PHYSICS + +#include "CCPhysicsBody.h" +#include "CCPhysicsShape.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/CCPhysicsHelper.h" + +#include "draw_nodes/CCDrawNode.h" +#include "cocoa/CCArray.h" +#include "layers_scenes_transitions_nodes/CCScene.h" +#include "CCDirector.h" NS_CC_BEGIN #if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) -class PhysicsWorldInfo +namespace PhysicsInnerCallbackFunctions { -public: - cpSpace* space; + int collisionBeginCallbackFunc(cpArbiter *arb, struct cpSpace *space, void *data) + { + PhysicsWorld* world = static_cast(data); + + CP_ARBITER_GET_SHAPES(arb, a, b); + + auto ita = PhysicsShapeInfo::map.find(a); + auto itb = PhysicsShapeInfo::map.find(b); + CC_ASSERT(ita != PhysicsShapeInfo::map.end() && itb != PhysicsShapeInfo::map.end()); + + PhysicsContact* contact = PhysicsContact::create(ita->second->shape, itb->second->shape); + arb->data = contact; + + return world->collisionBeginCallback(*static_cast(arb->data)); + } -public: - PhysicsWorldInfo(); - ~PhysicsWorldInfo(); -}; - -PhysicsWorldInfo::PhysicsWorldInfo() -{ - space = cpSpaceNew(); -} - -PhysicsWorldInfo::~PhysicsWorldInfo() -{ - cpSpaceFree(space); + int collisionPreSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data) + { + PhysicsWorld* world = static_cast(data); + return world->collisionPreSolveCallback(*static_cast(arb->data), + PhysicsContactPreSolve()); + } + + void collisionPostSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data) + { + PhysicsWorld* world = static_cast(data); + world->collisionPostSolveCallback(*static_cast(arb->data), + PhysicsContactPostSolve()); + } + + void collisionSeparateCallbackFunc(cpArbiter *arb, cpSpace *space, void *data) + { + PhysicsWorld* world = static_cast(data); + PhysicsContact* contact = static_cast(arb->data); + + world->collisionSeparateCallback(*contact); + + delete contact; + } } bool PhysicsWorld::init() { - _worldInfo = new PhysicsWorldInfo(); + _info = new PhysicsWorldInfo(); - cpSpaceSetGravity(_worldInfo->space, cpv(_gravity.x, _gravity.y)); + cpSpaceSetGravity(_info->space, PhysicsHelper::point2cpv(_gravity)); + + cpSpaceSetDefaultCollisionHandler(_info->space, + PhysicsInnerCallbackFunctions::collisionBeginCallbackFunc, + PhysicsInnerCallbackFunctions::collisionPreSolveCallbackFunc, + PhysicsInnerCallbackFunctions::collisionPostSolveCallbackFunc, + PhysicsInnerCallbackFunctions::collisionSeparateCallbackFunc, + this); return true; } +void PhysicsWorld::addShape(PhysicsShape* shape) +{ + for (auto it = shape->_info->shapes.begin(); it != shape->_info->shapes.end(); it++) + { + if (cpBodyIsStatic(shape->getBody()->_info->body)) + { + cpSpaceAddStaticShape(_info->space, *it); + }else + { + cpSpaceAddShape(_info->space, *it); + } + } +} + void PhysicsWorld::addChild(PhysicsBody* body) { + auto shapes = body->getShapes(); + // add body to space + if (body->isDynamic()) + { + cpSpaceAddBody(_info->space, body->_info->body); + } + + // add shapes to space + for (auto it = shapes.begin(); it != shapes.end(); it++) + { + addShape(*it); + } + + if (_bodys == nullptr) + { + _bodys = Array::create(body, NULL); + _bodys->retain(); + }else + { + _bodys->addObject(body); + } +} + +void PhysicsWorld::update(float delta) +{ + cpSpaceStep(_info->space, delta); + + if (_drawNode) + { + _drawNode->removeFromParent(); + _drawNode = nullptr; + } + + if (_debugDraw) + { + debugDraw(); + } +} + +void PhysicsWorld::debugDraw() +{ + if (_debugDraw && _bodys != nullptr) + { + _drawNode= DrawNode::create(); + + Object* child = nullptr; + CCARRAY_FOREACH(_bodys, child) + { + PhysicsBody* body = dynamic_cast(child); + + std::vector shapes = body->getShapes(); + + for (auto it = shapes.begin(); it != shapes.end(); ++it) + { + drawWithShape(_drawNode, *it); + } + } + + if (_scene) + { + _scene->addChild(_drawNode); + } + } +} + +void PhysicsWorld::setScene(Scene *scene) +{ + _scene = scene; + scene->retain(); +} + +void PhysicsWorld::drawWithShape(DrawNode* node, PhysicsShape* shape) +{ + for (auto it = shape->_info->shapes.begin(); it != shape->_info->shapes.end(); ++it) + { + cpShape *shape = *it; + + switch ((*it)->klass_private->type) + { + case CP_CIRCLE_SHAPE: + { + float radius = PhysicsHelper::cpfloat2float(cpCircleShapeGetRadius(shape)); + Point centre = PhysicsHelper::cpv2point(cpBodyGetPos(cpShapeGetBody(shape))) + + PhysicsHelper::cpv2point(cpCircleShapeGetOffset(shape)); + + Point seg[4] = {}; + seg[0] = Point(centre.x - radius, centre.y - radius); + seg[1] = Point(centre.x - radius, centre.y + radius); + seg[2] = Point(centre.x + radius, centre.y + radius); + seg[3] = Point(centre.x + radius, centre.y - radius); + node->drawPolygon(seg, 4, Color4F(), 1, Color4F(1, 0, 0, 1)); + break; + } + case CP_SEGMENT_SHAPE: + { + cpSegmentShape *seg = (cpSegmentShape *)shape; + node->drawSegment(PhysicsHelper::cpv2point(seg->ta), + PhysicsHelper::cpv2point(seg->tb), + PhysicsHelper::cpfloat2float(seg->r==0 ? 1 : seg->r), Color4F(1, 0, 0, 1)); + break; + } + case CP_POLY_SHAPE: + { + cpPolyShape* poly = (cpPolyShape*)shape; + int num = poly->numVerts; + Point* seg = new Point[num]; + + PhysicsHelper::cpvs2points(poly->tVerts, seg, num); + + node->drawPolygon(seg, num, Color4F(1, 0, 0, 0.3), 1, Color4F(1, 0, 0, 1)); + + delete[] seg; + break; + } + default: + break; + } + } +} + +int PhysicsWorld::collisionBeginCallback(const PhysicsContact& contact) +{ + if (_delegate) + { + return _delegate->onContactBegin(contact); + } + + return true; +} + +int PhysicsWorld::collisionPreSolveCallback(const PhysicsContact& contact, const PhysicsContactPreSolve& solve) +{ + if (_delegate) + { + return _delegate->onContactPreSolve(contact, solve); + } + + return true; +} + +void PhysicsWorld::collisionPostSolveCallback(const PhysicsContact& contact, const PhysicsContactPostSolve& solve) +{ + if (_delegate) + { + _delegate->onContactPostSove(contact, solve); + } +} + +void PhysicsWorld::collisionSeparateCallback(const PhysicsContact& contact) +{ + if (_delegate) + { + _delegate->onContactEnd(contact); + } } #elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D) -struct PhysicsInfo -{ - -}; #endif PhysicsWorld* PhysicsWorld::create() @@ -83,16 +297,25 @@ PhysicsWorld* PhysicsWorld::create() } PhysicsWorld::PhysicsWorld() -: _gravity(Point(0, -9.8)) -, _speed(1.0) -, _worldInfo(nullptr) +: _gravity(Point(0.0f, -98.0f)) +, _speed(1.0f) +, _info(nullptr) +, _delegate(nullptr) +, _bodys(nullptr) +, _scene(nullptr) +, _debugDraw(false) +, _drawNode(nullptr) { } PhysicsWorld::~PhysicsWorld() { - CC_SAFE_DELETE(_worldInfo); + CC_SAFE_DELETE(_info); + CC_SAFE_RELEASE(_bodys); + CC_SAFE_RELEASE(_scene); } NS_CC_END + +#endif // CC_USE_PHYSICS diff --git a/cocos2dx/physics/CCPhysicsWorld.h b/cocos2dx/physics/CCPhysicsWorld.h index 5bf807c159..1cb2530351 100644 --- a/cocos2dx/physics/CCPhysicsWorld.h +++ b/cocos2dx/physics/CCPhysicsWorld.h @@ -36,10 +36,26 @@ NS_CC_BEGIN class PhysicsBody; class PhysicsJoint; class PhysicsWorldInfo; +class PhysicsShape; +class PhysicsContact; +class PhysicsContactPreSolve; +class PhysicsContactPostSolve; class PhysicsContactDelegate; +class Array; class Sprite; class Scene; +class DrawNode; + +namespace PhysicsInnerCallbackFunctions +{ +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + int collisionBeginCallbackFunc(cpArbiter *arb, struct cpSpace *space, void *data); + int collisionPreSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); + void collisionPostSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); + void collisionSeparateCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); +#endif +} class PhysicsWorld { @@ -53,21 +69,46 @@ public: Array* getBodysInRect(Rect rect) const; Array* getAllBody() const; - void registerContactDelegate(PhysicsContactDelegate* delegate); + inline void registerContactDelegate(PhysicsContactDelegate* delegate) { _delegate = delegate; } + inline void unregisterContactDelegate() { _delegate = nullptr; } inline Point getGravity() { return _gravity; } inline void setGravity(Point gravity) { _gravity = gravity; } + inline bool getDebugDraw() { return _debugDraw; } + inline void setDebugDraw(bool debugDraw) { _debugDraw = debugDraw; } + protected: static PhysicsWorld* create(); bool init(); + + void setScene(Scene* scene); + virtual void addChild(PhysicsBody* body); + virtual void addShape(PhysicsShape* shape); + virtual void update(float delta); + + virtual void debugDraw(); + virtual void drawWithShape(DrawNode* node, PhysicsShape* shape); + + + virtual int collisionBeginCallback(const PhysicsContact& contact); + virtual int collisionPreSolveCallback(const PhysicsContact& contact, const PhysicsContactPreSolve& solve); + virtual void collisionPostSolveCallback(const PhysicsContact& contact, const PhysicsContactPostSolve& solve); + virtual void collisionSeparateCallback(const PhysicsContact& contact); protected: Point _gravity; float _speed; + PhysicsWorldInfo* _info; + PhysicsContactDelegate* _delegate; - PhysicsWorldInfo* _worldInfo; + + Array* _bodys; + Scene* _scene; + + bool _debugDraw; + DrawNode* _drawNode; protected: PhysicsWorld(); @@ -75,6 +116,14 @@ protected: friend class Sprite; friend class Scene; + friend class PhysicsBody; + +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + friend int PhysicsInnerCallbackFunctions::collisionBeginCallbackFunc(cpArbiter *arb, struct cpSpace *space, void *data); + friend int PhysicsInnerCallbackFunctions::collisionPreSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); + friend void PhysicsInnerCallbackFunctions::collisionPostSolveCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); + friend void PhysicsInnerCallbackFunctions::collisionSeparateCallbackFunc(cpArbiter *arb, cpSpace *space, void *data); +#endif }; NS_CC_END diff --git a/cocos2dx/physics/chipmunk/CCPhysicsBodyInfo.cpp b/cocos2dx/physics/chipmunk/CCPhysicsBodyInfo.cpp new file mode 100644 index 0000000000..4627c02499 --- /dev/null +++ b/cocos2dx/physics/chipmunk/CCPhysicsBodyInfo.cpp @@ -0,0 +1,45 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCPhysicsBodyInfo.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) +NS_CC_BEGIN + +PhysicsBodyInfo::PhysicsBodyInfo() +: body(nullptr) +{ +} + +PhysicsBodyInfo::~PhysicsBodyInfo() +{ + if (body) cpBodyFree(body); +} + +Clonable* PhysicsBodyInfo::clone() const +{ + +} + +NS_CC_END +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK diff --git a/cocos2dx/physics/CCPhysicsContactDelegate.h b/cocos2dx/physics/chipmunk/CCPhysicsBodyInfo.h similarity index 69% rename from cocos2dx/physics/CCPhysicsContactDelegate.h rename to cocos2dx/physics/chipmunk/CCPhysicsBodyInfo.h index a371b6e044..796f384584 100644 --- a/cocos2dx/physics/CCPhysicsContactDelegate.h +++ b/cocos2dx/physics/chipmunk/CCPhysicsBodyInfo.h @@ -22,31 +22,31 @@ THE SOFTWARE. ****************************************************************************/ -#include "CCPhysicsSetting.h" -#ifdef CC_USE_PHYSICS - -#ifndef __CCPHYSICS_CONTACTDELEGATE_H__ -#define __CCPHYSICS_CONTACTDELEGATE_H__ +#include "../CCPhysicsSetting.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) +#ifndef __CCPHYSICS_BODY_INFO_H__ +#define __CCPHYSICS_BODY_INFO_H__ +#include "platform/CCPlatformMacros.h" #include "cocoa/CCObject.h" -#include "cocoa/CCGeometry.h" NS_CC_BEGIN -class PhysicsBody; - -class PhysicsContactDelegate +class PhysicsBodyInfo : public Clonable { public: - PhysicsContactDelegate(); - virtual ~PhysicsContactDelegate(); + cpBody* body; -public: - virtual void onContactBegin(PhysicsBody* bodyA, PhysicsBody* bodyB, float collisionImpulse, Point contactPoint) = 0; - virtual void onContactEnd(PhysicsBody* bodyA, PhysicsBody* bodyB, float collisionImpulse, Point contactPoint) = 0; +private: + PhysicsBodyInfo(); + ~PhysicsBodyInfo(); + + Clonable* clone() const override; + + friend class PhysicsBody; }; NS_CC_END -#endif //__CCPHYSICS_CONTACTDELEGATE_H__ +#endif // __CCPHYSICS_BODY_INFO_H__ -#endif // CC_USE_PHYSICS +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK diff --git a/cocos2dx/physics/chipmunk/CCPhysicsContactInfo.cpp b/cocos2dx/physics/chipmunk/CCPhysicsContactInfo.cpp new file mode 100644 index 0000000000..53b4f29b14 --- /dev/null +++ b/cocos2dx/physics/chipmunk/CCPhysicsContactInfo.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCPhysicsContactInfo.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) +NS_CC_BEGIN + +PhysicsContactInfo::PhysicsContactInfo(PhysicsContact* contact) +: contact(contact) +{ +} + +PhysicsContactInfo::~PhysicsContactInfo() +{ +} + +NS_CC_END +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK diff --git a/cocos2dx/physics/chipmunk/CCPhysicsContactInfo.h b/cocos2dx/physics/chipmunk/CCPhysicsContactInfo.h new file mode 100644 index 0000000000..b0d123ae21 --- /dev/null +++ b/cocos2dx/physics/chipmunk/CCPhysicsContactInfo.h @@ -0,0 +1,49 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "../CCPhysicsSetting.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + +#ifndef __CCPHYSICS_CONTACT_INFO_H__ +#define __CCPHYSICS_CONTACT_INFO_H__ +#include "platform/CCPlatformMacros.h" +NS_CC_BEGIN + +class PhysicsContact; +class PhysicsContactInfo +{ +public: + PhysicsContact* contact; + +private: + PhysicsContactInfo(PhysicsContact* contact); + ~PhysicsContactInfo(); + + friend class PhysicsContact; +}; + +NS_CC_END +#endif // __CCPHYSICS_WORLD_INFO_H__ + +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK diff --git a/cocos2dx/physics/chipmunk/CCPhysicsHelper.h b/cocos2dx/physics/chipmunk/CCPhysicsHelper.h new file mode 100644 index 0000000000..07508e9b13 --- /dev/null +++ b/cocos2dx/physics/chipmunk/CCPhysicsHelper.h @@ -0,0 +1,68 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "../CCPhysicsSetting.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + +#ifndef __CCPHYSICS_HELPER_H__ +#define __CCPHYSICS_HELPER_H__ + +#include "platform/CCPlatformMacros.h" +#include "cocoa/CCGeometry.h" + +NS_CC_BEGIN + +class PhysicsHelper +{ +public: + static Point cpv2point(const cpVect& vec) { return Point(vec.x, vec.y); } + static cpVect point2cpv(const Point& point) { return cpv(point.x, point.y); } + static Size cpv2size(const cpVect& vec) { return Size(vec.x, vec.y); } + static cpVect size2cpv(const Size& size) { return cpv(size.width, size.height); } + static float cpfloat2float(cpFloat f) { return f; } + static cpFloat float2cpfloat(float f) { return f; } + + static void cpvs2points(const cpVect* cpvs, Point* points, int count) + { + for (int i = 0; i < count; ++i) + { + points[i] = cpv2point(cpvs[i]); + } + } + + static cpVect* points2cpvs(const Point* points, cpVect* cpvs, int count) + { + for (int i = 0; i < count; ++i) + { + cpvs[i] = point2cpv(points[i]); + } + + return cpvs; + } +}; + +NS_CC_END +#endif // __CCPHYSICS_HELPER_H__ + +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK diff --git a/cocos2dx/physics/chipmunk/CCPhysicsJointInfo.cpp b/cocos2dx/physics/chipmunk/CCPhysicsJointInfo.cpp new file mode 100644 index 0000000000..aca28aa0fb --- /dev/null +++ b/cocos2dx/physics/chipmunk/CCPhysicsJointInfo.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCPhysicsJointInfo.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) +NS_CC_BEGIN + +PhysicsJointInfo::PhysicsJointInfo() +: joint(nullptr) +{ +} + +PhysicsJointInfo::~PhysicsJointInfo() +{ + if (joint) + { + cpConstraintFree(joint); + } +} + +NS_CC_END +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK diff --git a/cocos2dx/physics/chipmunk/CCPhysicsJointInfo.h b/cocos2dx/physics/chipmunk/CCPhysicsJointInfo.h new file mode 100644 index 0000000000..4174c866f6 --- /dev/null +++ b/cocos2dx/physics/chipmunk/CCPhysicsJointInfo.h @@ -0,0 +1,50 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "../CCPhysicsSetting.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + +#ifndef __CCPHYSICS_JOINT_INFO_H__ +#define __CCPHYSICS_JOINT_INFO_H__ + +#include "platform/CCPlatformMacros.h" + +NS_CC_BEGIN + +class PhysicsJointInfo +{ +public: + cpConstraint* joint; + +private: + PhysicsJointInfo(); + ~PhysicsJointInfo(); + + friend class PhysicsJoint; +}; + +NS_CC_END +#endif // __CCPHYSICS_SHAPE_INFO_H__ + +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK diff --git a/cocos2dx/physics/chipmunk/CCPhysicsShapeInfo.cpp b/cocos2dx/physics/chipmunk/CCPhysicsShapeInfo.cpp new file mode 100644 index 0000000000..f22d7a3267 --- /dev/null +++ b/cocos2dx/physics/chipmunk/CCPhysicsShapeInfo.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCPhysicsShapeInfo.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) +NS_CC_BEGIN + +std::map PhysicsShapeInfo::map; + +PhysicsShapeInfo::PhysicsShapeInfo(PhysicsShape* shape) +: shape(shape) +{ +} + +PhysicsShapeInfo::~PhysicsShapeInfo() +{ + for (auto it = shapes.begin(); it != shapes.end(); it++) + { + cpShapeFree(*it); + + auto mit = map.find(*it); + if (mit != map.end()) map.erase(*it); + } +} + +void PhysicsShapeInfo::add(cpShape* shape) +{ + if (shape == nullptr) return; + + shapes.push_back(shape); + map.insert(std::pair(shape, this)); +} + +void PhysicsShapeInfo::remove(cpShape* shape) +{ + if (shape == nullptr) return; + + auto it = find(shapes.begin(), shapes.end(), shape); + if (it != shapes.end()) + { + shapes.erase(it); + + auto mit = map.find(shape); + if (mit != map.end()) map.erase(mit); + } +} + +NS_CC_END +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK diff --git a/cocos2dx/physics/chipmunk/CCPhysicsShapeInfo.h b/cocos2dx/physics/chipmunk/CCPhysicsShapeInfo.h new file mode 100644 index 0000000000..7114bd3961 --- /dev/null +++ b/cocos2dx/physics/chipmunk/CCPhysicsShapeInfo.h @@ -0,0 +1,61 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "../CCPhysicsSetting.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + +#ifndef __CCPHYSICS_SHAPE_INFO_H__ +#define __CCPHYSICS_SHAPE_INFO_H__ +#include + +#include "platform/CCPlatformMacros.h" +#include + +NS_CC_BEGIN + +class PhysicsShape; + +class PhysicsShapeInfo +{ +public: + void add(cpShape* shape); + void remove(cpShape* shape); + void removeall(); + +public: + std::vector shapes; + static std::map map; + PhysicsShape* shape; + +private: + PhysicsShapeInfo(PhysicsShape* shape); + ~PhysicsShapeInfo(); + + friend class PhysicsShape; +}; + +NS_CC_END +#endif // __CCPHYSICS_SHAPE_INFO_H__ + +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK diff --git a/cocos2dx/physics/chipmunk/CCPhysicsWorldInfo.cpp b/cocos2dx/physics/chipmunk/CCPhysicsWorldInfo.cpp new file mode 100644 index 0000000000..57f601ead7 --- /dev/null +++ b/cocos2dx/physics/chipmunk/CCPhysicsWorldInfo.cpp @@ -0,0 +1,40 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCPhysicsWorldInfo.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) +NS_CC_BEGIN + +PhysicsWorldInfo::PhysicsWorldInfo() +{ + space = cpSpaceNew(); +} + +PhysicsWorldInfo::~PhysicsWorldInfo() +{ + cpSpaceFree(space); +} + +NS_CC_END +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK diff --git a/cocos2dx/physics/chipmunk/CCPhysicsWorldInfo.h b/cocos2dx/physics/chipmunk/CCPhysicsWorldInfo.h new file mode 100644 index 0000000000..a1f1e66342 --- /dev/null +++ b/cocos2dx/physics/chipmunk/CCPhysicsWorldInfo.h @@ -0,0 +1,48 @@ +/**************************************************************************** + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "../CCPhysicsSetting.h" +#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK) + +#ifndef __CCPHYSICS_WORLD_INFO_H__ +#define __CCPHYSICS_WORLD_INFO_H__ +#include "platform/CCPlatformMacros.h" +NS_CC_BEGIN + +class PhysicsWorldInfo +{ +public: + cpSpace* space; + +private: + PhysicsWorldInfo(); + ~PhysicsWorldInfo(); + + friend class PhysicsWorld; +}; + +NS_CC_END +#endif // __CCPHYSICS_WORLD_INFO_H__ + +#endif // CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK diff --git a/cocos2dx/physics/chipmunk/ChipmunkDebugDraw.c b/cocos2dx/physics/chipmunk/ChipmunkDebugDraw.c new file mode 100644 index 0000000000..38b06af1a0 --- /dev/null +++ b/cocos2dx/physics/chipmunk/ChipmunkDebugDraw.c @@ -0,0 +1,446 @@ +/* Copyright (c) 2007 Scott Lembcke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +#ifdef __APPLE__ + #include "OpenGL/gl.h" + #include "OpenGL/glu.h" + #include +#else + #ifdef WIN32 + #include + #endif + + #include + #include + #include +#endif + +#include "chipmunk_private.h" +#include "ChipmunkDebugDraw.h" + +/* + IMPORTANT - READ ME! + + This file sets up a simple interface that the individual demos can use to get + a Chipmunk space running and draw what's in it. In order to keep the Chipmunk + examples clean and simple, they contain no graphics code. All drawing is done + by accessing the Chipmunk structures at a very low level. It is NOT + recommended to write a game or application this way as it does not scale + beyond simple shape drawing and is very dependent on implementation details + about Chipmunk which may change with little to no warning. +*/ + +const Color LINE_COLOR = {200.0/255.0, 210.0/255.0, 230.0/255.0, 1.0}; +const Color CONSTRAINT_COLOR = {0.0, 0.75, 0.0, 1.0}; +const float SHAPE_ALPHA = 1.0; + +float ChipmunkDebugDrawPointLineScale = 1.0; + +static Color +ColorFromHash(cpHashValue hash, float alpha) +{ + unsigned long val = (unsigned long)hash; + + // scramble the bits up using Robert Jenkins' 32 bit integer hash function + val = (val+0x7ed55d16) + (val<<12); + val = (val^0xc761c23c) ^ (val>>19); + val = (val+0x165667b1) + (val<<5); + val = (val+0xd3a2646c) ^ (val<<9); + val = (val+0xfd7046c5) + (val<<3); + val = (val^0xb55a4f09) ^ (val>>16); + + GLfloat r = (val>>0) & 0xFF; + GLfloat g = (val>>8) & 0xFF; + GLfloat b = (val>>16) & 0xFF; + + GLfloat max = cpfmax(cpfmax(r, g), b); + GLfloat min = cpfmin(cpfmin(r, g), b); + GLfloat intensity = 0.75; + + // Saturate and scale the color + if(min == max){ + return RGBAColor(intensity, 0.0, 0.0, alpha); + } else { + GLfloat coef = alpha*intensity/(max - min); + return RGBAColor( + (r - min)*coef, + (g - min)*coef, + (b - min)*coef, + alpha + ); + } +} + +static inline void +glColor_from_color(Color color){ + glColor4fv((GLfloat *)&color); +} + +static Color +ColorForShape(cpShape *shape) +{ + if(cpShapeGetSensor(shape)){ + return LAColor(1, 0); + } else { + cpBody *body = shape->body; + + if(cpBodyIsSleeping(body)){ + return LAColor(0.2, 1); + } else if(body->node.idleTime > shape->space->sleepTimeThreshold) { + return LAColor(0.66, 1); + } else { + return ColorFromHash(shape->hashid, SHAPE_ALPHA); + } + } +} + +static const GLfloat circleVAR[] = { + 0.0000f, 1.0000f, + 0.2588f, 0.9659f, + 0.5000f, 0.8660f, + 0.7071f, 0.7071f, + 0.8660f, 0.5000f, + 0.9659f, 0.2588f, + 1.0000f, 0.0000f, + 0.9659f, -0.2588f, + 0.8660f, -0.5000f, + 0.7071f, -0.7071f, + 0.5000f, -0.8660f, + 0.2588f, -0.9659f, + 0.0000f, -1.0000f, + -0.2588f, -0.9659f, + -0.5000f, -0.8660f, + -0.7071f, -0.7071f, + -0.8660f, -0.5000f, + -0.9659f, -0.2588f, + -1.0000f, -0.0000f, + -0.9659f, 0.2588f, + -0.8660f, 0.5000f, + -0.7071f, 0.7071f, + -0.5000f, 0.8660f, + -0.2588f, 0.9659f, + 0.0000f, 1.0000f, + 0.0f, 0.0f, // For an extra line to see the rotation. +}; +static const int circleVAR_count = sizeof(circleVAR)/sizeof(GLfloat)/2; + +void ChipmunkDebugDrawCircle(cpVect center, cpFloat angle, cpFloat radius, Color lineColor, Color fillColor) +{ + glVertexPointer(2, GL_FLOAT, 0, circleVAR); + + glPushMatrix(); { + glTranslatef(center.x, center.y, 0.0f); + glRotatef(angle*180.0f/M_PI, 0.0f, 0.0f, 1.0f); + glScalef(radius, radius, 1.0f); + + if(fillColor.a > 0){ + glColor_from_color(fillColor); + glDrawArrays(GL_TRIANGLE_FAN, 0, circleVAR_count - 1); + } + + if(lineColor.a > 0){ + glColor_from_color(lineColor); + glDrawArrays(GL_LINE_STRIP, 0, circleVAR_count); + } + } glPopMatrix(); +} + +static const GLfloat pillVAR[] = { + 0.0000f, 1.0000f, 1.0f, + 0.2588f, 0.9659f, 1.0f, + 0.5000f, 0.8660f, 1.0f, + 0.7071f, 0.7071f, 1.0f, + 0.8660f, 0.5000f, 1.0f, + 0.9659f, 0.2588f, 1.0f, + 1.0000f, 0.0000f, 1.0f, + 0.9659f, -0.2588f, 1.0f, + 0.8660f, -0.5000f, 1.0f, + 0.7071f, -0.7071f, 1.0f, + 0.5000f, -0.8660f, 1.0f, + 0.2588f, -0.9659f, 1.0f, + 0.0000f, -1.0000f, 1.0f, + + 0.0000f, -1.0000f, 0.0f, + -0.2588f, -0.9659f, 0.0f, + -0.5000f, -0.8660f, 0.0f, + -0.7071f, -0.7071f, 0.0f, + -0.8660f, -0.5000f, 0.0f, + -0.9659f, -0.2588f, 0.0f, + -1.0000f, -0.0000f, 0.0f, + -0.9659f, 0.2588f, 0.0f, + -0.8660f, 0.5000f, 0.0f, + -0.7071f, 0.7071f, 0.0f, + -0.5000f, 0.8660f, 0.0f, + -0.2588f, 0.9659f, 0.0f, + 0.0000f, 1.0000f, 0.0f, +}; +static const int pillVAR_count = sizeof(pillVAR)/sizeof(GLfloat)/3; + +void ChipmunkDebugDrawSegment(cpVect a, cpVect b, Color color) +{ + GLfloat verts[] = { + a.x, a.y, + b.x, b.y, + }; + + glVertexPointer(2, GL_FLOAT, 0, verts); + glColor_from_color(color); + glDrawArrays(GL_LINES, 0, 2); +} + +void ChipmunkDebugDrawFatSegment(cpVect a, cpVect b, cpFloat radius, Color lineColor, Color fillColor) +{ + if(radius){ + glVertexPointer(3, GL_FLOAT, 0, pillVAR); + glPushMatrix(); { + cpVect d = cpvsub(b, a); + cpVect r = cpvmult(d, radius/cpvlength(d)); + + const GLfloat matrix[] = { + r.x, r.y, 0.0f, 0.0f, + -r.y, r.x, 0.0f, 0.0f, + d.x, d.y, 0.0f, 0.0f, + a.x, a.y, 0.0f, 1.0f, + }; + glMultMatrixf(matrix); + + if(fillColor.a > 0){ + glColor_from_color(fillColor); + glDrawArrays(GL_TRIANGLE_FAN, 0, pillVAR_count); + } + + if(lineColor.a > 0){ + glColor_from_color(lineColor); + glDrawArrays(GL_LINE_LOOP, 0, pillVAR_count); + } + } glPopMatrix(); + } else { + ChipmunkDebugDrawSegment(a, b, lineColor); + } +} + +void ChipmunkDebugDrawPolygon(int count, cpVect *verts, Color lineColor, Color fillColor) +{ +#if CP_USE_DOUBLES + glVertexPointer(2, GL_DOUBLE, 0, verts); +#else + glVertexPointer(2, GL_FLOAT, 0, verts); +#endif + + if(fillColor.a > 0){ + glColor_from_color(fillColor); + glDrawArrays(GL_TRIANGLE_FAN, 0, count); + } + + if(lineColor.a > 0){ + glColor_from_color(lineColor); + glDrawArrays(GL_LINE_LOOP, 0, count); + } +} + +void ChipmunkDebugDrawPoints(cpFloat size, int count, cpVect *verts, Color color) +{ +#if CP_USE_DOUBLES + glVertexPointer(2, GL_DOUBLE, 0, verts); +#else + glVertexPointer(2, GL_FLOAT, 0, verts); +#endif + + glPointSize(size*ChipmunkDebugDrawPointLineScale); + glColor_from_color(color); + glDrawArrays(GL_POINTS, 0, count); +} + +void ChipmunkDebugDrawBB(cpBB bb, Color color) +{ + cpVect verts[] = { + cpv(bb.l, bb.b), + cpv(bb.l, bb.t), + cpv(bb.r, bb.t), + cpv(bb.r, bb.b), + }; + ChipmunkDebugDrawPolygon(4, verts, color, LAColor(0, 0)); +} + +static void +drawShape(cpShape *shape, void *unused) +{ + cpBody *body = shape->body; + Color color = ColorForShape(shape); + + switch(shape->klass->type){ + case CP_CIRCLE_SHAPE: { + cpCircleShape *circle = (cpCircleShape *)shape; + ChipmunkDebugDrawCircle(circle->tc, body->a, circle->r, LINE_COLOR, color); + break; + } + case CP_SEGMENT_SHAPE: { + cpSegmentShape *seg = (cpSegmentShape *)shape; + ChipmunkDebugDrawFatSegment(seg->ta, seg->tb, seg->r, LINE_COLOR, color); + break; + } + case CP_POLY_SHAPE: { + cpPolyShape *poly = (cpPolyShape *)shape; + ChipmunkDebugDrawPolygon(poly->numVerts, poly->tVerts, LINE_COLOR, color); + break; + } + default: break; + } +} + +void ChipmunkDebugDrawShape(cpShape *shape) +{ + drawShape(shape, NULL); +} + +void ChipmunkDebugDrawShapes(cpSpace *space) +{ + cpSpaceEachShape(space, drawShape, NULL); +} + +static const GLfloat springVAR[] = { + 0.00f, 0.0f, + 0.20f, 0.0f, + 0.25f, 3.0f, + 0.30f,-6.0f, + 0.35f, 6.0f, + 0.40f,-6.0f, + 0.45f, 6.0f, + 0.50f,-6.0f, + 0.55f, 6.0f, + 0.60f,-6.0f, + 0.65f, 6.0f, + 0.70f,-3.0f, + 0.75f, 6.0f, + 0.80f, 0.0f, + 1.00f, 0.0f, +}; +static const int springVAR_count = sizeof(springVAR)/sizeof(GLfloat)/2; + +static void +drawSpring(cpDampedSpring *spring, cpBody *body_a, cpBody *body_b) +{ + cpVect a = cpvadd(body_a->p, cpvrotate(spring->anchr1, body_a->rot)); + cpVect b = cpvadd(body_b->p, cpvrotate(spring->anchr2, body_b->rot)); + + cpVect points[] = {a, b}; + ChipmunkDebugDrawPoints(5, 2, points, CONSTRAINT_COLOR); + + cpVect delta = cpvsub(b, a); + + glVertexPointer(2, GL_FLOAT, 0, springVAR); + glPushMatrix(); { + GLfloat x = a.x; + GLfloat y = a.y; + GLfloat cos = delta.x; + GLfloat sin = delta.y; + GLfloat s = 1.0f/cpvlength(delta); + + const GLfloat matrix[] = { + cos, sin, 0.0f, 0.0f, + -sin*s, cos*s, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + x, y, 0.0f, 1.0f, + }; + + glMultMatrixf(matrix); + glDrawArrays(GL_LINE_STRIP, 0, springVAR_count); + } glPopMatrix(); +} + +static void +drawConstraint(cpConstraint *constraint, void *unused) +{ + cpBody *body_a = constraint->a; + cpBody *body_b = constraint->b; + + const cpConstraintClass *klass = constraint->klass; + 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)); + + cpVect points[] = {a, b}; + ChipmunkDebugDrawPoints(5, 2, points, CONSTRAINT_COLOR); + ChipmunkDebugDrawSegment(a, b, CONSTRAINT_COLOR); + } 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)); + + cpVect points[] = {a, b}; + ChipmunkDebugDrawPoints(5, 2, points, CONSTRAINT_COLOR); + ChipmunkDebugDrawSegment(a, b, CONSTRAINT_COLOR); + } 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)); + + cpVect points[] = {a, b}; + ChipmunkDebugDrawPoints(10, 2, points, CONSTRAINT_COLOR); + } 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)); + + ChipmunkDebugDrawPoints(5, 1, &c, CONSTRAINT_COLOR); + ChipmunkDebugDrawSegment(a, b, CONSTRAINT_COLOR); + } else if(klass == cpDampedSpringGetClass()){ + drawSpring((cpDampedSpring *)constraint, body_a, body_b); + } +} + +void ChipmunkDebugDrawConstraint(cpConstraint *constraint) +{ + drawConstraint(constraint, NULL); +} + +void ChipmunkDebugDrawConstraints(cpSpace *space) +{ + cpSpaceEachConstraint(space, drawConstraint, NULL); +} + +void ChipmunkDebugDrawCollisionPoints(cpSpace *space) +{ + cpArray *arbiters = space->arbiters; + + glColor3f(1.0f, 0.0f, 0.0f); + glPointSize(4.0f*ChipmunkDebugDrawPointLineScale); + + glBegin(GL_POINTS); { + for(int i=0; inum; i++){ + cpArbiter *arb = (cpArbiter*)arbiters->arr[i]; + + for(int j=0; jnumContacts; j++){ + cpVect v = arb->contacts[j].p; + glVertex2f(v.x, v.y); + } + } + } glEnd(); +} diff --git a/cocos2dx/physics/chipmunk/ChipmunkDebugDraw.h b/cocos2dx/physics/chipmunk/ChipmunkDebugDraw.h new file mode 100644 index 0000000000..9cc0a722fd --- /dev/null +++ b/cocos2dx/physics/chipmunk/ChipmunkDebugDraw.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2007 Scott Lembcke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +typedef struct Color { + float r, g, b, a; +} Color; + +static inline Color RGBAColor(float r, float g, float b, float a){ + Color color = {r, g, b, a}; + return color; +} + +static inline Color LAColor(float l, float a){ + Color color = {l, l, l, a}; + return color; +} + +extern float ChipmunkDebugDrawPointLineScale; + +void ChipmunkDebugDrawCircle(cpVect center, cpFloat angle, cpFloat radius, Color lineColor, Color fillColor); +void ChipmunkDebugDrawSegment(cpVect a, cpVect b, Color color); +void ChipmunkDebugDrawFatSegment(cpVect a, cpVect b, cpFloat radius, Color lineColor, Color fillColor); +void ChipmunkDebugDrawPolygon(int count, cpVect *verts, Color lineColor, Color fillColor); +void ChipmunkDebugDrawPoints(cpFloat size, int count, cpVect *verts, Color color); +void ChipmunkDebugDrawBB(cpBB bb, Color color); + +void ChipmunkDebugDrawConstraint(cpConstraint *constraint); +void ChipmunkDebugDrawShape(cpShape *shape); + +void ChipmunkDebugDrawShapes(cpSpace *space); +void ChipmunkDebugDrawConstraints(cpSpace *space); +void ChipmunkDebugDrawCollisionPoints(cpSpace *space); diff --git a/cocos2dx/sprite_nodes/CCSprite.cpp b/cocos2dx/sprite_nodes/CCSprite.cpp index ed8f0460c3..80c6fd696c 100644 --- a/cocos2dx/sprite_nodes/CCSprite.cpp +++ b/cocos2dx/sprite_nodes/CCSprite.cpp @@ -296,13 +296,18 @@ Sprite* Sprite::initWithCGImage(CGImageRef pImage, const char *pszKey) Sprite::Sprite(void) : _shouldBeHidden(false) , _texture(nullptr) +#ifdef CC_USE_PHYSICS , _physicsBody(nullptr) +#endif { } Sprite::~Sprite(void) { CC_SAFE_RELEASE(_texture); +#ifdef CC_USE_PHYSICS + CC_SAFE_RELEASE(_physicsBody); +#endif } void Sprite::setTextureRect(const Rect& rect) @@ -447,16 +452,6 @@ void Sprite::setTextureCoords(Rect rect) } } -void Sprite::setPhysicsBody(PhysicsBody* body) -{ - _physicsBody = body; -} - -PhysicsBody* Sprite::getPhysicsBody() const -{ - return _physicsBody; -} - void Sprite::updateTransform(void) { CCASSERT(_batchNode, "updateTransform is only valid when Sprite is being rendered using an SpriteBatchNode"); @@ -795,12 +790,27 @@ void Sprite::setPosition(const Point& pos) { Node::setPosition(pos); SET_DIRTY_RECURSIVELY(); + +#ifdef CC_USE_PHYSICS + if (_physicsBody) + { + _physicsBody->setPosition(pos); + } +#endif } -void Sprite::setRotation(float fRotation) +void Sprite::setRotation(float rotation) { - Node::setRotation(fRotation); + Node::setRotation(rotation); + SET_DIRTY_RECURSIVELY(); + +#ifdef CC_USE_PHYSICS + if (_physicsBody) + { + _physicsBody->setRotation(rotation); + } +#endif } void Sprite::setRotationX(float fRotationX) @@ -897,6 +907,33 @@ bool Sprite::isFlipY(void) const return _flipY; } +#ifdef CC_USE_PHYSICS +void Sprite::setPhysicsBody(PhysicsBody* body) +{ + _physicsBody = body; + _physicsBody->retain(); + _physicsBody->setPosition(getPosition()); + _physicsBody->setRotation(getRotation()); +} + +PhysicsBody* Sprite::getPhysicsBody() const +{ + return _physicsBody; +} + +void Sprite::visit() +{ + if (_physicsBody) + { + Node::setPosition(_physicsBody->getPosition()); + Node::setRotation(_physicsBody->getRotation()); + SET_DIRTY_RECURSIVELY(); + } + + Node::visit(); +} +#endif //CC_USE_PHYSICS + // // RGBA protocol // diff --git a/cocos2dx/sprite_nodes/CCSprite.h b/cocos2dx/sprite_nodes/CCSprite.h index 4d4d0e7bdf..6f66e630f6 100644 --- a/cocos2dx/sprite_nodes/CCSprite.h +++ b/cocos2dx/sprite_nodes/CCSprite.h @@ -454,6 +454,8 @@ public: * get the PhysicsBody the sprite have */ PhysicsBody* getPhysicsBody() const; + + virtual void visit() override; #endif /// @} End of Sprite properties getter/setters diff --git a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp index a1d9180b72..a95e864344 100644 --- a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp +++ b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp @@ -1,25 +1,42 @@ #include "PhysicsTest.h" #include "../testResource.h" -#include "cocos-ext.h" -USING_NS_CC_EXT; +USING_NS_CC; PhysicsTestLayer::PhysicsTestLayer() : _spriteTexture(NULL) { #ifdef CC_USE_PHYSICS - //Set up sprite -#if 1 - // Use batch node. Faster - auto parent = SpriteBatchNode::create("Images/blocks.png", 100); + setTouchEnabled(true); + setAccelerometerEnabled(true); + + // title + auto label = LabelTTF::create("Multi touch the screen", "Marker Felt", 36); + label->setPosition(Point( VisibleRect::center().x, VisibleRect::top().y - 30)); + this->addChild(label, -1); + + // menu for debug layer + MenuItemFont::setFontSize(18); + auto item = MenuItemFont::create("Toggle debug", CC_CALLBACK_1(PhysicsTestLayer::toggleDebugCallback, this)); + + auto menu = Menu::create(item, NULL); + this->addChild(menu); + menu->setPosition(Point(VisibleRect::right().x-100, VisibleRect::top().y-60)); + + auto sp = Sprite::create(); + auto body = PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size); + sp->setPhysicsBody(body); + this->addChild(sp); + sp->setPosition(VisibleRect::center()); + + auto parent = SpriteBatchNode::create("Images/grossini_dance_atlas.png", 100); _spriteTexture = parent->getTexture(); -#else - // doesn't use batch node. Slower - _spriteTexture = TextureCache::getInstance()->addImage("Images/blocks.png"); - auto parent = Node::create(); -#endif + + addNewSpriteAtPosition(VisibleRect::center()); + + createResetButton(); #else - auto label = LabelTTF::create("Should define CC_ENABLE_BOX2D_INTEGRATION=1\n to run this test case", + auto label = LabelTTF::create("Should define CC_USE_BOX2D or CC_USE_CHIPMUNK\n to run this test case", "Arial", 18); auto size = Director::getInstance()->getWinSize(); @@ -29,11 +46,18 @@ PhysicsTestLayer::PhysicsTestLayer() #endif } -PhysicsTestLayer::~PhysicsTestLayer() +void PhysicsTestLayer::toggleDebugCallback(Object* sender) { +#ifdef CC_USE_PHYSICS + if (dynamic_cast(this->getParent()) != nullptr) + { + PhysicsWorld* world = dynamic_cast(this->getParent())->getPhysicsWorld(); + world->setDebugDraw(!world->getDebugDraw()); + } +#endif } -void PhysicsTestLayer::initPhysics() +PhysicsTestLayer::~PhysicsTestLayer() { } @@ -41,6 +65,7 @@ void PhysicsTestLayer::createResetButton() { auto reset = MenuItemImage::create("Images/r1.png", "Images/r2.png", [](Object *sender) { auto s = new PhysicsTestScene(); + s->initTest(); auto child = new PhysicsTestLayer(); s->addChild(child); child->release(); @@ -55,37 +80,13 @@ void PhysicsTestLayer::createResetButton() } -void PhysicsTestLayer::addNewSpriteAtPosition(Point p) -{ - CCLOG("Add sprite %0.2f x %02.f",p.x,p.y); - -#if CC_ENABLE_BOX2D_INTEGRATION - auto parent = this->getChildByTag(kTagParentNode); - - //We have a 64x64 sprite sheet with 4 different 32x32 images. The following code is - //just randomly picking one of the images - int idx = (CCRANDOM_0_1() > .5 ? 0:1); - int idy = (CCRANDOM_0_1() > .5 ? 0:1); - auto sprite = PhysicsSprite::createWithTexture(_spriteTexture,Rect(32 * idx,32 * idy,32,32)); - parent->addChild(sprite); - sprite->setB2Body(body); - sprite->setPTMRatio(PTM_RATIO); - sprite->setPosition( Point( p.x, p.y) ); -#endif -} - void PhysicsTestLayer::ccTouchesEnded(Set* touches, Event* event) { //Add a new body/atlas sprite at the touched location - SetIterator it; - Touch* touch; - for( it = touches->begin(); it != touches->end(); it++) + for( auto &item: *touches) { - touch = static_cast(*it); - - if(!touch) - break; + auto touch = static_cast(item); auto location = touch->getLocation(); @@ -93,9 +94,40 @@ void PhysicsTestLayer::ccTouchesEnded(Set* touches, Event* event) } } +void PhysicsTestLayer::addNewSpriteAtPosition(Point p) +{ +#ifdef CC_USE_PHYSICS + CCLOG("Add sprite %0.2f x %02.f",p.x,p.y); + + int posx, posy; + + posx = CCRANDOM_0_1() * 200.0f; + posy = CCRANDOM_0_1() * 200.0f; + + posx = (posx % 4) * 85; + posy = (posy % 3) * 121; + + auto sp = Sprite::createWithTexture(_spriteTexture, Rect(posx, posy, 85, 121)); + auto body = PhysicsBody::createBox(Size(48, 108)); + sp->setPhysicsBody(body); + sp->setPosition(p); + this->addChild(sp); +#endif +} + bool PhysicsTestScene::initTest() { - return TestScene::initWithPhysics(); +#ifdef CC_USE_PHYSICS + if (TestScene::initWithPhysics()) + { + this->getPhysicsWorld()->setDebugDraw(true); + return true; + } +#else + return TestScene::init(); +#endif + + return false; } void PhysicsTestScene::runThisTest() diff --git a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h index 8140015488..73cfb56935 100644 --- a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h +++ b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h @@ -11,10 +11,10 @@ class PhysicsTestLayer : public Layer public: PhysicsTestLayer(); ~PhysicsTestLayer(); - - void initPhysics(); + void createResetButton(); + void toggleDebugCallback(Object* sender); void addNewSpriteAtPosition(Point p); virtual void ccTouchesEnded(Set* touches, Event* event); } ;