2013-09-09 10:29:02 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2013 cocos2d-x.org
|
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
2013-09-09 10:40:31 +08:00
|
|
|
#include "CCPhysicsBody.h"
|
2013-09-10 17:36:49 +08:00
|
|
|
#ifdef CC_USE_PHYSICS
|
|
|
|
|
2013-10-26 12:33:31 +08:00
|
|
|
#include <climits>
|
2013-09-17 14:31:43 +08:00
|
|
|
#include <algorithm>
|
|
|
|
|
2013-09-17 17:39:08 +08:00
|
|
|
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
|
|
|
|
#include "chipmunk.h"
|
|
|
|
#elif (CC_PHYSICS_ENGINE == CCPHYSICS_BOX2D)
|
|
|
|
#include "Box2D.h"
|
|
|
|
#endif
|
|
|
|
|
2013-09-16 21:22:22 +08:00
|
|
|
#include "CCPhysicsShape.h"
|
|
|
|
#include "CCPhysicsJoint.h"
|
|
|
|
#include "CCPhysicsWorld.h"
|
|
|
|
|
2013-10-31 18:18:02 +08:00
|
|
|
#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"
|
2013-09-16 21:22:22 +08:00
|
|
|
|
2013-09-10 17:36:49 +08:00
|
|
|
NS_CC_BEGIN
|
|
|
|
|
|
|
|
|
|
|
|
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
|
|
|
|
|
2013-09-16 21:22:22 +08:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
static const float MASS_DEFAULT = 1.0;
|
2013-10-14 13:56:08 +08:00
|
|
|
static const float MOMENT_DEFAULT = 200;
|
2013-09-16 21:22:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PhysicsBody::PhysicsBody()
|
2013-11-01 16:26:03 +08:00
|
|
|
: _node(nullptr)
|
2013-10-28 11:08:41 +08:00
|
|
|
, _shapes(nullptr)
|
2013-09-16 21:22:22 +08:00
|
|
|
, _world(nullptr)
|
|
|
|
, _info(nullptr)
|
2013-09-30 20:43:19 +08:00
|
|
|
, _dynamic(true)
|
2013-09-29 09:39:20 +08:00
|
|
|
, _enable(true)
|
2013-10-15 16:55:08 +08:00
|
|
|
, _rotationEnable(true)
|
|
|
|
, _gravityEnable(true)
|
2013-09-16 21:22:22 +08:00
|
|
|
, _massDefault(true)
|
2013-10-14 13:56:08 +08:00
|
|
|
, _momentDefault(true)
|
2013-09-16 21:22:22 +08:00
|
|
|
, _mass(MASS_DEFAULT)
|
2013-10-15 16:55:08 +08:00
|
|
|
, _area(0.0f)
|
|
|
|
, _density(0.0f)
|
2013-10-14 13:56:08 +08:00
|
|
|
, _moment(MOMENT_DEFAULT)
|
2013-10-15 16:55:08 +08:00
|
|
|
, _linearDamping(0.0f)
|
|
|
|
, _angularDamping(0.0f)
|
2013-09-29 09:39:20 +08:00
|
|
|
, _tag(0)
|
2013-10-21 23:16:21 +08:00
|
|
|
, _categoryBitmask(UINT_MAX)
|
|
|
|
, _collisionBitmask(UINT_MAX)
|
2013-11-04 14:36:38 +08:00
|
|
|
, _contactTestBitmask(UINT_MAX)
|
2013-10-29 17:31:35 +08:00
|
|
|
, _group(0)
|
2013-09-10 17:36:49 +08:00
|
|
|
{
|
2013-09-16 21:22:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PhysicsBody::~PhysicsBody()
|
|
|
|
{
|
2013-10-28 11:08:41 +08:00
|
|
|
if (_world)
|
|
|
|
{
|
|
|
|
removeFromWorld();
|
|
|
|
}
|
2013-09-10 17:36:49 +08:00
|
|
|
|
2013-09-29 09:39:20 +08:00
|
|
|
removeAllShapes();
|
2013-09-16 21:22:22 +08:00
|
|
|
|
|
|
|
for (auto it = _joints.begin(); it != _joints.end(); ++it)
|
|
|
|
{
|
|
|
|
PhysicsJoint* joint = *it;
|
2013-10-28 11:08:41 +08:00
|
|
|
PhysicsBody* other = joint->getBodyA() == this ? joint->getBodyB() : joint->getBodyA();
|
2013-09-16 21:22:22 +08:00
|
|
|
|
|
|
|
other->_joints.erase(std::find(other->_joints.begin(), other->_joints.end(), joint));
|
2013-10-28 11:08:41 +08:00
|
|
|
|
2013-09-16 21:22:22 +08:00
|
|
|
delete joint;
|
|
|
|
}
|
2013-10-28 11:08:41 +08:00
|
|
|
CC_SAFE_DELETE(_info);
|
2013-09-16 21:22:22 +08:00
|
|
|
}
|
2013-09-10 17:36:49 +08:00
|
|
|
|
2013-10-10 18:31:43 +08:00
|
|
|
PhysicsBody* PhysicsBody::create()
|
|
|
|
{
|
|
|
|
PhysicsBody* body = new PhysicsBody();
|
|
|
|
if (body && body->init())
|
|
|
|
{
|
|
|
|
body->autorelease();
|
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
CC_SAFE_DELETE(body);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2013-10-28 11:08:41 +08:00
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-11-05 15:54:33 +08:00
|
|
|
PhysicsBody* PhysicsBody::createCircle(float radius, PhysicsMaterial material, Point offset)
|
2013-09-10 17:36:49 +08:00
|
|
|
{
|
2013-09-16 21:22:22 +08:00
|
|
|
PhysicsBody* body = new PhysicsBody();
|
|
|
|
if (body && body->init())
|
|
|
|
{
|
2013-11-05 15:54:33 +08:00
|
|
|
body->addShape(PhysicsShapeCircle::create(radius, material, offset));
|
2013-09-16 21:22:22 +08:00
|
|
|
body->autorelease();
|
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
CC_SAFE_DELETE(body);
|
|
|
|
return nullptr;
|
2013-09-10 17:36:49 +08:00
|
|
|
}
|
|
|
|
|
2013-11-05 15:54:33 +08:00
|
|
|
PhysicsBody* PhysicsBody::createBox(Size size, PhysicsMaterial material, Point offset)
|
2013-09-10 17:36:49 +08:00
|
|
|
{
|
2013-09-16 21:22:22 +08:00
|
|
|
PhysicsBody* body = new PhysicsBody();
|
|
|
|
if (body && body->init())
|
|
|
|
{
|
2013-11-05 15:54:33 +08:00
|
|
|
body->addShape(PhysicsShapeBox::create(size, material, offset));
|
2013-09-16 21:22:22 +08:00
|
|
|
body->autorelease();
|
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
CC_SAFE_DELETE(body);
|
|
|
|
return nullptr;
|
2013-09-10 17:36:49 +08:00
|
|
|
}
|
|
|
|
|
2013-11-05 15:54:33 +08:00
|
|
|
PhysicsBody* PhysicsBody::createPolygon(Point* points, int count, PhysicsMaterial material, Point offset)
|
2013-09-16 21:22:22 +08:00
|
|
|
{
|
|
|
|
PhysicsBody* body = new PhysicsBody();
|
|
|
|
if (body && body->init())
|
|
|
|
{
|
2013-11-05 15:54:33 +08:00
|
|
|
body->addShape(PhysicsShapePolygon::create(points, count, material, offset));
|
2013-09-16 21:22:22 +08:00
|
|
|
body->autorelease();
|
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
CC_SAFE_DELETE(body);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2013-10-09 17:53:12 +08:00
|
|
|
PhysicsBody* PhysicsBody::createEdgeSegment(Point a, Point b, PhysicsMaterial material, float border/* = 1*/)
|
2013-09-10 17:36:49 +08:00
|
|
|
{
|
2013-09-16 21:22:22 +08:00
|
|
|
PhysicsBody* body = new PhysicsBody();
|
2013-09-30 20:43:19 +08:00
|
|
|
if (body && body->init())
|
2013-09-16 21:22:22 +08:00
|
|
|
{
|
2013-10-09 17:53:12 +08:00
|
|
|
body->addShape(PhysicsShapeEdgeSegment::create(a, b, material, border));
|
2013-09-30 20:43:19 +08:00
|
|
|
body->_dynamic = false;
|
2013-09-16 21:22:22 +08:00
|
|
|
body->autorelease();
|
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
CC_SAFE_DELETE(body);
|
|
|
|
return nullptr;
|
2013-09-10 17:36:49 +08:00
|
|
|
}
|
|
|
|
|
2013-11-05 15:54:33 +08:00
|
|
|
PhysicsBody* PhysicsBody::createEdgeBox(Size size, PhysicsMaterial material, float border/* = 1*/, Point offset)
|
2013-09-10 17:36:49 +08:00
|
|
|
{
|
2013-09-16 21:22:22 +08:00
|
|
|
PhysicsBody* body = new PhysicsBody();
|
2013-09-30 20:43:19 +08:00
|
|
|
if (body && body->init())
|
2013-09-16 21:22:22 +08:00
|
|
|
{
|
2013-11-05 15:54:33 +08:00
|
|
|
body->addShape(PhysicsShapeEdgeBox::create(size, material, border, offset));
|
2013-09-30 20:43:19 +08:00
|
|
|
body->_dynamic = false;
|
2013-09-16 21:22:22 +08:00
|
|
|
body->autorelease();
|
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
CC_SAFE_DELETE(body);
|
|
|
|
|
|
|
|
return nullptr;
|
2013-09-10 17:36:49 +08:00
|
|
|
}
|
|
|
|
|
2013-10-09 17:53:12 +08:00
|
|
|
PhysicsBody* PhysicsBody::createEdgePolygon(Point* points, int count, PhysicsMaterial material, float border/* = 1*/)
|
2013-09-10 17:36:49 +08:00
|
|
|
{
|
2013-09-16 21:22:22 +08:00
|
|
|
PhysicsBody* body = new PhysicsBody();
|
2013-09-30 20:43:19 +08:00
|
|
|
if (body && body->init())
|
2013-09-10 17:36:49 +08:00
|
|
|
{
|
2013-10-09 17:53:12 +08:00
|
|
|
body->addShape(PhysicsShapeEdgePolygon::create(points, count, material, border));
|
2013-09-30 20:43:19 +08:00
|
|
|
body->_dynamic = false;
|
2013-09-16 21:22:22 +08:00
|
|
|
body->autorelease();
|
2013-09-10 17:36:49 +08:00
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
CC_SAFE_DELETE(body);
|
2013-09-16 21:22:22 +08:00
|
|
|
|
2013-09-10 17:36:49 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2013-10-09 17:53:12 +08:00
|
|
|
PhysicsBody* PhysicsBody::createEdgeChain(Point* points, int count, PhysicsMaterial material, float border/* = 1*/)
|
2013-09-16 21:22:22 +08:00
|
|
|
{
|
|
|
|
PhysicsBody* body = new PhysicsBody();
|
2013-09-30 20:43:19 +08:00
|
|
|
if (body && body->init())
|
2013-09-16 21:22:22 +08:00
|
|
|
{
|
2013-10-09 17:53:12 +08:00
|
|
|
body->addShape(PhysicsShapeEdgeChain::create(points, count, material, border));
|
2013-09-30 20:43:19 +08:00
|
|
|
body->_dynamic = false;
|
2013-09-16 21:22:22 +08:00
|
|
|
body->autorelease();
|
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
CC_SAFE_DELETE(body);
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2013-09-10 17:36:49 +08:00
|
|
|
bool PhysicsBody::init()
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
_info = new PhysicsBodyInfo();
|
|
|
|
CC_BREAK_IF(_info == nullptr);
|
2013-10-28 11:08:41 +08:00
|
|
|
_shapes = Array::create();
|
|
|
|
CC_BREAK_IF(_shapes == nullptr);
|
|
|
|
_shapes->retain();
|
2013-09-10 17:36:49 +08:00
|
|
|
|
2013-10-14 13:56:08 +08:00
|
|
|
_info->body = cpBodyNew(PhysicsHelper::float2cpfloat(_mass), PhysicsHelper::float2cpfloat(_moment));
|
2013-10-17 10:57:48 +08:00
|
|
|
|
2013-09-10 17:36:49 +08:00
|
|
|
CC_BREAK_IF(_info->body == nullptr);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} while (false);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-09-16 21:22:22 +08:00
|
|
|
void PhysicsBody::setDynamic(bool dynamic)
|
2013-09-10 17:36:49 +08:00
|
|
|
{
|
2013-09-30 13:02:17 +08:00
|
|
|
if (dynamic != _dynamic)
|
2013-09-10 17:36:49 +08:00
|
|
|
{
|
2013-10-15 16:55:08 +08:00
|
|
|
_dynamic = dynamic;
|
2013-11-04 14:36:38 +08:00
|
|
|
if (dynamic)
|
2013-09-16 21:22:22 +08:00
|
|
|
{
|
2013-11-04 14:36:38 +08:00
|
|
|
cpBodySetMass(_info->body, _mass);
|
|
|
|
|
|
|
|
if (_world != nullptr)
|
2013-10-15 16:55:08 +08:00
|
|
|
{
|
|
|
|
cpSpaceAddBody(_world->_info->space, _info->body);
|
2013-11-04 14:36:38 +08:00
|
|
|
}
|
|
|
|
}else
|
|
|
|
{
|
|
|
|
cpBodySetMass(_info->body, PHYSICS_INFINITY);
|
|
|
|
|
|
|
|
if (_world != nullptr)
|
2013-10-15 16:55:08 +08:00
|
|
|
{
|
|
|
|
cpSpaceRemoveBody(_world->_info->space, _info->body);
|
|
|
|
}
|
2013-09-16 21:22:22 +08:00
|
|
|
}
|
2013-09-30 13:02:17 +08:00
|
|
|
|
2013-10-15 16:55:08 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::setRotationEnable(bool enable)
|
|
|
|
{
|
|
|
|
if (_rotationEnable != enable)
|
|
|
|
{
|
|
|
|
cpBodySetMoment(_info->body, enable ? _moment : PHYSICS_INFINITY);
|
|
|
|
_rotationEnable = enable;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::setGravityEnable(bool enable)
|
|
|
|
{
|
|
|
|
if (_gravityEnable != enable)
|
|
|
|
{
|
|
|
|
_gravityEnable = enable;
|
|
|
|
|
|
|
|
if (_world != nullptr)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
2013-10-29 17:31:35 +08:00
|
|
|
applyForce(_world->getGravity() * _mass);
|
2013-10-15 16:55:08 +08:00
|
|
|
}else
|
|
|
|
{
|
2013-10-29 17:31:35 +08:00
|
|
|
applyForce(-_world->getGravity() * _mass);
|
2013-10-15 16:55:08 +08:00
|
|
|
}
|
|
|
|
}
|
2013-09-10 17:36:49 +08:00
|
|
|
}
|
2013-09-16 21:22:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::setPosition(Point position)
|
|
|
|
{
|
|
|
|
cpBodySetPos(_info->body, PhysicsHelper::point2cpv(position));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::setRotation(float rotation)
|
|
|
|
{
|
|
|
|
cpBodySetAngle(_info->body, PhysicsHelper::float2cpfloat(rotation));
|
|
|
|
}
|
|
|
|
|
|
|
|
Point PhysicsBody::getPosition() const
|
|
|
|
{
|
|
|
|
cpVect vec = cpBodyGetPos(_info->body);
|
|
|
|
return PhysicsHelper::cpv2point(vec);
|
|
|
|
}
|
|
|
|
|
|
|
|
float PhysicsBody::getRotation() const
|
|
|
|
{
|
|
|
|
return -PhysicsHelper::cpfloat2float(cpBodyGetAngle(_info->body) / 3.14f * 180.0f);
|
|
|
|
}
|
|
|
|
|
2013-10-29 17:31:35 +08:00
|
|
|
PhysicsShape* PhysicsBody::addShape(PhysicsShape* shape)
|
2013-09-16 21:22:22 +08:00
|
|
|
{
|
2013-10-29 17:31:35 +08:00
|
|
|
if (shape == nullptr) return nullptr;
|
2013-09-10 17:36:49 +08:00
|
|
|
|
2013-10-09 13:41:19 +08:00
|
|
|
// add shape to body
|
2013-10-28 11:08:41 +08:00
|
|
|
if (_shapes->getIndexOfObject(shape) == UINT_MAX)
|
2013-09-30 20:43:19 +08:00
|
|
|
{
|
2013-10-09 13:41:19 +08:00
|
|
|
shape->setBody(this);
|
2013-09-30 20:43:19 +08:00
|
|
|
|
2013-10-14 14:05:57 +08:00
|
|
|
// calculate the area, mass, and desity
|
|
|
|
// area must update before mass, because the density changes depend on it.
|
2013-09-30 20:43:19 +08:00
|
|
|
_area += shape->getArea();
|
2013-10-14 14:05:57 +08:00
|
|
|
addMass(shape->getMass());
|
2013-10-14 13:56:08 +08:00
|
|
|
addMoment(shape->getMoment());
|
2013-09-30 20:43:19 +08:00
|
|
|
|
2013-10-15 16:55:08 +08:00
|
|
|
if (_world != nullptr)
|
2013-09-30 20:43:19 +08:00
|
|
|
{
|
2013-10-15 16:55:08 +08:00
|
|
|
_world->addShape(shape);
|
2013-09-30 20:43:19 +08:00
|
|
|
}
|
|
|
|
|
2013-10-28 11:08:41 +08:00
|
|
|
_shapes->addObject(shape);
|
2013-10-29 17:31:35 +08:00
|
|
|
|
|
|
|
if (_group != CP_NO_GROUP && shape->getGroup() == CP_NO_GROUP)
|
|
|
|
{
|
|
|
|
shape->setGroup(_group);
|
|
|
|
}
|
2013-09-30 20:43:19 +08:00
|
|
|
}
|
2013-10-29 17:31:35 +08:00
|
|
|
|
|
|
|
return shape;
|
2013-09-16 21:22:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::applyForce(Point force)
|
|
|
|
{
|
2013-10-15 16:55:08 +08:00
|
|
|
applyForce(force, Point::ZERO);
|
2013-09-16 21:22:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::applyForce(Point force, Point offset)
|
|
|
|
{
|
|
|
|
cpBodyApplyForce(_info->body, PhysicsHelper::point2cpv(force), PhysicsHelper::point2cpv(offset));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::applyImpulse(Point impulse)
|
|
|
|
{
|
|
|
|
applyImpulse(impulse, Point());
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::applyImpulse(Point impulse, Point offset)
|
|
|
|
{
|
|
|
|
cpBodyApplyImpulse(_info->body, PhysicsHelper::point2cpv(impulse), PhysicsHelper::point2cpv(offset));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::applyTorque(float torque)
|
|
|
|
{
|
|
|
|
cpBodySetTorque(_info->body, PhysicsHelper::float2cpfloat(torque));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::setMass(float mass)
|
|
|
|
{
|
2013-10-14 13:56:08 +08:00
|
|
|
if (mass <= 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-09-16 21:22:22 +08:00
|
|
|
_mass = mass;
|
|
|
|
_massDefault = false;
|
2013-09-10 17:36:49 +08:00
|
|
|
|
2013-10-14 13:56:08 +08:00
|
|
|
// update density
|
|
|
|
if (_mass == PHYSICS_INFINITY)
|
|
|
|
{
|
|
|
|
_density = PHYSICS_INFINITY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (_area > 0)
|
|
|
|
{
|
|
|
|
_density = _mass / _area;
|
|
|
|
}else
|
|
|
|
{
|
|
|
|
_density = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-16 21:22:22 +08:00
|
|
|
cpBodySetMass(_info->body, PhysicsHelper::float2cpfloat(_mass));
|
2013-09-10 17:36:49 +08:00
|
|
|
}
|
|
|
|
|
2013-10-14 13:56:08 +08:00
|
|
|
void PhysicsBody::addMass(float mass)
|
|
|
|
{
|
|
|
|
if (mass == PHYSICS_INFINITY)
|
|
|
|
{
|
2013-10-15 13:48:01 +08:00
|
|
|
_mass = PHYSICS_INFINITY;
|
2013-10-14 13:56:08 +08:00
|
|
|
_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;
|
|
|
|
}
|
|
|
|
}
|
2013-10-15 13:48:01 +08:00
|
|
|
|
|
|
|
cpBodySetMass(_info->body, PhysicsHelper::float2cpfloat(_mass));
|
2013-10-14 13:56:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-15 16:55:08 +08:00
|
|
|
if (_rotationEnable)
|
|
|
|
{
|
|
|
|
cpBodySetMoment(_info->body, PhysicsHelper::float2cpfloat(_moment));
|
|
|
|
}
|
2013-10-14 13:56:08 +08:00
|
|
|
}
|
|
|
|
|
2013-09-30 20:43:19 +08:00
|
|
|
void PhysicsBody::setVelocity(Point velocity)
|
|
|
|
{
|
|
|
|
cpBodySetVel(_info->body, PhysicsHelper::point2cpv(velocity));
|
|
|
|
}
|
|
|
|
|
|
|
|
Point PhysicsBody::getVelocity()
|
|
|
|
{
|
|
|
|
return PhysicsHelper::cpv2point(cpBodyGetVel(_info->body));
|
|
|
|
}
|
|
|
|
|
2013-11-05 15:54:33 +08:00
|
|
|
Point PhysicsBody::getVelocityAtLocalPoint(Point point)
|
|
|
|
{
|
|
|
|
return PhysicsHelper::cpv2point(cpBodyGetVelAtLocalPoint(_info->body, PhysicsHelper::point2cpv(point)));
|
|
|
|
}
|
|
|
|
|
|
|
|
Point PhysicsBody::getVelocityAtWorldPoint(Point point)
|
|
|
|
{
|
|
|
|
return PhysicsHelper::cpv2point(cpBodyGetVelAtWorldPoint(_info->body, PhysicsHelper::point2cpv(point)));
|
|
|
|
}
|
|
|
|
|
2013-10-15 16:55:08 +08:00
|
|
|
void PhysicsBody::setAngularVelocity(float velocity)
|
|
|
|
{
|
|
|
|
cpBodySetAngVel(_info->body, PhysicsHelper::float2cpfloat(velocity));
|
|
|
|
}
|
|
|
|
|
|
|
|
float PhysicsBody::getAngularVelocity()
|
2013-09-16 21:22:22 +08:00
|
|
|
{
|
2013-10-15 16:55:08 +08:00
|
|
|
return PhysicsHelper::cpfloat2float(cpBodyGetAngVel(_info->body));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::setVelocityLimit(float limit)
|
|
|
|
{
|
|
|
|
cpBodySetVelLimit(_info->body, PhysicsHelper::float2cpfloat(limit));
|
|
|
|
}
|
|
|
|
|
|
|
|
float PhysicsBody::getVelocityLimit()
|
|
|
|
{
|
|
|
|
return PhysicsHelper::cpfloat2float(cpBodyGetVelLimit(_info->body));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::setAngularVelocityLimit(float limit)
|
|
|
|
{
|
|
|
|
cpBodySetVelLimit(_info->body, PhysicsHelper::float2cpfloat(limit));
|
|
|
|
}
|
|
|
|
|
|
|
|
float PhysicsBody::getAngularVelocityLimit()
|
|
|
|
{
|
|
|
|
return PhysicsHelper::cpfloat2float(cpBodyGetAngVelLimit(_info->body));
|
|
|
|
}
|
|
|
|
|
2013-10-14 13:56:08 +08:00
|
|
|
void PhysicsBody::setMoment(float moment)
|
2013-09-16 21:22:22 +08:00
|
|
|
{
|
2013-10-14 13:56:08 +08:00
|
|
|
_moment = moment;
|
|
|
|
_momentDefault = false;
|
2013-09-16 21:22:22 +08:00
|
|
|
|
2013-10-15 16:55:08 +08:00
|
|
|
if (_rotationEnable)
|
|
|
|
{
|
|
|
|
cpBodySetMoment(_info->body, PhysicsHelper::float2cpfloat(_moment));
|
|
|
|
}
|
2013-09-16 21:22:22 +08:00
|
|
|
}
|
|
|
|
|
2013-11-01 16:26:03 +08:00
|
|
|
PhysicsShape* PhysicsBody::getShapeByTag(int tag) const
|
2013-09-29 09:39:20 +08:00
|
|
|
{
|
2013-10-28 11:08:41 +08:00
|
|
|
for (auto child : *_shapes)
|
2013-09-29 09:39:20 +08:00
|
|
|
{
|
2013-10-28 11:08:41 +08:00
|
|
|
PhysicsShape* shape = dynamic_cast<PhysicsShape*>(child);
|
2013-09-29 09:39:20 +08:00
|
|
|
if (shape->getTag() == tag)
|
|
|
|
{
|
|
|
|
return shape;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::removeShapeByTag(int tag)
|
|
|
|
{
|
2013-10-28 11:08:41 +08:00
|
|
|
for (auto child : *_shapes)
|
2013-09-29 09:39:20 +08:00
|
|
|
{
|
2013-10-28 11:08:41 +08:00
|
|
|
PhysicsShape* shape = dynamic_cast<PhysicsShape*>(child);
|
2013-09-29 09:39:20 +08:00
|
|
|
if (shape->getTag() == tag)
|
|
|
|
{
|
|
|
|
removeShape(shape);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::removeShape(PhysicsShape* shape)
|
|
|
|
{
|
2013-10-28 11:08:41 +08:00
|
|
|
if (_shapes->getIndexOfObject(shape) == UINT_MAX)
|
2013-09-29 09:39:20 +08:00
|
|
|
{
|
2013-10-14 13:56:08 +08:00
|
|
|
// 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());
|
2013-09-30 20:43:19 +08:00
|
|
|
|
2013-10-17 10:57:48 +08:00
|
|
|
//remove
|
2013-09-29 09:39:20 +08:00
|
|
|
if (_world)
|
|
|
|
{
|
|
|
|
_world->removeShape(shape);
|
|
|
|
}
|
2013-10-17 10:57:48 +08:00
|
|
|
shape->setBody(nullptr);
|
2013-10-28 11:08:41 +08:00
|
|
|
_shapes->removeObject(shape);
|
2013-09-29 09:39:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::removeAllShapes()
|
|
|
|
{
|
2013-10-28 11:08:41 +08:00
|
|
|
for (auto child : *_shapes)
|
2013-09-29 09:39:20 +08:00
|
|
|
{
|
2013-10-28 11:08:41 +08:00
|
|
|
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());
|
|
|
|
|
2013-09-29 09:39:20 +08:00
|
|
|
if (_world)
|
|
|
|
{
|
|
|
|
_world->removeShape(shape);
|
|
|
|
}
|
2013-10-28 11:08:41 +08:00
|
|
|
shape->setBody(nullptr);
|
2013-09-29 09:39:20 +08:00
|
|
|
}
|
|
|
|
|
2013-10-28 11:08:41 +08:00
|
|
|
_shapes->removeAllObjects();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::removeFromWorld()
|
|
|
|
{
|
|
|
|
if (_world)
|
|
|
|
{
|
|
|
|
_world->removeBody(this);
|
|
|
|
}
|
2013-09-29 09:39:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::setEnable(bool enable)
|
|
|
|
{
|
|
|
|
if (_enable != enable)
|
|
|
|
{
|
|
|
|
_enable = enable;
|
|
|
|
|
|
|
|
if (_world)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
_world->addBody(this);
|
|
|
|
}else
|
|
|
|
{
|
|
|
|
_world->removeBody(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-01 16:26:03 +08:00
|
|
|
bool PhysicsBody::isResting() const
|
2013-10-15 16:55:08 +08:00
|
|
|
{
|
|
|
|
return cpBodyIsSleeping(_info->body) == cpTrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsBody::update(float delta)
|
|
|
|
{
|
|
|
|
// damping compute
|
|
|
|
if (_dynamic)
|
|
|
|
{
|
|
|
|
_info->body->v.x *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f);
|
|
|
|
_info->body->v.y *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f);
|
|
|
|
_info->body->w *= cpfclamp(1.0f - delta * _angularDamping, 0.0f, 1.0f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-29 17:31:35 +08:00
|
|
|
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)));
|
|
|
|
}
|
|
|
|
|
2013-09-10 17:36:49 +08:00
|
|
|
#elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
NS_CC_END
|
|
|
|
|
|
|
|
#endif // CC_USE_PHYSICS
|