Merge pull request #4022 from boyu0/iss2771_physical

issue #2771: physical
This commit is contained in:
minggo 2013-11-03 18:40:14 -08:00
commit 25b0ffe853
47 changed files with 1778 additions and 579 deletions

View File

@ -1 +1 @@
8c640bf1e2f1cd0a489e6169c930234b809636f2
5a0361664f33af4303065c98da4b8d8e4efe48b4

View File

@ -149,16 +149,16 @@ platform/CCThread.cpp \
../physics/CCPhysicsJoint.cpp \
../physics/CCPhysicsShape.cpp \
../physics/CCPhysicsWorld.cpp \
../physics/box2d/CCPhysicsBodyInfo.cpp \
../physics/box2d/CCPhysicsContactInfo.cpp \
../physics/box2d/CCPhysicsJointInfo.cpp \
../physics/box2d/CCPhysicsShapeInfo.cpp \
../physics/box2d/CCPhysicsWorldInfo.cpp \
../physics/chipmunk/CCPhysicsBodyInfo.cpp \
../physics/chipmunk/CCPhysicsContactInfo.cpp \
../physics/chipmunk/CCPhysicsJointInfo.cpp \
../physics/chipmunk/CCPhysicsShapeInfo.cpp \
../physics/chipmunk/CCPhysicsWorldInfo.cpp \
../physics/box2d/CCPhysicsBodyInfo_box2d.cpp \
../physics/box2d/CCPhysicsContactInfo_box2d.cpp \
../physics/box2d/CCPhysicsJointInfo_box2d.cpp \
../physics/box2d/CCPhysicsShapeInfo_box2d.cpp \
../physics/box2d/CCPhysicsWorldInfo_box2d.cpp \
../physics/chipmunk/CCPhysicsBodyInfo_chipmunk.cpp \
../physics/chipmunk/CCPhysicsContactInfo_chipmunk.cpp \
../physics/chipmunk/CCPhysicsJointInfo_chipmunk.cpp \
../physics/chipmunk/CCPhysicsShapeInfo_chipmunk.cpp \
../physics/chipmunk/CCPhysicsWorldInfo_chipmunk.cpp \
../../external/tinyxml2/tinyxml2.cpp \
../../external/unzip/ioapi.cpp \
../../external/unzip/unzip.cpp

View File

@ -87,29 +87,6 @@ Layer *Layer::create()
}
}
#ifdef CC_USE_PHYSICS
void Layer::addChild(Node* child)
{
Node::addChild(child);
}
void Layer::addChild(Node* child, int zOrder)
{
Node::addChild(child, zOrder);
}
void Layer::addChild(Node* child, int zOrder, int tag)
{
Node::addChild(child, zOrder, tag);
if (this->getParent() &&
dynamic_cast<Scene*>(this->getParent()) != nullptr)
{
dynamic_cast<Scene*>(this->getParent())->addChildToPhysicsWorld(child);
}
}
#endif
// LayerRGBA
LayerRGBA::LayerRGBA()
: _displayedOpacity(255)

View File

@ -112,12 +112,6 @@ public:
//
// Overrides
//
#ifdef CC_USE_PHYSICS
virtual void addChild(Node* child) override;
virtual void addChild(Node* child, int zOrder) override;
virtual void addChild(Node* child, int zOrder, int tag) override;
#endif // CC_USE_PHYSICS
};
#ifdef __apple__

View File

@ -43,6 +43,7 @@ THE SOFTWARE.
#include "CCEventDispatcher.h"
#include "CCEvent.h"
#include "CCEventTouch.h"
#include "CCScene.h"
#ifdef CC_USE_PHYSICS
#include "CCPhysicsBody.h"
@ -629,6 +630,17 @@ void Node::addChild(Node *child, int zOrder, int tag)
}
this->insertChild(child, zOrder);
#ifdef CC_USE_PHYSICS
for (Node* node = this->getParent(); node != nullptr; node = node->getParent())
{
if (dynamic_cast<Scene*>(node) != nullptr)
{
(dynamic_cast<Scene*>(node))->addChildToPhysicsWorld(child);
break;
}
}
#endif
child->_tag = tag;
@ -752,6 +764,14 @@ void Node::detachChild(Node *child, int childIndex, bool doCleanup)
child->onExitTransitionDidStart();
child->onExit();
}
#ifdef CC_USE_PHYSICS
if (child->_physicsBody != nullptr)
{
child->_physicsBody->removeFromWorld();
}
#endif
// If you don't do cleanup, the child's actions will not get removed and the
// its scheduledSelectors_ dict will not get released!
@ -1369,10 +1389,12 @@ void Node::setPhysicsBody(PhysicsBody* body)
{
if (_physicsBody != nullptr)
{
_physicsBody->_node = nullptr;
_physicsBody->release();
}
_physicsBody = body;
_physicsBody->_node = this;
_physicsBody->retain();
_physicsBody->setPosition(getPosition());
_physicsBody->setRotation(getRotation());

View File

@ -102,8 +102,7 @@ bool Scene::initWithPhysics()
Director * pDirector;
CC_BREAK_IF( ! (pDirector = Director::getInstance()) );
this->setContentSize(pDirector->getWinSize());
CC_BREAK_IF(! (_physicsWorld = PhysicsWorld::create()));
_physicsWorld->setScene(this);
CC_BREAK_IF(! (_physicsWorld = PhysicsWorld::create(*this)));
this->scheduleUpdate();
// success
@ -136,14 +135,8 @@ void Scene::addChildToPhysicsWorld(Node* child)
std::function<void(Object*)> addToPhysicsWorldFunc = nullptr;
addToPhysicsWorldFunc = [this, &addToPhysicsWorldFunc](Object* child) -> void
{
if (dynamic_cast<SpriteBatchNode*>(child) != nullptr)
{
Object* subChild = nullptr;
CCARRAY_FOREACH((dynamic_cast<SpriteBatchNode*>(child))->getChildren(), subChild)
{
addToPhysicsWorldFunc(subChild);
}
}else if (dynamic_cast<Node*>(child) != nullptr)
if (dynamic_cast<Node*>(child) != nullptr)
{
Node* node = dynamic_cast<Node*>(child);
@ -151,20 +144,16 @@ void Scene::addChildToPhysicsWorld(Node* child)
{
_physicsWorld->addBody(node->getPhysicsBody());
}
Object* subChild = nullptr;
CCARRAY_FOREACH(node->getChildren(), subChild)
{
addToPhysicsWorldFunc(subChild);
}
}
};
if(dynamic_cast<Layer*>(child) != nullptr)
{
Object* subChild = nullptr;
CCARRAY_FOREACH(child->getChildren(), subChild)
{
addToPhysicsWorldFunc(subChild);
}
}else
{
addToPhysicsWorldFunc(child);
}
addToPhysicsWorldFunc(child);
}
}

View File

@ -87,7 +87,7 @@ protected:
PhysicsWorld* _physicsWorld;
#endif // CC_USE_PHYSICS
friend class Layer;
friend class Node;
friend class SpriteBatchNode;
};

View File

@ -181,17 +181,6 @@ void SpriteBatchNode::addChild(Node *child, int zOrder, int tag)
Node::addChild(child, zOrder, tag);
appendChild(sprite);
if (this->getParent() &&
dynamic_cast<Layer*>(this->getParent()) != nullptr)
{
if (this->getParent()->getParent() &&
dynamic_cast<Scene*>(this->getParent()->getParent()))
{
dynamic_cast<Scene*>(this->getParent()->getParent())->addChildToPhysicsWorld(child);
}
}
}
// override reorderChild

View File

@ -75,16 +75,16 @@ CCParticleExamples.cpp \
CCParticleSystem.cpp \
CCParticleSystemQuad.cpp \
CCParticleBatchNode.cpp \
../physics/box2d/CCPhysicsContactInfo.cpp \
../physics/box2d/CCPhysicsJointInfo.cpp \
../physics/box2d/CCPhysicsShapeInfo.cpp \
../physics/box2d/CCPhysicsBodyInfo.cpp \
../physics/box2d/CCPhysicsWorldInfo.cpp \
../physics/chipmunk/CCPhysicsContactInfo.cpp \
../physics/chipmunk/CCPhysicsJointInfo.cpp \
../physics/chipmunk/CCPhysicsShapeInfo.cpp \
../physics/chipmunk/CCPhysicsBodyInfo.cpp \
../physics/chipmunk/CCPhysicsWorldInfo.cpp \
../physics/box2d/CCPhysicsContactInfo_box2d.cpp \
../physics/box2d/CCPhysicsJointInfo_box2d.cpp \
../physics/box2d/CCPhysicsShapeInfo_box2d.cpp \
../physics/box2d/CCPhysicsBodyInfo_box2d.cpp \
../physics/box2d/CCPhysicsWorldInfo_box2d.cpp \
../physics/chipmunk/CCPhysicsContactInfo_chipmunk.cpp \
../physics/chipmunk/CCPhysicsJointInfo_chipmunk.cpp \
../physics/chipmunk/CCPhysicsShapeInfo_chipmunk.cpp \
../physics/chipmunk/CCPhysicsBodyInfo_chipmunk.cpp \
../physics/chipmunk/CCPhysicsWorldInfo_chipmunk.cpp \
../physics/CCPhysicsBody.cpp \
../physics/CCPhysicsContact.cpp \
../physics/CCPhysicsShape.cpp \

View File

@ -192,21 +192,21 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou
<ClCompile Include="..\math\kazmath\src\vec2.c" />
<ClCompile Include="..\math\kazmath\src\vec3.c" />
<ClCompile Include="..\math\kazmath\src\vec4.c" />
<ClCompile Include="..\physics\Box2D\CCPhysicsBodyInfo.cpp" />
<ClCompile Include="..\physics\Box2D\CCPhysicsContactInfo.cpp" />
<ClCompile Include="..\physics\Box2D\CCPhysicsJointInfo.cpp" />
<ClCompile Include="..\physics\Box2D\CCPhysicsShapeInfo.cpp" />
<ClCompile Include="..\physics\Box2D\CCPhysicsWorldInfo.cpp" />
<ClCompile Include="..\physics\box2d\CCPhysicsBodyInfo_box2d.cpp" />
<ClCompile Include="..\physics\box2d\CCPhysicsContactInfo_box2d.cpp" />
<ClCompile Include="..\physics\box2d\CCPhysicsJointInfo_box2d.cpp" />
<ClCompile Include="..\physics\box2d\CCPhysicsShapeInfo_box2d.cpp" />
<ClCompile Include="..\physics\box2d\CCPhysicsWorldInfo_box2d.cpp" />
<ClCompile Include="..\physics\CCPhysicsBody.cpp" />
<ClCompile Include="..\physics\CCPhysicsContact.cpp" />
<ClCompile Include="..\physics\CCPhysicsJoint.cpp" />
<ClCompile Include="..\physics\CCPhysicsShape.cpp" />
<ClCompile Include="..\physics\CCPhysicsWorld.cpp" />
<ClCompile Include="..\physics\chipmunk\CCPhysicsBodyInfo.cpp" />
<ClCompile Include="..\physics\chipmunk\CCPhysicsContactInfo.cpp" />
<ClCompile Include="..\physics\chipmunk\CCPhysicsJointInfo.cpp" />
<ClCompile Include="..\physics\chipmunk\CCPhysicsShapeInfo.cpp" />
<ClCompile Include="..\physics\chipmunk\CCPhysicsWorldInfo.cpp" />
<ClCompile Include="..\physics\chipmunk\CCPhysicsBodyInfo_chipmunk.cpp" />
<ClCompile Include="..\physics\chipmunk\CCPhysicsContactInfo_chipmunk.cpp" />
<ClCompile Include="..\physics\chipmunk\CCPhysicsJointInfo_chipmunk.cpp" />
<ClCompile Include="..\physics\chipmunk\CCPhysicsShapeInfo_chipmunk.cpp" />
<ClCompile Include="..\physics\chipmunk\CCPhysicsWorldInfo_chipmunk.cpp" />
<ClCompile Include="base64.cpp" />
<ClCompile Include="CCAction.cpp" />
<ClCompile Include="CCActionCamera.cpp" />
@ -361,24 +361,24 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou
<ClInclude Include="..\math\kazmath\include\kazmath\vec2.h" />
<ClInclude Include="..\math\kazmath\include\kazmath\vec3.h" />
<ClInclude Include="..\math\kazmath\include\kazmath\vec4.h" />
<ClInclude Include="..\physics\Box2D\CCPhysicsBodyInfo.h" />
<ClInclude Include="..\physics\Box2D\CCPhysicsContactInfo.h" />
<ClInclude Include="..\physics\Box2D\CCPhysicsHelper.h" />
<ClInclude Include="..\physics\Box2D\CCPhysicsJointInfo.h" />
<ClInclude Include="..\physics\Box2D\CCPhysicsShapeInfo.h" />
<ClInclude Include="..\physics\Box2D\CCPhysicsWorldInfo.h" />
<ClInclude Include="..\physics\box2d\CCPhysicsBodyInfo_box2d.h" />
<ClInclude Include="..\physics\box2d\CCPhysicsContactInfo_box2d.h" />
<ClInclude Include="..\physics\box2d\CCPhysicsHelper_box2d.h" />
<ClInclude Include="..\physics\box2d\CCPhysicsJointInfo_box2d.h" />
<ClInclude Include="..\physics\box2d\CCPhysicsShapeInfo_box2d.h" />
<ClInclude Include="..\physics\box2d\CCPhysicsWorldInfo_box2d.h" />
<ClInclude Include="..\physics\CCPhysicsBody.h" />
<ClInclude Include="..\physics\CCPhysicsContact.h" />
<ClInclude Include="..\physics\CCPhysicsJoint.h" />
<ClInclude Include="..\physics\CCPhysicsSetting.h" />
<ClInclude Include="..\physics\CCPhysicsShape.h" />
<ClInclude Include="..\physics\CCPhysicsWorld.h" />
<ClInclude Include="..\physics\chipmunk\CCPhysicsBodyInfo.h" />
<ClInclude Include="..\physics\chipmunk\CCPhysicsContactInfo.h" />
<ClInclude Include="..\physics\chipmunk\CCPhysicsHelper.h" />
<ClInclude Include="..\physics\chipmunk\CCPhysicsJointInfo.h" />
<ClInclude Include="..\physics\chipmunk\CCPhysicsShapeInfo.h" />
<ClInclude Include="..\physics\chipmunk\CCPhysicsWorldInfo.h" />
<ClInclude Include="..\physics\chipmunk\CCPhysicsBodyInfo_chipmunk.h" />
<ClInclude Include="..\physics\chipmunk\CCPhysicsContactInfo_chipmunk.h" />
<ClInclude Include="..\physics\chipmunk\CCPhysicsHelper_chipmunk.h" />
<ClInclude Include="..\physics\chipmunk\CCPhysicsJointInfo_chipmunk.h" />
<ClInclude Include="..\physics\chipmunk\CCPhysicsShapeInfo_chipmunk.h" />
<ClInclude Include="..\physics\chipmunk\CCPhysicsWorldInfo_chipmunk.h" />
<ClInclude Include="base64.h" />
<ClInclude Include="CCAction.h" />
<ClInclude Include="CCActionCamera.h" />

View File

@ -129,36 +129,6 @@
<ClCompile Include="..\physics\CCPhysicsWorld.cpp">
<Filter>physics</Filter>
</ClCompile>
<ClCompile Include="..\physics\chipmunk\CCPhysicsBodyInfo.cpp">
<Filter>physics\chipmunk</Filter>
</ClCompile>
<ClCompile Include="..\physics\chipmunk\CCPhysicsContactInfo.cpp">
<Filter>physics\chipmunk</Filter>
</ClCompile>
<ClCompile Include="..\physics\chipmunk\CCPhysicsJointInfo.cpp">
<Filter>physics\chipmunk</Filter>
</ClCompile>
<ClCompile Include="..\physics\chipmunk\CCPhysicsShapeInfo.cpp">
<Filter>physics\chipmunk</Filter>
</ClCompile>
<ClCompile Include="..\physics\chipmunk\CCPhysicsWorldInfo.cpp">
<Filter>physics\chipmunk</Filter>
</ClCompile>
<ClCompile Include="..\physics\Box2D\CCPhysicsBodyInfo.cpp">
<Filter>physics\Box2D</Filter>
</ClCompile>
<ClCompile Include="..\physics\Box2D\CCPhysicsContactInfo.cpp">
<Filter>physics\Box2D</Filter>
</ClCompile>
<ClCompile Include="..\physics\Box2D\CCPhysicsJointInfo.cpp">
<Filter>physics\Box2D</Filter>
</ClCompile>
<ClCompile Include="..\physics\Box2D\CCPhysicsShapeInfo.cpp">
<Filter>physics\Box2D</Filter>
</ClCompile>
<ClCompile Include="..\physics\Box2D\CCPhysicsWorldInfo.cpp">
<Filter>physics\Box2D</Filter>
</ClCompile>
<ClCompile Include="CCNode.cpp">
<Filter>base_nodes</Filter>
</ClCompile>
@ -578,6 +548,36 @@
<ClCompile Include="CCEventMouse.cpp">
<Filter>event_dispatcher</Filter>
</ClCompile>
<ClCompile Include="..\physics\box2d\CCPhysicsBodyInfo_box2d.cpp">
<Filter>physics\Box2D</Filter>
</ClCompile>
<ClCompile Include="..\physics\box2d\CCPhysicsContactInfo_box2d.cpp">
<Filter>physics\Box2D</Filter>
</ClCompile>
<ClCompile Include="..\physics\box2d\CCPhysicsJointInfo_box2d.cpp">
<Filter>physics\Box2D</Filter>
</ClCompile>
<ClCompile Include="..\physics\box2d\CCPhysicsShapeInfo_box2d.cpp">
<Filter>physics\Box2D</Filter>
</ClCompile>
<ClCompile Include="..\physics\box2d\CCPhysicsWorldInfo_box2d.cpp">
<Filter>physics\Box2D</Filter>
</ClCompile>
<ClCompile Include="..\physics\chipmunk\CCPhysicsBodyInfo_chipmunk.cpp">
<Filter>physics\chipmunk</Filter>
</ClCompile>
<ClCompile Include="..\physics\chipmunk\CCPhysicsContactInfo_chipmunk.cpp">
<Filter>physics\chipmunk</Filter>
</ClCompile>
<ClCompile Include="..\physics\chipmunk\CCPhysicsJointInfo_chipmunk.cpp">
<Filter>physics\chipmunk</Filter>
</ClCompile>
<ClCompile Include="..\physics\chipmunk\CCPhysicsShapeInfo_chipmunk.cpp">
<Filter>physics\chipmunk</Filter>
</ClCompile>
<ClCompile Include="..\physics\chipmunk\CCPhysicsWorldInfo_chipmunk.cpp">
<Filter>physics\chipmunk</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\physics\CCPhysicsBody.h">
@ -598,42 +598,6 @@
<ClInclude Include="..\physics\CCPhysicsWorld.h">
<Filter>physics</Filter>
</ClInclude>
<ClInclude Include="..\physics\chipmunk\CCPhysicsBodyInfo.h">
<Filter>physics\chipmunk</Filter>
</ClInclude>
<ClInclude Include="..\physics\chipmunk\CCPhysicsContactInfo.h">
<Filter>physics\chipmunk</Filter>
</ClInclude>
<ClInclude Include="..\physics\chipmunk\CCPhysicsHelper.h">
<Filter>physics\chipmunk</Filter>
</ClInclude>
<ClInclude Include="..\physics\chipmunk\CCPhysicsJointInfo.h">
<Filter>physics\chipmunk</Filter>
</ClInclude>
<ClInclude Include="..\physics\chipmunk\CCPhysicsShapeInfo.h">
<Filter>physics\chipmunk</Filter>
</ClInclude>
<ClInclude Include="..\physics\chipmunk\CCPhysicsWorldInfo.h">
<Filter>physics\chipmunk</Filter>
</ClInclude>
<ClInclude Include="..\physics\Box2D\CCPhysicsBodyInfo.h">
<Filter>physics\Box2D</Filter>
</ClInclude>
<ClInclude Include="..\physics\Box2D\CCPhysicsContactInfo.h">
<Filter>physics\Box2D</Filter>
</ClInclude>
<ClInclude Include="..\physics\Box2D\CCPhysicsHelper.h">
<Filter>physics\Box2D</Filter>
</ClInclude>
<ClInclude Include="..\physics\Box2D\CCPhysicsJointInfo.h">
<Filter>physics\Box2D</Filter>
</ClInclude>
<ClInclude Include="..\physics\Box2D\CCPhysicsShapeInfo.h">
<Filter>physics\Box2D</Filter>
</ClInclude>
<ClInclude Include="..\physics\Box2D\CCPhysicsWorldInfo.h">
<Filter>physics\Box2D</Filter>
</ClInclude>
<ClInclude Include="CCNode.h">
<Filter>base_nodes</Filter>
</ClInclude>
@ -1164,5 +1128,41 @@
<ClInclude Include="CCEventMouse.h">
<Filter>event_dispatcher</Filter>
</ClInclude>
<ClInclude Include="..\physics\box2d\CCPhysicsBodyInfo_box2d.h">
<Filter>physics\Box2D</Filter>
</ClInclude>
<ClInclude Include="..\physics\box2d\CCPhysicsContactInfo_box2d.h">
<Filter>physics\Box2D</Filter>
</ClInclude>
<ClInclude Include="..\physics\box2d\CCPhysicsHelper_box2d.h">
<Filter>physics\Box2D</Filter>
</ClInclude>
<ClInclude Include="..\physics\box2d\CCPhysicsJointInfo_box2d.h">
<Filter>physics\Box2D</Filter>
</ClInclude>
<ClInclude Include="..\physics\box2d\CCPhysicsShapeInfo_box2d.h">
<Filter>physics\Box2D</Filter>
</ClInclude>
<ClInclude Include="..\physics\box2d\CCPhysicsWorldInfo_box2d.h">
<Filter>physics\Box2D</Filter>
</ClInclude>
<ClInclude Include="..\physics\chipmunk\CCPhysicsBodyInfo_chipmunk.h">
<Filter>physics\chipmunk</Filter>
</ClInclude>
<ClInclude Include="..\physics\chipmunk\CCPhysicsContactInfo_chipmunk.h">
<Filter>physics\chipmunk</Filter>
</ClInclude>
<ClInclude Include="..\physics\chipmunk\CCPhysicsHelper_chipmunk.h">
<Filter>physics\chipmunk</Filter>
</ClInclude>
<ClInclude Include="..\physics\chipmunk\CCPhysicsJointInfo_chipmunk.h">
<Filter>physics\chipmunk</Filter>
</ClInclude>
<ClInclude Include="..\physics\chipmunk\CCPhysicsShapeInfo_chipmunk.h">
<Filter>physics\chipmunk</Filter>
</ClInclude>
<ClInclude Include="..\physics\chipmunk\CCPhysicsWorldInfo_chipmunk.h">
<Filter>physics\chipmunk</Filter>
</ClInclude>
</ItemGroup>
</Project>
</Project>

View File

@ -207,6 +207,7 @@ typedef int (Object::*SEL_Compare)(Object*);
#define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)
#define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
#define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
#define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3 ##__VA_ARGS__)
// end of base_nodes group
/// @}

View File

@ -37,17 +37,16 @@
#include "CCPhysicsJoint.h"
#include "CCPhysicsWorld.h"
#include "chipmunk/CCPhysicsBodyInfo.h"
#include "box2d/CCPhysicsBodyInfo.h"
#include "chipmunk/CCPhysicsJointInfo.h"
#include "box2d/CCPhysicsJointInfo.h"
#include "chipmunk/CCPhysicsWorldInfo.h"
#include "box2d/CCPhysicsWorldInfo.h"
#include "chipmunk/CCPhysicsShapeInfo.h"
#include "box2d/CCPhysicsShapeInfo.h"
#include "chipmunk/CCPhysicsHelper.h"
#include "box2d/CCPhysicsHelper.h"
#include "chipmunk/CCPhysicsBodyInfo_chipmunk.h"
#include "box2d/CCPhysicsBodyInfo_box2d.h"
#include "chipmunk/CCPhysicsJointInfo_chipmunk.h"
#include "box2d/CCPhysicsJointInfo_box2d.h"
#include "chipmunk/CCPhysicsWorldInfo_chipmunk.h"
#include "box2d/CCPhysicsWorldInfo_box2d.h"
#include "chipmunk/CCPhysicsShapeInfo_chipmunk.h"
#include "box2d/CCPhysicsShapeInfo_box2d.h"
#include "chipmunk/CCPhysicsHelper_chipmunk.h"
#include "box2d/CCPhysicsHelper_box2d.h"
NS_CC_BEGIN
@ -58,11 +57,11 @@ namespace
{
static const float MASS_DEFAULT = 1.0;
static const float MOMENT_DEFAULT = 200;
static float GROUP_INDEX = 0;
}
PhysicsBody::PhysicsBody()
: _owner(nullptr)
: _node(nullptr)
, _shapes(nullptr)
, _world(nullptr)
, _info(nullptr)
, _dynamic(true)
@ -81,23 +80,29 @@ PhysicsBody::PhysicsBody()
, _categoryBitmask(UINT_MAX)
, _collisionBitmask(UINT_MAX)
, _contactTestBitmask(0)
, _group(0)
{
}
PhysicsBody::~PhysicsBody()
{
CC_SAFE_DELETE(_info);
if (_world)
{
removeFromWorld();
}
removeAllShapes();
for (auto it = _joints.begin(); it != _joints.end(); ++it)
{
PhysicsJoint* joint = *it;
PhysicsBody* other = joint->getBodyA() == this ? joint->getBodyA() : joint->getBodyB();
PhysicsBody* other = joint->getBodyA() == this ? joint->getBodyB() : joint->getBodyA();
other->_joints.erase(std::find(other->_joints.begin(), other->_joints.end(), joint));
delete joint;
}
CC_SAFE_DELETE(_info);
}
PhysicsBody* PhysicsBody::create()
@ -113,6 +118,45 @@ PhysicsBody* PhysicsBody::create()
return nullptr;
}
PhysicsBody* PhysicsBody::create(float mass)
{
PhysicsBody* body = new PhysicsBody();
if (body)
{
body->_mass = mass;
body->_massDefault = false;
if (body->init())
{
body->autorelease();
return body;
}
}
CC_SAFE_DELETE(body);
return nullptr;
}
PhysicsBody* PhysicsBody::create(float mass, float moment)
{
PhysicsBody* body = new PhysicsBody();
if (body)
{
body->_mass = mass;
body->_massDefault = false;
body->_moment = moment;
body->_momentDefault = false;
if (body->init())
{
body->autorelease();
return body;
}
}
CC_SAFE_DELETE(body);
return nullptr;
}
PhysicsBody* PhysicsBody::createCircle(float radius, PhysicsMaterial material)
{
PhysicsBody* body = new PhysicsBody();
@ -224,9 +268,11 @@ bool PhysicsBody::init()
{
_info = new PhysicsBodyInfo();
CC_BREAK_IF(_info == nullptr);
_shapes = Array::create();
CC_BREAK_IF(_shapes == nullptr);
_shapes->retain();
_info->body = cpBodyNew(PhysicsHelper::float2cpfloat(_mass), PhysicsHelper::float2cpfloat(_moment));
_info->group = ++GROUP_INDEX;
CC_BREAK_IF(_info->body == nullptr);
@ -274,10 +320,10 @@ void PhysicsBody::setGravityEnable(bool enable)
{
if (enable)
{
applyForce(_world->getGravity());
applyForce(_world->getGravity() * _mass);
}else
{
applyForce(-_world->getGravity());
applyForce(-_world->getGravity() * _mass);
}
}
}
@ -304,15 +350,14 @@ float PhysicsBody::getRotation() const
return -PhysicsHelper::cpfloat2float(cpBodyGetAngle(_info->body) / 3.14f * 180.0f);
}
void PhysicsBody::addShape(PhysicsShape* shape)
PhysicsShape* PhysicsBody::addShape(PhysicsShape* shape)
{
if (shape == nullptr) return;
if (shape == nullptr) return nullptr;
// add shape to body
if (std::find(_shapes.begin(), _shapes.end(), shape) == _shapes.end())
if (_shapes->getIndexOfObject(shape) == UINT_MAX)
{
shape->setBody(this);
_shapes.push_back(shape);
// calculate the area, mass, and desity
// area must update before mass, because the density changes depend on it.
@ -325,8 +370,15 @@ void PhysicsBody::addShape(PhysicsShape* shape)
_world->addShape(shape);
}
shape->retain();
_shapes->addObject(shape);
if (_group != CP_NO_GROUP && shape->getGroup() == CP_NO_GROUP)
{
shape->setGroup(_group);
}
}
return shape;
}
void PhysicsBody::applyForce(Point force)
@ -518,10 +570,11 @@ void PhysicsBody::setMoment(float moment)
}
}
PhysicsShape* PhysicsBody::getShapeByTag(int tag)
PhysicsShape* PhysicsBody::getShapeByTag(int tag) const
{
for (auto shape : _shapes)
for (auto child : *_shapes)
{
PhysicsShape* shape = dynamic_cast<PhysicsShape*>(child);
if (shape->getTag() == tag)
{
return shape;
@ -533,8 +586,9 @@ PhysicsShape* PhysicsBody::getShapeByTag(int tag)
void PhysicsBody::removeShapeByTag(int tag)
{
for (auto shape : _shapes)
for (auto child : *_shapes)
{
PhysicsShape* shape = dynamic_cast<PhysicsShape*>(child);
if (shape->getTag() == tag)
{
removeShape(shape);
@ -545,9 +599,7 @@ void PhysicsBody::removeShapeByTag(int tag)
void PhysicsBody::removeShape(PhysicsShape* shape)
{
auto it = std::find(_shapes.begin(), _shapes.end(), shape);
if (it != _shapes.end())
if (_shapes->getIndexOfObject(shape) == UINT_MAX)
{
// deduce the area, mass and moment
// area must update before mass, because the density changes depend on it.
@ -560,25 +612,39 @@ void PhysicsBody::removeShape(PhysicsShape* shape)
{
_world->removeShape(shape);
}
_shapes.erase(it);
shape->setBody(nullptr);
shape->release();
_shapes->removeObject(shape);
}
}
void PhysicsBody::removeAllShapes()
{
for (auto shape : _shapes)
for (auto child : *_shapes)
{
PhysicsShape* shape = dynamic_cast<PhysicsShape*>(child);
// deduce the area, mass and moment
// area must update before mass, because the density changes depend on it.
_area -= shape->getArea();
addMass(-shape->getMass());
addMoment(-shape->getMoment());
if (_world)
{
_world->removeShape(shape);
}
delete shape;
shape->setBody(nullptr);
}
_shapes.clear();
_shapes->removeAllObjects();
}
void PhysicsBody::removeFromWorld()
{
if (_world)
{
_world->removeBody(this);
}
}
void PhysicsBody::setEnable(bool enable)
@ -600,7 +666,7 @@ void PhysicsBody::setEnable(bool enable)
}
}
bool PhysicsBody::isResting()
bool PhysicsBody::isResting() const
{
return cpBodyIsSleeping(_info->body) == cpTrue;
}
@ -616,14 +682,53 @@ void PhysicsBody::update(float delta)
}
}
//Clonable* PhysicsBody::clone() const
//{
// PhysicsBody* body = new PhysicsBody();
//
// body->autorelease();
//
// return body;
//}
void PhysicsBody::setCategoryBitmask(int bitmask)
{
_categoryBitmask = bitmask;
for (auto shape : *_shapes)
{
((PhysicsShape*)shape)->setCategoryBitmask(bitmask);
}
}
void PhysicsBody::setContactTestBitmask(int bitmask)
{
_contactTestBitmask = bitmask;
for (auto shape : *_shapes)
{
((PhysicsShape*)shape)->setContactTestBitmask(bitmask);
}
}
void PhysicsBody::setCollisionBitmask(int bitmask)
{
_collisionBitmask = bitmask;
for (auto shape : *_shapes)
{
((PhysicsShape*)shape)->setCollisionBitmask(bitmask);
}
}
void PhysicsBody::setGroup(int group)
{
for (auto shape : *_shapes)
{
((PhysicsShape*)shape)->setGroup(group);
}
}
Point PhysicsBody::world2Local(const Point& point)
{
return PhysicsHelper::cpv2point(cpBodyWorld2Local(_info->body, PhysicsHelper::point2cpv(point)));
}
Point PhysicsBody::local2World(const Point& point)
{
return PhysicsHelper::cpv2point(cpBodyLocal2World(_info->body, PhysicsHelper::point2cpv(point)));
}
#elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)

View File

@ -30,6 +30,7 @@
#include "CCObject.h"
#include "CCGeometry.h"
#include "CCArray.h"
#include "CCPhysicsShape.h"
@ -43,7 +44,7 @@ class PhysicsJoint;
class PhysicsBodyInfo;
const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT(1.0f, 1.0f, 1.0f);
const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT(0.1f, 0.5f, 0.5f);
/**
* A body affect by physics.
@ -53,6 +54,8 @@ class PhysicsBody : public Object//, public Clonable
{
public:
static PhysicsBody* create();
static PhysicsBody* create(float mass);
static PhysicsBody* create(float mass, float moment);
/**
* @brief Create a body contains a circle shape.
*/
@ -84,7 +87,7 @@ public:
*/
static PhysicsBody* createEdgeChain(Point* points, int count, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT, float border = 1);
virtual void addShape(PhysicsShape* shape);
virtual PhysicsShape* addShape(PhysicsShape* shape);
/**
* @brief Applies a immediate force to body.
@ -119,12 +122,12 @@ public:
/*
* @brief get the body shapes.
*/
inline std::vector<PhysicsShape*>& getShapes() { return _shapes; }
inline Array* getShapes() const { return _shapes; }
/*
* @brief get the first body shapes.
*/
inline PhysicsShape* getShape() { return _shapes.size() >= 1 ? _shapes.front() : nullptr; }
PhysicsShape* getShapeByTag(int tag);
inline PhysicsShape* getShape() const { return _shapes->count() >= 1 ? dynamic_cast<PhysicsShape*>(_shapes->getObjectAtIndex(0)) : nullptr; }
PhysicsShape* getShapeByTag(int tag) const;
/*
* @brief remove a shape from body
*/
@ -135,6 +138,8 @@ public:
*/
void removeAllShapes();
void removeFromWorld();
/*
* @brief get the world body added to.
*/
@ -142,20 +147,23 @@ public:
/*
* @brief get all joints the body have
*/
inline const std::vector<PhysicsJoint*>* getJoints() const { return &_joints; }
inline const std::vector<PhysicsJoint*>& getJoints() const { return _joints; }
/*
* @brief get the sprite the body set to.
*/
inline Sprite* getOwner() const { return _owner; }
inline Node* getNode() const { return _node; }
inline void setCategoryBitmask(int bitmask) { _categoryBitmask = bitmask; }
void setCategoryBitmask(int bitmask);
void setContactTestBitmask(int bitmask);
void setCollisionBitmask(int bitmask);
inline int getCategoryBitmask() const { return _categoryBitmask; }
inline void setContactTestBitmask(int bitmask) { _contactTestBitmask = bitmask; }
inline int getContactTestBitmask() const { return _contactTestBitmask; }
inline void setCollisionBitmask(int bitmask) { _collisionBitmask = bitmask; }
inline int getCollisionBitmask() const { return _collisionBitmask; }
void setGroup(int group);
inline int getGroup() const { return _group; }
/*
* @brief get the body position.
*/
@ -169,7 +177,7 @@ public:
* @brief test the body is dynamic or not.
* a dynamic body will effect with gravity.
*/
inline bool isDynamic() { return _dynamic; }
inline bool isDynamic() const { return _dynamic; }
/*
* @brief set dynamic to body.
* a dynamic body will effect with gravity.
@ -184,7 +192,7 @@ public:
/*
* @brief get the body mass.
*/
inline float getMass() { return _mass; }
inline float getMass() const { return _mass; }
/*
* @brief add mass to body.
* if _mass(mass of the body) == PHYSICS_INFINITY, it remains.
@ -203,7 +211,7 @@ public:
/*
* @brief get the body moment of inertia.
*/
inline float getMoment(float moment) { return _moment; }
inline float getMoment(float moment) const { return _moment; }
/*
* @brief add moment of inertia to body.
* if _moment(moment of the body) == PHYSICS_INFINITY, it remains.
@ -220,27 +228,29 @@ public:
/*
* @brief get angular damping.
*/
inline float getLinearDamping() { return _linearDamping; }
inline float getLinearDamping() const { return _linearDamping; }
inline void setLinearDamping(float damping) { _linearDamping = damping; }
inline float getAngularDamping() { return _angularDamping; }
inline float getAngularDamping() const { return _angularDamping; }
inline void setAngularDamping(float damping) { _angularDamping = damping; }
//virtual Clonable* clone() const override;
bool isResting();
inline bool isEnable() { return _enable; }
bool isResting() const;
inline bool isEnable() const { return _enable; }
void setEnable(bool enable);
inline bool isRotationEnable() { return _rotationEnable; }
inline bool isRotationEnable() const { return _rotationEnable; }
void setRotationEnable(bool enable);
inline bool isGravityEnable() { return _gravityEnable; }
inline bool isGravityEnable() const { return _gravityEnable; }
void setGravityEnable(bool enable);
inline int getTag() { return _tag; }
inline int getTag() const { return _tag; }
inline void setTag(int tag) { _tag = tag; }
Point world2Local(const Point& point);
Point local2World(const Point& point);
protected:
@ -256,9 +266,9 @@ protected:
virtual ~PhysicsBody();
protected:
Sprite* _owner;
Node* _node;
std::vector<PhysicsJoint*> _joints;
std::vector<PhysicsShape*> _shapes;
Array* _shapes;
PhysicsWorld* _world;
PhysicsBodyInfo* _info;
bool _dynamic;
@ -275,9 +285,10 @@ protected:
float _angularDamping;
int _tag;
int _categoryBitmask;
int _collisionBitmask;
int _contactTestBitmask;
int _categoryBitmask;
int _collisionBitmask;
int _contactTestBitmask;
int _group;
friend class PhysicsWorld;
friend class PhysicsShape;

View File

@ -30,16 +30,32 @@
#include "Box2D.h"
#endif
#include "chipmunk/CCPhysicsContactInfo.h"
#include "box2d/CCPhysicsContactInfo.h"
#include "CCPhysicsBody.h"
#include "chipmunk/CCPhysicsContactInfo_chipmunk.h"
#include "box2d/CCPhysicsContactInfo_box2d.h"
#include "chipmunk/CCPhysicsHelper_chipmunk.h"
#include "box2d/CCPhysicsHelper_box2d.h"
#include "CCEventCustom.h"
NS_CC_BEGIN
const char* PHYSICSCONTACT_EVENT_NAME = "PhysicsContactEvent";
PhysicsContact::PhysicsContact()
: _shapeA(nullptr)
: Event(Event::Type::CUSTOM)
, _world(nullptr)
, _shapeA(nullptr)
, _shapeB(nullptr)
, _eventCode(EventCode::NONE)
, _info(nullptr)
, _notify(true)
, _begin(false)
, _data(nullptr)
, _contactInfo(nullptr)
, _contactData(nullptr)
, _result(true)
{
}
@ -47,6 +63,7 @@ PhysicsContact::PhysicsContact()
PhysicsContact::~PhysicsContact()
{
CC_SAFE_DELETE(_info);
CC_SAFE_DELETE(_contactData);
}
PhysicsContact* PhysicsContact::create(PhysicsShape* a, PhysicsShape* b)
@ -78,37 +95,69 @@ bool PhysicsContact::init(PhysicsShape* a, PhysicsShape* b)
return false;
}
// PhysicsContactPreSolve implementation
PhysicsContactPreSolve::PhysicsContactPreSolve()
void PhysicsContact::generateContactData()
{
if (_contactInfo == nullptr)
{
return;
}
cpArbiter* arb = static_cast<cpArbiter*>(_contactInfo);
_contactData = new PhysicsContactData();
_contactData->count = cpArbiterGetCount(arb);
for (int i=0; i<_contactData->count; ++i)
{
_contactData->points[i] = PhysicsHelper::cpv2point(cpArbiterGetPoint(arb, i));
}
_contactData->normal = _contactData->count > 0 ? PhysicsHelper::cpv2point(cpArbiterGetNormal(arb, 0)) : Point::ZERO;
}
// PhysicsContactPreSolve implementation
PhysicsContactPreSolve::PhysicsContactPreSolve(PhysicsContactData* data, void* contactInfo)
: _preContactData(data)
, _contactInfo(contactInfo)
{
}
float PhysicsContactPreSolve::getElasticity() const
{
return static_cast<cpArbiter*>(_contactInfo)->e;
}
float PhysicsContactPreSolve::getFriciton() const
{
return static_cast<cpArbiter*>(_contactInfo)->u;
}
Point PhysicsContactPreSolve::getSurfaceVelocity() const
{
return PhysicsHelper::cpv2point(static_cast<cpArbiter*>(_contactInfo)->surface_vr);
}
void PhysicsContactPreSolve::setElasticity(float elasticity)
{
static_cast<cpArbiter*>(_contactInfo)->e = elasticity;
}
void PhysicsContactPreSolve::setFriction(float friction)
{
static_cast<cpArbiter*>(_contactInfo)->u = friction;
}
void PhysicsContactPreSolve::setSurfaceVelocity(Point surfaceVelocity)
{
static_cast<cpArbiter*>(_contactInfo)->surface_vr = PhysicsHelper::point2cpv(surfaceVelocity);
}
PhysicsContactPreSolve::~PhysicsContactPreSolve()
{
CC_SAFE_DELETE(_preContactData);
}
PhysicsContactPreSolve* PhysicsContactPreSolve::create()
{
PhysicsContactPreSolve * solve = new PhysicsContactPreSolve();
if(solve && solve->init())
{
return solve;
}
CC_SAFE_DELETE(solve);
return nullptr;
}
bool PhysicsContactPreSolve::init()
{
return true;
}
// PhysicsContactPostSolve implementation
PhysicsContactPostSolve::PhysicsContactPostSolve()
PhysicsContactPostSolve::PhysicsContactPostSolve(void* contactInfo)
: _contactInfo(contactInfo)
{
}
@ -118,36 +167,331 @@ PhysicsContactPostSolve::~PhysicsContactPostSolve()
}
PhysicsContactPostSolve* PhysicsContactPostSolve::create()
float PhysicsContactPostSolve::getElasticity() const
{
PhysicsContactPostSolve * solve = new PhysicsContactPostSolve();
if(solve && solve->init())
{
return solve;
}
CC_SAFE_DELETE(solve);
return nullptr;
return static_cast<cpArbiter*>(_contactInfo)->e;
}
bool PhysicsContactPostSolve::init()
float PhysicsContactPostSolve::getFriciton() const
{
return true;
return static_cast<cpArbiter*>(_contactInfo)->u;
}
PhysicsContactListener::PhysicsContactListener()
Point PhysicsContactPostSolve::getSurfaceVelocity() const
{
return PhysicsHelper::cpv2point(static_cast<cpArbiter*>(_contactInfo)->surface_vr);
}
EventListenerPhysicsContact::EventListenerPhysicsContact()
: onContactBegin(nullptr)
, onContactPreSolve(nullptr)
, onContactPostSolve(nullptr)
, onContactEnd(nullptr)
, onContactSeperate(nullptr)
{
}
bool EventListenerPhysicsContact::init()
{
auto func = [this](EventCustom* event) -> void
{
return onEvent(event);
};
return EventListenerCustom::init(std::hash<std::string>()(PHYSICSCONTACT_EVENT_NAME), func);
}
void EventListenerPhysicsContact::onEvent(EventCustom* event)
{
PhysicsContact& contact = *(PhysicsContact*)(event->getUserData());
switch (contact.getEventCode())
{
case PhysicsContact::EventCode::BEGIN:
{
bool ret = true;
if (onContactBegin != nullptr
&& contact.getNotify()
&& test(contact.getShapeA(), contact.getShapeB()))
{
contact._begin = true;
contact.generateContactData();
// the mask has high priority than _listener->onContactBegin.
// so if the mask test is false, the two bodies won't have collision.
if (ret)
{
ret = onContactBegin(event, contact);
}else
{
onContactBegin(event, contact);
}
}
contact.setResult(ret);
break;
}
case PhysicsContact::EventCode::PRESOLVE:
{
bool ret = true;
if (onContactPreSolve != nullptr
&& test(contact.getShapeA(), contact.getShapeB()))
{
PhysicsContactPreSolve solve(contact._begin ? nullptr : contact._contactData, contact._contactInfo);
contact._begin = false;
contact.generateContactData();
ret = onContactPreSolve(event, contact, solve);
}
contact.setResult(ret);
break;
}
case PhysicsContact::EventCode::POSTSOLVE:
{
if (onContactPreSolve != nullptr
&& test(contact.getShapeA(), contact.getShapeB()))
{
PhysicsContactPostSolve solve(contact._contactInfo);
onContactPostSolve(event, contact, solve);
}
break;
}
case PhysicsContact::EventCode::SEPERATE:
{
if (onContactSeperate != nullptr
&& test(contact.getShapeA(), contact.getShapeB()))
{
onContactSeperate(event, contact);
}
break;
}
default:
break;
}
}
EventListenerPhysicsContact::~EventListenerPhysicsContact()
{
}
PhysicsContactListener::~PhysicsContactListener()
EventListenerPhysicsContact* EventListenerPhysicsContact::create()
{
EventListenerPhysicsContact* obj = new EventListenerPhysicsContact();
if (obj != nullptr && obj->init())
{
obj->autorelease();
return obj;
}
CC_SAFE_DELETE(obj);
return nullptr;
}
bool EventListenerPhysicsContact::test(PhysicsShape* shapeA, PhysicsShape* shapeB)
{
CC_UNUSED_PARAM(shapeA);
CC_UNUSED_PARAM(shapeB);
return true;
}
bool EventListenerPhysicsContact::checkAvailable()
{
if (onContactBegin == nullptr && onContactPreSolve == nullptr
&& onContactPostSolve == nullptr && onContactSeperate == nullptr)
{
CCASSERT(false, "Invalid PhysicsContactListener.");
return false;
}
return true;
}
EventListenerPhysicsContact* EventListenerPhysicsContact::clone()
{
EventListenerPhysicsContact* obj = EventListenerPhysicsContact::create();
if (obj != nullptr)
{
obj->onContactBegin = onContactBegin;
obj->onContactPreSolve = onContactPreSolve;
obj->onContactPostSolve = onContactPostSolve;
obj->onContactSeperate = onContactSeperate;
return obj;
}
CC_SAFE_DELETE(obj);
return nullptr;
}
EventListenerPhysicsContactWithBodies* EventListenerPhysicsContactWithBodies::create(PhysicsBody* bodyA, PhysicsBody* bodyB)
{
EventListenerPhysicsContactWithBodies* obj = new EventListenerPhysicsContactWithBodies();
if (obj != nullptr && obj->init())
{
obj->_a = bodyA;
obj->_b = bodyB;
obj->autorelease();
return obj;
}
CC_SAFE_DELETE(obj);
return nullptr;
}
EventListenerPhysicsContactWithBodies::EventListenerPhysicsContactWithBodies()
: _a(nullptr)
, _b(nullptr)
{
}
EventListenerPhysicsContactWithBodies::~EventListenerPhysicsContactWithBodies()
{
}
bool EventListenerPhysicsContactWithBodies::test(PhysicsShape* shapeA, PhysicsShape* shapeB)
{
if ((shapeA->getBody() == _a && shapeB->getBody() == _b)
|| (shapeA->getBody() == _b && shapeB->getBody() == _a))
{
return true;
}
return false;
}
EventListenerPhysicsContactWithBodies* EventListenerPhysicsContactWithBodies::clone()
{
EventListenerPhysicsContactWithBodies* obj = EventListenerPhysicsContactWithBodies::create(_a, _b);
if (obj != nullptr)
{
obj->onContactBegin = onContactBegin;
obj->onContactPreSolve = onContactPreSolve;
obj->onContactPostSolve = onContactPostSolve;
obj->onContactSeperate = onContactSeperate;
return obj;
}
CC_SAFE_DELETE(obj);
return nullptr;
}
EventListenerPhysicsContactWithShapes::EventListenerPhysicsContactWithShapes()
: _a(nullptr)
, _b(nullptr)
{
}
EventListenerPhysicsContactWithShapes::~EventListenerPhysicsContactWithShapes()
{
}
EventListenerPhysicsContactWithShapes* EventListenerPhysicsContactWithShapes::create(PhysicsShape* shapeA, PhysicsShape* shapeB)
{
EventListenerPhysicsContactWithShapes* obj = new EventListenerPhysicsContactWithShapes();
if (obj != nullptr && obj->init())
{
obj->_a = shapeA;
obj->_b = shapeB;
obj->autorelease();
return obj;
}
CC_SAFE_DELETE(obj);
return nullptr;
}
bool EventListenerPhysicsContactWithShapes::test(PhysicsShape* shapeA, PhysicsShape* shapeB)
{
if ((shapeA == _a && shapeB == _b)
|| (shapeA == _b && shapeB == _a))
{
return true;
}
return false;
}
EventListenerPhysicsContactWithShapes* EventListenerPhysicsContactWithShapes::clone()
{
EventListenerPhysicsContactWithShapes* obj = EventListenerPhysicsContactWithShapes::create(_a, _b);
if (obj != nullptr)
{
obj->onContactBegin = onContactBegin;
obj->onContactPreSolve = onContactPreSolve;
obj->onContactPostSolve = onContactPostSolve;
obj->onContactSeperate = onContactSeperate;
return obj;
}
CC_SAFE_DELETE(obj);
return nullptr;
}
EventListenerPhysicsContactWithGroup::EventListenerPhysicsContactWithGroup()
: _group(CP_NO_GROUP)
{
}
EventListenerPhysicsContactWithGroup::~EventListenerPhysicsContactWithGroup()
{
}
EventListenerPhysicsContactWithGroup* EventListenerPhysicsContactWithGroup::create(int group)
{
EventListenerPhysicsContactWithGroup* obj = new EventListenerPhysicsContactWithGroup();
if (obj != nullptr && obj->init())
{
obj->_group = group;
obj->autorelease();
return obj;
}
CC_SAFE_DELETE(obj);
return nullptr;
}
bool EventListenerPhysicsContactWithGroup::test(PhysicsShape* shapeA, PhysicsShape* shapeB)
{
if (shapeA->getGroup() == _group || shapeB->getGroup() == _group)
{
return true;
}
return false;
}
EventListenerPhysicsContactWithGroup* EventListenerPhysicsContactWithGroup::clone()
{
EventListenerPhysicsContactWithGroup* obj = EventListenerPhysicsContactWithGroup::create(_group);
if (obj != nullptr)
{
obj->onContactBegin = onContactBegin;
obj->onContactPreSolve = onContactPreSolve;
obj->onContactPostSolve = onContactPostSolve;
obj->onContactSeperate = onContactSeperate;
return obj;
}
CC_SAFE_DELETE(obj);
return nullptr;
}
NS_CC_END
#endif // CC_USE_PHYSICS

View File

@ -30,20 +30,45 @@
#include "CCObject.h"
#include "CCGeometry.h"
#include "CCEventListenerCustom.h"
#include "CCEvent.h"
NS_CC_BEGIN
class PhysicsShape;
class PhysicsBody;
class PhysicsWorld;
class PhysicsContactInfo;
typedef struct PhysicsContactData
{
Point points[PHYSICS_CONTACT_POINT_MAX];
int count;
Point normal;
PhysicsContactData()
: count(0)
{}
}PhysicsContactData;
/**
* @brief Contact infomation. it will created automatically when two shape contact with each other. and it will destoried automatically when two shape separated.
*/
class PhysicsContact
class PhysicsContact : Event
{
public:
enum class EventCode
{
NONE,
BEGIN,
PRESOLVE,
POSTSOLVE,
SEPERATE
};
/*
* @brief get contact shape A.
*/
@ -52,35 +77,53 @@ public:
* @brief get contact shape B.
*/
inline PhysicsShape* getShapeB() const { return _shapeB; }
inline const PhysicsContactData* getContactData() const { return _contactData; }
/*
* @brief get data.
*/
inline void* getData() { return _data; }
inline void* getData() const { return _data; }
/*
* @brief set data to contact. you must manage the memory yourself, Generally you can set data at contact begin, and distory it at contact end.
*/
inline void setData(void* data) { _data = data; }
EventCode getEventCode() const { return _eventCode; };
private:
static PhysicsContact* create(PhysicsShape* a, PhysicsShape* b);
bool init(PhysicsShape* a, PhysicsShape* b);
inline bool getNotify() { return _notify; }
void setEventCode(EventCode eventCode) { _eventCode = eventCode; };
inline bool getNotify() const { return _notify; }
inline void setNotify(bool notify) { _notify = notify; }
inline PhysicsWorld* getWorld() const { return _world; }
inline void setWorld(PhysicsWorld* world) { _world = world; }
inline void setResult(bool result) { _result = result; }
inline bool resetResult() { bool ret = _result; _result = true; return ret; }
void generateContactData();
private:
PhysicsContact();
~PhysicsContact();
private:
PhysicsWorld* _world;
PhysicsShape* _shapeA;
PhysicsShape* _shapeB;
EventCode _eventCode;
PhysicsContactInfo* _info;
void* _data;
bool _notify;
bool _begin;
bool _result;
friend class PhysicsWorld;
void* _data;
void* _contactInfo;
PhysicsContactData* _contactData;
friend class EventListenerPhysicsContact;
friend class PhysicsWorldCallback;
friend class PhysicsWorld;
};
/*
@ -88,14 +131,27 @@ private:
*/
class PhysicsContactPreSolve
{
public:
// getter/setter
float getElasticity() const;
float getFriciton() const;
Point getSurfaceVelocity() const;
void setElasticity(float elasticity);
void setFriction(float friction);
void setSurfaceVelocity(Point surfaceVelocity);
private:
PhysicsContactPreSolve();
PhysicsContactPreSolve(PhysicsContactData* data, void* contactInfo);
~PhysicsContactPreSolve();
static PhysicsContactPreSolve* create();
bool init();
private:
float _elasticity;
float _friction;
Point _surfaceVelocity;
PhysicsContactData* _preContactData;
void* _contactInfo;
friend class PhysicsWorldCallback;
friend class EventListenerPhysicsContact;
};
/*
@ -103,43 +159,110 @@ private:
*/
class PhysicsContactPostSolve
{
public:
// getter
float getElasticity() const;
float getFriciton() const;
Point getSurfaceVelocity() const;
private:
PhysicsContactPostSolve();
PhysicsContactPostSolve(void* contactInfo);
~PhysicsContactPostSolve();
static PhysicsContactPostSolve* create();
bool init();
private:
void* _contactInfo;
friend class PhysicsWorldCallback;
friend class EventListenerPhysicsContact;
};
/*
* @brief contact listener.
*/
class PhysicsContactListener
class EventListenerPhysicsContact : public EventListenerCustom
{
public:
PhysicsContactListener();
virtual ~PhysicsContactListener();
static EventListenerPhysicsContact* create();
virtual bool test(PhysicsShape* shapeA, PhysicsShape* shapeB);
virtual bool checkAvailable() override;
virtual EventListenerPhysicsContact* clone() override;
public:
/*
* @brief it will called at two shapes start to contact, and only call it once.
*/
std::function<bool(PhysicsWorld& world, const PhysicsContact& contact)> onContactBegin;
std::function<bool(EventCustom* event, const PhysicsContact& contact)> onContactBegin;
/*
* @brief Two shapes are touching during this step. Return false from the callback to make world ignore the collision this step or true to process it normally. Additionally, you may override collision values, elasticity, or surface velocity values.
*/
std::function<bool(PhysicsWorld& world, const PhysicsContact& contact, const PhysicsContactPreSolve& solve)> onContactPreSolve;
std::function<bool(EventCustom* event, const PhysicsContact& contact, const PhysicsContactPreSolve& solve)> onContactPreSolve;
/*
* @brief Two shapes are touching and their collision response has been processed. You can retrieve the collision impulse or kinetic energy at this time if you want to use it to calculate sound volumes or damage amounts. See cpArbiter for more info
*/
std::function<void(PhysicsWorld& world, const PhysicsContact& contact, const PhysicsContactPostSolve& solve)> onContactPostSolve;
std::function<void(EventCustom* event, const PhysicsContact& contact, const PhysicsContactPostSolve& solve)> onContactPostSolve;
/*
* @brief it will called at two shapes separated, and only call it once.
* onContactBegin and onContactEnd will called in pairs.
* onContactBegin and onContactSeperate will called in pairs.
*/
std::function<void(PhysicsWorld& world, const PhysicsContact& contact)> onContactEnd;
std::function<void(EventCustom* event, const PhysicsContact& contact)> onContactSeperate;
protected:
bool init();
void onEvent(EventCustom* event);
protected:
EventListenerPhysicsContact();
virtual ~EventListenerPhysicsContact();
};
class EventListenerPhysicsContactWithBodies : public EventListenerPhysicsContact
{
public:
static EventListenerPhysicsContactWithBodies* create(PhysicsBody* bodyA, PhysicsBody* bodyB);
virtual bool test(PhysicsShape* shapeA, PhysicsShape* shapeB) override;
virtual EventListenerPhysicsContactWithBodies* clone() override;
protected:
PhysicsBody* _a;
PhysicsBody* _b;
protected:
EventListenerPhysicsContactWithBodies();
virtual ~EventListenerPhysicsContactWithBodies();
};
class EventListenerPhysicsContactWithShapes : public EventListenerPhysicsContact
{
public:
static EventListenerPhysicsContactWithShapes* create(PhysicsShape* shapeA, PhysicsShape* shapeB);
virtual bool test(PhysicsShape* shapeA, PhysicsShape* shapeB) override;
virtual EventListenerPhysicsContactWithShapes* clone() override;
protected:
PhysicsShape* _a;
PhysicsShape* _b;
protected:
EventListenerPhysicsContactWithShapes();
virtual ~EventListenerPhysicsContactWithShapes();
};
class EventListenerPhysicsContactWithGroup : public EventListenerPhysicsContact
{
public:
static EventListenerPhysicsContactWithGroup* create(int group);
virtual bool test(PhysicsShape* shapeA, PhysicsShape* shapeB) override;
virtual EventListenerPhysicsContactWithGroup* clone() override;
protected:
int _group;
protected:
EventListenerPhysicsContactWithGroup();
virtual ~EventListenerPhysicsContactWithGroup();
};
NS_CC_END

View File

@ -33,14 +33,15 @@
#include "CCPhysicsBody.h"
#include "chipmunk/CCPhysicsJointInfo.h"
#include "box2d/CCPhysicsJointInfo.h"
#include "chipmunk/CCPhysicsBodyInfo.h"
#include "box2d/CCPhysicsBodyInfo.h"
#include "chipmunk/CCPhysicsShapeInfo.h"
#include "box2d/CCPhysicsShapeInfo.h"
#include "chipmunk/CCPhysicsHelper.h"
#include "box2d/CCPhysicsHelper.h"
#include "chipmunk/CCPhysicsJointInfo_chipmunk.h"
#include "box2d/CCPhysicsJointInfo_box2d.h"
#include "chipmunk/CCPhysicsBodyInfo_chipmunk.h"
#include "box2d/CCPhysicsBodyInfo_box2d.h"
#include "chipmunk/CCPhysicsShapeInfo_chipmunk.h"
#include "box2d/CCPhysicsShapeInfo_box2d.h"
#include "chipmunk/CCPhysicsHelper_chipmunk.h"
#include "box2d/CCPhysicsHelper_box2d.h"
#include "CCNode.h"
NS_CC_BEGIN
@ -61,9 +62,6 @@ PhysicsJoint::~PhysicsJoint()
setCollisionEnable(true);
CC_SAFE_DELETE(_info);
CC_SAFE_RELEASE(_bodyA);
CC_SAFE_RELEASE(_bodyB);
}
bool PhysicsJoint::init(cocos2d::PhysicsBody *a, cocos2d::PhysicsBody *b)
@ -75,14 +73,12 @@ bool PhysicsJoint::init(cocos2d::PhysicsBody *a, cocos2d::PhysicsBody *b)
if (a != nullptr)
{
_bodyA = a;
_bodyA->retain();
_bodyA->_joints.push_back(this);
}
if (b != nullptr)
{
_bodyB = b;
_bodyB->retain();
_bodyB->_joints.push_back(this);
}
@ -148,23 +144,33 @@ PhysicsJointLimit::~PhysicsJointLimit()
}
PhysicsJointDistance::PhysicsJointDistance()
{
}
PhysicsJointDistance::~PhysicsJointDistance()
{
}
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
PhysicsBodyInfo* PhysicsJoint::bodyInfo(PhysicsBody* body) const
PhysicsBodyInfo* PhysicsJoint::getBodyInfo(PhysicsBody* body) const
{
return body->_info;
}
Node* PhysicsJoint::getBodyNode(PhysicsBody* body) const
{
return body->_node;
}
void PhysicsJoint::setCollisionEnable(bool enable)
{
if (_collisionEnable != enable)
{
_collisionEnable = enable;
for (auto shape : _bodyB->_shapes)
{
shape->_info->setGroup(enable ? _bodyB->_info->group : _bodyA->_info->group);
}
}
}
@ -174,7 +180,6 @@ PhysicsJointFixed* PhysicsJointFixed::create(PhysicsBody* a, PhysicsBody* b, con
if (joint && joint->init(a, b, anchr))
{
joint->autorelease();
return joint;
}
@ -188,15 +193,18 @@ bool PhysicsJointFixed::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr)
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
getBodyNode(a)->setPosition(anchr);
getBodyNode(b)->setPosition(anchr);
// add a pivot joint to fixed two body together
cpConstraint* joint = cpPivotJointNew(bodyInfo(a)->body, bodyInfo(b)->body,
cpConstraint* joint = cpPivotJointNew(getBodyInfo(a)->body, getBodyInfo(b)->body,
PhysicsHelper::point2cpv(anchr));
CC_BREAK_IF(joint);
CC_BREAK_IF(joint == nullptr);
_info->add(joint);
// add a gear joint to make two body have the same rotation.
joint = cpGearJointNew(bodyInfo(a)->body, bodyInfo(b)->body, 0, 1);
CC_BREAK_IF(joint);
joint = cpGearJointNew(getBodyInfo(a)->body, getBodyInfo(b)->body, 0, 1);
CC_BREAK_IF(joint == nullptr);
_info->add(joint);
setCollisionEnable(false);
@ -213,7 +221,6 @@ PhysicsJointPin* PhysicsJointPin::create(PhysicsBody* a, PhysicsBody* b, const P
if (joint && joint->init(a, b, anchr))
{
joint->autorelease();
return joint;
}
@ -226,22 +233,29 @@ bool PhysicsJointPin::init(PhysicsBody *a, PhysicsBody *b, const Point& anchr)
do
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
cpConstraint* joint = cpPivotJointNew(bodyInfo(a)->body, bodyInfo(b)->body,
cpConstraint* joint = cpPivotJointNew(getBodyInfo(a)->body, getBodyInfo(b)->body,
PhysicsHelper::point2cpv(anchr));
CC_BREAK_IF(joint);
CC_BREAK_IF(joint == nullptr);
_info->add(joint);
setCollisionEnable(false);
return true;
} while (false);
return false;
}
void PhysicsJointPin::setMaxForce(float force)
{
_info->joints.front()->maxForce = PhysicsHelper::float2cpfloat(force);
}
float PhysicsJointPin::getMaxForce() const
{
return PhysicsHelper::cpfloat2float(_info->joints.front()->maxForce);
}
PhysicsJointSliding* PhysicsJointSliding::create(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr)
{
PhysicsJointSliding* joint = new PhysicsJointSliding();
@ -261,12 +275,12 @@ bool PhysicsJointSliding::init(PhysicsBody* a, PhysicsBody* b, const Point& groo
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
cpConstraint* joint = cpGrooveJointNew(bodyInfo(a)->body, bodyInfo(b)->body,
cpConstraint* joint = cpGrooveJointNew(getBodyInfo(a)->body, getBodyInfo(b)->body,
PhysicsHelper::point2cpv(grooveA),
PhysicsHelper::point2cpv(grooveB),
PhysicsHelper::point2cpv(anchr));
CC_BREAK_IF(joint);
CC_BREAK_IF(joint == nullptr);
_info->add(joint);
@ -296,13 +310,13 @@ bool PhysicsJointLimit::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
cpConstraint* joint = cpSlideJointNew(bodyInfo(a)->body, bodyInfo(b)->body,
cpConstraint* joint = cpSlideJointNew(getBodyInfo(a)->body, getBodyInfo(b)->body,
PhysicsHelper::point2cpv(anchr1),
PhysicsHelper::point2cpv(anchr2),
0,
PhysicsHelper::float2cpfloat(anchr1.getDistance(anchr2)));
CC_BREAK_IF(joint);
CC_BREAK_IF(joint == nullptr);
_info->add(joint);
@ -312,7 +326,7 @@ bool PhysicsJointLimit::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1
return false;
}
float PhysicsJointLimit::getMin()
float PhysicsJointLimit::getMin() const
{
return PhysicsHelper::cpfloat2float(cpSlideJointGetMin(_info->joints.front()));
}
@ -322,7 +336,7 @@ void PhysicsJointLimit::setMin(float min)
cpSlideJointSetMin(_info->joints.front(), PhysicsHelper::float2cpfloat(min));
}
float PhysicsJointLimit::getMax()
float PhysicsJointLimit::getMax() const
{
return PhysicsHelper::cpfloat2float(cpSlideJointGetMax(_info->joints.front()));
}
@ -332,6 +346,39 @@ void PhysicsJointLimit::setMax(float max)
cpSlideJointSetMax(_info->joints.front(), PhysicsHelper::float2cpfloat(max));
}
PhysicsJointDistance* PhysicsJointDistance::create(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2)
{
PhysicsJointDistance* joint = new PhysicsJointDistance();
if (joint && joint->init(a, b, anchr1, anchr2))
{
return joint;
}
CC_SAFE_DELETE(joint);
return nullptr;
}
bool PhysicsJointDistance::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2)
{
do
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
cpConstraint* joint = cpPinJointNew(getBodyInfo(a)->body,
getBodyInfo(b)->body,
PhysicsHelper::point2cpv(anchr1), PhysicsHelper::point2cpv(anchr2));
CC_BREAK_IF(joint == nullptr);
_info->add(joint);
return true;
} while (false);
return false;
}
#elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
#endif

View File

@ -40,20 +40,20 @@ class PhysicsBodyInfo;
/*
* @brief An PhysicsJoint object connects two physics bodies together.
*/
class PhysicsJoint : public Object
class PhysicsJoint
{
protected:
PhysicsJoint();
virtual ~PhysicsJoint() = 0;
public:
PhysicsBody* getBodyA() { return _bodyA; }
PhysicsBody* getBodyB() { return _bodyB; }
inline int getTag() { return _tag; }
PhysicsBody* getBodyA() const { return _bodyA; }
PhysicsBody* getBodyB() const { return _bodyB; }
inline int getTag() const { return _tag; }
inline void setTag(int tag) { _tag = tag; }
inline bool isEnable() { return _enable; }
inline bool isEnable() const { return _enable; }
void setEnable(bool enable);
inline bool isCollisionEnable() { return _collisionEnable; }
inline bool isCollisionEnable() const { return _collisionEnable; }
void setCollisionEnable(bool enable);
protected:
@ -62,7 +62,8 @@ protected:
/**
* PhysicsShape is PhysicsBody's friend class, but all the subclasses isn't. so this method is use for subclasses to catch the bodyInfo from PhysicsBody.
*/
PhysicsBodyInfo* bodyInfo(PhysicsBody* body) const;
PhysicsBodyInfo* getBodyInfo(PhysicsBody* body) const;
Node* getBodyNode(PhysicsBody* body) const;
protected:
PhysicsBody* _bodyA;
@ -82,7 +83,7 @@ protected:
class PhysicsJointFixed : public PhysicsJoint
{
public:
PhysicsJointFixed* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr);
static PhysicsJointFixed* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr);
@ -98,7 +99,7 @@ protected:
class PhysicsJointSliding : public PhysicsJoint
{
public:
PhysicsJointSliding* create(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr);
static PhysicsJointSliding* create(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr);
@ -132,9 +133,9 @@ class PhysicsJointLimit : public PhysicsJoint
public:
PhysicsJointLimit* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2);
float getMin();
float getMin() const;
void setMin(float min);
float getMax();
float getMax() const;
void setMax(float max);
protected:
@ -153,6 +154,9 @@ class PhysicsJointPin : public PhysicsJoint
public:
static PhysicsJointPin* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr);
void setMaxForce(float force);
float getMaxForce() const;
protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr);
@ -161,6 +165,20 @@ protected:
virtual ~PhysicsJointPin();
};
class PhysicsJointDistance : public PhysicsJoint
{
public:
static PhysicsJointDistance* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2);
protected:
PhysicsJointDistance();
virtual ~PhysicsJointDistance();
};
NS_CC_END
#endif // __CCPHYSICS_JOINT_H__

View File

@ -46,6 +46,11 @@
namespace cocos2d
{
extern const float PHYSICS_INFINITY;
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
static const int PHYSICS_CONTACT_POINT_MAX = 4;
#else
#endif
}
#endif // __CCPHYSICS_SETTING_H__

View File

@ -34,11 +34,11 @@
#include "CCPhysicsBody.h"
#include "CCPhysicsWorld.h"
#include "chipmunk/CCPhysicsBodyInfo.h"
#include "box2d/CCPhysicsBodyInfo.h"
#include "chipmunk/CCPhysicsShapeInfo.h"
#include "box2d/CCPhysicsShapeInfo.h"
#include "chipmunk/CCPhysicsHelper.h"
#include "chipmunk/CCPhysicsBodyInfo_chipmunk.h"
#include "box2d/CCPhysicsBodyInfo_box2d.h"
#include "chipmunk/CCPhysicsShapeInfo_chipmunk.h"
#include "box2d/CCPhysicsShapeInfo_box2d.h"
#include "chipmunk/CCPhysicsHelper_chipmunk.h"
NS_CC_BEGIN
@ -50,6 +50,10 @@ PhysicsShape::PhysicsShape()
, _mass(0)
, _moment(0)
, _tag(0)
, _categoryBitmask(UINT_MAX)
, _collisionBitmask(UINT_MAX)
, _contactTestBitmask(0)
, _group(0)
{
}
@ -272,12 +276,12 @@ void PhysicsShape::setBody(PhysicsBody *body)
if (body == nullptr)
{
_info->setBody(nullptr);
_info->setGroup(CP_NO_GROUP);
//_info->setGroup(CP_NO_GROUP);
_body = nullptr;
}else
{
_info->setBody(body->_info->body);
_info->setGroup(body->_info->group);
//_info->setGroup(body->_info->group);
_body = body;
}
}
@ -349,7 +353,7 @@ float PhysicsShapeCircle::calculateDefaultMoment()
cpCircleShapeGetOffset(shape)));
}
float PhysicsShapeCircle::getRadius()
float PhysicsShapeCircle::getRadius() const
{
return PhysicsHelper::cpfloat2float(cpCircleShapeGetRadius(_info->shapes.front()));
}
@ -401,12 +405,12 @@ bool PhysicsShapeEdgeSegment::init(Point a, Point b, PhysicsMaterial material/*
return false;
}
Point PhysicsShapeEdgeSegment::getPointA()
Point PhysicsShapeEdgeSegment::getPointA() const
{
return PhysicsHelper::cpv2point(((cpSegmentShape*)(_info->shapes.front()))->ta);
}
Point PhysicsShapeEdgeSegment::getPointB()
Point PhysicsShapeEdgeSegment::getPointB() const
{
return PhysicsHelper::cpv2point(((cpSegmentShape*)(_info->shapes.front()))->tb);
}
@ -499,7 +503,7 @@ float PhysicsShapeBox::calculateDefaultMoment()
: PhysicsHelper::cpfloat2float(cpMomentForPoly(_mass, ((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts, cpvzero));
}
Point* PhysicsShapeBox::getPoints(Point* points)
Point* PhysicsShapeBox::getPoints(Point* points) const
{
cpShape* shape = _info->shapes.front();
return PhysicsHelper::cpvs2points(((cpPolyShape*)shape)->verts, points, ((cpPolyShape*)shape)->numVerts);
@ -507,7 +511,7 @@ Point* PhysicsShapeBox::getPoints(Point* points)
return points;
}
Size PhysicsShapeBox::getSize()
Size PhysicsShapeBox::getSize() const
{
cpShape* shape = _info->shapes.front();
return PhysicsHelper::cpv2size(cpv(cpvdist(cpPolyShapeGetVert(shape, 0), cpPolyShapeGetVert(shape, 1)),
@ -590,13 +594,13 @@ float PhysicsShapePolygon::calculateDefaultMoment()
: PhysicsHelper::cpfloat2float(cpMomentForPoly(_mass, ((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts, cpvzero));
}
Point* PhysicsShapePolygon::getPoints(Point* points)
Point* PhysicsShapePolygon::getPoints(Point* points) const
{
cpShape* shape = _info->shapes.front();
return PhysicsHelper::cpvs2points(((cpPolyShape*)shape)->verts, points, ((cpPolyShape*)shape)->numVerts);
}
int PhysicsShapePolygon::getPointsCount()
int PhysicsShapePolygon::getPointsCount() const
{
return ((cpPolyShape*)_info->shapes.front())->numVerts;
}
@ -711,7 +715,7 @@ Point PhysicsShapeEdgePolygon::getCenter()
return _center;
}
int PhysicsShapeEdgePolygon::getPointsCount()
int PhysicsShapeEdgePolygon::getPointsCount() const
{
return _info->shapes.size() + 1;
}
@ -772,11 +776,22 @@ Point PhysicsShapeEdgeChain::getCenter()
return _center;
}
int PhysicsShapeEdgeChain::getPointsCount()
int PhysicsShapeEdgeChain::getPointsCount() const
{
return _info->shapes.size() + 1;
}
void PhysicsShape::setGroup(int group)
{
if (group < 0)
{
for (auto shape : _info->shapes)
{
cpShapeSetGroup(shape, (cpGroup)group);
}
}
}
#elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
#endif

View File

@ -57,7 +57,7 @@ typedef struct PhysicsMaterial
{}
}PhysicsMaterial;
const PhysicsMaterial PHYSICSSHAPE_MATERIAL_DEFAULT(0.0f, 1.0f, 1.0f);
const PhysicsMaterial PHYSICSSHAPE_MATERIAL_DEFAULT(0.0f, 0.5f, 0.5f);
/**
* @brief A shape for body. You do not create PhysicsWorld objects directly, instead, you can view PhysicsBody to see how to create it.
@ -102,6 +102,16 @@ public:
static Point* recenterPoints(Point* points, int count, Point center = Point::ZERO);
static Point getPolyonCenter(Point* points, int count);
inline void setCategoryBitmask(int bitmask) { _categoryBitmask = bitmask; }
inline int getCategoryBitmask() const { return _categoryBitmask; }
inline void setContactTestBitmask(int bitmask) { _contactTestBitmask = bitmask; }
inline int getContactTestBitmask() const { return _contactTestBitmask; }
inline void setCollisionBitmask(int bitmask) { _collisionBitmask = bitmask; }
inline int getCollisionBitmask() const { return _collisionBitmask; }
void setGroup(int group);
inline int getGroup() { return _group; }
protected:
bool init(Type type);
@ -125,6 +135,10 @@ protected:
float _moment;
PhysicsMaterial _material;
int _tag;
int _categoryBitmask;
int _collisionBitmask;
int _contactTestBitmask;
int _group;
friend class PhysicsWorld;
friend class PhysicsBody;
@ -142,8 +156,8 @@ public:
float calculateDefaultArea() override;
float calculateDefaultMoment() override;
float getRadius();
Point getOffset();
float getRadius() const;
Point getOffset() override;
protected:
bool init(float radius, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
@ -163,8 +177,8 @@ public:
float calculateDefaultArea() override;
float calculateDefaultMoment() override;
Point* getPoints(Point* points);
Size getSize();
Point* getPoints(Point* points) const;
Size getSize() const;
Point getOffset() override { return _offset; }
protected:
@ -189,8 +203,8 @@ public:
float calculateDefaultArea() override;
float calculateDefaultMoment() override;
Point* getPoints(Point* points);
int getPointsCount();
Point* getPoints(Point* points) const;
int getPointsCount() const;
Point getCenter() override;
protected:
bool init(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
@ -209,8 +223,8 @@ class PhysicsShapeEdgeSegment : public PhysicsShape
public:
static PhysicsShapeEdgeSegment* create(Point a, Point b, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
Point getPointA();
Point getPointB();
Point getPointA() const;
Point getPointB() const;
Point getCenter() override;
protected:
@ -232,8 +246,8 @@ class PhysicsShapeEdgeBox : public PhysicsShape
public:
static PhysicsShapeEdgeBox* create(Size size, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 0, Point offset = Point(0, 0));
Point getOffset() override { return _offset; }
Point* getPoints(Point* points);
int getPointsCount();
Point* getPoints(Point* points) const;
int getPointsCount() const;
protected:
bool init(Size size, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1, Point offset = Point(0, 0));
@ -254,8 +268,8 @@ class PhysicsShapeEdgePolygon : public PhysicsShape
public:
static PhysicsShapeEdgePolygon* create(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
Point getCenter() override;
Point* getPoints(Point* points);
int getPointsCount();
Point* getPoints(Point* points) const;
int getPointsCount() const;
protected:
bool init(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
@ -276,8 +290,8 @@ class PhysicsShapeEdgeChain : public PhysicsShape
public:
static PhysicsShapeEdgeChain* create(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
Point getCenter() override;
Point* getPoints(Point* points);
int getPointsCount();
Point* getPoints(Point* points) const;
int getPointsCount() const;
protected:
bool init(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);

View File

@ -37,29 +37,35 @@
#include "CCPhysicsJoint.h"
#include "CCPhysicsContact.h"
#include "chipmunk/CCPhysicsWorldInfo.h"
#include "box2d/CCPhysicsWorldInfo.h"
#include "chipmunk/CCPhysicsBodyInfo.h"
#include "box2d/CCPhysicsBodyInfo.h"
#include "chipmunk/CCPhysicsShapeInfo.h"
#include "box2d/CCPhysicsShapeInfo.h"
#include "chipmunk/CCPhysicsContactInfo.h"
#include "box2d/CCPhysicsContactInfo.h"
#include "chipmunk/CCPhysicsJointInfo.h"
#include "box2d/CCPhysicsJointInfo.h"
#include "chipmunk/CCPhysicsHelper.h"
#include "chipmunk/CCPhysicsWorldInfo_chipmunk.h"
#include "box2d/CCPhysicsWorldInfo_box2d.h"
#include "chipmunk/CCPhysicsBodyInfo_chipmunk.h"
#include "box2d/CCPhysicsBodyInfo_box2d.h"
#include "chipmunk/CCPhysicsShapeInfo_chipmunk.h"
#include "box2d/CCPhysicsShapeInfo_box2d.h"
#include "chipmunk/CCPhysicsContactInfo_chipmunk.h"
#include "box2d/CCPhysicsContactInfo_box2d.h"
#include "chipmunk/CCPhysicsJointInfo_chipmunk.h"
#include "box2d/CCPhysicsJointInfo_box2d.h"
#include "chipmunk/CCPhysicsHelper_chipmunk.h"
#include "CCDrawNode.h"
#include "CCArray.h"
#include "CCScene.h"
#include "CCDirector.h"
#include "CCEventDispatcher.h"
#include "CCEventCustom.h"
#include <algorithm>
NS_CC_BEGIN
extern const char* PHYSICSCONTACT_EVENT_NAME;
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
const float PHYSICS_INFINITY = INFINITY;
namespace
{
typedef struct RayCastCallbackInfo
@ -96,8 +102,6 @@ public:
bool PhysicsWorldCallback::continues = true;
const float PHYSICS_INFINITY = INFINITY;
int PhysicsWorldCallback::collisionBeginCallbackFunc(cpArbiter *arb, struct cpSpace *space, PhysicsWorld *world)
{
CP_ARBITER_GET_SHAPES(arb, a, b);
@ -108,20 +112,19 @@ int PhysicsWorldCallback::collisionBeginCallbackFunc(cpArbiter *arb, struct cpSp
PhysicsContact* contact = PhysicsContact::create(ita->second->shape, itb->second->shape);
arb->data = contact;
contact->_contactInfo = arb;
return world->collisionBeginCallback(*static_cast<PhysicsContact*>(arb->data));
return world->collisionBeginCallback(*contact);
}
int PhysicsWorldCallback::collisionPreSolveCallbackFunc(cpArbiter *arb, cpSpace *space, PhysicsWorld *world)
{
return world->collisionPreSolveCallback(*static_cast<PhysicsContact*>(arb->data),
PhysicsContactPreSolve());
return world->collisionPreSolveCallback(*static_cast<PhysicsContact*>(arb->data));
}
void PhysicsWorldCallback::collisionPostSolveCallbackFunc(cpArbiter *arb, cpSpace *space, PhysicsWorld *world)
{
world->collisionPostSolveCallback(*static_cast<PhysicsContact*>(arb->data),
PhysicsContactPostSolve());
world->collisionPostSolveCallback(*static_cast<PhysicsContact*>(arb->data));
}
void PhysicsWorldCallback::collisionSeparateCallbackFunc(cpArbiter *arb, cpSpace *space, PhysicsWorld *world)
@ -176,20 +179,31 @@ void PhysicsWorldCallback::nearestPointQueryFunc(cpShape *shape, cpFloat distanc
arr->addObject(it->second->shape);
}
bool PhysicsWorld::init()
bool PhysicsWorld::init(Scene& scene)
{
_info = new PhysicsWorldInfo();
do
{
_info = new PhysicsWorldInfo();
CC_BREAK_IF(_info == nullptr);
_bodies = Array::create();
CC_BREAK_IF(_bodies == nullptr);
_bodies->retain();
_scene = &scene;
cpSpaceSetGravity(_info->space, PhysicsHelper::point2cpv(_gravity));
cpSpaceSetDefaultCollisionHandler(_info->space,
(cpCollisionBeginFunc)PhysicsWorldCallback::collisionBeginCallbackFunc,
(cpCollisionPreSolveFunc)PhysicsWorldCallback::collisionPreSolveCallbackFunc,
(cpCollisionPostSolveFunc)PhysicsWorldCallback::collisionPostSolveCallbackFunc,
(cpCollisionSeparateFunc)PhysicsWorldCallback::collisionSeparateCallbackFunc,
this);
return true;
} while (false);
cpSpaceSetGravity(_info->space, PhysicsHelper::point2cpv(_gravity));
cpSpaceSetDefaultCollisionHandler(_info->space,
(cpCollisionBeginFunc)PhysicsWorldCallback::collisionBeginCallbackFunc,
(cpCollisionPreSolveFunc)PhysicsWorldCallback::collisionPreSolveCallbackFunc,
(cpCollisionPostSolveFunc)PhysicsWorldCallback::collisionPostSolveCallbackFunc,
(cpCollisionSeparateFunc)PhysicsWorldCallback::collisionSeparateCallbackFunc,
this);
return true;
return false;
}
void PhysicsWorld::addJoint(PhysicsJoint* joint)
@ -198,8 +212,6 @@ void PhysicsWorld::addJoint(PhysicsJoint* joint)
if (it == _joints.end())
{
_joints.push_back(joint);
for (auto subjoint : joint->_info->joints)
{
if (!cpSpaceContainsConstraint(_info->space, subjoint))
@ -207,21 +219,47 @@ void PhysicsWorld::addJoint(PhysicsJoint* joint)
cpSpaceAddConstraint(_info->space, subjoint);
}
}
_joints.push_back(joint);
}
}
void PhysicsWorld::removeJoint(PhysicsJoint* joint)
{
auto it = std::find(_joints.begin(), _joints.end(), joint);
if (it != _joints.end())
{
for (auto subjoint : joint->_info->joints)
{
if (cpSpaceContainsConstraint(_info->space, subjoint))
{
cpSpaceRemoveConstraint(_info->space, subjoint);
}
}
_joints.remove(joint);
}
}
void PhysicsWorld::removeAllJoints()
{
for (auto joint : _joints)
{
for (auto subjoint : joint->_info->joints)
{
if (!cpSpaceContainsConstraint(_info->space, subjoint))
{
cpSpaceRemoveConstraint(_info->space, subjoint);
}
}
}
_joints.clear();
}
void PhysicsWorld::addShape(PhysicsShape* shape)
PhysicsShape* PhysicsWorld::addShape(PhysicsShape* shape)
{
for (auto cps : shape->_info->shapes)
{
@ -233,19 +271,29 @@ void PhysicsWorld::addShape(PhysicsShape* shape)
if (cpBodyIsStatic(shape->getBody()->_info->body))
{
cpSpaceAddStaticShape(_info->space, cps);
}else
}
else
{
cpSpaceAddShape(_info->space, cps);
}
}
return shape;
}
void PhysicsWorld::addBody(PhysicsBody* body)
PhysicsBody* PhysicsWorld::addBody(PhysicsBody* body)
{
CCASSERT(body != nullptr, "the body can not be nullptr");
if (body->getWorld() != this && body->getWorld() != nullptr)
{
body->removeFromWorld();
}
if (body->isEnable())
{
body->_world = this;
//is gravity enable
if (!body->isGravityEnable())
{
@ -259,45 +307,42 @@ void PhysicsWorld::addBody(PhysicsBody* body)
}
// add shapes to space
for (auto shape : body->getShapes())
for (auto shape : *body->getShapes())
{
addShape(shape);
addShape(dynamic_cast<PhysicsShape*>(shape));
}
}
if (_bodys == nullptr)
{
_bodys = Array::create(body, NULL);
_bodys->retain();
}else
{
_bodys->addObject(body);
}
_bodies->addObject(body);
return body;
}
void PhysicsWorld::removeBody(PhysicsBody* body)
{
CCASSERT(body != nullptr, "the body can not be nullptr");
if (body->getWorld() == this)
if (body->getWorld() != this)
{
// reset the gravity
if (!body->isGravityEnable())
{
body->applyForce(-_gravity);
}
return;
}
// reset the gravity
if (!body->isGravityEnable())
{
body->applyForce(-_gravity);
}
// remove joints
for (auto joint : body->_joints)
{
removeJoint(joint);
}
// remove shaps
for (auto shape : body->getShapes())
for (auto shape : *body->getShapes())
{
for (auto cps : shape->_info->shapes)
{
if (cpSpaceContainsShape(_info->space, cps))
{
cpSpaceRemoveShape(_info->space, cps);
}
}
removeShape(dynamic_cast<PhysicsShape*>(shape));
}
// remove body
@ -306,15 +351,13 @@ void PhysicsWorld::removeBody(PhysicsBody* body)
cpSpaceRemoveBody(_info->space, body->_info->body);
}
if (_bodys != nullptr)
{
_bodys->removeObject(body);
}
body->_world = nullptr;
_bodies->removeObject(body);
}
void PhysicsWorld::removeBodyByTag(int tag)
{
for (Object* obj : *_bodys)
for (Object* obj : *_bodies)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
if (body->getTag() == tag)
@ -325,6 +368,43 @@ void PhysicsWorld::removeBodyByTag(int tag)
}
}
void PhysicsWorld::removeAllBodies()
{
for (Object* obj : *_bodies)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
// reset the gravity
if (!body->isGravityEnable())
{
body->applyForce(-_gravity);
}
// remove joints
for (auto joint : body->_joints)
{
removeJoint(joint);
}
// remove shaps
for (auto shape : *body->getShapes())
{
removeShape(dynamic_cast<PhysicsShape*>(shape));
}
// remove body
if (cpSpaceContainsBody(_info->space, body->_info->body))
{
cpSpaceRemoveBody(_info->space, body->_info->body);
}
body->_world = nullptr;
}
_bodies->removeAllObjects();
CC_SAFE_RELEASE(_bodies);
}
void PhysicsWorld::removeShape(PhysicsShape* shape)
{
for (auto cps : shape->_info->shapes)
@ -338,7 +418,7 @@ void PhysicsWorld::removeShape(PhysicsShape* shape)
void PhysicsWorld::update(float delta)
{
for (auto body : *_bodys)
for (auto body : *_bodies)
{
body->update(delta);
}
@ -359,22 +439,25 @@ void PhysicsWorld::update(float delta)
void PhysicsWorld::debugDraw()
{
if (_debugDraw && _bodys != nullptr)
if (_debugDraw && _bodies != nullptr)
{
_drawNode= DrawNode::create();
for (Object* obj : *_bodys)
for (Object* obj : *_bodies)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
std::vector<PhysicsShape*> shapes = body->getShapes();
for (auto shape : shapes)
for (auto shape : *body->getShapes())
{
drawWithShape(_drawNode, shape);
drawWithShape(_drawNode, dynamic_cast<PhysicsShape*>(shape));
}
}
for (auto joint : _joints)
{
drawWithJoint(_drawNode, joint);
}
if (_scene)
{
_scene->addChild(_drawNode);
@ -382,9 +465,65 @@ void PhysicsWorld::debugDraw()
}
}
void PhysicsWorld::setScene(Scene *scene)
void PhysicsWorld::drawWithJoint(DrawNode* node, PhysicsJoint* joint)
{
_scene = scene;
for (auto it = joint->_info->joints.begin(); it != joint->_info->joints.end(); ++it)
{
cpConstraint *constraint = *it;
cpBody *body_a = constraint->a;
cpBody *body_b = constraint->b;
const cpConstraintClass *klass = constraint->klass_private;
if(klass == cpPinJointGetClass())
{
cpPinJoint *joint = (cpPinJoint *)constraint;
cpVect a = cpvadd(body_a->p, cpvrotate(joint->anchr1, body_a->rot));
cpVect b = cpvadd(body_b->p, cpvrotate(joint->anchr2, body_b->rot));
node->drawSegment(PhysicsHelper::cpv2point(a), PhysicsHelper::cpv2point(b), 1, Color4F(0.0f, 0.0f, 1.0f, 1.0f));
node->drawDot(PhysicsHelper::cpv2point(a), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
node->drawDot(PhysicsHelper::cpv2point(b), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
}
else if(klass == cpSlideJointGetClass())
{
cpSlideJoint *joint = (cpSlideJoint *)constraint;
cpVect a = cpvadd(body_a->p, cpvrotate(joint->anchr1, body_a->rot));
cpVect b = cpvadd(body_b->p, cpvrotate(joint->anchr2, body_b->rot));
node->drawSegment(PhysicsHelper::cpv2point(a), PhysicsHelper::cpv2point(b), 1, Color4F(0.0f, 0.0f, 1.0f, 1.0f));
node->drawDot(PhysicsHelper::cpv2point(a), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
node->drawDot(PhysicsHelper::cpv2point(b), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
}
else if(klass == cpPivotJointGetClass())
{
cpPivotJoint *joint = (cpPivotJoint *)constraint;
cpVect a = cpvadd(body_a->p, cpvrotate(joint->anchr1, body_a->rot));
cpVect b = cpvadd(body_b->p, cpvrotate(joint->anchr2, body_b->rot));
node->drawDot(PhysicsHelper::cpv2point(a), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
node->drawDot(PhysicsHelper::cpv2point(b), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
}
else if(klass == cpGrooveJointGetClass())
{
cpGrooveJoint *joint = (cpGrooveJoint *)constraint;
cpVect a = cpvadd(body_a->p, cpvrotate(joint->grv_a, body_a->rot));
cpVect b = cpvadd(body_a->p, cpvrotate(joint->grv_b, body_a->rot));
cpVect c = cpvadd(body_b->p, cpvrotate(joint->anchr2, body_b->rot));
node->drawSegment(PhysicsHelper::cpv2point(a), PhysicsHelper::cpv2point(b), 1, Color4F(0.0f, 0.0f, 1.0f, 1.0f));
node->drawDot(PhysicsHelper::cpv2point(c), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
}
else if(klass == cpDampedSpringGetClass())
{
}
}
}
void PhysicsWorld::drawWithShape(DrawNode* node, PhysicsShape* shape)
@ -443,63 +582,90 @@ void PhysicsWorld::drawWithShape(DrawNode* node, PhysicsShape* shape)
int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact)
{
bool ret = true;
PhysicsBody* bodyA = contact.getShapeA()->getBody();
PhysicsBody* bodyB = contact.getShapeB()->getBody();
if ((bodyA->getCategoryBitmask() & bodyB->getContactTestBitmask()) == 0
|| (bodyB->getContactTestBitmask() & bodyA->getCategoryBitmask()) == 0)
PhysicsShape* shapeA = contact.getShapeA();
PhysicsShape* shapeB = contact.getShapeB();
PhysicsBody* bodyA = shapeA->getBody();
PhysicsBody* bodyB = shapeB->getBody();
std::vector<PhysicsJoint*> jointsA = bodyA->getJoints();
// check the joint is collision enable or not
for (PhysicsJoint* joint : jointsA)
{
if (std::find(_joints.begin(), _joints.end(), joint) == _joints.end())
{
continue;
}
if (!joint->isCollisionEnable())
{
PhysicsBody* body = joint->getBodyA() == bodyA ? joint->getBodyB() : joint->getBodyA();
if (body == bodyB)
{
contact.setNotify(false);
return false;
}
}
}
// bitmask check
if ((shapeA->getCategoryBitmask() & shapeB->getContactTestBitmask()) == 0
|| (shapeB->getContactTestBitmask() & shapeA->getCategoryBitmask()) == 0)
{
contact.setNotify(false);
}
if ((bodyA->getCategoryBitmask() & bodyB->getCollisionBitmask()) == 0
|| (bodyB->getCategoryBitmask() & bodyA->getCollisionBitmask()) == 0)
if (shapeA->getGroup() != 0 && shapeA->getGroup() == shapeB->getGroup())
{
ret = false;
ret = shapeA->getGroup() > 0;
}
if (contact.getNotify() && _listener && _listener->onContactBegin)
else
{
// the mask has high priority than _listener->onContactBegin.
// so if the mask test is false, the two bodies won't have collision.
if (ret)
if ((shapeA->getCategoryBitmask() & shapeB->getCollisionBitmask()) == 0
|| (shapeB->getCategoryBitmask() & shapeA->getCollisionBitmask()) == 0)
{
ret = _listener->onContactBegin(*this, contact);
}else
{
_listener->onContactBegin(*this, contact);
ret = false;
}
}
return ret;
contact.setEventCode(PhysicsContact::EventCode::BEGIN);
contact.setWorld(this);
EventCustom event(PHYSICSCONTACT_EVENT_NAME);
event.setUserData(&contact);
_scene->getEventDispatcher()->dispatchEvent(&event);
return ret ? contact.resetResult() : false;
}
int PhysicsWorld::collisionPreSolveCallback(PhysicsContact& contact, const PhysicsContactPreSolve& solve)
int PhysicsWorld::collisionPreSolveCallback(PhysicsContact& contact)
{
if (!contact.getNotify())
{
return true;
}
if (_listener && _listener->onContactPreSolve)
{
return _listener->onContactPreSolve(*this, contact, solve);
}
contact.setEventCode(PhysicsContact::EventCode::PRESOLVE);
contact.setWorld(this);
EventCustom event(PHYSICSCONTACT_EVENT_NAME);
event.setUserData(&contact);
_scene->getEventDispatcher()->dispatchEvent(&event);
return true;
return contact.resetResult();
}
void PhysicsWorld::collisionPostSolveCallback(PhysicsContact& contact, const PhysicsContactPostSolve& solve)
void PhysicsWorld::collisionPostSolveCallback(PhysicsContact& contact)
{
if (!contact.getNotify())
{
return;
}
if (_listener && _listener->onContactPreSolve)
{
_listener->onContactPostSolve(*this, contact, solve);
}
contact.setEventCode(PhysicsContact::EventCode::POSTSOLVE);
contact.setWorld(this);
EventCustom event(PHYSICSCONTACT_EVENT_NAME);
event.setUserData(&contact);
_scene->getEventDispatcher()->dispatchEvent(&event);
}
void PhysicsWorld::collisionSeparateCallback(PhysicsContact& contact)
@ -509,17 +675,18 @@ void PhysicsWorld::collisionSeparateCallback(PhysicsContact& contact)
return;
}
if (_listener && _listener->onContactEnd)
{
_listener->onContactEnd(*this, contact);
}
contact.setEventCode(PhysicsContact::EventCode::SEPERATE);
contact.setWorld(this);
EventCustom event(PHYSICSCONTACT_EVENT_NAME);
event.setUserData(&contact);
_scene->getEventDispatcher()->dispatchEvent(&event);
}
void PhysicsWorld::setGravity(Point gravity)
{
if (_bodys != nullptr)
if (_bodies != nullptr)
{
for (auto child : *_bodys)
for (auto child : *_bodies)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(child);
@ -541,7 +708,7 @@ void PhysicsWorld::rayCast(PhysicsRayCastCallback& callback, Point point1, Point
{
if (callback.report != nullptr)
{
RayCastCallbackInfo info = {this, &callback, point1, point2, data};
RayCastCallbackInfo info = { this, &callback, point1, point2, data };
PhysicsWorldCallback::continues = true;
cpSpaceSegmentQuery(this->_info->space,
@ -571,7 +738,7 @@ void PhysicsWorld::rectQuery(PhysicsRectQueryCallback& callback, Rect rect, void
}
}
Array* PhysicsWorld::getShapesAtPoint(Point point)
Array* PhysicsWorld::getShapesAtPoint(Point point) const
{
Array* arr = Array::create();
cpSpaceNearestPointQuery(this->_info->space,
@ -585,7 +752,7 @@ Array* PhysicsWorld::getShapesAtPoint(Point point)
return arr;
}
PhysicsShape* PhysicsWorld::getShapeAtPoint(Point point)
PhysicsShape* PhysicsWorld::getShapeAtPoint(Point point) const
{
cpShape* shape = cpSpaceNearestPointQueryNearest(this->_info->space,
PhysicsHelper::point2cpv(point),
@ -597,19 +764,32 @@ PhysicsShape* PhysicsWorld::getShapeAtPoint(Point point)
return shape == nullptr ? nullptr : PhysicsShapeInfo::map.find(shape)->second->shape;
}
Array* PhysicsWorld::getAllBody() const
Array* PhysicsWorld::getAllBodies() const
{
return _bodys;
return _bodies;
}
PhysicsBody* PhysicsWorld::getBodyByTag(int tag) const
{
for (auto body : *_bodies)
{
if (((PhysicsBody*)body)->getTag() == tag)
{
return (PhysicsBody*)body;
}
}
return nullptr;
}
#elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
#endif
PhysicsWorld* PhysicsWorld::create()
PhysicsWorld* PhysicsWorld::create(Scene& scene)
{
PhysicsWorld * world = new PhysicsWorld();
if(world && world->init())
if(world && world->init(scene))
{
return world;
}
@ -622,8 +802,7 @@ PhysicsWorld::PhysicsWorld()
: _gravity(Point(0.0f, -98.0f))
, _speed(1.0f)
, _info(nullptr)
, _listener(nullptr)
, _bodys(nullptr)
, _bodies(nullptr)
, _scene(nullptr)
, _debugDraw(false)
, _drawNode(nullptr)
@ -633,8 +812,9 @@ PhysicsWorld::PhysicsWorld()
PhysicsWorld::~PhysicsWorld()
{
removeAllBodies();
removeAllJoints();
CC_SAFE_DELETE(_info);
CC_SAFE_RELEASE(_bodys);
}
NS_CC_END

View File

@ -40,9 +40,6 @@ class PhysicsJoint;
class PhysicsWorldInfo;
class PhysicsShape;
class PhysicsContact;
class PhysicsContactPreSolve;
class PhysicsContactPostSolve;
class PhysicsContactListener;
class Array;
class Sprite;
@ -97,56 +94,57 @@ public:
void rayCast(PhysicsRayCastCallback& callback, Point point1, Point point2, void* data);
void rectQuery(PhysicsRectQueryCallback& callback, Rect rect, void* data);
Array* getShapesAtPoint(Point point);
PhysicsShape* getShapeAtPoint(Point point);
Array* getAllBody() const;
Array* getShapesAtPoint(Point point) const;
PhysicsShape* getShapeAtPoint(Point point) const;
Array* getAllBodies() const;
PhysicsBody* getBodyByTag(int tag) const;
/** Register a listener to receive contact callbacks*/
inline void registerContactListener(PhysicsContactListener* delegate) { _listener = delegate; }
//inline void registerContactListener(EventListenerPhysicsContact* delegate) { _listener = delegate; }
/** Unregister a listener. */
inline void unregisterContactListener() { _listener = nullptr; }
//inline void unregisterContactListener() { _listener = nullptr; }
inline Scene& getScene() const { return *_scene; }
/** get the gravity value */
inline Point getGravity() { return _gravity; }
inline Point getGravity() const { return _gravity; }
/** set the gravity value */
void setGravity(Point gravity);
/** test the debug draw is enabled */
inline bool isDebugDraw() { return _debugDraw; }
inline bool isDebugDraw() const { return _debugDraw; }
/** set the debug draw */
inline void setDebugDraw(bool debugDraw) { _debugDraw = debugDraw; }
virtual void removeBody(PhysicsBody* body);
virtual void removeBodyByTag(int tag);
virtual void removeAllBodies();
protected:
static PhysicsWorld* create();
bool init();
static PhysicsWorld* create(Scene& scene);
bool init(Scene& scene);
void setScene(Scene* scene);
virtual void addBody(PhysicsBody* body);
virtual void addShape(PhysicsShape* shape);
virtual PhysicsBody* addBody(PhysicsBody* body);
virtual PhysicsShape* addShape(PhysicsShape* shape);
virtual void removeShape(PhysicsShape* shape);
virtual void update(float delta);
virtual void debugDraw();
virtual void drawWithShape(DrawNode* node, PhysicsShape* shape);
virtual void drawWithJoint(DrawNode* node, PhysicsJoint* joint);
virtual int collisionBeginCallback(PhysicsContact& contact);
virtual int collisionPreSolveCallback(PhysicsContact& contact, const PhysicsContactPreSolve& solve);
virtual void collisionPostSolveCallback(PhysicsContact& contact, const PhysicsContactPostSolve& solve);
virtual int collisionPreSolveCallback(PhysicsContact& contact);
virtual void collisionPostSolveCallback(PhysicsContact& contact);
virtual void collisionSeparateCallback(PhysicsContact& contact);
protected:
Point _gravity;
float _speed;
PhysicsWorldInfo* _info;
PhysicsContactListener* _listener;
//EventListenerPhysicsContact* _listener;
Array* _bodys;
Array* _bodies;
std::list<PhysicsJoint*> _joints;
Scene* _scene;

View File

@ -22,7 +22,7 @@
THE SOFTWARE.
****************************************************************************/
#include "CCPhysicsBodyInfo.h"
#include "CCPhysicsBodyInfo_box2d.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
NS_CC_BEGIN

View File

@ -27,7 +27,9 @@
#ifndef __CCPHYSICS_BODY_INFO_H__
#define __CCPHYSICS_BODY_INFO_H__
#include "CCPlatformMacros.h"
NS_CC_BEGIN
class PhysicsBodyInfo

View File

@ -22,7 +22,7 @@
THE SOFTWARE.
****************************************************************************/
#include "CCPhysicsContactInfo.h"
#include "CCPhysicsContactInfo_box2d.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
NS_CC_BEGIN

View File

@ -27,6 +27,7 @@
#ifndef __CCPHYSICS_CONTACT_INFO_H__
#define __CCPHYSICS_CONTACT_INFO_H__
#include "CCPlatformMacros.h"
NS_CC_BEGIN

View File

@ -27,7 +27,6 @@
#ifndef __CCPHYSICS_HELPER_H__
#define __CCPHYSICS_HELPER_H__
#include "CCPlatformMacros.h"
#include "CCGeometry.h"

View File

@ -22,7 +22,7 @@
THE SOFTWARE.
****************************************************************************/
#include "CCPhysicsJointInfo.h"
#include "CCPhysicsJointInfo_box2d.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
NS_CC_BEGIN

View File

@ -27,6 +27,7 @@
#ifndef __CCPHYSICS_JOINT_INFO_H__
#define __CCPHYSICS_JOINT_INFO_H__
#include "CCPlatformMacros.h"
NS_CC_BEGIN

View File

@ -22,7 +22,7 @@
THE SOFTWARE.
****************************************************************************/
#include "CCPhysicsShapeInfo.h"
#include "CCPhysicsShapeInfo_box2d.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
NS_CC_BEGIN

View File

@ -27,6 +27,7 @@
#ifndef __CCPHYSICS_SHAPE_INFO_H__
#define __CCPHYSICS_SHAPE_INFO_H__
#include "CCPlatformMacros.h"
NS_CC_BEGIN

View File

@ -22,7 +22,7 @@
THE SOFTWARE.
****************************************************************************/
#include "CCPhysicsWorldInfo.h"
#include "CCPhysicsWorldInfo_box2d.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
NS_CC_BEGIN

View File

@ -27,6 +27,7 @@
#ifndef __CCPHYSICS_WORLD_INFO_H__
#define __CCPHYSICS_WORLD_INFO_H__
#include "CCPlatformMacros.h"
NS_CC_BEGIN

View File

@ -22,13 +22,12 @@
THE SOFTWARE.
****************************************************************************/
#include "CCPhysicsBodyInfo.h"
#include "CCPhysicsBodyInfo_chipmunk.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
NS_CC_BEGIN
PhysicsBodyInfo::PhysicsBodyInfo()
: body(nullptr)
, group(CP_NO_GROUP)
{
}

View File

@ -27,6 +27,7 @@
#ifndef __CCPHYSICS_BODY_INFO_H__
#define __CCPHYSICS_BODY_INFO_H__
#include "chipmunk.h"
#include "CCPlatformMacros.h"
#include "CCObject.h"
@ -37,7 +38,6 @@ class PhysicsBodyInfo : public Clonable
{
public:
cpBody* body;
cpGroup group;
private:
PhysicsBodyInfo();

View File

@ -22,7 +22,7 @@
THE SOFTWARE.
****************************************************************************/
#include "CCPhysicsContactInfo.h"
#include "CCPhysicsContactInfo_chipmunk.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
NS_CC_BEGIN

View File

@ -27,6 +27,7 @@
#ifndef __CCPHYSICS_CONTACT_INFO_H__
#define __CCPHYSICS_CONTACT_INFO_H__
#include "chipmunk.h"
#include "CCPlatformMacros.h"
NS_CC_BEGIN

View File

@ -22,7 +22,7 @@
THE SOFTWARE.
****************************************************************************/
#include "CCPhysicsJointInfo.h"
#include "CCPhysicsJointInfo_chipmunk.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#include <algorithm>
NS_CC_BEGIN

View File

@ -27,6 +27,7 @@
#ifndef __CCPHYSICS_JOINT_INFO_H__
#define __CCPHYSICS_JOINT_INFO_H__
#include "chipmunk.h"
#include "CCPlatformMacros.h"
#include <vector>

View File

@ -22,7 +22,7 @@
THE SOFTWARE.
****************************************************************************/
#include "CCPhysicsShapeInfo.h"
#include "CCPhysicsShapeInfo_chipmunk.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#include <algorithm>
NS_CC_BEGIN

View File

@ -22,7 +22,7 @@
THE SOFTWARE.
****************************************************************************/
#include "CCPhysicsWorldInfo.h"
#include "CCPhysicsWorldInfo_chipmunk.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
NS_CC_BEGIN

View File

@ -27,6 +27,7 @@
#ifndef __CCPHYSICS_WORLD_INFO_H__
#define __CCPHYSICS_WORLD_INFO_H__
#include "chipmunk.h"
#include "CCPlatformMacros.h"
NS_CC_BEGIN

View File

@ -10,6 +10,10 @@ namespace
CL(PhysicsDemoPlink),
CL(PhysicsDemoClickAdd),
CL(PhysicsDemoRayCast),
CL(PhysicsDemoJoints),
CL(PhysicsDemoActions),
CL(PhysicsDemoPump),
CL(PhysicsDemoOneWayPlatform),
};
static int sceneIdx=-1;
@ -51,6 +55,7 @@ namespace
}
static const Color4F STATIC_COLOR(1.0f, 0.0f, 0.0f, 1.0f);
static const int DRAG_BODYS_TAG = 0x80;
}
@ -92,7 +97,6 @@ PhysicsDemo::PhysicsDemo()
: _scene(nullptr)
, _ball(nullptr)
, _spriteTexture(nullptr)
, _mouse(nullptr)
{
}
@ -160,7 +164,7 @@ void PhysicsDemo::onEnter()
#endif
}
void PhysicsDemo::addGrossiniAtPosition(Point p, float scale/* = 1.0*/)
Sprite* PhysicsDemo::addGrossiniAtPosition(Point p, float scale/* = 1.0*/)
{
#ifdef CC_USE_PHYSICS
CCLOG("Add sprite %0.2f x %02.f",p.x,p.y);
@ -178,6 +182,8 @@ void PhysicsDemo::addGrossiniAtPosition(Point p, float scale/* = 1.0*/)
sp->setPhysicsBody(PhysicsBody::createBox(Size(48.0f * scale, 108.0f * scale)));
this->addChild(sp);
sp->setPosition(p);
return sp;
#endif
}
@ -198,8 +204,10 @@ void PhysicsDemoClickAdd::onEnter()
#ifdef CC_USE_PHYSICS
auto touchListener = EventListenerTouchAllAtOnce::create();
touchListener->onTouchesEnded = CC_CALLBACK_2(PhysicsDemoClickAdd::onTouchesEnded, this);
auto touchListener = EventListenerTouchOneByOne::create();
touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsDemoClickAdd::onTouchBegan, this);
touchListener->onTouchMoved = CC_CALLBACK_2(PhysicsDemoClickAdd::onTouchMoved, this);
touchListener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoClickAdd::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
auto accListener = EventListenerAcceleration::create(CC_CALLBACK_2(PhysicsDemoClickAdd::onAcceleration, this));
@ -316,7 +324,7 @@ namespace
}
}
Sprite* PhysicsDemo::makeBall(float x, float y, float radius, PhysicsMaterial material)
Sprite* PhysicsDemo::makeBall(Point point, float radius, PhysicsMaterial material)
{
Sprite* ball = nullptr;
if (_ball != nullptr)
@ -331,12 +339,12 @@ Sprite* PhysicsDemo::makeBall(float x, float y, float radius, PhysicsMaterial ma
auto body = PhysicsBody::createCircle(radius, material);
ball->setPhysicsBody(body);
ball->setPosition(Point(x, y));
ball->setPosition(Point(point.x, point.y));
return ball;
}
Sprite* PhysicsDemo::makeBox(float x, float y, Size size, PhysicsMaterial material)
Sprite* PhysicsDemo::makeBox(Point point, Size size, PhysicsMaterial material)
{
auto box = CCRANDOM_0_1() > 0.5f ? Sprite::create("Images/YellowSquare.png") : Sprite::create("Images/CyanSquare.png");
@ -345,12 +353,12 @@ Sprite* PhysicsDemo::makeBox(float x, float y, Size size, PhysicsMaterial materi
auto body = PhysicsBody::createBox(size);
box->setPhysicsBody(body);
box->setPosition(Point(x, y));
box->setPosition(Point(point.x, point.y));
return box;
}
Sprite* PhysicsDemo::makeTriangle(float x, float y, Size size, PhysicsMaterial material)
Sprite* PhysicsDemo::makeTriangle(Point point, Size size, PhysicsMaterial material)
{
auto triangle = CCRANDOM_0_1() > 0.5f ? Sprite::create("Images/YellowTriangle.png") : Sprite::create("Images/CyanTriangle.png");
@ -367,33 +375,66 @@ Sprite* PhysicsDemo::makeTriangle(float x, float y, Size size, PhysicsMaterial m
auto body = PhysicsBody::createPolygon(vers, 3);
triangle->setPhysicsBody(body);
triangle->setPosition(Point(x, y));
triangle->setPosition(Point(point.x, point.y));
return triangle;
}
void PhysicsDemo::onTouchesBegan(const std::vector<Touch*>& touches, Event* event)
bool PhysicsDemo::onTouchBegan(Touch* touch, Event* event)
{
for( auto &touch: touches)
auto location = touch->getLocation();
Array* arr = _scene->getPhysicsWorld()->getShapesAtPoint(location);
PhysicsShape* shape = nullptr;
for (Object* obj : *arr)
{
auto location = touch->getLocation();
Array* arr = _scene->getPhysicsWorld()->getShapesAtPoint(location);
shape = dynamic_cast<PhysicsShape*>(obj);
PhysicsShape* shape = nullptr;
for (Object* obj : *arr)
if ((shape->getTag() & DRAG_BODYS_TAG) != 0)
{
break;
}
}
if (shape != nullptr)
{
Node* mouse = Node::create();
mouse->setPhysicsBody(PhysicsBody::create(PHYSICS_INFINITY, PHYSICS_INFINITY));
mouse->getPhysicsBody()->setDynamic(false);
mouse->setPosition(location);
this->addChild(mouse);
PhysicsJointPin* joint = PhysicsJointPin::create(mouse->getPhysicsBody(), shape->getBody(), location);
joint->setMaxForce(5000.0f * shape->getBody()->getMass());
_scene->getPhysicsWorld()->addJoint(joint);
_mouses.insert(std::make_pair(touch->getID(), mouse));
return true;
}
return false;
}
void PhysicsDemo::onTouchMoved(Touch* touch, Event* event)
{
auto it = _mouses.find(touch->getID());
if (it != _mouses.end())
{
it->second->getPhysicsBody()->setVelocity((touch->getLocation() - it->second->getPosition()) * 60.0f);
it->second->setPosition(touch->getLocation());
}
}
void PhysicsDemo::onTouchesMoved(const std::vector<Touch*>& touches, Event* event)
void PhysicsDemo::onTouchEnded(Touch* touch, Event* event)
{
auto it = _mouses.find(touch->getID());
}
void PhysicsDemo::onTouchesEnded(const std::vector<Touch*>& touches, Event* event)
{
if (it != _mouses.end())
{
this->removeChild(it->second);
_mouses.erase(it);
}
}
@ -414,9 +455,9 @@ void PhysicsDemoLogoSmash::onEnter()
float x_jitter = 0.05*frand();
float y_jitter = 0.05*frand();
Node* ball = makeBall(2*(x - logo_width/2 + x_jitter) + VisibleRect::getVisibleRect().size.width/2,
2*(logo_height-y + y_jitter) + VisibleRect::getVisibleRect().size.height/2 - logo_height/2,
0.95f, PhysicsMaterial(1.0f, 0.0f, 0.0f));
Node* ball = makeBall(Point(2*(x - logo_width/2 + x_jitter) + VisibleRect::getVisibleRect().size.width/2,
2*(logo_height-y + y_jitter) + VisibleRect::getVisibleRect().size.height/2 - logo_height/2),
0.95f, PhysicsMaterial(0.01f, 0.0f, 0.0f));
ball->getPhysicsBody()->setMass(1.0);
ball->getPhysicsBody()->setMoment(PHYSICS_INFINITY);
@ -428,7 +469,7 @@ void PhysicsDemoLogoSmash::onEnter()
}
auto bullet = makeBall(400, 0, 10, PhysicsMaterial(PHYSICS_INFINITY, 0, 0));
auto bullet = makeBall(Point(400, 0), 10, PhysicsMaterial(PHYSICS_INFINITY, 0, 0));
bullet->getPhysicsBody()->setVelocity(Point(400, 0));
bullet->setPosition(Point(-1000, VisibleRect::getVisibleRect().size.height/2));
@ -445,6 +486,12 @@ void PhysicsDemoPyramidStack::onEnter()
{
PhysicsDemo::onEnter();
auto touchListener = EventListenerTouchOneByOne::create();
touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsDemoPyramidStack::onTouchBegan, this);
touchListener->onTouchMoved = CC_CALLBACK_2(PhysicsDemoPyramidStack::onTouchMoved, this);
touchListener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoPyramidStack::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
auto node = Node::create();
node->setPhysicsBody(PhysicsBody::createEdgeSegment(VisibleRect::leftBottom() + Point(0, 50), VisibleRect::rightBottom() + Point(0, 50)));
this->addChild(node);
@ -459,7 +506,9 @@ void PhysicsDemoPyramidStack::onEnter()
{
for(int j=0; j<=i; j++)
{
addGrossiniAtPosition(VisibleRect::bottom() + Point((i/2 - j) * 11, (14 - i) * 23 + 100), 0.2f);
auto sp = addGrossiniAtPosition(VisibleRect::bottom() + Point((i/2 - j) * 11, (14 - i) * 23 + 100), 0.2f);
sp->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
}
}
}
@ -694,13 +743,13 @@ void PhysicsDemoRayCast::onTouchesEnded(const std::vector<Touch*>& touches, Even
if (r < 1.0f/3.0f)
{
addChild(makeBall(location.x, location.y, 5 + CCRANDOM_0_1()*10));
addChild(makeBall(location, 5 + CCRANDOM_0_1()*10));
}else if(r < 2.0f/3.0f)
{
addChild(makeBox(location.x, location.y, Size(10 + CCRANDOM_0_1()*15, 10 + CCRANDOM_0_1()*15)));
addChild(makeBox(location, Size(10 + CCRANDOM_0_1()*15, 10 + CCRANDOM_0_1()*15)));
}else
{
addChild(makeTriangle(location.x, location.y, Size(10 + CCRANDOM_0_1()*20, 10 + CCRANDOM_0_1()*20)));
addChild(makeTriangle(location, Size(10 + CCRANDOM_0_1()*20, 10 + CCRANDOM_0_1()*20)));
}
}
}
@ -710,26 +759,307 @@ std::string PhysicsDemoRayCast::title()
return "Ray Cast";
}
void PhysicsDemoJoints::onEnter()
{
PhysicsDemo::onEnter();
auto listener = EventListenerTouchAllAtOnce::create();
listener->onTouchesEnded = CC_CALLBACK_2(PhysicsDemoJoints::onTouchesEnded, this);
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoJoints::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
_scene->getPhysicsWorld()->setGravity(Point::ZERO);
//_scene->getPhysicsWorld()->setGravity(Point::ZERO);
float width = (VisibleRect::getVisibleRect().size.width - 10) / 4;
float height = (VisibleRect::getVisibleRect().size.height - 50) / 4;
}
void PhysicsDemoJoints::onTouchesEnded(const std::vector<Touch*>& touches, Event* event)
{
Node* node = Node::create();
PhysicsBody* box = PhysicsBody::create();
node->setPhysicsBody(box);
box->setDynamic(false);
node->setPosition(Point::ZERO);
this->addChild(node);
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
Point offset(VisibleRect::leftBottom().x + 5 + j * width + width/2, VisibleRect::leftBottom().y + 50 + i * height + height/2);
box->addShape(PhysicsShapeEdgeBox::create(Size(width, height), PHYSICSSHAPE_MATERIAL_DEFAULT, 1, offset));
switch (i*4 + j)
{
case 0:
{
auto sp1 = makeBall(offset - Point(30, 0), 10);
sp1->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
auto sp2 = makeBall(offset + Point(30, 0), 10);
sp2->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
PhysicsJointPin* joint = PhysicsJointPin::create(sp1->getPhysicsBody(), sp2->getPhysicsBody(), offset);
_scene->getPhysicsWorld()->addJoint(joint);
this->addChild(sp1);
this->addChild(sp2);
break;
}
case 1:
{
auto sp1 = makeBall(offset - Point(30, 0), 10);
sp1->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
auto sp2 = makeBox(offset + Point(30, 0), Size(30, 10));
sp2->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
PhysicsJointFixed* joint = PhysicsJointFixed::create(sp1->getPhysicsBody(), sp2->getPhysicsBody(), offset);
_scene->getPhysicsWorld()->addJoint(joint);
this->addChild(sp1);
this->addChild(sp2);
break;
}
default:
break;
}
}
}
}
std::string PhysicsDemoJoints::title()
{
return "Joints";
}
void PhysicsDemoActions::onEnter()
{
PhysicsDemo::onEnter();
auto touchListener = EventListenerTouchOneByOne::create();
touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsDemoActions::onTouchBegan, this);
touchListener->onTouchMoved = CC_CALLBACK_2(PhysicsDemoActions::onTouchMoved, this);
touchListener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoActions::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
auto node = Node::create();
node->setPhysicsBody(PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size));
node->setPosition(VisibleRect::center());
this->addChild(node);
Sprite* sp1 = addGrossiniAtPosition(VisibleRect::center());
Sprite* sp2 = addGrossiniAtPosition(VisibleRect::left() + Point(50, 0));
Sprite* sp3 = addGrossiniAtPosition(VisibleRect::right() - Point(20, 0));
Sprite* sp4 = addGrossiniAtPosition(VisibleRect::leftTop() + Point(50, -50));
sp4->getPhysicsBody()->setGravityEnable(false);
auto actionTo = JumpTo::create(2, Point(100,100), 50, 4);
auto actionBy = JumpBy::create(2, Point(300,0), 50, 4);
auto actionUp = JumpBy::create(2, Point(0,50), 80, 4);
auto actionByBack = actionBy->reverse();
sp1->runAction(RepeatForever::create(actionUp));
sp2->runAction(RepeatForever::create(Sequence::create(actionBy, actionByBack, NULL)));
sp3->runAction(actionTo);
sp4->runAction(RepeatForever::create(Sequence::create(actionBy->clone(), actionByBack->clone(), NULL)));
}
std::string PhysicsDemoActions::title()
{
return "Actions";
}
void PhysicsDemoPump::onEnter()
{
PhysicsDemo::onEnter();
_distance = 0.0f;
_rotationV = 0.0f;
auto touchListener = EventListenerTouchOneByOne::create();
touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsDemoPump::onTouchBegan, this);
touchListener->onTouchMoved = CC_CALLBACK_2(PhysicsDemoPump::onTouchMoved, this);
touchListener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoPump::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
scheduleUpdate();
auto node = Node::create();
auto body = PhysicsBody::create();
body->setDynamic(false);
PhysicsMaterial staticMaterial(PHYSICS_INFINITY, 0, 0.5f);
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(50, 0), VisibleRect::leftTop() + Point(50, -130), staticMaterial, 2.0f));
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(190, 0), VisibleRect::leftTop() + Point(100, -50), staticMaterial, 2.0f));
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(100, -50), VisibleRect::leftTop() + Point(100, -90), staticMaterial, 2.0f));
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(50, -130), VisibleRect::leftTop() + Point(100, -145), staticMaterial, 2.0f));
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(100, -145), VisibleRect::leftBottom() + Point(100, 80), staticMaterial, 2.0f));
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(150, -80), VisibleRect::leftBottom() + Point(150, 80), staticMaterial, 2.0f));
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(150, -80), VisibleRect::rightTop() + Point(-100, -150), staticMaterial, 2.0f));
body->setCategoryBitmask(0x01);
// balls
for (int i = 0; i < 6; ++i)
{
auto ball = makeBall(VisibleRect::leftTop() + Point(75 + CCRANDOM_0_1() * 90, 0), 22, PhysicsMaterial(0.05f, 0.0f, 0.1f));
ball->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
addChild(ball);
}
node->setPhysicsBody(body);
this->addChild(node);
Point vec[4] =
{
VisibleRect::leftTop() + Point(102, -148),
VisibleRect::leftTop() + Point(148, -161),
VisibleRect::leftBottom() + Point(148, 20),
VisibleRect::leftBottom() + Point(102, 20)
};
auto _world = _scene->getPhysicsWorld();
// small gear
auto sgear = Node::create();
auto sgearB = PhysicsBody::createCircle(44);
sgear->setPhysicsBody(sgearB);
sgear->setPosition(VisibleRect::leftBottom() + Point(125, 0));
this->addChild(sgear);
sgearB->setCategoryBitmask(0x04);
sgearB->setCollisionBitmask(0x04);
sgearB->setTag(1);
_world->addJoint(PhysicsJointPin::create(body, sgearB, sgearB->getPosition()));
// big gear
auto bgear = Node::create();
auto bgearB = PhysicsBody::createCircle(100);
bgear->setPhysicsBody(bgearB);
bgear->setPosition(VisibleRect::leftBottom() + Point(275, 0));
this->addChild(bgear);
bgearB->setCategoryBitmask(0x04);
_world->addJoint(PhysicsJointPin::create(body, bgearB, bgearB->getPosition()));
// pump
auto pump = Node::create();
pump->setPosition(PhysicsShape::getPolyonCenter(vec, 4));
auto pumpB = PhysicsBody::createPolygon(PhysicsShape::recenterPoints(vec, 4), 4);
pump->setPhysicsBody(pumpB);
this->addChild(pump);
pumpB->setCategoryBitmask(0x02);
pumpB->setGravityEnable(false);
_world->addJoint(PhysicsJointDistance::create(pumpB, sgearB, Point(0, 0), Point(0, -44)));
// plugger
Point seg[] = {VisibleRect::leftTop() + Point(75, -120), VisibleRect::leftBottom() + Point(75, -100)};
Point segCenter = (seg[1] + seg[0])/2;
seg[1] -= segCenter;
seg[0] -= segCenter;
auto plugger = Node::create();
auto pluggerB = PhysicsBody::createEdgeSegment(seg[0], seg[1], PhysicsMaterial(0.01f, 0.0f, 0.5f), 20);
pluggerB->setDynamic(true);
pluggerB->setMass(30);
pluggerB->setMoment(100000);
plugger->setPhysicsBody(pluggerB);
plugger->setPosition(segCenter);
this->addChild(plugger);
pluggerB->setCategoryBitmask(0x02);
sgearB->setCollisionBitmask(0x04 | 0x01);
_world->addJoint(PhysicsJointPin::create(body, pluggerB, VisibleRect::leftBottom() + Point(75, -90)));
_world->addJoint(PhysicsJointDistance::create(pluggerB, sgearB, pluggerB->world2Local(VisibleRect::leftBottom() + Point(75, 0)), Point(44, 0)));
}
void PhysicsDemoPump::update(float delta)
{
for (auto obj : *_scene->getPhysicsWorld()->getAllBodies())
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
if (body->getTag() == DRAG_BODYS_TAG && body->getPosition().y < 0.0f)
{
body->getNode()->setPosition(VisibleRect::leftTop() + Point(75 + CCRANDOM_0_1() * 90, 0));
body->setVelocity(Point(0, 0));
}
}
PhysicsBody* gear = _scene->getPhysicsWorld()->getBodyByTag(1);
if (gear != nullptr)
{
if (_distance != 0.0f)
{
_rotationV += _distance/2500.0f;
if (_rotationV > 30) _rotationV = 30.0f;
if (_rotationV < -30) _rotationV = -30.0f;
}
gear->setAngularVelocity(_rotationV);
_rotationV *= 0.995f;
}
}
bool PhysicsDemoPump::onTouchBegan(Touch* touch, Event* event)
{
PhysicsDemo::onTouchBegan(touch, event);
_distance = touch->getLocation().x - VisibleRect::center().x;
return true;
}
void PhysicsDemoPump::onTouchMoved(Touch* touch, Event* event)
{
PhysicsDemo::onTouchMoved(touch, event);
_distance = touch->getLocation().x - VisibleRect::center().x;
}
void PhysicsDemoPump::onTouchEnded(Touch* touch, Event* event)
{
PhysicsDemo::onTouchEnded(touch, event);
_distance = 0;
}
std::string PhysicsDemoPump::title()
{
return "Pump";
}
void PhysicsDemoOneWayPlatform::onEnter()
{
PhysicsDemo::onEnter();
auto touchListener = EventListenerTouchOneByOne::create();
touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsDemoOneWayPlatform::onTouchBegan, this);
touchListener->onTouchMoved = CC_CALLBACK_2(PhysicsDemoOneWayPlatform::onTouchMoved, this);
touchListener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoOneWayPlatform::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
auto ground = Node::create();
ground->setPhysicsBody(PhysicsBody::createEdgeSegment(VisibleRect::leftBottom() + Point(0, 50), VisibleRect::rightBottom() + Point(0, 50)));
this->addChild(ground);
auto platform = Node::create();
platform->setPhysicsBody(PhysicsBody::createBox(Size(200, 50)));
platform->getPhysicsBody()->setDynamic(false);
platform->setPosition(VisibleRect::center());
this->addChild(platform);
auto ball = makeBall(VisibleRect::center() - Point(0, 50), 5);
ball->getPhysicsBody()->setVelocity(Point(0, 200));
this->addChild(ball);
auto contactListener = EventListenerPhysicsContactWithBodies::create(platform->getPhysicsBody(), ball->getPhysicsBody());
contactListener->onContactPreSolve = CC_CALLBACK_3(PhysicsDemoOneWayPlatform::onPreSolve, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);
}
bool PhysicsDemoOneWayPlatform::onPreSolve(EventCustom* event, const PhysicsContact& contact, const PhysicsContactPreSolve& solve)
{
return true;
}
std::string PhysicsDemoOneWayPlatform::title()
{
return "One Way Platform";
}

View File

@ -5,6 +5,8 @@
#include "../testBasic.h"
#include "../BaseTest.h"
#include <map>
class PhysicsTestScene : public TestScene
{
@ -36,19 +38,19 @@ public:
void backCallback(Object* sender);
void toggleDebugCallback(Object* sender);
void addGrossiniAtPosition(Point p, float scale = 1.0);
Sprite* makeBall(float x, float y, float radius, PhysicsMaterial material = PhysicsMaterial(1.0f, 1.0f, 1.0f));
Sprite* makeBox(float x, float y, Size size, PhysicsMaterial material = PhysicsMaterial(1.0f, 1.0f, 1.0f));
Sprite* makeTriangle(float x, float y, Size size, PhysicsMaterial material = PhysicsMaterial(1.0f, 1.0f, 1.0f));
Sprite* addGrossiniAtPosition(Point p, float scale = 1.0);
Sprite* makeBall(Point point, float radius, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
Sprite* makeBox(Point point, Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
Sprite* makeTriangle(Point point, Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
void onTouchesBegan(const std::vector<Touch*>& touches, Event* event);
void onTouchesMoved(const std::vector<Touch*>& touches, Event* event);
void onTouchesEnded(const std::vector<Touch*>& touches, Event* event);
bool onTouchBegan(Touch* touch, Event* event);
void onTouchMoved(Touch* touch, Event* event);
void onTouchEnded(Touch* touch, Event* event);
protected:
Texture2D* _spriteTexture; // weak ref
SpriteBatchNode* _ball;
DrawNode* _mouse;
std::map<int, Node*> _mouses;
};
class PhysicsDemoClickAdd : public PhysicsDemo
@ -105,12 +107,40 @@ private:
class PhysicsDemoJoints : public PhysicsDemo
{
public:
PhysicsDemoJoints();
void onEnter() override;
std::string title() override;
};
class PhysicsDemoActions : public PhysicsDemo
{
public:
void onEnter() override;
std::string title() override;
void onTouchesEnded(const std::vector<Touch*>& touches, Event* event);
};
class PhysicsDemoPump : public PhysicsDemo
{
public:
void onEnter() override;
std::string title() override;
void update(float delta) override;
bool onTouchBegan(Touch* touch, Event* event);
void onTouchMoved(Touch* touch, Event* event);
void onTouchEnded(Touch* touch, Event* event);
private:
float _distance;
float _rotationV;
};
class PhysicsDemoOneWayPlatform : public PhysicsDemo
{
public:
void onEnter() override;
std::string title() override;
bool onPreSolve(EventCustom* event, const PhysicsContact& contact, const PhysicsContactPreSolve& solve);
};
#endif