diff --git a/cocos2dx/physics/CCPhysicsBody.cpp b/cocos2dx/physics/CCPhysicsBody.cpp index 2dc38bf286..eb98bef258 100644 --- a/cocos2dx/physics/CCPhysicsBody.cpp +++ b/cocos2dx/physics/CCPhysicsBody.cpp @@ -56,8 +56,7 @@ NS_CC_BEGIN namespace { static const float MASS_DEFAULT = 1.0; - static const float DENSITY_DEFAULT = 1.0; - static const float ANGULARDAMPING_DEFAULT = 200; + static const float MOMENT_DEFAULT = 200; } PhysicsBody::PhysicsBody() @@ -67,11 +66,11 @@ PhysicsBody::PhysicsBody() , _dynamic(true) , _enable(true) , _massDefault(true) -, _angularDampingDefault(true) +, _momentDefault(true) , _mass(MASS_DEFAULT) , _area(0.0) -, _density(DENSITY_DEFAULT) -, _angularDamping(ANGULARDAMPING_DEFAULT) +, _density(0) +, _moment(MOMENT_DEFAULT) , _tag(0) { } @@ -217,7 +216,7 @@ bool PhysicsBody::init() _info = new PhysicsBodyInfo(); CC_BREAK_IF(_info == nullptr); - _info->body = cpBodyNew(PhysicsHelper::float2cpfloat(_mass), PhysicsHelper::float2cpfloat(_angularDamping)); + _info->body = cpBodyNew(PhysicsHelper::float2cpfloat(_mass), PhysicsHelper::float2cpfloat(_moment)); CC_BREAK_IF(_info->body == nullptr); return true; @@ -233,7 +232,7 @@ void PhysicsBody::setDynamic(bool dynamic) if (dynamic) { cpBodySetMass(_info->body, PhysicsHelper::float2cpfloat(_mass)); - cpBodySetMoment(_info->body, PhysicsHelper::float2cpfloat(_angularDamping)); + cpBodySetMoment(_info->body, PhysicsHelper::float2cpfloat(_moment)); }else { cpBodySetMass(_info->body, PHYSICS_INFINITY); @@ -322,21 +321,7 @@ void PhysicsBody::addShape(PhysicsShape* shape) } } - if (shape->getAngularDumping() > 0) - { - if (shape->getAngularDumping() == INFINITY) - { - _angularDamping = INFINITY; - _angularDampingDefault = false; - cpBodySetMoment(_info->body, _angularDamping); - } - else if (_angularDamping != INFINITY) - { - _angularDamping = (_angularDampingDefault ? 0 : _angularDamping) + shape->getAngularDumping(); - _angularDampingDefault = false; - cpBodySetMoment(_info->body, _angularDamping); - } - } + addMoment(shape->getMoment()); if (_world != nullptr) _world->addShape(shape); @@ -371,12 +356,112 @@ void PhysicsBody::applyTorque(float torque) void PhysicsBody::setMass(float mass) { + if (mass <= 0) + { + return; + } + _mass = mass; _massDefault = false; + // update density + if (_mass == PHYSICS_INFINITY) + { + _density = PHYSICS_INFINITY; + } + else + { + if (_area > 0) + { + _density = _mass / _area; + }else + { + _density = 0; + } + } + cpBodySetMass(_info->body, PhysicsHelper::float2cpfloat(_mass)); } +void PhysicsBody::addMass(float mass) +{ + if (mass == PHYSICS_INFINITY) + { + mass = PHYSICS_INFINITY; + _massDefault = false; + _density = PHYSICS_INFINITY; + } + else if (mass == -PHYSICS_INFINITY) + { + return; + } + else if (_mass != PHYSICS_INFINITY) + { + if (_massDefault) + { + _mass = 0; + _massDefault = false; + } + + if (_mass + mass > 0) + { + _mass += mass; + }else + { + _mass = MASS_DEFAULT; + _massDefault = true; + } + + if (_area > 0) + { + _density = _mass / _area; + } + else + { + _density = 0; + } + } +} + +void PhysicsBody::addMoment(float moment) +{ + if (moment == PHYSICS_INFINITY) + { + // if moment is INFINITY, the moment of the body will become INFINITY + _moment = PHYSICS_INFINITY; + _momentDefault = false; + } + else if (moment == -PHYSICS_INFINITY) + { + // if moment is -INFINITY, it won't change + return; + } + else + { + // if moment of the body is INFINITY is has no effect + if (_moment != PHYSICS_INFINITY) + { + if (_momentDefault) + { + _moment = 0; + _momentDefault = false; + } + + if (_moment + moment > 0) + { + _moment += moment; + } + else + { + _moment = MOMENT_DEFAULT; + _momentDefault = true; + } + } + } + + cpBodySetMoment(_info->body, moment); +} + void PhysicsBody::setVelocity(Point velocity) { cpBodySetVel(_info->body, PhysicsHelper::point2cpv(velocity)); @@ -387,12 +472,12 @@ Point PhysicsBody::getVelocity() return PhysicsHelper::cpv2point(cpBodyGetVel(_info->body)); } -void PhysicsBody::setAngularDamping(float angularDamping) +void PhysicsBody::setMoment(float moment) { - _angularDamping = angularDamping; - _angularDampingDefault = false; + _moment = moment; + _momentDefault = false; - cpBodySetMoment(_info->body, _angularDamping); + cpBodySetMoment(_info->body, _moment); } PhysicsShape* PhysicsBody::getShapeByTag(int tag) @@ -434,42 +519,11 @@ void PhysicsBody::removeShape(PhysicsShape* shape) _shapes.erase(it); - // deduce the mass, area and angularDamping - if (_mass != PHYSICS_INFINITY && shape->getMass() != PHYSICS_INFINITY) - { - if (_mass - shape->getMass() <= 0) - { - _mass = MASS_DEFAULT; - _massDefault = true; - }else - { - _mass = _mass = shape->getMass(); - } - - _area -= shape->getArea(); - - if (_mass == PHYSICS_INFINITY) - { - _density = PHYSICS_INFINITY; - } - else if (_area > 0) - { - _density = _mass / _area; - } - else - { - _density = DENSITY_DEFAULT; - } - - if (_angularDamping - shape->getAngularDumping() > 0) - { - _angularDamping -= shape->getAngularDumping(); - }else - { - _angularDamping = ANGULARDAMPING_DEFAULT; - _angularDampingDefault = true; - } - } + // 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()); shape->release(); } diff --git a/cocos2dx/physics/CCPhysicsBody.h b/cocos2dx/physics/CCPhysicsBody.h index 9bfd9ece3e..84507cfb00 100644 --- a/cocos2dx/physics/CCPhysicsBody.h +++ b/cocos2dx/physics/CCPhysicsBody.h @@ -172,21 +172,49 @@ public: /* * @brief set the body mass. + * @note if you need add/subtract mass to body, don't use setMass(getMass() +/- mass), because the mass of body may be equal to PHYSICS_INFINITY, it will cause some unexpected result, please use addMass() instead. */ void setMass(float mass); /* * @brief get the body mass. */ inline float getMass() { return _mass; } + /* + * @brief add mass to body. + * if _mass(mass of the body) == PHYSICS_INFINITY, it remains. + * if mass == PHYSICS_INFINITY, _mass will be PHYSICS_INFINITY. + * if mass == -PHYSICS_INFINITY, _mass will not change. + * if mass + _mass <= 0, _mass will equal to MASS_DEFAULT(1.0) + * other wise, mass = mass + _mass; + */ + void addMass(float mass); + /* + * @brief set the body moment of inertia. + * @note if you need add/subtract moment to body, don't use setMoment(getMoment() +/- moment), because the moment of body may be equal to PHYSICS_INFINITY, it will cause some unexpected result, please use addMoment() instead. + */ + void setMoment(float moment); + /* + * @brief get the body moment of inertia. + */ + inline float getMoment(float moment) { return _moment; } + /* + * @brief add moment of inertia to body. + * if _moment(moment of the body) == PHYSICS_INFINITY, it remains. + * if moment == PHYSICS_INFINITY, _moment will be PHYSICS_INFINITY. + * if moment == -PHYSICS_INFINITY, _moment will not change. + * if moment + _moment <= 0, _moment will equal to MASS_DEFAULT(1.0) + * other wise, moment = moment + _moment; + */ + void addMoment(float moment); /* * @brief set angular damping. */ - void setAngularDamping(float angularDamping); + //void setAngularDamping(float angularDamping); /* * @brief get angular damping. */ - inline float getAngularDamping() { return _angularDamping; } + //inline float getAngularDamping() { return _angularDamping; } //virtual Clonable* clone() const override; @@ -196,6 +224,7 @@ public: inline int getTag() { return _tag; } inline void setTag(int tag) { _tag = tag; } + protected: bool init(); @@ -216,11 +245,12 @@ protected: bool _dynamic; bool _enable; bool _massDefault; - bool _angularDampingDefault; + bool _momentDefault; float _mass; float _area; float _density; - float _angularDamping; + float _moment; + //float _angularDamping; int _tag; int _categoryBitmask; diff --git a/cocos2dx/physics/CCPhysicsShape.cpp b/cocos2dx/physics/CCPhysicsShape.cpp index b373e0710e..05bf303f91 100644 --- a/cocos2dx/physics/CCPhysicsShape.cpp +++ b/cocos2dx/physics/CCPhysicsShape.cpp @@ -48,7 +48,7 @@ PhysicsShape::PhysicsShape() , _type(Type::UNKNOWN) , _area(0) , _mass(0) -, _angularDamping(0) +, _moment(0) , _tag(0) , _enable(true) { @@ -234,7 +234,7 @@ bool PhysicsShapeCircle::init(float radius, PhysicsMaterial material/* = Materia _area = PhysicsHelper::cpfloat2float(cpAreaForCircle(0, radius)); _mass = _material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : _material.density * _area; - _angularDamping = _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY : cpMomentForCircle(_mass, 0, radius, PhysicsHelper::point2cpv(offset)); + _moment = _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY : cpMomentForCircle(_mass, 0, radius, PhysicsHelper::point2cpv(offset)); _info->add(shape); @@ -273,7 +273,7 @@ bool PhysicsShapeEdgeSegment::init(Point a, Point b, PhysicsMaterial material/* CC_BREAK_IF(shape == nullptr); _mass = PHYSICS_INFINITY; - _angularDamping = PHYSICS_INFINITY; + _moment = PHYSICS_INFINITY; _info->add(shape); @@ -311,7 +311,7 @@ bool PhysicsShapeBox::init(Size size, PhysicsMaterial material/* = MaterialDefau _area = PhysicsHelper::cpfloat2float(cpAreaForPoly(4, ((cpPolyShape*)shape)->verts)); _mass = _material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : _material.density * _area; - _angularDamping = _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY : cpMomentForBox(_mass, PhysicsHelper::float2cpfloat(size.width), PhysicsHelper::float2cpfloat(size.height)); + _moment = _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY : cpMomentForBox(_mass, PhysicsHelper::float2cpfloat(size.width), PhysicsHelper::float2cpfloat(size.height)); _info->add(shape); @@ -352,7 +352,7 @@ bool PhysicsShapePolygon::init(Point* points, int count, PhysicsMaterial materia _area = PhysicsHelper::cpfloat2float(cpAreaForPoly(((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts)); _mass = _material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : _material.density * _area; - _angularDamping = _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY : cpMomentForPoly(_mass, ((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts, PhysicsHelper::point2cpv(offset)); + _moment = _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY : cpMomentForPoly(_mass, ((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts, PhysicsHelper::point2cpv(offset)); _info->add(shape); @@ -401,7 +401,7 @@ bool PhysicsShapeEdgeBox::init(Size size, PhysicsMaterial material/* = MaterialD CC_BREAK_IF(i < 4); _mass = PHYSICS_INFINITY; - _angularDamping = PHYSICS_INFINITY; + _moment = PHYSICS_INFINITY; initEnd(); @@ -450,7 +450,7 @@ bool PhysicsShapeEdgePolygon::init(Point* points, int count, PhysicsMaterial mat CC_BREAK_IF(i < count); _mass = PHYSICS_INFINITY; - _angularDamping = PHYSICS_INFINITY; + _moment = PHYSICS_INFINITY; initEnd(); @@ -500,7 +500,7 @@ bool PhysicsShapeEdgeChain::init(Point* points, int count, PhysicsMaterial mater CC_BREAK_IF(i < count); _mass = PHYSICS_INFINITY; - _angularDamping = PHYSICS_INFINITY; + _moment = PHYSICS_INFINITY; initEnd(); diff --git a/cocos2dx/physics/CCPhysicsShape.h b/cocos2dx/physics/CCPhysicsShape.h index d754f6030b..688ccad2a6 100644 --- a/cocos2dx/physics/CCPhysicsShape.h +++ b/cocos2dx/physics/CCPhysicsShape.h @@ -79,8 +79,8 @@ public: inline PhysicsBody* getBody(){ return _body; } inline Type getType() { return _type; } inline float getArea() { return _area; } - inline float getAngularDumping() { return _angularDamping; } - void setAngularDumping(float angularDumping); + inline float getMoment() { return _moment; } + void setMoment(float moment); inline void setTag(int tag) { _tag = tag; } inline int getTag() { return _tag; } void setEnable(bool enable); @@ -115,7 +115,7 @@ protected: Type _type; float _area; float _mass; - float _angularDamping; + float _moment; PhysicsMaterial _material; int _tag; bool _enable; diff --git a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp index 0ab5ba4ae4..91c67da54d 100644 --- a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp +++ b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp @@ -311,9 +311,8 @@ Node* PhysicsDemoLogoSmash::makeBall(float x, float y) auto body = PhysicsBody::createCircle(0.95, PhysicsMaterial(1, 0, 0)); body->setMass(1.0); - body->setAngularDamping(PHYSICS_INFINITY); + body->setMoment(PHYSICS_INFINITY); - //body->setDynamic(false); ball->setPhysicsBody(body); ball->setPosition(Point(x, y));