Merge pull request #9780 from Dhilan007/v3-physics-gravity

Fixed physics body not still after disable gravitational force by PhysicsBody::setGravityEnable.
This commit is contained in:
minggo 2015-01-06 13:59:31 +08:00
commit c8387dd2a8
3 changed files with 38 additions and 91 deletions

View File

@ -42,6 +42,11 @@
#include "chipmunk/CCPhysicsShapeInfo_chipmunk.h" #include "chipmunk/CCPhysicsShapeInfo_chipmunk.h"
#include "chipmunk/CCPhysicsHelper_chipmunk.h" #include "chipmunk/CCPhysicsHelper_chipmunk.h"
static inline void cpBodyUpdateVelocityWithoutGravity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
{
cpBodyUpdateVelocity(body, cpvzero, damping, dt);
}
NS_CC_BEGIN NS_CC_BEGIN
extern const float PHYSICS_INFINITY; extern const float PHYSICS_INFINITY;
@ -189,7 +194,7 @@ PhysicsBody* PhysicsBody::createEdgeSegment(const Vec2& a, const Vec2& b, const
if (body && body->init()) if (body && body->init())
{ {
body->addShape(PhysicsShapeEdgeSegment::create(a, b, material, border)); body->addShape(PhysicsShapeEdgeSegment::create(a, b, material, border));
body->_dynamic = false; body->setDynamic(false);
body->autorelease(); body->autorelease();
return body; return body;
} }
@ -204,7 +209,7 @@ PhysicsBody* PhysicsBody::createEdgeBox(const Size& size, const PhysicsMaterial&
if (body && body->init()) if (body && body->init())
{ {
body->addShape(PhysicsShapeEdgeBox::create(size, material, border, offset)); body->addShape(PhysicsShapeEdgeBox::create(size, material, border, offset));
body->_dynamic = false; body->setDynamic(false);
body->autorelease(); body->autorelease();
return body; return body;
} }
@ -220,7 +225,7 @@ PhysicsBody* PhysicsBody::createEdgePolygon(const Vec2* points, int count, const
if (body && body->init()) if (body && body->init())
{ {
body->addShape(PhysicsShapeEdgePolygon::create(points, count, material, border)); body->addShape(PhysicsShapeEdgePolygon::create(points, count, material, border));
body->_dynamic = false; body->setDynamic(false);
body->autorelease(); body->autorelease();
return body; return body;
} }
@ -236,7 +241,7 @@ PhysicsBody* PhysicsBody::createEdgeChain(const Vec2* points, int count, const P
if (body && body->init()) if (body && body->init())
{ {
body->addShape(PhysicsShapeEdgeChain::create(points, count, material, border)); body->addShape(PhysicsShapeEdgeChain::create(points, count, material, border));
body->_dynamic = false; body->setDynamic(false);
body->autorelease(); body->autorelease();
return body; return body;
} }
@ -278,38 +283,35 @@ void PhysicsBody::setDynamic(bool dynamic)
if (dynamic != _dynamic) if (dynamic != _dynamic)
{ {
_dynamic = dynamic; _dynamic = dynamic;
auto body = _info->getBody();
if (dynamic) if (dynamic)
{ {
cpBodySetMass(_info->getBody(), _mass); if (_world && body->CP_PRIVATE(space))
cpBodySetMoment(_info->getBody(), _moment);
if (_world != nullptr)
{ {
// reset the gravity enable cpSpaceConvertBodyToDynamic(_world->_info->getSpace(), body, _mass, _moment);
if (isGravityEnabled()) cpSpaceAddBody(_world->_info->getSpace(), body);
{ }
_gravityEnabled = false; else
setGravityEnable(true); {
} cpBodySetMass(body, _mass);
cpBodySetMoment(body, _moment);
cpSpaceAddBody(_world->_info->getSpace(), _info->getBody()); body->CP_PRIVATE(node).idleTime = 0.0f;
} }
} }
else else
{ {
if (_world != nullptr) if (_world && body->CP_PRIVATE(space))
{ {
cpSpaceRemoveBody(_world->_info->getSpace(), _info->getBody()); cpSpaceRemoveBody(_world->_info->getSpace(), body);
cpSpaceConvertBodyToStatic(_world->_info->getSpace(), body);
}
else
{
cpBodySetMass(body, PHYSICS_INFINITY);
cpBodySetMoment(body, PHYSICS_INFINITY);
body->CP_PRIVATE(node).idleTime = (cpFloat)INFINITY;
} }
// avoid incorrect collion simulation.
cpBodySetMass(_info->getBody(), PHYSICS_INFINITY);
cpBodySetMoment(_info->getBody(), PHYSICS_INFINITY);
cpBodySetVel(_info->getBody(), cpvzero);
cpBodySetAngVel(_info->getBody(), 0.0f);
resetForces();
} }
} }
} }
@ -324,20 +326,15 @@ void PhysicsBody::setRotationEnable(bool enable)
void PhysicsBody::setGravityEnable(bool enable) void PhysicsBody::setGravityEnable(bool enable)
{ {
if (_gravityEnabled != enable) _gravityEnabled = enable;
if (enable)
{ {
_gravityEnabled = enable; _info->getBody()->velocity_func = cpBodyUpdateVelocity;
}
if (_world != nullptr) else
{ {
if (enable) _info->getBody()->velocity_func = cpBodyUpdateVelocityWithoutGravity;
{
applyForce(_world->getGravity() * _mass);
}else
{
applyForce(-_world->getGravity() * _mass);
}
}
} }
} }
@ -439,12 +436,6 @@ void PhysicsBody::applyForce(const Vect& force, const Vec2& offset)
void PhysicsBody::resetForces() void PhysicsBody::resetForces()
{ {
cpBodyResetForces(_info->getBody()); cpBodyResetForces(_info->getBody());
// if _gravityEnabled is false, add a reverse of gravity force to body
if (_world != nullptr && _dynamic && !_gravityEnabled && _mass != PHYSICS_INFINITY)
{
applyForce(-_world->getGravity() * _mass);
}
} }
void PhysicsBody::applyImpulse(const Vect& impulse) void PhysicsBody::applyImpulse(const Vect& impulse)
@ -468,8 +459,6 @@ void PhysicsBody::setMass(float mass)
{ {
return; return;
} }
int oldMass = _mass;
_mass = mass; _mass = mass;
_massDefault = false; _massDefault = false;
@ -492,14 +481,12 @@ void PhysicsBody::setMass(float mass)
// the static body's mass and moment is always infinity // the static body's mass and moment is always infinity
if (_dynamic) if (_dynamic)
{ {
updateMass(oldMass, _mass); cpBodySetMass(_info->getBody(), _mass);
} }
} }
void PhysicsBody::addMass(float mass) void PhysicsBody::addMass(float mass)
{ {
float oldMass = _mass;
if (mass == PHYSICS_INFINITY) if (mass == PHYSICS_INFINITY)
{ {
_mass = PHYSICS_INFINITY; _mass = PHYSICS_INFINITY;
@ -540,7 +527,7 @@ void PhysicsBody::addMass(float mass)
// the static body's mass and moment is always infinity // the static body's mass and moment is always infinity
if (_dynamic) if (_dynamic)
{ {
updateMass(oldMass, _mass); cpBodySetMass(_info->getBody(), _mass);
} }
} }
@ -938,21 +925,6 @@ Vec2 PhysicsBody::local2World(const Vec2& point)
return PhysicsHelper::cpv2point(cpBodyLocal2World(_info->getBody(), PhysicsHelper::point2cpv(point))); return PhysicsHelper::cpv2point(cpBodyLocal2World(_info->getBody(), PhysicsHelper::point2cpv(point)));
} }
void PhysicsBody::updateMass(float oldMass, float newMass)
{
if (_dynamic && !_gravityEnabled && _world != nullptr && oldMass != PHYSICS_INFINITY)
{
applyForce(_world->getGravity() * oldMass);
}
cpBodySetMass(_info->getBody(), newMass);
if (_dynamic && !_gravityEnabled && _world != nullptr && newMass != PHYSICS_INFINITY)
{
applyForce(-_world->getGravity() * newMass);
}
}
NS_CC_END NS_CC_END
#endif // CC_USE_PHYSICS #endif // CC_USE_PHYSICS

View File

@ -312,7 +312,6 @@ protected:
void removeJoint(PhysicsJoint* joint); void removeJoint(PhysicsJoint* joint);
inline void updateDamping() { _isDamping = _linearDamping != 0.0f || _angularDamping != 0.0f; } inline void updateDamping() { _isDamping = _linearDamping != 0.0f || _angularDamping != 0.0f; }
void updateMass(float oldMass, float newMass);
protected: protected:
PhysicsBody(); PhysicsBody();

View File

@ -475,12 +475,6 @@ void PhysicsWorld::doAddBody(PhysicsBody* body)
{ {
if (body->isEnabled()) if (body->isEnabled())
{ {
//is gravity enable
if (!body->isGravityEnabled())
{
body->applyForce(-_gravity * body->getMass());
}
// add body to space // add body to space
if (body->isDynamic()) if (body->isDynamic())
{ {
@ -801,12 +795,6 @@ void PhysicsWorld::doRemoveBody(PhysicsBody* body)
{ {
CCASSERT(body != nullptr, "the body can not be nullptr"); CCASSERT(body != nullptr, "the body can not be nullptr");
// reset the gravity
if (!body->isGravityEnabled())
{
body->applyForce(_gravity * body->getMass());
}
// remove shaps // remove shaps
for (auto& shape : body->getShapes()) for (auto& shape : body->getShapes())
{ {
@ -863,18 +851,6 @@ PhysicsBody* PhysicsWorld::getBody(int tag) const
void PhysicsWorld::setGravity(const Vect& gravity) void PhysicsWorld::setGravity(const Vect& gravity)
{ {
if (!_bodies.empty())
{
for (auto& body : _bodies)
{
// reset gravity for body
if (!body->isGravityEnabled())
{
body->applyForce((_gravity - gravity) * body->getMass());
}
}
}
_gravity = gravity; _gravity = gravity;
_info->setGravity(gravity); _info->setGravity(gravity);
} }