Improve performance of physics

This commit is contained in:
Wenhai Lin 2015-01-07 17:08:04 +08:00
parent 2847a940ed
commit 8524a5fb97
16 changed files with 670 additions and 977 deletions

View File

@ -859,12 +859,6 @@ void RotateTo::update(float time)
}
else
{
// _startAngle.x != _startAngle.y || _diffAngle.x != _diffAngle.y
if (_target->getPhysicsBody() != nullptr)
{
CCLOG("RotateTo WARNING: PhysicsBody doesn't support skew rotation");
}
_target->setRotationSkewX(_startAngle.x + _diffAngle.x * time);
_target->setRotationSkewY(_startAngle.y + _diffAngle.y * time);
}
@ -1002,12 +996,6 @@ void RotateBy::update(float time)
}
else
{
// _startAngle.x != _startAngle.y || _deltaAngle.x != _deltaAngle.y
if (_target->getPhysicsBody() != nullptr)
{
CCLOG("RotateBy WARNING: PhysicsBody doesn't support skew rotation");
}
_target->setRotationSkewX(_startAngle.x + _deltaAngle.x * time);
_target->setRotationSkewY(_startAngle.y + _deltaAngle.y * time);
}

View File

@ -60,7 +60,6 @@ THE SOFTWARE.
#define RENDER_IN_SUBPIXEL(__ARGS__) (ceil(__ARGS__))
#endif
extern int g_physicsSceneCount;
NS_CC_BEGIN
@ -125,6 +124,8 @@ Node::Node(void)
, _physicsBody(nullptr)
, _physicsScaleStartX(1.0f)
, _physicsScaleStartY(1.0f)
, _physicsRotation(0.0f)
, _physicsTransformDirty(true)
#endif
, _displayedOpacity(255)
, _realOpacity(255)
@ -330,13 +331,6 @@ void Node::setRotation(float rotation)
_rotationZ_X = _rotationZ_Y = rotation;
_transformUpdated = _transformDirty = _inverseDirty = true;
#if CC_USE_PHYSICS
if (!_physicsBody || !_physicsBody->_rotationResetTag)
{
updatePhysicsBodyRotation(getScene());
}
#endif
updateRotationQuat();
}
@ -472,16 +466,6 @@ void Node::setScale(float scale)
_scaleX = _scaleY = _scaleZ = scale;
_transformUpdated = _transformDirty = _inverseDirty = true;
#if CC_USE_PHYSICS
if(g_physicsSceneCount == 0)
return;
auto scene = getScene();
if (!scene || scene->getPhysicsWorld())
{
updatePhysicsBodyTransform(scene);
}
#endif
}
/// scaleX getter
@ -499,17 +483,6 @@ void Node::setScale(float scaleX,float scaleY)
_scaleX = scaleX;
_scaleY = scaleY;
_transformUpdated = _transformDirty = _inverseDirty = true;
#if CC_USE_PHYSICS
if(g_physicsSceneCount == 0)
return;
auto scene = getScene();
if (!scene || scene->getPhysicsWorld())
{
updatePhysicsBodyTransform(scene);
}
#endif
}
/// scaleX setter
@ -520,17 +493,6 @@ void Node::setScaleX(float scaleX)
_scaleX = scaleX;
_transformUpdated = _transformDirty = _inverseDirty = true;
#if CC_USE_PHYSICS
if(g_physicsSceneCount == 0)
return;
auto scene = getScene();
if (!scene || scene->getPhysicsWorld())
{
updatePhysicsBodyTransform(scene);
}
#endif
}
/// scaleY getter
@ -570,17 +532,6 @@ void Node::setScaleY(float scaleY)
_scaleY = scaleY;
_transformUpdated = _transformDirty = _inverseDirty = true;
#if CC_USE_PHYSICS
if (g_physicsSceneCount == 0)
return;
auto scene = getScene();
if (!scene || scene->getPhysicsWorld())
{
updatePhysicsBodyTransform(scene);
}
#endif
}
@ -612,13 +563,6 @@ void Node::setPosition(float x, float y)
_transformUpdated = _transformDirty = _inverseDirty = true;
_usingNormalizedPosition = false;
#if CC_USE_PHYSICS
if (!_physicsBody || !_physicsBody->_positionResetTag)
{
updatePhysicsBodyPosition(getScene());
}
#endif
}
void Node::setPosition3D(const Vec3& position)
@ -1076,7 +1020,6 @@ void Node::addChildHelper(Node* child, int localZOrder, int tag, const std::stri
auto scene = this->getScene();
if (scene && scene->getPhysicsWorld())
{
child->updatePhysicsBodyTransform(scene);
scene->addChildToPhysicsWorld(child);
}
#endif
@ -1301,6 +1244,12 @@ void Node::visit()
uint32_t Node::processParentFlags(const Mat4& parentTransform, uint32_t parentFlags)
{
#if CC_USE_PHYSICS
if (_physicsBody && _updateTransformFromPhysics)
{
updateTransformFromPhysics(parentTransform, parentFlags);
}
#endif
if(_usingNormalizedPosition)
{
CCASSERT(_parent, "setNormalizedPosition() doesn't work with orphan nodes");
@ -2023,87 +1972,6 @@ void Node::removeAllComponents()
// MARK: Physics
void Node::updatePhysicsBodyTransform(Scene* scene)
{
updatePhysicsBodyScale(scene);
updatePhysicsBodyPosition(scene);
updatePhysicsBodyRotation(scene);
}
void Node::updatePhysicsBodyPosition(Scene* scene)
{
if (_physicsBody != nullptr)
{
if (scene && scene->getPhysicsWorld())
{
Vec2 pos = _parent == scene ? _position : scene->convertToNodeSpace(_parent->convertToWorldSpace(_position));
_physicsBody->setPosition(pos);
}
else
{
_physicsBody->setPosition(_position);
}
}
for (Node* child : _children)
{
child->updatePhysicsBodyPosition(scene);
}
}
void Node::updatePhysicsBodyRotation(Scene* scene)
{
if (_physicsBody != nullptr)
{
if (scene != nullptr && scene->getPhysicsWorld() != nullptr)
{
float rotation = _rotationZ_X;
for (Node* parent = _parent; parent != scene; parent = parent->_parent)
{
rotation += parent->getRotation();
}
_physicsBody->setRotation(rotation);
}
else
{
_physicsBody->setRotation(_rotationZ_X);
}
}
for (auto child : _children)
{
child->updatePhysicsBodyRotation(scene);
child->updatePhysicsBodyPosition(scene);
}
}
void Node::updatePhysicsBodyScale(Scene* scene)
{
if (_physicsBody != nullptr)
{
if (scene != nullptr && scene->getPhysicsWorld() != nullptr)
{
float scaleX = _scaleX / _physicsScaleStartX;
float scaleY = _scaleY / _physicsScaleStartY;
for (Node* parent = _parent; parent != scene; parent = parent->_parent)
{
scaleX *= parent->_scaleX;
scaleY *= parent->_scaleY;
}
_physicsBody->setScale(scaleX, scaleY);
}
else
{
_physicsBody->setScale(_scaleX / _physicsScaleStartX, _scaleY / _physicsScaleStartY);
}
}
for (const auto& child : _children)
{
child->updatePhysicsBodyScale(scene);
}
}
void Node::setPhysicsBody(PhysicsBody* body)
{
if (_physicsBody == body)
@ -2111,9 +1979,17 @@ void Node::setPhysicsBody(PhysicsBody* body)
return;
}
if (body != nullptr)
if (_physicsBody)
{
if (body->getNode() != nullptr)
_physicsBody->removeFromWorld();
_physicsBody->_node = nullptr;
_physicsBody->release();
_physicsBody = nullptr;
}
if (body)
{
if (body->getNode())
{
body->getNode()->setPhysicsBody(nullptr);
}
@ -2128,52 +2004,65 @@ void Node::setPhysicsBody(PhysicsBody* body)
CCLOG("Node warning: setPhysicsBody sets anchor point to Vec2::ANCHOR_MIDDLE.");
setAnchorPoint(Vec2::ANCHOR_MIDDLE);
}
}
if (_physicsBody != nullptr)
{
PhysicsWorld* world = _physicsBody->getWorld();
_physicsBody->removeFromWorld();
_physicsBody->_node = nullptr;
_physicsBody->release();
if (world != nullptr && body != nullptr)
{
world->addBody(body);
}
}
_physicsBody = body;
_physicsScaleStartX = _scaleX;
_physicsScaleStartY = _scaleY;
if (body != nullptr)
{
Node* node;
Scene* scene = nullptr;
for (node = this->getParent(); node != nullptr; node = node->getParent())
{
Scene* tmpScene = dynamic_cast<Scene*>(node);
if (tmpScene != nullptr && tmpScene->getPhysicsWorld() != nullptr)
{
scene = tmpScene;
break;
}
}
if (scene != nullptr)
auto scene = getScene();
if (scene && scene->getPhysicsWorld())
{
_physicsTransformDirty = true;
scene->getPhysicsWorld()->addBody(body);
}
updatePhysicsBodyTransform(scene);
}
}
PhysicsBody* Node::getPhysicsBody() const
void Node::updatePhysicsBodyTransform(Scene* scene, const Mat4& parentTransform, uint32_t parentFlags, float parentScaleX, float parentScaleY)
{
return _physicsBody;
_updateTransformFromPhysics = false;
auto flags = processParentFlags(parentTransform, parentFlags);
_updateTransformFromPhysics = true;
auto scaleX = parentScaleX * _scaleX;
auto scaleY = parentScaleY * _scaleY;
if (_parent)
{
_physicsRotation = _parent->_physicsRotation + _rotationZ_X;
}
if (_physicsBody && ((flags & FLAGS_DIRTY_MASK) || _physicsTransformDirty))
{
_physicsTransformDirty = false;
Vec3 vec3(_position.x, _position.y, 0);
Vec3 ret;
parentTransform.transformPoint(vec3, &ret);
_physicsBody->setPosition(Vec2(ret.x, ret.y));
_physicsBody->setScale(scaleX / _physicsScaleStartX, scaleY / _physicsScaleStartY);
_physicsBody->setRotation(_physicsRotation);
}
for (auto node : _children)
{
node->updatePhysicsBodyTransform(scene, _modelViewTransform, flags, scaleX, scaleY);
}
}
void Node::updateTransformFromPhysics(const Mat4& parentTransform, uint32_t parentFlags)
{
auto newPos = _physicsBody->getPosition();
auto& recordPos = _physicsBody->_recordPosition;
if (parentFlags || recordPos.x != newPos.x || recordPos.y != newPos.y)
{
recordPos = newPos;
Vec3 vec3(newPos.x, newPos.y, 0);
Vec3 ret;
parentTransform.getInversed().transformPoint(vec3, &ret);
setPosition(ret.x, ret.y);
}
_physicsRotation = _physicsBody->getRotation();
setRotation(_physicsRotation - _parent->_physicsRotation);
}
#endif //CC_USE_PHYSICS
// MARK: Opacity and Color

View File

@ -1532,13 +1532,16 @@ public:
/**
* get the PhysicsBody the sprite have
*/
PhysicsBody* getPhysicsBody() const;
PhysicsBody* getPhysicsBody() const { return _physicsBody; }
/**
* remove this node from physics world. it will remove all the physics bodies in it's children too.
*/
void removeFromPhysicsWorld();
void updateTransformFromPhysics(const Mat4& parentTransform, uint32_t parentFlags);
virtual void updatePhysicsBodyTransform(Scene* scene, const Mat4& parentTransform, uint32_t parentFlags, float parentScaleX, float parentScaleY);
#endif
// overrides
@ -1612,13 +1615,6 @@ protected:
// update Rotation3D from quaternion
void updateRotation3D();
#if CC_USE_PHYSICS
void updatePhysicsBodyTransform(Scene* layer);
virtual void updatePhysicsBodyPosition(Scene* layer);
virtual void updatePhysicsBodyRotation(Scene* layer);
virtual void updatePhysicsBodyScale(Scene* scene);
#endif // CC_USE_PHYSICS
private:
void addChildHelper(Node* child, int localZOrder, int tag, const std::string &name, bool setTag);
@ -1709,6 +1705,9 @@ protected:
PhysicsBody* _physicsBody; ///< the physicsBody the node have
float _physicsScaleStartX; ///< the scale x value when setPhysicsBody
float _physicsScaleStartY; ///< the scale y value when setPhysicsBody
float _physicsRotation;
bool _physicsTransformDirty;
bool _updateTransformFromPhysics;
#endif
// opacity controls

View File

@ -37,8 +37,6 @@ THE SOFTWARE.
#include "physics/CCPhysicsWorld.h"
#endif
int g_physicsSceneCount = 0;
NS_CC_BEGIN
Scene::Scene()
@ -60,10 +58,6 @@ Scene::Scene()
Scene::~Scene()
{
#if CC_USE_PHYSICS
if (_physicsWorld)
{
g_physicsSceneCount--;
}
CC_SAFE_DELETE(_physicsWorld);
#endif
Director::getInstance()->getEventDispatcher()->removeEventListener(_event);
@ -177,15 +171,6 @@ void Scene::addChild(Node* child, int zOrder, const std::string &name)
addChildToPhysicsWorld(child);
}
void Scene::update(float delta)
{
Node::update(delta);
if (nullptr != _physicsWorld && _physicsWorld->isAutoStep())
{
_physicsWorld->update(delta);
}
}
Scene* Scene::createWithPhysics()
{
Scene *ret = new (std::nothrow) Scene();
@ -212,9 +197,7 @@ bool Scene::initWithPhysics()
this->setContentSize(director->getWinSize());
CC_BREAK_IF(! (_physicsWorld = PhysicsWorld::construct(*this)));
this->scheduleUpdate();
// success
g_physicsSceneCount += 1;
ret = true;
} while (0);
return ret;

View File

@ -108,7 +108,6 @@ private:
public:
virtual void addChild(Node* child, int zOrder, int tag) override;
virtual void addChild(Node* child, int zOrder, const std::string &name) override;
virtual void update(float delta) override;
inline PhysicsWorld* getPhysicsWorld() { return _physicsWorld; }
static Scene *createWithPhysics();

View File

@ -367,7 +367,16 @@ void SpriteBatchNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t f
}
for (const auto &child : _children)
{
#if CC_USE_PHYSICS
auto physicsBody = child->getPhysicsBody();
if (physicsBody)
{
child->updateTransformFromPhysics(transform, flags);
}
#endif
child->updateTransform();
}
_batchCommand.init(
_globalZOrder,

View File

@ -65,6 +65,10 @@ THE SOFTWARE.
#include "CCScriptSupport.h"
#endif
#if CC_USE_PHYSICS
#include "physics/CCPhysicsWorld.h"
#endif
/**
Position of the FPS
@ -265,12 +269,6 @@ void Director::drawScene()
// calculate "global" dt
calculateDeltaTime();
// skip one flame when _deltaTime equal to zero.
if(_deltaTime < FLT_EPSILON)
{
return;
}
if (_openGLView)
{
_openGLView->pollEvents();
@ -297,6 +295,13 @@ void Director::drawScene()
if (_runningScene)
{
#if CC_USE_PHYSICS
auto physicsWorld = _runningScene->getPhysicsWorld();
if (physicsWorld && physicsWorld->isAutoStep())
{
physicsWorld->update(_deltaTime, false);
}
#endif
//clear draw stats
_renderer->clearDrawStats();

View File

@ -68,9 +68,8 @@ PhysicsBody::PhysicsBody()
, _linearDamping(0.0f)
, _angularDamping(0.0f)
, _tag(0)
, _positionResetTag(false)
, _rotationResetTag(false)
, _rotationOffset(0)
, _recordPosition(Vec2::ZERO)
{
}
@ -333,6 +332,7 @@ void PhysicsBody::setGravityEnable(bool enable)
void PhysicsBody::setPosition(const Vec2& position)
{
_recordPosition = position;
cpBodySetPos(_cpBody, PhysicsHelper::point2cpv(position + _positionOffset));
}
@ -341,14 +341,6 @@ void PhysicsBody::setRotation(float rotation)
cpBodySetAngle(_cpBody, -PhysicsHelper::float2cpfloat((rotation + _rotationOffset) * (M_PI / 180.0f)));
}
void PhysicsBody::setScale(float scale)
{
for (auto shape : _shapes)
{
shape->setScale(scale);
}
}
void PhysicsBody::setScale(float scaleX, float scaleY)
{
for (auto shape : _shapes)
@ -357,22 +349,6 @@ void PhysicsBody::setScale(float scaleX, float scaleY)
}
}
void PhysicsBody::setScaleX(float scaleX)
{
for (auto shape : _shapes)
{
shape->setScaleX(scaleX);
}
}
void PhysicsBody::setScaleY(float scaleY)
{
for (auto shape : _shapes)
{
shape->setScaleY(scaleY);
}
}
Vec2 PhysicsBody::getPosition() const
{
cpVect vec = cpBodyGetPos(_cpBody);
@ -402,7 +378,7 @@ PhysicsShape* PhysicsBody::addShape(PhysicsShape* shape, bool addMassAndMoment/*
addMoment(shape->getMoment());
}
if (_world != nullptr)
if (_world && _cpBody->CP_PRIVATE(space))
{
_world->addShape(shape);
}
@ -764,30 +740,8 @@ void PhysicsBody::setResting(bool rest) const
void PhysicsBody::update(float delta)
{
if (_node != nullptr)
if (_node)
{
for (auto shape : _shapes)
{
shape->update(delta);
}
Node* parent = _node->getParent();
Node* scene = &_world->getScene();
Vec2 position = parent != scene ? parent->convertToNodeSpace(scene->convertToWorldSpace(getPosition())) : getPosition();
float rotation = getRotation();
for (; parent != scene; parent = parent->getParent())
{
rotation -= parent->getRotation();
}
_positionResetTag = true;
_rotationResetTag = true;
_node->setPosition(position);
_node->setRotation(rotation);
_positionResetTag = false;
_rotationResetTag = false;
// damping compute
if (_isDamping && _dynamic && !isResting())
{

View File

@ -306,10 +306,7 @@ protected:
virtual void setPosition(const Vec2& position);
virtual void setRotation(float rotation);
virtual void setScale(float scale);
virtual void setScale(float scaleX, float scaleY);
virtual void setScaleX(float scaleX);
virtual void setScaleY(float scaleY);
void update(float delta);
@ -341,8 +338,7 @@ protected:
float _angularDamping;
int _tag;
bool _positionResetTag; /// To avoid reset the body position when body invoke Node::setPosition().
bool _rotationResetTag; /// To avoid reset the body rotation when body invoke Node::setRotation().
Vec2 _recordPosition;
Vec2 _positionOffset;
float _rotationOffset;

View File

@ -40,7 +40,9 @@ PhysicsJoint::PhysicsJoint()
, _enable(false)
, _collisionEnable(true)
, _destoryMark(false)
, _initDirty(true)
, _tag(0)
, _maxForce(PHYSICS_INFINITY)
{
}
@ -50,10 +52,11 @@ PhysicsJoint::~PhysicsJoint()
// reset the shapes collision group
setCollisionEnable(true);
for (auto constraint : _cpConstraints)
for (cpConstraint* joint : _cpConstraints)
{
cpConstraintFree(constraint);
cpConstraintFree(joint);
}
_cpConstraints.clear();
}
bool PhysicsJoint::init(cocos2d::PhysicsBody *a, cocos2d::PhysicsBody *b)
@ -64,8 +67,8 @@ bool PhysicsJoint::init(cocos2d::PhysicsBody *a, cocos2d::PhysicsBody *b)
CCASSERT(a != b, "the two bodies are equal");
_bodyA = a;
_bodyA->_joints.push_back(this);
_bodyB = b;
_bodyA->_joints.push_back(this);
_bodyB->_joints.push_back(this);
return true;
@ -74,30 +77,47 @@ bool PhysicsJoint::init(cocos2d::PhysicsBody *a, cocos2d::PhysicsBody *b)
return false;
}
bool PhysicsJoint::initJoint()
{
bool ret = !_initDirty;
while (_initDirty)
{
ret = createConstraints();
CC_BREAK_IF(!ret);
for (auto subjoint : _cpConstraints)
{
subjoint->maxForce = _maxForce;
subjoint->errorBias = cpfpow(1.0f - 0.15f, 60.0f);
cpSpaceAddConstraint(_world->_cpSpace, subjoint);
}
_initDirty = false;
ret = true;
}
return ret;
}
void PhysicsJoint::setEnable(bool enable)
{
if (_enable != enable)
{
_enable = enable;
if (_world != nullptr)
if (_world)
{
if (enable)
{
_world->addJointOrDelay(this);
}else
_world->addJoint(this);
}
else
{
_world->removeJointOrDelay(this);
_world->removeJoint(this, false);
}
}
}
}
Node* PhysicsJoint::getBodyNode(PhysicsBody* body) const
{
return body->_node;
}
void PhysicsJoint::setCollisionEnable(bool enable)
{
if (_collisionEnable != enable)
@ -114,51 +134,22 @@ void PhysicsJoint::removeFormWorld()
}
}
void PhysicsJoint::destroy(PhysicsJoint* joint)
{
if (joint!= nullptr)
{
// remove the joint and delete it.
if (joint->_world != nullptr)
{
joint->_world->removeJoint(joint, true);
}
else
{
if (joint->_bodyA != nullptr)
{
joint->_bodyA->removeJoint(joint);
}
if (joint->_bodyB != nullptr)
{
joint->_bodyB->removeJoint(joint);
}
delete joint;
}
}
}
void PhysicsJoint::setMaxForce(float force)
{
_maxForce = force;
for (auto joint : _cpConstraints)
{
joint->maxForce = PhysicsHelper::float2cpfloat(force);
}
}
float PhysicsJoint::getMaxForce() const
{
return PhysicsHelper::cpfloat2float(_cpConstraints.front()->maxForce);
}
PhysicsJointFixed* PhysicsJointFixed::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr)
{
PhysicsJointFixed* joint = new (std::nothrow) PhysicsJointFixed();
auto joint = new (std::nothrow) PhysicsJointFixed();
if (joint && joint->init(a, b, anchr))
if (joint && joint->init(a, b))
{
joint->_anchr = anchr;
return joint;
}
@ -166,27 +157,25 @@ PhysicsJointFixed* PhysicsJointFixed::construct(PhysicsBody* a, PhysicsBody* b,
return nullptr;
}
bool PhysicsJointFixed::init(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr)
bool PhysicsJointFixed::createConstraints()
{
do
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
getBodyNode(a)->setPosition(anchr);
getBodyNode(b)->setPosition(anchr);
_bodyA->getNode()->setPosition(_anchr);
_bodyB->getNode()->setPosition(_anchr);
// add a pivot joint to fixed two body together
auto constraint = cpPivotJointNew(a->getCPBody(), b->getCPBody(),
PhysicsHelper::point2cpv(anchr));
CC_BREAK_IF(constraint == nullptr);
_cpConstraints.push_back(constraint);
auto joint = cpPivotJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(),
PhysicsHelper::point2cpv(_anchr));
CC_BREAK_IF(joint == nullptr);
_cpConstraints.push_back(joint);
// add a gear joint to make two body have the same rotation.
constraint = cpGearJointNew(a->getCPBody(), b->getCPBody(), 0, 1);
CC_BREAK_IF(constraint == nullptr);
_cpConstraints.push_back(constraint);
joint = cpGearJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), 0, 1);
CC_BREAK_IF(joint == nullptr);
_cpConstraints.push_back(joint);
setCollisionEnable(false);
_collisionEnable = false;
return true;
} while (false);
@ -194,12 +183,14 @@ bool PhysicsJointFixed::init(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr)
return false;
}
PhysicsJointPin* PhysicsJointPin::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr)
PhysicsJointPin* PhysicsJointPin::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& pivot)
{
PhysicsJointPin* joint = new (std::nothrow) PhysicsJointPin();
auto joint = new (std::nothrow) PhysicsJointPin();
if (joint && joint->init(a, b, anchr))
if (joint && joint->init(a, b))
{
joint->_anchr1 = pivot;
joint->_useSpecificAnchr = false;
return joint;
}
@ -207,17 +198,41 @@ PhysicsJointPin* PhysicsJointPin::construct(PhysicsBody* a, PhysicsBody* b, cons
return nullptr;
}
bool PhysicsJointPin::init(PhysicsBody *a, PhysicsBody *b, const Vec2& anchr)
PhysicsJointPin* PhysicsJointPin::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2)
{
auto joint = new (std::nothrow) PhysicsJointPin();
if (joint && joint->init(a, b))
{
joint->_anchr1 = anchr1;
joint->_anchr2 = anchr2;
joint->_useSpecificAnchr = true;
return joint;
}
CC_SAFE_DELETE(joint);
return nullptr;
}
bool PhysicsJointPin::createConstraints()
{
do
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
auto constraint = cpPivotJointNew(a->getCPBody(), b->getCPBody(),
PhysicsHelper::point2cpv(anchr));
cpConstraint* joint = nullptr;
if (_useSpecificAnchr)
{
joint = cpPivotJointNew2(_bodyA->getCPBody(), _bodyB->getCPBody(),
PhysicsHelper::point2cpv(_anchr1), PhysicsHelper::point2cpv(_anchr2));
}
else
{
joint = cpPivotJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(),
PhysicsHelper::point2cpv(_anchr1));
}
CC_BREAK_IF(constraint == nullptr);
_cpConstraints.push_back(constraint);
CC_BREAK_IF(joint == nullptr);
_cpConstraints.push_back(joint);
return true;
} while (false);
@ -227,10 +242,15 @@ bool PhysicsJointPin::init(PhysicsBody *a, PhysicsBody *b, const Vec2& anchr)
PhysicsJointLimit* PhysicsJointLimit::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2, float min, float max)
{
PhysicsJointLimit* joint = new (std::nothrow) PhysicsJointLimit();
auto joint = new (std::nothrow) PhysicsJointLimit();
if (joint && joint->init(a, b, anchr1, anchr2, min, max))
if (joint && joint->init(a, b))
{
joint->_anchr1 = anchr1;
joint->_anchr2 = anchr2;
joint->_min = min;
joint->_max = max;
return joint;
}
@ -243,21 +263,18 @@ PhysicsJointLimit* PhysicsJointLimit::construct(PhysicsBody* a, PhysicsBody* b,
return construct(a, b, anchr1, anchr2, 0, b->local2World(anchr1).getDistance(a->local2World(anchr2)));
}
bool PhysicsJointLimit::init(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2, float min, float max)
bool PhysicsJointLimit::createConstraints()
{
do
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
auto joint = cpSlideJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(),
PhysicsHelper::point2cpv(_anchr1),
PhysicsHelper::point2cpv(_anchr2),
PhysicsHelper::float2cpfloat(_min),
PhysicsHelper::float2cpfloat(_max));
auto constraint = cpSlideJointNew(a->getCPBody(), b->getCPBody(),
PhysicsHelper::point2cpv(anchr1),
PhysicsHelper::point2cpv(anchr2),
PhysicsHelper::float2cpfloat(min),
PhysicsHelper::float2cpfloat(max));
CC_BREAK_IF(constraint == nullptr);
_cpConstraints.push_back(constraint);
CC_BREAK_IF(joint == nullptr);
_cpConstraints.push_back(joint);
return true;
} while (false);
@ -307,10 +324,13 @@ void PhysicsJointLimit::setAnchr2(const Vec2& anchr)
PhysicsJointDistance* PhysicsJointDistance::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2)
{
PhysicsJointDistance* joint = new (std::nothrow) PhysicsJointDistance();
auto joint = new (std::nothrow) PhysicsJointDistance();
if (joint && joint->init(a, b, anchr1, anchr2))
if (joint && joint->init(a, b))
{
joint->_anchr1 = anchr1;
joint->_anchr2 = anchr2;
return joint;
}
@ -318,20 +338,16 @@ PhysicsJointDistance* PhysicsJointDistance::construct(PhysicsBody* a, PhysicsBod
return nullptr;
}
bool PhysicsJointDistance::init(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2)
bool PhysicsJointDistance::createConstraints()
{
do
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
auto constraint = cpPinJointNew(a->getCPBody(),
b->getCPBody(),
PhysicsHelper::point2cpv(anchr1),
PhysicsHelper::point2cpv(anchr2));
CC_BREAK_IF(constraint == nullptr);
_cpConstraints.push_back(constraint);
auto joint = cpPinJointNew(_bodyA->getCPBody(),
_bodyB->getCPBody(),
PhysicsHelper::point2cpv(_anchr1),
PhysicsHelper::point2cpv(_anchr2));
CC_BREAK_IF(joint == nullptr);
_cpConstraints.push_back(joint);
return true;
} while (false);
@ -351,10 +367,15 @@ void PhysicsJointDistance::setDistance(float distance)
PhysicsJointSpring* PhysicsJointSpring::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2, float stiffness, float damping)
{
PhysicsJointSpring* joint = new (std::nothrow) PhysicsJointSpring();
auto joint = new (std::nothrow) PhysicsJointSpring();
if (joint && joint->init(a, b, anchr1, anchr2, stiffness, damping))
if (joint && joint->init(a, b))
{
joint->_anchr1 = anchr1;
joint->_anchr2 = anchr2;
joint->_stiffness = stiffness;
joint->_damping = damping;
return joint;
}
@ -362,22 +383,19 @@ PhysicsJointSpring* PhysicsJointSpring::construct(PhysicsBody* a, PhysicsBody* b
return nullptr;
}
bool PhysicsJointSpring::init(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2, float stiffness, float damping)
bool PhysicsJointSpring::createConstraints()
{
do {
CC_BREAK_IF(!PhysicsJoint::init(a, b));
auto joint = cpDampedSpringNew(_bodyA->getCPBody(),
_bodyB->getCPBody(),
PhysicsHelper::point2cpv(_anchr1),
PhysicsHelper::point2cpv(_anchr2),
PhysicsHelper::float2cpfloat(_bodyB->local2World(_anchr1).getDistance(_bodyA->local2World(_anchr2))),
PhysicsHelper::float2cpfloat(_stiffness),
PhysicsHelper::float2cpfloat(_damping));
auto constraint = cpDampedSpringNew(a->getCPBody(),
b->getCPBody(),
PhysicsHelper::point2cpv(anchr1),
PhysicsHelper::point2cpv(anchr2),
PhysicsHelper::float2cpfloat(_bodyB->local2World(anchr1).getDistance(_bodyA->local2World(anchr2))),
PhysicsHelper::float2cpfloat(stiffness),
PhysicsHelper::float2cpfloat(damping));
CC_BREAK_IF(constraint == nullptr);
_cpConstraints.push_back(constraint);
CC_BREAK_IF(joint == nullptr);
_cpConstraints.push_back(joint);
return true;
} while (false);
@ -437,10 +455,14 @@ void PhysicsJointSpring::setDamping(float damping)
PhysicsJointGroove* PhysicsJointGroove::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& grooveA, const Vec2& grooveB, const Vec2& anchr2)
{
PhysicsJointGroove* joint = new (std::nothrow) PhysicsJointGroove();
auto joint = new (std::nothrow) PhysicsJointGroove();
if (joint && joint->init(a, b, grooveA, grooveB, anchr2))
if (joint && joint->init(a, b))
{
joint->_grooveA = grooveA;
joint->_grooveB = grooveB;
joint->_anchr2 = anchr2;
return joint;
}
@ -448,20 +470,17 @@ PhysicsJointGroove* PhysicsJointGroove::construct(PhysicsBody* a, PhysicsBody* b
return nullptr;
}
bool PhysicsJointGroove::init(PhysicsBody* a, PhysicsBody* b, const Vec2& grooveA, const Vec2& grooveB, const Vec2& anchr2)
bool PhysicsJointGroove::createConstraints()
{
do {
CC_BREAK_IF(!PhysicsJoint::init(a, b));
auto joint = cpGrooveJointNew(_bodyA->getCPBody(),
_bodyB->getCPBody(),
PhysicsHelper::point2cpv(_grooveA),
PhysicsHelper::point2cpv(_grooveB),
PhysicsHelper::point2cpv(_anchr2));
auto constraint = cpGrooveJointNew(a->getCPBody(),
b->getCPBody(),
PhysicsHelper::point2cpv(grooveA),
PhysicsHelper::point2cpv(grooveB),
PhysicsHelper::point2cpv(anchr2));
CC_BREAK_IF(constraint == nullptr);
_cpConstraints.push_back(constraint);
CC_BREAK_IF(joint == nullptr);
_cpConstraints.push_back(joint);
return true;
} while (false);
@ -501,10 +520,13 @@ void PhysicsJointGroove::setAnchr2(const Vec2& anchr2)
PhysicsJointRotarySpring* PhysicsJointRotarySpring::construct(PhysicsBody* a, PhysicsBody* b, float stiffness, float damping)
{
PhysicsJointRotarySpring* joint = new (std::nothrow) PhysicsJointRotarySpring();
auto joint = new (std::nothrow) PhysicsJointRotarySpring();
if (joint && joint->init(a, b, stiffness, damping))
if (joint && joint->init(a, b))
{
joint->_stiffness = stiffness;
joint->_damping = damping;
return joint;
}
@ -512,20 +534,17 @@ PhysicsJointRotarySpring* PhysicsJointRotarySpring::construct(PhysicsBody* a, Ph
return nullptr;
}
bool PhysicsJointRotarySpring::init(PhysicsBody* a, PhysicsBody* b, float stiffness, float damping)
bool PhysicsJointRotarySpring::createConstraints()
{
do {
CC_BREAK_IF(!PhysicsJoint::init(a, b));
auto constraint = cpDampedRotarySpringNew(a->getCPBody(),
b->getCPBody(),
auto joint = cpDampedRotarySpringNew(_bodyA->getCPBody(),
_bodyB->getCPBody(),
PhysicsHelper::float2cpfloat(_bodyB->getRotation() - _bodyA->getRotation()),
PhysicsHelper::float2cpfloat(stiffness),
PhysicsHelper::float2cpfloat(damping));
PhysicsHelper::float2cpfloat(_stiffness),
PhysicsHelper::float2cpfloat(_damping));
CC_BREAK_IF(constraint == nullptr);
_cpConstraints.push_back(constraint);
CC_BREAK_IF(joint == nullptr);
_cpConstraints.push_back(joint);
return true;
} while (false);
@ -565,10 +584,13 @@ void PhysicsJointRotarySpring::setDamping(float damping)
PhysicsJointRotaryLimit* PhysicsJointRotaryLimit::construct(PhysicsBody* a, PhysicsBody* b, float min, float max)
{
PhysicsJointRotaryLimit* joint = new (std::nothrow) PhysicsJointRotaryLimit();
auto joint = new (std::nothrow) PhysicsJointRotaryLimit();
if (joint && joint->init(a, b, min, max))
if (joint && joint->init(a, b))
{
joint->_min = min;
joint->_max = max;
return joint;
}
@ -581,20 +603,17 @@ PhysicsJointRotaryLimit* PhysicsJointRotaryLimit::construct(PhysicsBody* a, Phys
return construct(a, b, 0.0f, 0.0f);
}
bool PhysicsJointRotaryLimit::init(PhysicsBody* a, PhysicsBody* b, float min, float max)
bool PhysicsJointRotaryLimit::createConstraints()
{
do
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
auto joint = cpRotaryLimitJointNew(_bodyA->getCPBody(),
_bodyB->getCPBody(),
PhysicsHelper::float2cpfloat(_min),
PhysicsHelper::float2cpfloat(_max));
auto constraint = cpRotaryLimitJointNew(a->getCPBody(),
b->getCPBody(),
PhysicsHelper::float2cpfloat(min),
PhysicsHelper::float2cpfloat(max));
CC_BREAK_IF(constraint == nullptr);
_cpConstraints.push_back(constraint);
CC_BREAK_IF(joint == nullptr);
_cpConstraints.push_back(joint);
return true;
} while (false);
@ -624,10 +643,13 @@ void PhysicsJointRotaryLimit::setMax(float max)
PhysicsJointRatchet* PhysicsJointRatchet::construct(PhysicsBody* a, PhysicsBody* b, float phase, float ratchet)
{
PhysicsJointRatchet* joint = new (std::nothrow) PhysicsJointRatchet();
auto joint = new (std::nothrow) PhysicsJointRatchet();
if (joint && joint->init(a, b, phase, ratchet))
if (joint && joint->init(a, b))
{
joint->_phase = phase;
joint->_ratchet = ratchet;
return joint;
}
@ -635,20 +657,17 @@ PhysicsJointRatchet* PhysicsJointRatchet::construct(PhysicsBody* a, PhysicsBody*
return nullptr;
}
bool PhysicsJointRatchet::init(PhysicsBody* a, PhysicsBody* b, float phase, float ratchet)
bool PhysicsJointRatchet::createConstraints()
{
do
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
auto joint = cpRatchetJointNew(_bodyA->getCPBody(),
_bodyB->getCPBody(),
PhysicsHelper::float2cpfloat(_phase),
PhysicsHelper::cpfloat2float(_ratchet));
auto constraint = cpRatchetJointNew(a->getCPBody(),
b->getCPBody(),
PhysicsHelper::float2cpfloat(phase),
PhysicsHelper::cpfloat2float(ratchet));
CC_BREAK_IF(constraint == nullptr);
_cpConstraints.push_back(constraint);
CC_BREAK_IF(joint == nullptr);
_cpConstraints.push_back(joint);
return true;
} while (false);
@ -686,12 +705,15 @@ void PhysicsJointRatchet::setRatchet(float ratchet)
cpRatchetJointSetRatchet(_cpConstraints.front(), PhysicsHelper::float2cpfloat(ratchet));
}
PhysicsJointGear* PhysicsJointGear::construct(PhysicsBody* a, PhysicsBody* b, float phase, float ratchet)
PhysicsJointGear* PhysicsJointGear::construct(PhysicsBody* a, PhysicsBody* b, float phase, float ratio)
{
PhysicsJointGear* joint = new (std::nothrow) PhysicsJointGear();
auto joint = new (std::nothrow) PhysicsJointGear();
if (joint && joint->init(a, b, phase, ratchet))
if (joint && joint->init(a, b))
{
joint->_phase = phase;
joint->_ratio = ratio;
return joint;
}
@ -699,20 +721,17 @@ PhysicsJointGear* PhysicsJointGear::construct(PhysicsBody* a, PhysicsBody* b, fl
return nullptr;
}
bool PhysicsJointGear::init(PhysicsBody* a, PhysicsBody* b, float phase, float ratio)
bool PhysicsJointGear::createConstraints()
{
do
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
auto joint = cpGearJointNew(_bodyA->getCPBody(),
_bodyB->getCPBody(),
PhysicsHelper::float2cpfloat(_phase),
PhysicsHelper::float2cpfloat(_ratio));
auto constraint = cpGearJointNew(a->getCPBody(),
b->getCPBody(),
PhysicsHelper::float2cpfloat(phase),
PhysicsHelper::float2cpfloat(ratio));
CC_BREAK_IF(constraint == nullptr);
_cpConstraints.push_back(constraint);
CC_BREAK_IF(joint == nullptr);
_cpConstraints.push_back(joint);
return true;
} while (false);
@ -742,10 +761,12 @@ void PhysicsJointGear::setRatio(float ratio)
PhysicsJointMotor* PhysicsJointMotor::construct(PhysicsBody* a, PhysicsBody* b, float rate)
{
PhysicsJointMotor* joint = new (std::nothrow) PhysicsJointMotor();
auto joint = new (std::nothrow) PhysicsJointMotor();
if (joint && joint->init(a, b, rate))
if (joint && joint->init(a, b))
{
joint->_rate = rate;
return joint;
}
@ -753,19 +774,16 @@ PhysicsJointMotor* PhysicsJointMotor::construct(PhysicsBody* a, PhysicsBody* b,
return nullptr;
}
bool PhysicsJointMotor::init(PhysicsBody* a, PhysicsBody* b, float rate)
bool PhysicsJointMotor::createConstraints()
{
do
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
auto joint = cpSimpleMotorNew(_bodyA->getCPBody(),
_bodyB->getCPBody(),
PhysicsHelper::float2cpfloat(_rate));
auto constraint = cpSimpleMotorNew(a->getCPBody(),
b->getCPBody(),
PhysicsHelper::float2cpfloat(rate));
CC_BREAK_IF(constraint == nullptr);
_cpConstraints.push_back(constraint);
CC_BREAK_IF(joint == nullptr);
_cpConstraints.push_back(joint);
return true;
} while (false);

View File

@ -62,27 +62,30 @@ public:
void setCollisionEnable(bool enable);
/** Remove the joint from the world */
void removeFormWorld();
/** Distory the joint*/
static void destroy(PhysicsJoint* joint);
/** Set the max force between two bodies */
void setMaxForce(float force);
/** Get the max force setting */
float getMaxForce() const;
float getMaxForce() const { return _maxForce; }
protected:
bool init(PhysicsBody* a, PhysicsBody* b);
Node* getBodyNode(PhysicsBody* body) const;
protected:
bool initJoint();
virtual bool createConstraints() { return false; }
std::vector<cpConstraint*> _cpConstraints;
PhysicsBody* _bodyA;
PhysicsBody* _bodyB;
PhysicsWorld* _world;
std::vector<cpConstraint*> _cpConstraints;
bool _enable;
bool _collisionEnable;
bool _destoryMark;
int _tag;
float _maxForce;
bool _initDirty;
friend class PhysicsBody;
friend class PhysicsWorld;
@ -97,12 +100,13 @@ class CC_DLL PhysicsJointFixed : public PhysicsJoint
public:
static PhysicsJointFixed* construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr);
virtual bool createConstraints() override;
protected:
PhysicsJointFixed() {}
virtual ~PhysicsJointFixed() {}
Vec2 _anchr;
};
/*
@ -123,12 +127,16 @@ public:
float getMax() const;
void setMax(float max);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2, float min, float max);
virtual bool createConstraints() override;
protected:
PhysicsJointLimit() {}
virtual ~PhysicsJointLimit() {}
Vec2 _anchr1;
Vec2 _anchr2;
float _min;
float _max;
};
/*
@ -137,14 +145,18 @@ protected:
class CC_DLL PhysicsJointPin : public PhysicsJoint
{
public:
static PhysicsJointPin* construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr);
static PhysicsJointPin* construct(PhysicsBody* a, PhysicsBody* b, const Vec2& pivot);
static PhysicsJointPin* construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr);
virtual bool createConstraints() override;
protected:
PhysicsJointPin() {}
virtual ~PhysicsJointPin() {}
bool _useSpecificAnchr;
Vec2 _anchr1;
Vec2 _anchr2;
};
/** Set the fixed distance with two bodies */
@ -155,13 +167,14 @@ public:
float getDistance() const;
void setDistance(float distance);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2);
virtual bool createConstraints() override;
protected:
PhysicsJointDistance() {}
virtual ~PhysicsJointDistance() {}
Vec2 _anchr1;
Vec2 _anchr2;
};
/** Connecting two physics bodies together with a spring. */
@ -179,13 +192,16 @@ public:
void setStiffness(float stiffness);
float getDamping() const;
void setDamping(float damping);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2, float stiffness, float damping);
virtual bool createConstraints() override;
protected:
PhysicsJointSpring() {}
virtual ~PhysicsJointSpring() {}
Vec2 _anchr1;
Vec2 _anchr2;
float _stiffness;
float _damping;
};
/** Attach body a to a line, and attach body b to a dot */
@ -200,13 +216,15 @@ public:
void setGrooveB(const Vec2& grooveB);
Vec2 getAnchr2() const;
void setAnchr2(const Vec2& anchr2);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Vec2& grooveA, const Vec2& grooveB, const Vec2& anchr);
virtual bool createConstraints() override;
protected:
PhysicsJointGroove() {}
virtual ~PhysicsJointGroove() {}
Vec2 _grooveA;
Vec2 _grooveB;
Vec2 _anchr2;
};
/** Likes a spring joint, but works with rotary */
@ -221,13 +239,14 @@ public:
void setStiffness(float stiffness);
float getDamping() const;
void setDamping(float damping);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, float stiffness, float damping);
virtual bool createConstraints() override;
protected:
PhysicsJointRotarySpring() {}
virtual ~PhysicsJointRotarySpring() {}
float _stiffness;
float _damping;
};
/** Likes a limit joint, but works with rotary */
@ -241,13 +260,14 @@ public:
void setMin(float min);
float getMax() const;
void setMax(float max);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, float min, float max);
virtual bool createConstraints() override;
protected:
PhysicsJointRotaryLimit() {}
virtual ~PhysicsJointRotaryLimit() {}
float _min;
float _max;
};
/** Works like a socket wrench. */
@ -262,13 +282,14 @@ public:
void setPhase(float phase);
float getRatchet() const;
void setRatchet(float ratchet);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, float phase, float ratchet);
virtual bool createConstraints() override;
protected:
PhysicsJointRatchet() {}
virtual ~PhysicsJointRatchet() {}
float _phase;
float _ratchet;
};
/** Keeps the angular velocity ratio of a pair of bodies constant. */
@ -282,12 +303,14 @@ public:
float getRatio() const;
void setRatio(float ratchet);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, float phase, float ratio);
virtual bool createConstraints() override;
protected:
PhysicsJointGear() {}
virtual ~PhysicsJointGear() {}
float _phase;
float _ratio;
};
/** Keeps the relative angular velocity of a pair of bodies constant */
@ -298,13 +321,13 @@ public:
float getRate() const;
void setRate(float rate);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, float rate);
virtual bool createConstraints() override;
protected:
PhysicsJointMotor() {}
virtual ~PhysicsJointMotor() {}
float _rate;
};
NS_CC_END

View File

@ -50,7 +50,6 @@ PhysicsShape::PhysicsShape()
, _scaleY(1.0f)
, _newScaleX(1.0f)
, _newScaleY(1.0f)
, _dirty(false)
, _tag(0)
, _categoryBitmask(UINT_MAX)
, _collisionBitmask(UINT_MAX)
@ -112,50 +111,25 @@ void PhysicsShape::setMaterial(const PhysicsMaterial& material)
setFriction(material.friction);
}
void PhysicsShape::setScale(float scale)
{
setScaleX(scale);
setScaleY(scale);
}
void PhysicsShape::setScale(float scaleX, float scaleY)
{
setScaleX(scaleX);
setScaleY(scaleY);
}
void PhysicsShape::setScaleX(float scaleX)
if (_scaleX != scaleX || _scaleY != scaleY)
{
if (_scaleX == scaleX)
if (_type == Type::CIRCLE && scaleX != scaleY)
{
CCLOG("PhysicsShapeCircle WARNING: CANNOT support setScale with different x and y");
return;
}
_newScaleX = scaleX;
_dirty = true;
}
void PhysicsShape::setScaleY(float scaleY)
{
if (_scaleY == scaleY)
{
return;
}
_newScaleY = scaleY;
_dirty = true;
updateScale();
}
}
void PhysicsShape::update(float delta)
{
CC_UNUSED_PARAM(delta);
if (_dirty)
void PhysicsShape::updateScale()
{
_scaleX = _newScaleX;
_scaleY = _newScaleY;
_dirty = false;
}
}
void PhysicsShape::addShape(cpShape* shape)
@ -399,63 +373,18 @@ Vec2 PhysicsShapeCircle::getOffset()
return PhysicsHelper::cpv2point(cpCircleShapeGetOffset(_cpShapes.front()));
}
void PhysicsShapeCircle::setScale(float scale)
{
if (_scaleX == scale)
{
return;
}
_newScaleX = _newScaleY = scale;
_dirty = true;
}
void PhysicsShapeCircle::setScale(float scaleX, float scaleY)
{
if (scaleX != scaleY)
{
CCLOG("PhysicsShapeCircle WARNING: CANNOT support setScale with different x and y");
}
if (_scaleX == scaleX)
{
return;
}
_newScaleX = _newScaleY = scaleX;
_dirty = true;
}
void PhysicsShapeCircle::setScaleX(float scale)
{
CCLOG("PhysicsShapeCircle WARNING: CANNOT support setScaleX");
setScale(scale);
}
void PhysicsShapeCircle::setScaleY(float scale)
{
CCLOG("PhysicsShapeCircle WARNING: CANNOT support setScaleY");
setScale(scale);
}
void PhysicsShapeCircle::update(float delta)
{
if (_dirty)
void PhysicsShapeCircle::updateScale()
{
cpFloat factor = std::abs(PhysicsHelper::float2cpfloat(_newScaleX / _scaleX));
auto shape = _cpShapes.front();
auto v = cpCircleShapeGetOffset(shape);
cpShape* shape = _cpShapes.front();
cpVect v = cpCircleShapeGetOffset(shape);
v = cpvmult(v, PhysicsHelper::float2cpfloat(factor));
((cpCircleShape*)shape)->c = v;
cpCircleShapeSetRadius(shape, cpCircleShapeGetRadius(shape) * factor);
}
PhysicsShape::update(delta);
PhysicsShape::updateScale();
}
// PhysicsShapeEdgeSegment
@ -515,24 +444,21 @@ Vec2 PhysicsShapeEdgeSegment::getCenter()
return ( a + b ) / 2;
}
void PhysicsShapeEdgeSegment::update(float delta)
void PhysicsShapeEdgeSegment::updateScale()
{
if (_dirty)
{
auto factorX = PhysicsHelper::float2cpfloat(_newScaleX / _scaleX);
auto factorY = PhysicsHelper::float2cpfloat(_newScaleY / _scaleY);
cpFloat factorX = PhysicsHelper::float2cpfloat(_newScaleX / _scaleX);
cpFloat factorY = PhysicsHelper::float2cpfloat(_newScaleY / _scaleY);
auto shape = _cpShapes.front();
auto a = cpSegmentShapeGetA(shape);
cpShape* shape = _cpShapes.front();
cpVect a = cpSegmentShapeGetA(shape);
a.x *= factorX;
a.y *= factorY;
auto b = cpSegmentShapeGetB(shape);
cpVect b = cpSegmentShapeGetB(shape);
b.x *= factorX;
b.y *= factorY;
cpSegmentShapeSetEndpoints(shape, a, b);
}
PhysicsShape::update(delta);
PhysicsShape::updateScale();
}
// PhysicsShapeBox
@ -682,9 +608,7 @@ Vec2 PhysicsShapePolygon::getCenter()
return PhysicsHelper::cpv2point(cpCentroidForPoly(((cpPolyShape*)_cpShapes.front())->numVerts, ((cpPolyShape*)_cpShapes.front())->verts));
}
void PhysicsShapePolygon::update(float delta)
{
if (_dirty)
void PhysicsShapePolygon::updateScale()
{
cpFloat factorX = PhysicsHelper::float2cpfloat(_newScaleX / _scaleX);
cpFloat factorY = PhysicsHelper::float2cpfloat(_newScaleY / _scaleY);
@ -718,9 +642,8 @@ void PhysicsShapePolygon::update(float delta)
planes[i].n = n;
planes[i].d = cpvdot(n, vects[i]);
}
}
PhysicsShape::update(delta);
PhysicsShape::updateScale();
}
// PhysicsShapeEdgeBox
@ -865,9 +788,7 @@ PhysicsShapeEdgeChain* PhysicsShapeEdgeChain::create(const Vec2* points, int cou
return nullptr;
}
void PhysicsShapeEdgePolygon::update(float delta)
{
if (_dirty)
void PhysicsShapeEdgePolygon::updateScale()
{
cpFloat factorX = PhysicsHelper::float2cpfloat(_newScaleX / _scaleX);
cpFloat factorY = PhysicsHelper::float2cpfloat(_newScaleY / _scaleY);
@ -882,9 +803,8 @@ void PhysicsShapeEdgePolygon::update(float delta)
b.y *= factorY;
cpSegmentShapeSetEndpoints(shape, a, b);
}
}
PhysicsShape::update(delta);
PhysicsShape::updateScale();
}
bool PhysicsShapeEdgeChain::init(const Vec2* points, int count, const PhysicsMaterial& material/* = MaterialDefault*/, float border/* = 1*/)
@ -957,9 +877,7 @@ int PhysicsShapeEdgeChain::getPointsCount() const
return static_cast<int>(_cpShapes.size() + 1);
}
void PhysicsShapeEdgeChain::update(float delta)
{
if (_dirty)
void PhysicsShapeEdgeChain::updateScale()
{
cpFloat factorX = PhysicsHelper::float2cpfloat(_newScaleX / _scaleX);
cpFloat factorY = PhysicsHelper::float2cpfloat(_newScaleY / _scaleY);
@ -974,9 +892,8 @@ void PhysicsShapeEdgeChain::update(float delta)
b.y *= factorY;
cpSegmentShapeSetEndpoints(shape, a, b);
}
}
PhysicsShape::update(delta);
PhysicsShape::updateScale();
}
void PhysicsShape::setGroup(int group)

View File

@ -56,7 +56,7 @@ typedef struct CC_DLL PhysicsMaterial
{}
}PhysicsMaterial;
const PhysicsMaterial PHYSICSSHAPE_MATERIAL_DEFAULT(0.0f, 0.5f, 0.5f);
const PhysicsMaterial PHYSICSSHAPE_MATERIAL_DEFAULT;
/**
* @brief A shape for body. You do not create PhysicsWorld objects directly, instead, you can view PhysicsBody to see how to create it.
@ -153,11 +153,8 @@ protected:
/** calculate the area of this shape */
virtual float calculateArea() { return 0.0f; }
virtual void setScale(float scale);
virtual void setScale(float scaleX, float scaleY);
virtual void setScaleX(float scaleX);
virtual void setScaleY(float scaleY);
virtual void update(float delta);
virtual void updateScale();
void addShape(cpShape* shape);
protected:
@ -176,7 +173,6 @@ protected:
float _scaleY;
float _newScaleX;
float _newScaleY;
bool _dirty;
PhysicsMaterial _material;
int _tag;
int _categoryBitmask;
@ -206,11 +202,7 @@ public:
protected:
bool init(float radius, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, const Vec2& offset = Vec2::ZERO);
virtual float calculateArea() override;
virtual void setScale(float scale) override;
virtual void setScale(float scaleX, float scaleY) override;
virtual void setScaleX(float scale) override;
virtual void setScaleY(float scale) override;
virtual void update(float delta) override;
virtual void updateScale() override;
protected:
PhysicsShapeCircle();
@ -234,7 +226,7 @@ public:
protected:
bool init(const Vec2* points, int count, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, const Vec2& offset = Vec2::ZERO);
float calculateArea() override;
virtual void update(float delta) override;
virtual void updateScale() override;
protected:
PhysicsShapePolygon();
@ -270,7 +262,7 @@ public:
protected:
bool init(const Vec2& a, const Vec2& b, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
virtual void update(float delta) override;
virtual void updateScale() override;
protected:
PhysicsShapeEdgeSegment();
@ -290,7 +282,7 @@ public:
protected:
bool init(const Vec2* points, int count, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
virtual void update(float delta) override;
virtual void updateScale() override;
protected:
PhysicsShapeEdgePolygon();
@ -327,7 +319,7 @@ public:
protected:
bool init(const Vec2* points, int count, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
virtual void update(float delta) override;
virtual void updateScale() override;
protected:
PhysicsShapeEdgeChain();

View File

@ -481,7 +481,6 @@ void PhysicsWorld::doAddBody(PhysicsBody* body)
}
}
void PhysicsWorld::addBodyOrDelay(PhysicsBody* body)
{
auto removeBodyIter = _delayRemoveBodies.find(body);
@ -491,19 +490,12 @@ void PhysicsWorld::addBodyOrDelay(PhysicsBody* body)
return;
}
if (cpSpaceIsLocked(_cpSpace))
{
if (_delayAddBodies.find(body) == _delayAddBodies.end())
{
_delayAddBodies.pushBack(body);
_delayDirty = true;
}
}
else
{
doAddBody(body);
}
}
void PhysicsWorld::updateBodies()
{
@ -542,7 +534,6 @@ void PhysicsWorld::removeBody(int tag)
void PhysicsWorld::removeBody(PhysicsBody* body)
{
if (body->getWorld() != this)
{
CCLOG("Physics Warnning: this body doesn't belong to this world");
@ -550,25 +541,11 @@ void PhysicsWorld::removeBody(PhysicsBody* body)
}
// destory the body's joints
for (auto joint : body->_joints)
auto removeCopy = body->_joints;
for (auto joint : removeCopy)
{
// set destroy param to false to keep the iterator available
removeJoint(joint, false);
PhysicsBody* other = (joint->getBodyA() == body ? joint->getBodyB() : joint->getBodyA());
other->removeJoint(joint);
// test the distraction is delaied or not
if (std::find(_delayRemoveJoints.rbegin(), _delayRemoveJoints.rend(), joint) != _delayRemoveJoints.rend())
{
joint->_destoryMark = true;
removeJoint(joint, true);
}
else
{
delete joint;
}
}
body->_joints.clear();
removeBodyOrDelay(body);
@ -598,54 +575,35 @@ void PhysicsWorld::removeBodyOrDelay(PhysicsBody* body)
}
}
void PhysicsWorld::doAddJoint(PhysicsJoint *joint)
void PhysicsWorld::removeJoint(PhysicsJoint* joint, bool destroy)
{
if (joint)
{
for (auto constraint : joint->_cpConstraints)
{
cpSpaceAddConstraint(_cpSpace, constraint);
}
}
}
void PhysicsWorld::removeJoint(PhysicsJoint* joint, bool destroy)
{
if (joint->getWorld() != this)
{
if (destroy)
if (joint->getWorld() != this && destroy)
{
CCLOG("physics warnning: the joint is not in this world, it won't be destoried utill the body it conntect is destoried");
}
return;
}
removeJointOrDelay(joint);
_joints.remove(joint);
joint->_world = nullptr;
// clean the connection to this joint
if (destroy)
joint->_destoryMark = destroy;
if (cpSpaceIsLocked(_cpSpace))
{
if (joint->getBodyA() != nullptr)
auto it = std::find(_delayAddJoints.begin(), _delayAddJoints.end(), joint);
if (it != _delayAddJoints.end())
{
joint->getBodyA()->removeJoint(joint);
_delayAddJoints.erase(it);
return;
}
if (joint->getBodyB() != nullptr)
if (std::find(_delayRemoveJoints.rbegin(), _delayRemoveJoints.rend(), joint) == _delayRemoveJoints.rend())
{
joint->getBodyB()->removeJoint(joint);
_delayRemoveJoints.push_back(joint);
_delayDirty = true;
}
// test the distraction is delaied or not
if (std::find(_delayRemoveJoints.rbegin(), _delayRemoveJoints.rend(), joint) != _delayRemoveJoints.rend())
{
joint->_destoryMark = true;
}
else
{
delete joint;
doRemoveJoint(joint);
}
}
}
@ -657,24 +615,25 @@ void PhysicsWorld::updateJoints()
return;
}
auto addCopy = _delayAddJoints;
_delayAddJoints.clear();
for (auto joint : addCopy)
for (auto joint : _delayAddJoints)
{
doAddJoint(joint);
joint->_world = this;
if (joint->initJoint())
{
_joints.push_back(joint);
}
auto removeCopy = _delayRemoveJoints;
_delayRemoveJoints.clear();
for (auto joint : removeCopy)
{
doRemoveJoint(joint);
if (joint->_destoryMark)
else
{
delete joint;
}
}
_delayAddJoints.clear();
for (auto joint : _delayRemoveJoints)
{
doRemoveJoint(joint);
}
_delayRemoveJoints.clear();
}
void PhysicsWorld::removeShape(PhysicsShape* shape)
@ -691,8 +650,15 @@ void PhysicsWorld::removeShape(PhysicsShape* shape)
}
}
void PhysicsWorld::addJointOrDelay(PhysicsJoint* joint)
void PhysicsWorld::addJoint(PhysicsJoint* joint)
{
if (joint)
{
if (joint->getWorld() && joint->getWorld() != this)
{
joint->removeFormWorld();
}
auto it = std::find(_delayRemoveJoints.begin(), _delayRemoveJoints.end(), joint);
if (it != _delayRemoveJoints.end())
{
@ -700,86 +666,21 @@ void PhysicsWorld::addJointOrDelay(PhysicsJoint* joint)
return;
}
if (cpSpaceIsLocked(_cpSpace))
{
if (std::find(_delayAddJoints.begin(), _delayAddJoints.end(), joint) == _delayAddJoints.end())
{
_delayAddJoints.push_back(joint);
_delayDirty = true;
}
}else
{
doAddJoint(joint);
}
}
void PhysicsWorld::removeJointOrDelay(PhysicsJoint* joint)
{
auto it = std::find(_delayAddJoints.begin(), _delayAddJoints.end(), joint);
if (it != _delayAddJoints.end())
{
_delayAddJoints.erase(it);
return;
}
if (cpSpaceIsLocked(_cpSpace))
{
if (std::find(_delayRemoveJoints.rbegin(), _delayRemoveJoints.rend(), joint) == _delayRemoveJoints.rend())
{
_delayRemoveJoints.push_back(joint);
_delayDirty = true;
}
}else
{
doRemoveJoint(joint);
}
}
void PhysicsWorld::addJoint(PhysicsJoint* joint)
{
if (joint->getWorld() != nullptr && joint->getWorld() != this)
{
joint->removeFormWorld();
}
addJointOrDelay(joint);
_joints.push_back(joint);
joint->_world = this;
}
void PhysicsWorld::removeAllJoints(bool destroy)
{
for (auto joint : _joints)
auto removeCopy = _joints;
for (auto joint : removeCopy)
{
removeJointOrDelay(joint);
joint->_world = nullptr;
// clean the connection to this joint
if (destroy)
{
if (joint->getBodyA() != nullptr)
{
joint->getBodyA()->removeJoint(joint);
removeJoint(joint, destroy);
}
if (joint->getBodyB() != nullptr)
{
joint->getBodyB()->removeJoint(joint);
}
// test the distraction is delaied or not
if (std::find(_delayRemoveJoints.rbegin(), _delayRemoveJoints.rend(), joint) != _delayRemoveJoints.rend())
{
joint->_destoryMark = true;
}
else
{
delete joint;
}
}
}
_joints.clear();
}
void PhysicsWorld::addShape(PhysicsShape* physicsShape)
@ -816,6 +717,23 @@ void PhysicsWorld::doRemoveJoint(PhysicsJoint* joint)
{
cpSpaceRemoveConstraint(_cpSpace, constraint);
}
_joints.remove(joint);
joint->_world = nullptr;
if (joint->getBodyA())
{
joint->getBodyA()->removeJoint(joint);
}
if (joint->getBodyB())
{
joint->getBodyB()->removeJoint(joint);
}
if (joint->_destoryMark)
{
delete joint;
}
}
void PhysicsWorld::removeAllBodies()
@ -889,11 +807,18 @@ void PhysicsWorld::step(float delta)
void PhysicsWorld::update(float delta, bool userCall/* = false*/)
{
if (delta < FLT_EPSILON)
{
return;
}
_scene->updatePhysicsBodyTransform(_scene, _scene->getNodeToParentTransform(), 0, 1.0f, 1.0f);
while (_delayDirty)
{
// the updateJoints must run before the updateBodies.
updateJoints();
updateBodies();
updateJoints();
_delayDirty = !(_delayAddBodies.size() == 0 && _delayRemoveBodies.size() == 0 && _delayAddJoints.size() == 0 && _delayRemoveJoints.size() == 0);
}

View File

@ -45,6 +45,7 @@ class PhysicsContact;
typedef Vec2 Vect;
class Director;
class Node;
class Sprite;
class Scene;
@ -188,12 +189,9 @@ protected:
virtual void doAddBody(PhysicsBody* body);
virtual void doRemoveBody(PhysicsBody* body);
virtual void doAddJoint(PhysicsJoint* joint);
virtual void doRemoveJoint(PhysicsJoint* joint);
virtual void addBodyOrDelay(PhysicsBody* body);
virtual void removeBodyOrDelay(PhysicsBody* body);
virtual void addJointOrDelay(PhysicsJoint* joint);
virtual void removeJointOrDelay(PhysicsJoint* joint);
virtual void updateBodies();
virtual void updateJoints();
@ -228,6 +226,7 @@ protected:
friend class Node;
friend class Sprite;
friend class Scene;
friend class Director;
friend class PhysicsBody;
friend class PhysicsShape;
friend class PhysicsJoint;

View File

@ -434,7 +434,6 @@ void PhysicsDemo::onTouchEnded(Touch* touch, Event* event)
this->removeChild(it->second);
_mouses.erase(it);
}
}
void PhysicsDemoLogoSmash::onEnter()
@ -716,8 +715,6 @@ void PhysicsDemoJoints::onEnter()
listener->onTouchEnded = CC_CALLBACK_2(PhysicsDemoJoints::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
//_scene->getPhysicsWorld()->setGravity(Point::ZERO);
float width = (VisibleRect::getVisibleRect().size.width - 10) / 4;
float height = (VisibleRect::getVisibleRect().size.height - 50) / 4;
@ -768,7 +765,6 @@ void PhysicsDemoJoints::onEnter()
}
case 2:
{
auto sp1 = makeBall(offset - Vec2(30, 0), 10);
sp1->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
auto sp2 = makeBox(offset + Vec2(30, 0), Size(30, 10));
@ -988,6 +984,9 @@ void PhysicsDemoPump::onEnter()
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Vec2(150, -80), VisibleRect::rightTop() + Vec2(-100, -150), staticMaterial, 2.0f));
body->setCategoryBitmask(0x01);
node->setPhysicsBody(body);
node->setPosition(Vec2::ZERO);
this->addChild(node);
// balls
for (int i = 0; i < 6; ++i)
@ -997,8 +996,7 @@ void PhysicsDemoPump::onEnter()
addChild(ball);
}
node->setPhysicsBody(body);
this->addChild(node);
auto _world = _scene->getPhysicsWorld();
Vec2 vec[4] =
{
@ -1008,30 +1006,6 @@ void PhysicsDemoPump::onEnter()
VisibleRect::leftBottom() + Vec2(102, 20)
};
auto _world = _scene->getPhysicsWorld();
// small gear
auto sgear = Node::create();
auto sgearB = PhysicsBody::createCircle(44);
sgear->setPhysicsBody(sgearB);
sgear->setPosition(VisibleRect::leftBottom() + Vec2(125, 0));
this->addChild(sgear);
sgearB->setCategoryBitmask(0x04);
sgearB->setCollisionBitmask(0x04);
sgearB->setTag(1);
_world->addJoint(PhysicsJointPin::construct(body, sgearB, sgearB->getPosition()));
// big gear
auto bgear = Node::create();
auto bgearB = PhysicsBody::createCircle(100);
bgear->setPhysicsBody(bgearB);
bgear->setPosition(VisibleRect::leftBottom() + Vec2(275, 0));
this->addChild(bgear);
bgearB->setCategoryBitmask(0x04);
_world->addJoint(PhysicsJointPin::construct(body, bgearB, bgearB->getPosition()));
// pump
auto pump = Node::create();
auto center = PhysicsShape::getPolyonCenter(vec, 4);
@ -1041,8 +1015,31 @@ void PhysicsDemoPump::onEnter()
this->addChild(pump);
pumpB->setCategoryBitmask(0x02);
pumpB->setGravityEnable(false);
// small gear
auto sgear = Node::create();
auto sgearB = PhysicsBody::createCircle(44);
sgear->setPhysicsBody(sgearB);
sgear->setPosition(VisibleRect::leftBottom() + Vec2(125, 0));
this->addChild(sgear);
sgearB->setCategoryBitmask(0x04);
sgearB->setCollisionBitmask(0x04);
sgearB->setTag(1);
_world->addJoint(PhysicsJointPin::construct(body, sgearB, sgear->getPosition()));
_world->addJoint(PhysicsJointDistance::construct(pumpB, sgearB, Vec2(0, 0), Vec2(0, -44)));
// big gear
auto bgear = Node::create();
auto bgearB = PhysicsBody::createCircle(100);
bgear->setPhysicsBody(bgearB);
bgear->setPosition(VisibleRect::leftBottom() + Vec2(275, 0));
this->addChild(bgear);
bgearB->setCategoryBitmask(0x04);
_world->addJoint(PhysicsJointPin::construct(bgearB, body, bgear->getPosition()));
_world->addJoint(PhysicsJointGear::construct(sgearB, bgearB, -M_PI_2, -2.0f));
// plugger
Vec2 seg[] = {VisibleRect::leftTop() + Vec2(75, -120), VisibleRect::leftBottom() + Vec2(75, -100)};
Vec2 segCenter = (seg[1] + seg[0])/2;
@ -1059,7 +1056,7 @@ void PhysicsDemoPump::onEnter()
pluggerB->setCategoryBitmask(0x02);
sgearB->setCollisionBitmask(0x04 | 0x01);
_world->addJoint(PhysicsJointPin::construct(body, pluggerB, VisibleRect::leftBottom() + Vec2(75, -90)));
_world->addJoint(PhysicsJointDistance::construct(pluggerB, sgearB, pluggerB->world2Local(VisibleRect::leftBottom() + Vec2(75, 0)), Vec2(44, 0)));
_world->addJoint(PhysicsJointDistance::construct(pluggerB, sgearB, Vec2::ZERO, Vec2(44, 0)));
}
void PhysicsDemoPump::update(float delta)