Merge pull request #3916 from boyu0/iss2771_physical

[ci skip]issue 2771: physical
This commit is contained in:
minggo 2013-10-10 19:50:19 -07:00
commit 0130aae044
20 changed files with 1188 additions and 450 deletions

View File

@ -44,6 +44,10 @@ THE SOFTWARE.
#include "event_dispatcher/CCEvent.h"
#include "event_dispatcher/CCEventTouch.h"
#ifdef CC_USE_PHYSICS
#include "physics/CCPhysicsBody.h"
#endif
// externals
#include "kazmath/GL/matrix.h"
#include "support/component/CCComponent.h"
@ -128,6 +132,11 @@ Node::Node(void)
, _componentContainer(NULL)
, _eventPriority(0)
, _oldEventPriority(0)
#ifdef CC_USE_PHYSICS
, _physicsBody(nullptr)
, _physicsPositionMark(true)
, _physicsRotationMark(true)
#endif
{
// set default scheduler and actionManager
Director *director = Director::getInstance();
@ -179,6 +188,10 @@ Node::~Node()
CC_SAFE_DELETE(_componentContainer);
removeAllEventListeners();
#ifdef CC_USE_PHYSICS
CC_SAFE_RELEASE(_physicsBody);
#endif
}
bool Node::init()
@ -257,6 +270,15 @@ void Node::setRotation(float newRotation)
{
_rotationX = _rotationY = newRotation;
_transformDirty = _inverseDirty = true;
#ifdef CC_USE_PHYSICS
if (_physicsBody && _physicsRotationMark)
{
_physicsBody->setRotation(newRotation);
}
_physicsRotationMark = true;
#endif
}
float Node::getRotationX() const
@ -340,6 +362,15 @@ void Node::setPosition(const Point& newPosition)
{
_position = newPosition;
_transformDirty = _inverseDirty = true;
#ifdef CC_USE_PHYSICS
if (_physicsBody && _physicsPositionMark)
{
_physicsBody->setPosition(newPosition);
}
_physicsPositionMark = true;
#endif
}
void Node::getPosition(float* x, float* y) const
@ -808,6 +839,7 @@ void Node::visit()
{
return;
}
kmGLPushMatrix();
if (_grid && _grid->isActive())
@ -1268,6 +1300,16 @@ Point Node::convertTouchToNodeSpaceAR(Touch *touch) const
void Node::updateTransform()
{
#ifdef CC_USE_PHYSICS
if (_physicsBody)
{
_physicsPositionMark = false;
_physicsRotationMark = false;
setPosition(_physicsBody->getPosition());
setRotation(_physicsBody->getRotation());
}
#endif
// Recursively iterate over children
arrayMakeObjectsPerformSelector(_children, updateTransform, Node*);
}
@ -1337,6 +1379,26 @@ void Node::setDirtyForAllEventListeners()
}
}
#ifdef CC_USE_PHYSICS
void Node::setPhysicsBody(PhysicsBody* body)
{
if (_physicsBody != nullptr)
{
_physicsBody->release();
}
_physicsBody = body;
_physicsBody->retain();
_physicsBody->setPosition(getPosition());
_physicsBody->setRotation(getRotation());
}
PhysicsBody* Node::getPhysicsBody() const
{
return _physicsBody;
}
#endif //CC_USE_PHYSICS
// NodeRGBA
NodeRGBA::NodeRGBA()
: _displayedOpacity(255)

View File

@ -38,6 +38,7 @@
#include "script_support/CCScriptSupport.h"
#include "CCProtocols.h"
#include "event_dispatcher/CCEventDispatcher.h"
#include "physics/CCPhysicsSetting.h"
#include <vector>
@ -56,6 +57,9 @@ class Component;
class Dictionary;
class ComponentContainer;
class EventDispatcher;
#ifdef CC_USE_PHYSICS
class PhysicsBody;
#endif
/**
* @addtogroup base_nodes
@ -1374,6 +1378,19 @@ public:
*/
virtual void removeAllComponents();
/// @} end of component functions
#ifdef CC_USE_PHYSICS
/**
* set the PhysicsBody that let the sprite effect with physics
*/
virtual void setPhysicsBody(PhysicsBody* body);
/**
* get the PhysicsBody the sprite have
*/
PhysicsBody* getPhysicsBody() const;
#endif
private:
@ -1486,6 +1503,12 @@ protected:
int _eventPriority; ///< The scene graph based priority of event listener.
int _oldEventPriority; ///< The old scene graph based priority of event listener.
static int _globalEventPriorityIndex; ///< The index of global event priority.
#ifdef CC_USE_PHYSICS
PhysicsBody* _physicsBody; ///< the physicsBody the node have
bool _physicsPositionMark; ///< set this mark to false will skip the setRotation to physicsBody one time
bool _physicsRotationMark; ///< set this mark to false will skip the setPosition to physicsBody one time
#endif
};
//#pragma mark - NodeRGBA

View File

@ -28,12 +28,13 @@ THE SOFTWARE.
#include "CCDirector.h"
#include "CCLayer.h"
#include "sprite_nodes/CCSprite.h"
#include "sprite_nodes/CCSpriteBatchNode.h"
#include "physics/CCPhysicsWorld.h"
NS_CC_BEGIN
Scene::Scene()
#ifdef _physicsWorld
#ifdef CC_USE_PHYSICS
: _physicsWorld(nullptr)
#endif
{
@ -43,6 +44,9 @@ Scene::Scene()
Scene::~Scene()
{
#ifdef CC_USE_PHYSICS
CC_SAFE_DELETE(_physicsWorld);
#endif
}
bool Scene::init()
@ -129,15 +133,23 @@ void Scene::addChildToPhysicsWorld(Node* child)
{
if (_physicsWorld)
{
auto addToPhysicsWorldFunc = [this](Object* node) -> void
std::function<void(Object*)> addToPhysicsWorldFunc = nullptr;
addToPhysicsWorldFunc = [this, &addToPhysicsWorldFunc](Object* child) -> void
{
if (dynamic_cast<Sprite*>(node) != nullptr)
if (dynamic_cast<SpriteBatchNode*>(child) != nullptr)
{
Sprite* sp = dynamic_cast<Sprite*>(node);
if (sp->getPhysicsBody())
Object* subChild = nullptr;
CCARRAY_FOREACH((dynamic_cast<SpriteBatchNode*>(child))->getChildren(), subChild)
{
_physicsWorld->addChild(sp->getPhysicsBody());
addToPhysicsWorldFunc(subChild);
}
}else if (dynamic_cast<Node*>(child) != nullptr)
{
Node* node = dynamic_cast<Node*>(child);
if (node->getPhysicsBody())
{
_physicsWorld->addBody(node->getPhysicsBody());
}
}
};

View File

@ -88,6 +88,7 @@ protected:
#endif // CC_USE_PHYSICS
friend class Layer;
friend class SpriteBatchNode;
};
// end of scene group

View File

@ -42,6 +42,8 @@
#include "Box2D/CCPhysicsJointInfo.h"
#include "chipmunk/CCPhysicsWorldInfo.h"
#include "Box2D/CCPhysicsWorldInfo.h"
#include "chipmunk/CCPhysicsShapeInfo.h"
#include "Box2D/CCPhysicsShapeInfo.h"
#include "chipmunk/CCPhysicsHelper.h"
#include "Box2D/CCPhysicsHelper.h"
@ -62,13 +64,15 @@ PhysicsBody::PhysicsBody()
: _owner(nullptr)
, _world(nullptr)
, _info(nullptr)
, _dynamic(false)
, _dynamic(true)
, _enable(true)
, _massDefault(true)
, _angularDampingDefault(true)
, _mass(MASS_DEFAULT)
, _area(0.0)
, _density(DENSITY_DEFAULT)
, _angularDamping(ANGULARDAMPING_DEFAULT)
, _tag(0)
{
}
@ -76,10 +80,7 @@ PhysicsBody::~PhysicsBody()
{
CC_SAFE_DELETE(_info);
for (auto it = _shapes.begin(); it != _shapes.end(); ++it)
{
delete *it;
}
removeAllShapes();
for (auto it = _joints.begin(); it != _joints.end(); ++it)
{
@ -91,12 +92,11 @@ PhysicsBody::~PhysicsBody()
}
}
PhysicsBody* PhysicsBody::createCircle(float radius)
PhysicsBody* PhysicsBody::create()
{
PhysicsBody* body = new PhysicsBody();
if (body && body->init())
{
body->addCircle(radius);
body->autorelease();
return body;
}
@ -105,12 +105,12 @@ PhysicsBody* PhysicsBody::createCircle(float radius)
return nullptr;
}
PhysicsBody* PhysicsBody::createBox(Size size)
PhysicsBody* PhysicsBody::createCircle(float radius, PhysicsMaterial material)
{
PhysicsBody* body = new PhysicsBody();
if (body && body->init())
{
body->addBox(size);
body->addShape(PhysicsShapeCircle::create(radius, material));
body->autorelease();
return body;
}
@ -119,12 +119,12 @@ PhysicsBody* PhysicsBody::createBox(Size size)
return nullptr;
}
PhysicsBody* PhysicsBody::createPolygon(Point* points, int count)
PhysicsBody* PhysicsBody::createBox(Size size, PhysicsMaterial material)
{
PhysicsBody* body = new PhysicsBody();
if (body && body->init())
{
body->addPolygon(points, count);
body->addShape(PhysicsShapeBox::create(size, material));
body->autorelease();
return body;
}
@ -133,12 +133,12 @@ PhysicsBody* PhysicsBody::createPolygon(Point* points, int count)
return nullptr;
}
PhysicsBody* PhysicsBody::createEdgeSegment(Point a, Point b, float border/* = 1*/)
PhysicsBody* PhysicsBody::createPolygon(Point* points, int count, PhysicsMaterial material)
{
PhysicsBody* body = new PhysicsBody();
if (body && body->initStatic())
if (body && body->init())
{
body->addEdgeSegment(a, b, border);
body->addShape(PhysicsShapePolygon::create(points, count, material));
body->autorelease();
return body;
}
@ -147,27 +147,28 @@ PhysicsBody* PhysicsBody::createEdgeSegment(Point a, Point b, float border/* = 1
return nullptr;
}
PhysicsBody* PhysicsBody::createEdgeBox(Size size, float border/* = 1*/)
PhysicsBody* PhysicsBody::createEdgeSegment(Point a, Point b, PhysicsMaterial material, float border/* = 1*/)
{
PhysicsBody* body = new PhysicsBody();
if (body && body->initStatic())
if (body && body->init())
{
body->addEdgeBox(size, border);
body->addShape(PhysicsShapeEdgeSegment::create(a, b, material, border));
body->_dynamic = false;
body->autorelease();
return body;
}
CC_SAFE_DELETE(body);
return nullptr;
}
PhysicsBody* PhysicsBody::createEdgePolygon(Point* points, int count, float border/* = 1*/)
PhysicsBody* PhysicsBody::createEdgeBox(Size size, PhysicsMaterial material, float border/* = 1*/)
{
PhysicsBody* body = new PhysicsBody();
if (body && body->initStatic())
if (body && body->init())
{
body->addEdgePolygon(points, count, border);
body->addShape(PhysicsShapeEdgeBox::create(size, material, border));
body->_dynamic = false;
body->autorelease();
return body;
}
@ -177,12 +178,13 @@ PhysicsBody* PhysicsBody::createEdgePolygon(Point* points, int count, float bord
return nullptr;
}
PhysicsBody* PhysicsBody::createEdgeChain(Point* points, int count, float border/* = 1*/)
PhysicsBody* PhysicsBody::createEdgePolygon(Point* points, int count, PhysicsMaterial material, float border/* = 1*/)
{
PhysicsBody* body = new PhysicsBody();
if (body && body->initStatic())
if (body && body->init())
{
body->addEdgeChain(points, count);
body->addShape(PhysicsShapeEdgePolygon::create(points, count, material, border));
body->_dynamic = false;
body->autorelease();
return body;
}
@ -192,67 +194,20 @@ PhysicsBody* PhysicsBody::createEdgeChain(Point* points, int count, float border
return nullptr;
}
PhysicsShapeCircle* PhysicsBody::addCircle(float radius, Point offset/* = Point(0, 0)*/)
PhysicsBody* PhysicsBody::createEdgeChain(Point* points, int count, PhysicsMaterial material, float border/* = 1*/)
{
_area = PhysicsHelper::cpfloat2float(cpAreaForCircle(0, radius));
setMass((_massDefault ? 0 : getMass()) + _area * _density);
PhysicsBody* body = new PhysicsBody();
if (body && body->init())
{
body->addShape(PhysicsShapeEdgeChain::create(points, count, material, border));
body->_dynamic = false;
body->autorelease();
return body;
}
setAngularDamping((_angularDampingDefault ? 0 : getAngularDamping())
+ PhysicsHelper::cpfloat2float(cpMomentForCircle(getMass(), 0, radius, PhysicsHelper::point2cpv(offset))));
CC_SAFE_DELETE(body);
return PhysicsShapeCircle::create(this, radius, offset);
}
PhysicsShapeBox* PhysicsBody::addBox(Size size, Point offset/* = Point(0, 0)*/)
{
cpVect cpOffset = PhysicsHelper::size2cpv(size);
cpVect vec[4] = {};
vec[0] = cpv(0, 0);
vec[1] = cpv(0, cpOffset.y);
vec[2] = cpv(cpOffset.x, cpOffset.y);
vec[3] = cpv(cpOffset.x, 0);
_area = PhysicsHelper::cpfloat2float(cpAreaForPoly(4, vec));
setMass((_massDefault ? 0 : getMass()) + _area * _density);
setAngularDamping((_angularDampingDefault ? 0 : getAngularDamping())
+ PhysicsHelper::cpfloat2float(cpMomentForBox(getMass(), PhysicsHelper::float2cpfloat(size.width), PhysicsHelper::float2cpfloat(size.height))));
return PhysicsShapeBox::create(this, size, offset);
}
PhysicsShapePolygon* PhysicsBody::addPolygon(Point* points, int count, Point offset/* = Point(0, 0)*/)
{
cpVect* vec = new cpVect[count];
PhysicsHelper::points2cpvs(points, vec, count);
_area = PhysicsHelper::cpfloat2float(cpAreaForPoly(count, vec));
setAngularDamping((_angularDampingDefault ? 0 : getAngularDamping())
+ PhysicsHelper::cpfloat2float(cpMomentForPoly(getMass(), count, vec, PhysicsHelper::point2cpv(offset))));
delete[] vec;
return PhysicsShapePolygon::create(this, points, count, offset);
}
PhysicsShapeEdgeSegment* PhysicsBody::addEdgeSegment(Point a, Point b, float border/* = 1*/)
{
return PhysicsShapeEdgeSegment::create(this, a, b, border);
}
PhysicsShapeEdgeBox* PhysicsBody::addEdgeBox(Size size, float border/* = 1*/, Point offset/* = Point(0, 0)*/)
{
return PhysicsShapeEdgeBox::create(this, size, border, offset);
}
PhysicsShapeEdgePolygon* PhysicsBody::addEdgePolygon(Point* points, int count, float border/* = 1*/)
{
return PhysicsShapeEdgePolygon::create(this, points, count);
}
PhysicsShapeEdgeChain* PhysicsBody::addEdgeChain(Point* points, int count, float border/* = 1*/)
{
return PhysicsShapeEdgeChain::create(this, points, count, border);
return nullptr;
}
bool PhysicsBody::init()
@ -264,7 +219,6 @@ bool PhysicsBody::init()
_info->body = cpBodyNew(PhysicsHelper::float2cpfloat(_mass), PhysicsHelper::float2cpfloat(_angularDamping));
CC_BREAK_IF(_info->body == nullptr);
_dynamic = true;
return true;
} while (false);
@ -274,36 +228,22 @@ bool PhysicsBody::init()
void PhysicsBody::setDynamic(bool dynamic)
{
_dynamic = dynamic;
if (_world != nullptr && cpBodyIsStatic(_info->body) == (cpBool)_dynamic)
if (dynamic != _dynamic)
{
if (dynamic)
{
cpSpaceConvertBodyToDynamic(_world->_info->space, _info->body, _mass, _angularDamping);
cpBodySetMass(_info->body, PhysicsHelper::float2cpfloat(_mass));
cpBodySetMoment(_info->body, PhysicsHelper::float2cpfloat(_angularDamping));
}else
{
cpSpaceConvertBodyToStatic(_world->_info->space, _info->body);
cpBodySetMass(_info->body, PHYSICS_INFINITY);
cpBodySetMoment(_info->body, PHYSICS_INFINITY);
}
_dynamic = dynamic;
}
}
bool PhysicsBody::initStatic()
{
do
{
_info = new PhysicsBodyInfo();
CC_BREAK_IF(_info == nullptr);
_info->body = cpBodyNewStatic();
CC_BREAK_IF(_info->body == nullptr);
_dynamic = false;
return true;
} while (false);
return false;
}
void PhysicsBody::setPosition(Point position)
{
cpBodySetPos(_info->body, PhysicsHelper::point2cpv(position));
@ -329,9 +269,79 @@ void PhysicsBody::addShape(PhysicsShape* shape)
{
if (shape == nullptr) return;
_shapes.push_back(shape);
// already added
if (shape->getBody() == this)
{
return;
}
else if (shape->getBody() != nullptr)
{
shape->getBody()->removeShape(shape);
}
if (_world != nullptr) _world->addShape(shape);
// reset the body
if (shape->_info->body != _info->body)
{
for (cpShape* subShape : shape->_info->shapes)
{
cpShapeSetBody(subShape, _info->body);
}
shape->_info->body = _info->body;
}
// add shape to body
if (std::find(_shapes.begin(), _shapes.end(), shape) == _shapes.end())
{
shape->setBody(this);
_shapes.push_back(shape);
// calculate the mass, area and desity
_area += shape->getArea();
if (_mass == PHYSICS_INFINITY || shape->getMass() == PHYSICS_INFINITY)
{
_mass = PHYSICS_INFINITY;
_massDefault = false;
}else
{
if (shape->getMass() > 0)
{
_mass = (_massDefault ? 0 : _mass) + shape->getMass();
_massDefault = false;
}
}
cpBodySetMass(_info->body, _mass);
if (!_massDefault)
{
if (_mass == PHYSICS_INFINITY)
{
_density = PHYSICS_INFINITY;
}else
{
_density = _mass / _area;
}
}
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);
}
}
if (_world != nullptr) _world->addShape(shape);
shape->retain();
}
}
void PhysicsBody::applyForce(Point force)
@ -367,6 +377,16 @@ void PhysicsBody::setMass(float mass)
cpBodySetMass(_info->body, PhysicsHelper::float2cpfloat(_mass));
}
void PhysicsBody::setVelocity(Point velocity)
{
cpBodySetVel(_info->body, PhysicsHelper::point2cpv(velocity));
}
Point PhysicsBody::getVelocity()
{
return PhysicsHelper::cpv2point(cpBodyGetVel(_info->body));
}
void PhysicsBody::setAngularDamping(float angularDamping)
{
_angularDamping = angularDamping;
@ -375,6 +395,120 @@ void PhysicsBody::setAngularDamping(float angularDamping)
cpBodySetMoment(_info->body, _angularDamping);
}
PhysicsShape* PhysicsBody::getShapeByTag(int tag)
{
for (auto shape : _shapes)
{
if (shape->getTag() == tag)
{
return shape;
}
}
return nullptr;
}
void PhysicsBody::removeShapeByTag(int tag)
{
for (auto shape : _shapes)
{
if (shape->getTag() == tag)
{
removeShape(shape);
return;
}
}
}
void PhysicsBody::removeShape(PhysicsShape* shape)
{
auto it = std::find(_shapes.begin(), _shapes.end(), shape);
if (it != _shapes.end())
{
if (_world)
{
_world->removeShape(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;
}
}
shape->release();
}
}
void PhysicsBody::removeAllShapes()
{
for (auto shape : _shapes)
{
if (_world)
{
_world->removeShape(shape);
}
delete shape;
}
_shapes.clear();
}
void PhysicsBody::setEnable(bool enable)
{
if (_enable != enable)
{
_enable = enable;
if (_world)
{
if (enable)
{
_world->addBody(this);
}else
{
_world->removeBody(this);
}
}
}
}
//Clonable* PhysicsBody::clone() const
//{
// PhysicsBody* body = new PhysicsBody();

View File

@ -30,22 +30,21 @@
#include "cocoa/CCObject.h"
#include "cocoa/CCGeometry.h"
#include "CCPhysicsShape.h"
#include <vector>
NS_CC_BEGIN
class Sprite;
class PhysicsWorld;
class PhysicsJoint;
class PhysicsShape;
class PhysicsShapeCircle;
class PhysicsShapeBox;
class PhysicsShapePolygon;
class PhysicsShapeEdgeSegment;
class PhysicsShapeEdgeBox;
class PhysicsShapeEdgePolygon;
class PhysicsShapeEdgeChain;
class PhysicsBodyInfo;
const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT = {0.0f, 1.0f, 1.0f};
/**
* A body affect by physics.
* it can attach one or more shapes.
@ -53,68 +52,39 @@ class PhysicsBodyInfo;
class PhysicsBody : public Object//, public Clonable
{
public:
static PhysicsBody* create();
/**
* @brief Create a body contains a circle shape.
*/
static PhysicsBody* createCircle(float radius);
static PhysicsBody* createCircle(float radius, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
/**
* @brief Create a body contains a box shape.
*/
static PhysicsBody* createBox(Size size);
static PhysicsBody* createBox(Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
/**
* @brief Create a body contains a polygon shape.
* points is an array of Point structs defining a convex hull with a clockwise winding.
*/
static PhysicsBody* createPolygon(Point* points, int count);
static PhysicsBody* createPolygon(Point* points, int count, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
/**
* @brief Create a body contains a EdgeSegment shape.
*/
static PhysicsBody* createEdgeSegment(Point a, Point b, float border = 1);
static PhysicsBody* createEdgeSegment(Point a, Point b, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT, float border = 1);
/**
* @brief Create a body contains a EdgeBox shape.
*/
static PhysicsBody* createEdgeBox(Size size, float border = 1);
static PhysicsBody* createEdgeBox(Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT, float border = 1);
/**
* @brief Create a body contains a EdgePolygon shape.
*/
static PhysicsBody* createEdgePolygon(Point* points, int count, float border = 1);
static PhysicsBody* createEdgePolygon(Point* points, int count, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT, float border = 1);
/**
* @brief Create a body contains a EdgeChain shape.
*/
static PhysicsBody* createEdgeChain(Point* points, int count, float border = 1);
static PhysicsBody* createEdgeChain(Point* points, int count, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT, float border = 1);
/**
* @brief Attach a circle shape with body
*/
virtual PhysicsShapeCircle* addCircle(float radius, Point offset = Point(0, 0));
/**
* @brief Attach a box shape with body
*/
virtual PhysicsShapeBox* addBox(Size size, Point offset = Point(0, 0));
/**
* @brief Attach a polygon shape with body
*/
virtual PhysicsShapePolygon* addPolygon(Point* points, int count, Point offset = Point(0, 0));
/**
* @brief Attach a edge segment shape with body
*/
virtual PhysicsShapeEdgeSegment* addEdgeSegment(Point a, Point b, float border = 1);
/**
* @brief Attach a edge box shape with body
*/
virtual PhysicsShapeEdgeBox* addEdgeBox(Size size, float border = 1, Point offset = Point(0, 0));
/**
* @brief Attach a edge polygon shape with body
* points is an array of Point structs defining a convex hull with a clockwise winding.
*/
virtual PhysicsShapeEdgePolygon* addEdgePolygon(Point* points, int count, float border = 1);
/**
* @brief Attach a edge chain shape with body
* points is an array of Point structs defining a convex hull with a clockwise winding.
*/
virtual PhysicsShapeEdgeChain* addEdgeChain(Point* points, int count, float border = 1);
virtual void addShape(PhysicsShape* shape);
/**
* @brief Applies a immediate force to body.
@ -137,6 +107,9 @@ public:
*/
virtual void applyTorque(float torque);
virtual void setVelocity(Point velocity);
virtual Point getVelocity();
/*
* @brief get the body shapes.
*/
@ -145,10 +118,12 @@ public:
* @brief get the first body shapes.
*/
inline PhysicsShape* getShape() { return _shapes.size() >= 1 ? _shapes.front() : nullptr; }
PhysicsShape* getShapeByTag(int tag);
/*
* @brief remove a shape from body
*/
void removeShape(PhysicsShape* shape);
void removeShapeByTag(int tag);
/*
* @brief remove all shapes
*/
@ -215,14 +190,18 @@ public:
//virtual Clonable* clone() const override;
inline bool isEnable() { return _enable; }
void setEnable(bool enable);
inline int getTag() { return _tag; }
inline void setTag(int tag) { _tag = tag; }
protected:
bool init();
bool initStatic();
virtual void setPosition(Point position);
virtual void setRotation(float rotation);
virtual void addShape(PhysicsShape* shape);
protected:
PhysicsBody();
@ -235,12 +214,14 @@ protected:
PhysicsWorld* _world;
PhysicsBodyInfo* _info;
bool _dynamic;
bool _enable;
bool _massDefault;
bool _angularDampingDefault;
float _mass;
float _area;
float _density;
float _angularDamping;
int _tag;
int _categoryBitmask;
int _contactTestBitmask;
@ -249,7 +230,7 @@ protected:
friend class PhysicsWorld;
friend class PhysicsShape;
friend class PhysicsJoint;
friend class Sprite;
friend class Node;
};
NS_CC_END

View File

@ -46,6 +46,8 @@ PhysicsJoint::PhysicsJoint()
: _bodyA(nullptr)
, _bodyB(nullptr)
, _info(nullptr)
, _enable(false)
, _tag(0)
{
}
@ -79,6 +81,21 @@ bool PhysicsJoint::init(cocos2d::PhysicsBody *a, cocos2d::PhysicsBody *b)
return false;
}
void PhysicsJoint::setEnable(bool enable)
{
if (_enable != enable)
{
_enable = enable;
if (enable)
{
}else
{
}
}
}
PhysicsJointPin::PhysicsJointPin()
{

View File

@ -49,6 +49,10 @@ protected:
public:
PhysicsBody* getBodyA() { return _bodyA; }
PhysicsBody* getBodyB() { return _bodyB; }
inline int getTag() { return _tag; }
inline void setTag(int tag) { _tag = tag; }
inline bool isEnable() { return _enable; }
void setEnable(bool enable);
protected:
bool init(PhysicsBody* a, PhysicsBody* b);
@ -62,8 +66,11 @@ protected:
PhysicsBody* _bodyA;
PhysicsBody* _bodyB;
PhysicsJointInfo* _info;
bool _enable;
int _tag;
friend class PhysicsBody;
friend class PhysicsWorld;
};
/*

View File

@ -43,4 +43,9 @@
#define CC_USE_PHYSICS
#endif
namespace cocos2d
{
extern const float PHYSICS_INFINITY;
}
#endif // __CCPHYSICS_SETTING_H__

View File

@ -32,6 +32,7 @@
#endif
#include "CCPhysicsBody.h"
#include "CCPhysicsWorld.h"
#include "chipmunk/CCPhysicsBodyInfo.h"
#include "Box2D/CCPhysicsBodyInfo.h"
@ -45,6 +46,11 @@ PhysicsShape::PhysicsShape()
: _body(nullptr)
, _info(nullptr)
, _type(Type::UNKNOWN)
, _area(0)
, _mass(0)
, _angularDamping(0)
, _tag(0)
, _enable(true)
{
}
@ -54,20 +60,41 @@ PhysicsShape::~PhysicsShape()
CC_SAFE_DELETE(_info);
}
bool PhysicsShape::init(PhysicsBody* body, Type type)
bool PhysicsShape::init(Type type, PhysicsMaterial material/* = MaterialDefault*/)
{
if (body == nullptr) return false;
_body = body;
_info = new PhysicsShapeInfo(this);
if (_info == nullptr) return false;
_type = type;
_material = material;
return true;
}
void PhysicsShape::setMass(float mass)
{
}
void PhysicsShape::setEnable(bool enable)
{
if (_enable != enable)
{
_enable = enable;
if (_body->getWorld() && _body->isEnable())
{
if (enable)
{
_body->getWorld()->addShape(this);
}else
{
_body->getWorld()->removeShape(this);
}
}
}
}
void PhysicsShape::addToBody()
{
if(_body != nullptr) _body->addShape(this);
@ -75,7 +102,13 @@ void PhysicsShape::addToBody()
PhysicsBodyInfo* PhysicsShape::bodyInfo() const
{
return _body->_info;
if (_body != nullptr)
{
return _body->_info;
}else
{
return nullptr;
}
}
PhysicsShapeCircle::PhysicsShapeCircle()
@ -150,12 +183,38 @@ PhysicsShapeEdgeSegment::~PhysicsShapeEdgeSegment()
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
void PhysicsShape::initEnd()
{
for (auto shape : _info->shapes)
{
cpShapeSetElasticity(shape, _material.elasticity);
cpShapeSetFriction(shape, _material.friction);
}
}
void PhysicsShape::setElasticity(float elasticity)
{
for (cpShape* shape : _info->shapes)
{
cpShapeSetElasticity(shape, PhysicsHelper::float2cpfloat(elasticity));
}
}
void PhysicsShape::setFriction(float friction)
{
for (cpShape* shape : _info->shapes)
{
cpShapeSetFriction(shape, PhysicsHelper::float2cpfloat(friction));
}
}
// PhysicsShapeCircle
PhysicsShapeCircle* PhysicsShapeCircle::create(PhysicsBody* body, float radius, Point offset/* = Point(0, 0)*/)
PhysicsShapeCircle* PhysicsShapeCircle::create(float radius, PhysicsMaterial material/* = MaterialDefault*/, Point offset/* = Point(0, 0)*/)
{
PhysicsShapeCircle* shape = new PhysicsShapeCircle();
if (shape && shape->init(body, radius, offset))
if (shape && shape->init(radius, material, offset))
{
shape->autorelease();
return shape;
}
@ -163,19 +222,23 @@ PhysicsShapeCircle* PhysicsShapeCircle::create(PhysicsBody* body, float radius,
return nullptr;
}
bool PhysicsShapeCircle::init(PhysicsBody* body, float radius, Point offset /*= Point(0, 0)*/)
bool PhysicsShapeCircle::init(float radius, PhysicsMaterial material/* = MaterialDefault*/, Point offset /*= Point(0, 0)*/)
{
do
{
CC_BREAK_IF(!PhysicsShape::init(body, Type::CIRCLE));
CC_BREAK_IF(!PhysicsShape::init(Type::CIRCLE, material));
cpShape* shape = cpCircleShapeNew(bodyInfo()->body, radius, PhysicsHelper::point2cpv(offset));
cpShape* shape = cpCircleShapeNew(_info->shareBody, radius, PhysicsHelper::point2cpv(offset));
CC_BREAK_IF(shape == nullptr);
_info->add(shape);
addToBody();
_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));
_info->add(shape);
initEnd();
return true;
} while (false);
@ -183,11 +246,12 @@ bool PhysicsShapeCircle::init(PhysicsBody* body, float radius, Point offset /*=
}
// PhysicsShapeEdgeSegment
PhysicsShapeEdgeSegment* PhysicsShapeEdgeSegment::create(PhysicsBody* body, Point a, Point b, float border/* = 1*/)
PhysicsShapeEdgeSegment* PhysicsShapeEdgeSegment::create(Point a, Point b, PhysicsMaterial material/* = MaterialDefault*/, float border/* = 1*/)
{
PhysicsShapeEdgeSegment* shape = new PhysicsShapeEdgeSegment();
if (shape && shape->init(body, a, b, border))
if (shape && shape->init(a, b, material, border))
{
shape->autorelease();
return shape;
}
@ -195,21 +259,25 @@ PhysicsShapeEdgeSegment* PhysicsShapeEdgeSegment::create(PhysicsBody* body, Poin
return nullptr;
}
bool PhysicsShapeEdgeSegment::init(PhysicsBody* body, Point a, Point b, float border/* = 1*/)
bool PhysicsShapeEdgeSegment::init(Point a, Point b, PhysicsMaterial material/* = MaterialDefault*/, float border/* = 1*/)
{
do
{
CC_BREAK_IF(!PhysicsShape::init(body, Type::EDGESEGMENT));
CC_BREAK_IF(!PhysicsShape::init(Type::EDGESEGMENT, material));
cpShape* shape = cpSegmentShapeNew(bodyInfo()->body,
cpShape* shape = cpSegmentShapeNew(_info->shareBody,
PhysicsHelper::point2cpv(a),
PhysicsHelper::point2cpv(b),
PhysicsHelper::float2cpfloat(border));
CC_BREAK_IF(shape == nullptr);
_mass = PHYSICS_INFINITY;
_angularDamping = PHYSICS_INFINITY;
_info->add(shape);
addToBody();
initEnd();
return true;
} while (false);
@ -218,11 +286,12 @@ bool PhysicsShapeEdgeSegment::init(PhysicsBody* body, Point a, Point b, float bo
}
// PhysicsShapeBox
PhysicsShapeBox* PhysicsShapeBox::create(PhysicsBody* body, Size size, Point offset/* = Point(0, 0)*/)
PhysicsShapeBox* PhysicsShapeBox::create(Size size, PhysicsMaterial material/* = MaterialDefault*/, Point offset/* = Point(0, 0)*/)
{
PhysicsShapeBox* shape = new PhysicsShapeBox();
if (shape && shape->init(body, size, offset))
if (shape && shape->init(size, material, offset))
{
shape->autorelease();
return shape;
}
@ -230,18 +299,23 @@ PhysicsShapeBox* PhysicsShapeBox::create(PhysicsBody* body, Size size, Point off
return nullptr;
}
bool PhysicsShapeBox::init(PhysicsBody* body, Size size, Point offset /*= Point(0, 0)*/)
bool PhysicsShapeBox::init(Size size, PhysicsMaterial material/* = MaterialDefault*/, Point offset /*= Point(0, 0)*/)
{
do
{
CC_BREAK_IF(!PhysicsShape::init(body, Type::BOX));
CC_BREAK_IF(!PhysicsShape::init(Type::BOX, material));
cpShape* shape = cpBoxShapeNew(bodyInfo()->body, PhysicsHelper::float2cpfloat(size.width), PhysicsHelper::float2cpfloat(size.height));
cpShape* shape = cpBoxShapeNew(_info->shareBody, PhysicsHelper::float2cpfloat(size.width), PhysicsHelper::float2cpfloat(size.height));
CC_BREAK_IF(shape == nullptr);
_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));
_info->add(shape);
addToBody();
initEnd();
return true;
} while (false);
@ -250,11 +324,12 @@ bool PhysicsShapeBox::init(PhysicsBody* body, Size size, Point offset /*= Point(
}
// PhysicsShapeCircle
PhysicsShapePolygon* PhysicsShapePolygon::create(PhysicsBody* body, Point* points, int count, Point offset/* = Point(0, 0)*/)
PhysicsShapePolygon* PhysicsShapePolygon::create(Point* points, int count, PhysicsMaterial material/* = MaterialDefault*/, Point offset/* = Point(0, 0)*/)
{
PhysicsShapePolygon* shape = new PhysicsShapePolygon();
if (shape && shape->init(body, points, count, offset))
if (shape && shape->init(points, count, material, offset))
{
shape->autorelease();
return shape;
}
@ -262,20 +337,26 @@ PhysicsShapePolygon* PhysicsShapePolygon::create(PhysicsBody* body, Point* point
return nullptr;
}
bool PhysicsShapePolygon::init(PhysicsBody* body, Point* points, int count, Point offset /*= Point(0, 0)*/)
bool PhysicsShapePolygon::init(Point* points, int count, PhysicsMaterial material/* = MaterialDefault*/, Point offset /*= Point(0, 0)*/)
{
do
{
CC_BREAK_IF(!PhysicsShape::init(body, Type::POLYGEN));
CC_BREAK_IF(!PhysicsShape::init(Type::POLYGEN, material));
cpVect* vecs = new cpVect[count];
PhysicsHelper::points2cpvs(points, vecs, count);
cpShape* shape = cpPolyShapeNew(bodyInfo()->body, count, vecs, PhysicsHelper::point2cpv(offset));
cpShape* shape = cpPolyShapeNew(_info->shareBody, count, vecs, PhysicsHelper::point2cpv(offset));
CC_SAFE_DELETE(vecs);
CC_BREAK_IF(shape == nullptr);
_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));
_info->add(shape);
addToBody();
initEnd();
return true;
} while (false);
@ -284,11 +365,12 @@ bool PhysicsShapePolygon::init(PhysicsBody* body, Point* points, int count, Poin
}
// PhysicsShapeEdgeBox
PhysicsShapeEdgeBox* PhysicsShapeEdgeBox::create(PhysicsBody* body, Size size, float border/* = 1*/, Point offset/* = Point(0, 0)*/)
PhysicsShapeEdgeBox* PhysicsShapeEdgeBox::create(Size size, PhysicsMaterial material/* = MaterialDefault*/, float border/* = 1*/, Point offset/* = Point(0, 0)*/)
{
PhysicsShapeEdgeBox* shape = new PhysicsShapeEdgeBox();
if (shape && shape->init(body, size, border, offset))
if (shape && shape->init(size, material, border, offset))
{
shape->autorelease();
return shape;
}
@ -296,33 +378,32 @@ PhysicsShapeEdgeBox* PhysicsShapeEdgeBox::create(PhysicsBody* body, Size size, f
return nullptr;
}
bool PhysicsShapeEdgeBox::init(PhysicsBody* body, Size size, float border/* = 1*/, Point offset/*= Point(0, 0)*/)
bool PhysicsShapeEdgeBox::init(Size size, PhysicsMaterial material/* = MaterialDefault*/, float border/* = 1*/, Point offset/*= Point(0, 0)*/)
{
do
{
CC_BREAK_IF(!PhysicsShape::init(body, Type::EDGEBOX));
Point bodyPos = body->getPosition();
CC_BREAK_IF(!PhysicsShape::init(Type::EDGEBOX, material));
cpVect vec[4] = {};
vec[0] = PhysicsHelper::point2cpv(Point(bodyPos.x-size.width/2+offset.x, bodyPos.y-size.height/2+offset.y));
vec[1] = PhysicsHelper::point2cpv(Point(bodyPos.x+size.width/2+offset.x, bodyPos.y-size.height/2+offset.y));
vec[2] = PhysicsHelper::point2cpv(Point(bodyPos.x+size.width/2+offset.x, bodyPos.y+size.height/2+offset.y));
vec[3] = PhysicsHelper::point2cpv(Point(bodyPos.x-size.width/2+offset.x, bodyPos.y+size.height/2+offset.y));
vec[0] = PhysicsHelper::point2cpv(Point(-size.width/2+offset.x, -size.height/2+offset.y));
vec[1] = PhysicsHelper::point2cpv(Point(+size.width/2+offset.x, -size.height/2+offset.y));
vec[2] = PhysicsHelper::point2cpv(Point(+size.width/2+offset.x, +size.height/2+offset.y));
vec[3] = PhysicsHelper::point2cpv(Point(-size.width/2+offset.x, +size.height/2+offset.y));
int i = 0;
for (; i < 4; ++i)
{
cpShape* shape = cpSegmentShapeNew(bodyInfo()->body, vec[i], vec[(i+1)%4],
cpShape* shape = cpSegmentShapeNew(_info->shareBody, vec[i], vec[(i+1)%4],
PhysicsHelper::float2cpfloat(border));
CC_BREAK_IF(shape == nullptr);
cpShapeSetElasticity(shape, 1.0f);
cpShapeSetFriction(shape, 1.0f);
_info->add(shape);
}
CC_BREAK_IF(i < 4);
addToBody();
_mass = PHYSICS_INFINITY;
_angularDamping = PHYSICS_INFINITY;
initEnd();
return true;
} while (false);
@ -331,11 +412,12 @@ bool PhysicsShapeEdgeBox::init(PhysicsBody* body, Size size, float border/* = 1*
}
// PhysicsShapeEdgeBox
PhysicsShapeEdgePolygon* PhysicsShapeEdgePolygon::create(PhysicsBody* body, Point* points, int count, float border/* = 1*/)
PhysicsShapeEdgePolygon* PhysicsShapeEdgePolygon::create(Point* points, int count, PhysicsMaterial material/* = MaterialDefault*/, float border/* = 1*/)
{
PhysicsShapeEdgePolygon* shape = new PhysicsShapeEdgePolygon();
if (shape && shape->init(body, points, count, border))
{
if (shape && shape->init(points, count, material, border))
{
shape->autorelease();
return shape;
}
@ -343,12 +425,12 @@ PhysicsShapeEdgePolygon* PhysicsShapeEdgePolygon::create(PhysicsBody* body, Poin
return nullptr;
}
bool PhysicsShapeEdgePolygon::init(PhysicsBody* body, Point* points, int count, float border/* = 1*/)
bool PhysicsShapeEdgePolygon::init(Point* points, int count, PhysicsMaterial material/* = MaterialDefault*/, float border/* = 1*/)
{
cpVect* vec = nullptr;
do
{
CC_BREAK_IF(!PhysicsShape::init(body, Type::EDGEPOLYGEN));
CC_BREAK_IF(!PhysicsShape::init(Type::EDGEPOLYGEN, material));
vec = new cpVect[count];
PhysicsHelper::points2cpvs(points, vec, count);
@ -356,18 +438,22 @@ bool PhysicsShapeEdgePolygon::init(PhysicsBody* body, Point* points, int count,
int i = 0;
for (; i < count; ++i)
{
cpShape* shape = cpSegmentShapeNew(bodyInfo()->body, vec[i], vec[(i+1)%count],
cpShape* shape = cpSegmentShapeNew(_info->shareBody, vec[i], vec[(i+1)%count],
PhysicsHelper::float2cpfloat(border));
CC_BREAK_IF(shape == nullptr);
cpShapeSetElasticity(shape, 1.0f);
cpShapeSetFriction(shape, 1.0f);
_info->add(shape);
}
CC_SAFE_DELETE(vec);
CC_BREAK_IF(i < count);
addToBody();
_mass = PHYSICS_INFINITY;
_angularDamping = PHYSICS_INFINITY;
initEnd();
if (vec != nullptr) delete[] vec;
return true;
} while (false);
@ -377,11 +463,12 @@ bool PhysicsShapeEdgePolygon::init(PhysicsBody* body, Point* points, int count,
}
// PhysicsShapeEdgeChain
PhysicsShapeEdgeChain* PhysicsShapeEdgeChain::create(PhysicsBody* body, Point* points, int count, float border/* = 1*/)
PhysicsShapeEdgeChain* PhysicsShapeEdgeChain::create(Point* points, int count, PhysicsMaterial material/* = MaterialDefault*/, float border/* = 1*/)
{
PhysicsShapeEdgeChain* shape = new PhysicsShapeEdgeChain();
if (shape && shape->init(body, points, count, border))
if (shape && shape->init(points, count, material, border))
{
shape->autorelease();
return shape;
}
@ -389,12 +476,12 @@ PhysicsShapeEdgeChain* PhysicsShapeEdgeChain::create(PhysicsBody* body, Point* p
return nullptr;
}
bool PhysicsShapeEdgeChain::init(PhysicsBody* body, Point* points, int count, float border/* = 1*/)
bool PhysicsShapeEdgeChain::init(Point* points, int count, PhysicsMaterial material/* = MaterialDefault*/, float border/* = 1*/)
{
cpVect* vec = nullptr;
do
{
CC_BREAK_IF(!PhysicsShape::init(body, Type::EDGECHAIN));
CC_BREAK_IF(!PhysicsShape::init(Type::EDGECHAIN, material));
vec = new cpVect[count];
PhysicsHelper::points2cpvs(points, vec, count);
@ -402,18 +489,21 @@ bool PhysicsShapeEdgeChain::init(PhysicsBody* body, Point* points, int count, fl
int i = 0;
for (; i < count - 1; ++i)
{
cpShape* shape = cpSegmentShapeNew(bodyInfo()->body, vec[i], vec[i+1],
cpShape* shape = cpSegmentShapeNew(_info->shareBody, vec[i], vec[i+1],
PhysicsHelper::float2cpfloat(border));
CC_BREAK_IF(shape == nullptr);
cpShapeSetElasticity(shape, 1.0f);
cpShapeSetFriction(shape, 1.0f);
_info->add(shape);
}
if (vec != nullptr) delete[] vec;
CC_BREAK_IF(i < count);
addToBody();
_mass = PHYSICS_INFINITY;
_angularDamping = PHYSICS_INFINITY;
initEnd();
if (vec != nullptr) delete[] vec;
return true;
} while (false);
@ -422,7 +512,6 @@ bool PhysicsShapeEdgeChain::init(PhysicsBody* body, Point* points, int count, fl
return false;
}
#elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
#endif

View File

@ -37,7 +37,27 @@ class PhysicsShapeInfo;
class PhysicsBody;
class PhysicsBodyInfo;
/**
typedef struct PhysicsMaterial
{
float density;
float elasticity;
float friction;
PhysicsMaterial()
: density(0.0f)
, elasticity(0.0f)
, friction(0.0f){}
PhysicsMaterial(float density, float elasticity, float friction)
: density(density)
, elasticity(elasticity)
, friction(friction){}
}PhysicsMaterial;
const PhysicsMaterial PHYSICSSHAPE_MATERIAL_DEFAULT = {0.0f, 1.0f, 1.0f};
/**
* @brief A shape for body. You do not create PhysicsWorld objects directly, instead, you can view PhysicsBody to see how to create it.
*/
class PhysicsShape : public Object
@ -58,16 +78,32 @@ public:
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 void setTag(int tag) { _tag = tag; }
inline int getTag() { return _tag; }
void setEnable(bool enable);
inline bool isEnable() { return _enable; }
void addToBody();
inline float getMass() { return _mass; }
void setMass(float mass);
inline float getDensity() { return _material.density; }
void setDensity(float density);
void setElasticity(float elasticity);
void setFriction(float friction);
protected:
bool init(PhysicsBody* body, Type type);
bool init(Type type, PhysicsMaterial material);
void initEnd();
/**
* @brief PhysicsShape is PhysicsBody's friend class, but all the subclasses isn't. so this method is use for subclasses to catch the bodyInfo from PhysicsBody.
*/
PhysicsBodyInfo* bodyInfo() const;
void addToBody();
inline void setBody(PhysicsBody* body) { _body = body; }
protected:
PhysicsShape();
@ -77,6 +113,12 @@ protected:
PhysicsBody* _body;
PhysicsShapeInfo* _info;
Type _type;
float _area;
float _mass;
float _angularDamping;
PhysicsMaterial _material;
int _tag;
bool _enable;
friend class PhysicsWorld;
friend class PhysicsBody;
@ -85,9 +127,11 @@ protected:
/** A circle shape */
class PhysicsShapeCircle : public PhysicsShape
{
public:
static PhysicsShapeCircle* create(float radius, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
protected:
static PhysicsShapeCircle* create(PhysicsBody* body, float radius, Point offset = Point(0, 0));
bool init(PhysicsBody* body, float radius, Point offset = Point(0, 0));
bool init(float radius, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
protected:
PhysicsShapeCircle();
@ -99,9 +143,11 @@ protected:
/** A box shape */
class PhysicsShapeBox : public PhysicsShape
{
public:
static PhysicsShapeBox* create(Size size, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
protected:
static PhysicsShapeBox* create(PhysicsBody* body, Size size, Point offset = Point(0, 0));
bool init(PhysicsBody* body, Size size, Point offset = Point(0, 0));
bool init(Size size, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
protected:
PhysicsShapeBox();
@ -113,9 +159,11 @@ protected:
/** A polygon shape */
class PhysicsShapePolygon : public PhysicsShape
{
public:
static PhysicsShapePolygon* create(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
protected:
static PhysicsShapePolygon* create(PhysicsBody* body, Point* points, int count, Point offset = Point(0, 0));
bool init(PhysicsBody* body, Point* points, int count, Point offset = Point(0, 0));
bool init(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
protected:
PhysicsShapePolygon();
@ -127,9 +175,11 @@ protected:
/** A segment shape */
class PhysicsShapeEdgeSegment : public PhysicsShape
{
public:
static PhysicsShapeEdgeSegment* create(Point a, Point b, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
protected:
static PhysicsShapeEdgeSegment* create(PhysicsBody* body, Point a, Point b, float border = 1);
bool init(PhysicsBody* body, Point a, Point b, float border = 1);
bool init(Point a, Point b, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
protected:
PhysicsShapeEdgeSegment();
@ -142,10 +192,10 @@ protected:
class PhysicsShapeEdgeBox : public PhysicsShape
{
public:
static PhysicsShapeEdgeBox* create(PhysicsBody* body, Size size, float border = 0, Point offset = Point(0, 0));
static PhysicsShapeEdgeBox* create(Size size, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 0, Point offset = Point(0, 0));
protected:
bool init(PhysicsBody* body, Size size, float border = 1, Point offset = Point(0, 0));
bool init(Size size, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1, Point offset = Point(0, 0));
protected:
PhysicsShapeEdgeBox();
@ -158,10 +208,10 @@ protected:
class PhysicsShapeEdgePolygon : public PhysicsShape
{
public:
static PhysicsShapeEdgePolygon* create(PhysicsBody* body, Point* points, int count, float border = 1);
static PhysicsShapeEdgePolygon* create(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
protected:
bool init(PhysicsBody* body, Point* points, int count, float border = 1);
bool init(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
protected:
PhysicsShapeEdgePolygon();
@ -174,10 +224,10 @@ protected:
class PhysicsShapeEdgeChain : public PhysicsShape
{
public:
static PhysicsShapeEdgeChain* create(PhysicsBody* body, Point* points, int count, float border = 1);
static PhysicsShapeEdgeChain* create(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
protected:
bool init(PhysicsBody* body, Point* points, int count, float border = 1);
bool init(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
protected:
PhysicsShapeEdgeChain();

View File

@ -34,6 +34,7 @@
#include "CCPhysicsBody.h"
#include "CCPhysicsShape.h"
#include "CCPhysicsContact.h"
#include "CCPhysicsJoint.h"
#include "chipmunk/CCPhysicsWorldInfo.h"
#include "Box2D/CCPhysicsWorldInfo.h"
@ -43,6 +44,8 @@
#include "Box2D/CCPhysicsShapeInfo.h"
#include "chipmunk/CCPhysicsContactInfo.h"
#include "Box2D/CCPhysicsContactInfo.h"
#include "chipmunk/CCPhysicsJointInfo.h"
#include "Box2D/CCPhysicsJointInfo.h"
#include "chipmunk/CCPhysicsHelper.h"
#include "draw_nodes/CCDrawNode.h"
@ -50,10 +53,14 @@
#include "layers_scenes_transitions_nodes/CCScene.h"
#include "CCDirector.h"
#include <algorithm>
NS_CC_BEGIN
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
const float PHYSICS_INFINITY = INFINITY;
int PhysicsWorld::collisionBeginCallbackFunc(cpArbiter *arb, struct cpSpace *space, void *data)
{
PhysicsWorld* world = static_cast<PhysicsWorld*>(data);
@ -110,34 +117,69 @@ bool PhysicsWorld::init()
return true;
}
void PhysicsWorld::addJoint(PhysicsJoint* joint)
{
auto it = std::find(_joints.begin(), _joints.end(), joint);
if (it == _joints.end())
{
_joints.push_back(joint);
if (!cpSpaceContainsConstraint(_info->space, joint->_info->joint))
{
cpSpaceAddConstraint(_info->space, joint->_info->joint);
}
}
}
void PhysicsWorld::removeJoint(PhysicsJoint* joint)
{
}
void PhysicsWorld::removeAllJoints()
{
}
void PhysicsWorld::addShape(PhysicsShape* shape)
{
for (auto it = shape->_info->shapes.begin(); it != shape->_info->shapes.end(); it++)
for (auto cps : shape->_info->shapes)
{
if (cpSpaceContainsShape(_info->space, cps))
{
continue;
}
if (cpBodyIsStatic(shape->getBody()->_info->body))
{
cpSpaceAddStaticShape(_info->space, *it);
cpSpaceAddStaticShape(_info->space, cps);
}else
{
cpSpaceAddShape(_info->space, *it);
cpSpaceAddShape(_info->space, cps);
}
}
}
void PhysicsWorld::addChild(PhysicsBody* body)
void PhysicsWorld::addBody(PhysicsBody* body)
{
auto shapes = body->getShapes();
// add body to space
if (body->isDynamic())
if (body->isEnable())
{
cpSpaceAddBody(_info->space, body->_info->body);
}
// add shapes to space
for (auto it = shapes.begin(); it != shapes.end(); it++)
{
addShape(*it);
// add body to space
if (body->isDynamic())
{
cpSpaceAddBody(_info->space, body->_info->body);
}
// add shapes to space
for (auto shape : body->getShapes())
{
if (shape->isEnable())
{
addShape(shape);
}
}
}
if (_bodys == nullptr)
@ -150,6 +192,54 @@ void PhysicsWorld::addChild(PhysicsBody* body)
}
}
void PhysicsWorld::removeBody(PhysicsBody* body)
{
for (auto shape : body->getShapes())
{
for (auto cps : shape->_info->shapes)
{
if (cpSpaceContainsShape(_info->space, cps))
{
cpSpaceRemoveShape(_info->space, cps);
}
}
}
if (cpSpaceContainsBody(_info->space, body->_info->body))
{
cpSpaceRemoveBody(_info->space, body->_info->body);
}
if (_bodys != nullptr)
{
_bodys->removeObject(body);
}
}
void PhysicsWorld::removeBodyByTag(int tag)
{
for (Object* obj : *_bodys)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
if (body->getTag() == tag)
{
removeBody(body);
return;
}
}
}
void PhysicsWorld::removeShape(PhysicsShape* shape)
{
for (auto cps : shape->_info->shapes)
{
if (cpSpaceContainsShape(_info->space, cps))
{
cpSpaceRemoveShape(_info->space, cps);
}
}
}
void PhysicsWorld::update(float delta)
{
cpSpaceStep(_info->space, delta);
@ -171,17 +261,16 @@ void PhysicsWorld::debugDraw()
if (_debugDraw && _bodys != nullptr)
{
_drawNode= DrawNode::create();
Object* child = nullptr;
CCARRAY_FOREACH(_bodys, child)
for (Object* obj : *_bodys)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(child);
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
std::vector<PhysicsShape*> shapes = body->getShapes();
for (auto it = shapes.begin(); it != shapes.end(); ++it)
for (auto shape : shapes)
{
drawWithShape(_drawNode, *it);
drawWithShape(_drawNode, shape);
}
}
@ -195,7 +284,6 @@ void PhysicsWorld::debugDraw()
void PhysicsWorld::setScene(Scene *scene)
{
_scene = scene;
scene->retain();
}
void PhysicsWorld::drawWithShape(DrawNode* node, PhysicsShape* shape)
@ -322,7 +410,6 @@ PhysicsWorld::~PhysicsWorld()
{
CC_SAFE_DELETE(_info);
CC_SAFE_RELEASE(_bodys);
CC_SAFE_RELEASE(_scene);
}
NS_CC_END

View File

@ -28,6 +28,8 @@
#ifndef __CCPHYSICS_WORLD_H__
#define __CCPHYSICS_WORLD_H__
#include <list>
#include "cocoa/CCObject.h"
#include "cocoa/CCGeometry.h"
@ -86,14 +88,18 @@ public:
/** set the debug draw */
inline void setDebugDraw(bool debugDraw) { _debugDraw = debugDraw; }
virtual void removeBody(PhysicsBody* body);
virtual void removeBodyByTag(int tag);
protected:
static PhysicsWorld* create();
bool init();
void setScene(Scene* scene);
virtual void addChild(PhysicsBody* body);
virtual void addBody(PhysicsBody* body);
virtual void addShape(PhysicsShape* shape);
virtual void removeShape(PhysicsShape* shape);
virtual void update(float delta);
virtual void debugDraw();
@ -120,6 +126,7 @@ protected:
Array* _bodys;
std::list<PhysicsJoint*> _joints;
Scene* _scene;
bool _debugDraw;
@ -132,6 +139,7 @@ protected:
friend class Sprite;
friend class Scene;
friend class PhysicsBody;
friend class PhysicsShape;
};
NS_CC_END

View File

@ -28,20 +28,27 @@
NS_CC_BEGIN
std::map<cpShape*, PhysicsShapeInfo*> PhysicsShapeInfo::map;
cpBody* PhysicsShapeInfo::shareBody = nullptr;
PhysicsShapeInfo::PhysicsShapeInfo(PhysicsShape* shape)
: shape(shape)
{
if (shareBody == nullptr)
{
shareBody = cpBodyNewStatic();
}
body = shareBody;
}
PhysicsShapeInfo::~PhysicsShapeInfo()
{
for (auto it = shapes.begin(); it != shapes.end(); it++)
for (auto shape : shapes)
{
cpShapeFree(*it);
auto it = map.find(shape);
if (it != map.end()) map.erase(shape);
auto mit = map.find(*it);
if (mit != map.end()) map.erase(*it);
cpShapeFree(shape);
}
}

View File

@ -46,8 +46,10 @@ public:
public:
std::vector<cpShape*> shapes;
static std::map<cpShape*, PhysicsShapeInfo*> map;
PhysicsShape* shape;
cpBody* body;
static std::map<cpShape*, PhysicsShapeInfo*> map;
static cpBody* shareBody;
private:
PhysicsShapeInfo(PhysicsShape* shape);

View File

@ -296,18 +296,12 @@ Sprite* Sprite::initWithCGImage(CGImageRef pImage, const char *pszKey)
Sprite::Sprite(void)
: _shouldBeHidden(false)
, _texture(nullptr)
#ifdef CC_USE_PHYSICS
, _physicsBody(nullptr)
#endif
{
}
Sprite::~Sprite(void)
{
CC_SAFE_RELEASE(_texture);
#ifdef CC_USE_PHYSICS
CC_SAFE_RELEASE(_physicsBody);
#endif
}
void Sprite::setTextureRect(const Rect& rect)
@ -790,13 +784,6 @@ void Sprite::setPosition(const Point& pos)
{
Node::setPosition(pos);
SET_DIRTY_RECURSIVELY();
#ifdef CC_USE_PHYSICS
if (_physicsBody)
{
_physicsBody->setPosition(pos);
}
#endif
}
void Sprite::setRotation(float rotation)
@ -804,13 +791,6 @@ void Sprite::setRotation(float rotation)
Node::setRotation(rotation);
SET_DIRTY_RECURSIVELY();
#ifdef CC_USE_PHYSICS
if (_physicsBody)
{
_physicsBody->setRotation(rotation);
}
#endif
}
void Sprite::setRotationX(float fRotationX)
@ -907,33 +887,6 @@ bool Sprite::isFlippedY(void) const
return _flippedY;
}
#ifdef CC_USE_PHYSICS
void Sprite::setPhysicsBody(PhysicsBody* body)
{
_physicsBody = body;
_physicsBody->retain();
_physicsBody->setPosition(getPosition());
_physicsBody->setRotation(getRotation());
}
PhysicsBody* Sprite::getPhysicsBody() const
{
return _physicsBody;
}
void Sprite::visit()
{
if (_physicsBody)
{
Node::setPosition(_physicsBody->getPosition());
Node::setRotation(_physicsBody->getRotation());
SET_DIRTY_RECURSIVELY();
}
Node::visit();
}
#endif //CC_USE_PHYSICS
//
// RGBA protocol
//

View File

@ -461,20 +461,6 @@ public:
*/
void setFlippedY(bool flippedY);
#ifdef CC_USE_PHYSICS
/**
* set the PhysicsBody that let the sprite effect with physics
*/
virtual void setPhysicsBody(PhysicsBody* body);
/**
* get the PhysicsBody the sprite have
*/
PhysicsBody* getPhysicsBody() const;
virtual void visit() override;
#endif
/// @} End of Sprite properties getter/setters
/** @deprecated Use isFlippedY() instead */
@ -590,10 +576,6 @@ protected:
// image is flipped
bool _flippedX; /// Whether the sprite is flipped horizaontally or not.
bool _flippedY; /// Whether the sprite is flipped vertically or not.
#ifdef CC_USE_PHYSICS
PhysicsBody* _physicsBody; ///< the physicsBody the node have
#endif
};

View File

@ -40,6 +40,8 @@ THE SOFTWARE.
#include "CCDirector.h"
#include "support/TransformUtils.h"
#include "support/CCProfiling.h"
#include "layers_scenes_transitions_nodes/CCLayer.h"
#include "layers_scenes_transitions_nodes/CCScene.h"
// external
#include "kazmath/GL/matrix.h"
@ -180,6 +182,17 @@ void SpriteBatchNode::addChild(Node *child, int zOrder, int tag)
Node::addChild(child, zOrder, tag);
appendChild(sprite);
if (this->getParent() &&
dynamic_cast<Layer*>(this->getParent()) != nullptr)
{
if (this->getParent()->getParent() &&
dynamic_cast<Scene*>(this->getParent()->getParent()))
{
dynamic_cast<Scene*>(this->getParent()->getParent())->addChildToPhysicsWorld(child);
}
}
}
// override reorderChild

View File

@ -2,39 +2,204 @@
#include "../testResource.h"
USING_NS_CC;
PhysicsTestLayer::PhysicsTestLayer()
: _spriteTexture(nullptr)
, _scene(nullptr)
namespace
{
static std::function<Layer*()> createFunctions[] = {
CL(PhysicsDemoLogoSmash),
CL(PhysicsDemoPyramidStack),
CL(PhysicsDemoPlink),
CL(PhysicsDemoClickAdd),
};
static int sceneIdx=-1;
#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0]))
static Layer* next()
{
sceneIdx++;
sceneIdx = sceneIdx % MAX_LAYER;
auto layer = (createFunctions[sceneIdx])();
layer->init();
layer->autorelease();
return layer;
}
static Layer* back()
{
sceneIdx--;
int total = MAX_LAYER;
if( sceneIdx < 0 )
sceneIdx += total;
auto layer = (createFunctions[sceneIdx])();
layer->init();
layer->autorelease();
return layer;
}
static Layer* restart()
{
auto layer = (createFunctions[sceneIdx])();
layer->init();
layer->autorelease();
return layer;
}
}
bool PhysicsTestScene::_debugDraw = false;
bool PhysicsTestScene::initTest()
{
#ifdef CC_USE_PHYSICS
if(TestScene::initWithPhysics())
{
this->getPhysicsWorld()->setDebugDraw(_debugDraw);
return true;
}
#else
return TestScene::init();
#endif
return false;
}
void PhysicsTestScene::runThisTest()
{
#ifdef CC_USE_PHYSICS
sceneIdx = -1;
addChild(next());
Director::getInstance()->replaceScene(this);
#else
#endif
}
void PhysicsTestScene::toggleDebug()
{
_debugDraw = !_debugDraw;
getPhysicsWorld()->setDebugDraw(_debugDraw);
}
PhysicsDemo::PhysicsDemo()
: _scene(nullptr)
{
}
PhysicsDemo::~PhysicsDemo()
{
}
std::string PhysicsDemo::title()
{
return "PhysicsTest";
}
std::string PhysicsDemo::subtitle()
{
return "";
}
void PhysicsDemo::restartCallback(Object* sender)
{
auto s = new PhysicsTestScene();
s->initTest();
s->addChild( restart() );
Director::getInstance()->replaceScene(s);
s->release();
}
void PhysicsDemo::nextCallback(Object* sender)
{
auto s = new PhysicsTestScene();
s->initTest();
s->addChild( next() );
Director::getInstance()->replaceScene(s);
s->release();
}
void PhysicsDemo::backCallback(Object* sender)
{
auto s = new PhysicsTestScene();
s->initTest();
s->addChild( back() );
Director::getInstance()->replaceScene(s);
s->release();
}
void PhysicsDemo::onEnter()
{
BaseTest::onEnter();
_scene = dynamic_cast<PhysicsTestScene*>(this->getParent());
_spriteTexture = SpriteBatchNode::create("Images/grossini_dance_atlas.png", 100)->getTexture();
#ifdef CC_USE_PHYSICS
// menu for debug layer
MenuItemFont::setFontSize(18);
auto item = MenuItemFont::create("Toggle debug", CC_CALLBACK_1(PhysicsDemo::toggleDebugCallback, this));
auto menu = Menu::create(item, NULL);
this->addChild(menu);
menu->setPosition(Point(VisibleRect::right().x-50, VisibleRect::top().y-10));
#else
#endif
}
void PhysicsDemo::addGrossiniAtPosition(Point p, float scale/* = 1.0*/)
{
#ifdef CC_USE_PHYSICS
CCLOG("Add sprite %0.2f x %02.f",p.x,p.y);
int posx, posy;
posx = CCRANDOM_0_1() * 200.0f;
posy = CCRANDOM_0_1() * 200.0f;
posx = (posx % 4) * 85;
posy = (posy % 3) * 121;
auto sp = Sprite::createWithTexture(_spriteTexture, Rect(posx, posy, 85, 121));
sp->setScale(scale);
sp->setPhysicsBody(PhysicsBody::createBox(Size(48.0f * scale, 108.0f * scale)));
this->addChild(sp);
sp->setPosition(p);
#endif
}
void PhysicsDemo::toggleDebugCallback(Object* sender)
{
#ifdef CC_USE_PHYSICS
if (_scene != nullptr)
{
_scene->toggleDebug();
}
#endif
}
void PhysicsDemoClickAdd::onEnter()
{
PhysicsDemo::onEnter();
#ifdef CC_USE_PHYSICS
setTouchEnabled(true);
setAccelerometerEnabled(true);
// title
auto label = LabelTTF::create("Multi touch the screen", "Marker Felt", 36);
label->setPosition(Point( VisibleRect::center().x, VisibleRect::top().y - 30));
this->addChild(label, -1);
auto node = Node::create();
node->setPhysicsBody(PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size));
node->setPosition(VisibleRect::center());
this->addChild(node);
// menu for debug layer
MenuItemFont::setFontSize(18);
auto item = MenuItemFont::create("Toggle debug", CC_CALLBACK_1(PhysicsTestLayer::toggleDebugCallback, this));
auto menu = Menu::create(item, NULL);
this->addChild(menu);
menu->setPosition(Point(VisibleRect::right().x-100, VisibleRect::top().y-60));
auto sp = Sprite::create();
auto body = PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size);
sp->setPhysicsBody(body);
this->addChild(sp);
sp->setPosition(VisibleRect::center());
auto parent = SpriteBatchNode::create("Images/grossini_dance_atlas.png", 100);
_spriteTexture = parent->getTexture();
addNewSpriteAtPosition(VisibleRect::center());
createResetButton();
addGrossiniAtPosition(VisibleRect::center());
#else
auto label = LabelTTF::create("Should define CC_USE_BOX2D or CC_USE_CHIPMUNK\n to run this test case",
@ -47,41 +212,12 @@ PhysicsTestLayer::PhysicsTestLayer()
#endif
}
void PhysicsTestLayer::toggleDebugCallback(Object* sender)
std::string PhysicsDemoClickAdd::subtitle()
{
#ifdef CC_USE_PHYSICS
if (_scene != nullptr)
{
_scene->getPhysicsWorld()->setDebugDraw(!_scene->getPhysicsWorld()->isDebugDraw());
}
#endif
return "multi touch to add grossini";
}
PhysicsTestLayer::~PhysicsTestLayer()
{
}
void PhysicsTestLayer::createResetButton()
{
auto reset = MenuItemImage::create("Images/r1.png", "Images/r2.png", [](Object *sender) {
auto s = new PhysicsTestScene();
s->initTest();
auto child = new PhysicsTestLayer();
child->setScene(s);
s->addChild(child);
child->release();
Director::getInstance()->replaceScene(s);
s->release();
});
auto menu = Menu::create(reset, NULL);
menu->setPosition(Point(VisibleRect::bottom().x, VisibleRect::bottom().y + 30));
this->addChild(menu, -1);
}
void PhysicsTestLayer::onTouchesEnded(const std::vector<Touch*>& touches, Event* event)
void PhysicsDemoClickAdd::onTouchesEnded(const std::vector<Touch*>& touches, Event* event)
{
//Add a new body/atlas sprite at the touched location
@ -89,12 +225,11 @@ void PhysicsTestLayer::onTouchesEnded(const std::vector<Touch*>& touches, Event*
{
auto location = touch->getLocation();
addNewSpriteAtPosition( location );
addGrossiniAtPosition( location );
}
}
void PhysicsTestLayer::onAcceleration(Acceleration* acc, Event* event)
void PhysicsDemoClickAdd::onAcceleration(Acceleration* acc, Event* event)
{
#ifdef CC_USE_PHYSICS
static float prevX=0, prevY=0;
@ -117,48 +252,169 @@ void PhysicsTestLayer::onAcceleration(Acceleration* acc, Event* event)
#endif
}
void PhysicsTestLayer::addNewSpriteAtPosition(Point p)
namespace
{
#ifdef CC_USE_PHYSICS
CCLOG("Add sprite %0.2f x %02.f",p.x,p.y);
int posx, posy;
posx = CCRANDOM_0_1() * 200.0f;
posy = CCRANDOM_0_1() * 200.0f;
posx = (posx % 4) * 85;
posy = (posy % 3) * 121;
auto sp = Sprite::createWithTexture(_spriteTexture, Rect(posx, posy, 85, 121));
auto body = PhysicsBody::createBox(Size(48, 108));
sp->setPhysicsBody(body);
sp->setPosition(p);
this->addChild(sp);
#endif
}
bool PhysicsTestScene::initTest()
{
#ifdef CC_USE_PHYSICS
if (TestScene::initWithPhysics())
static const int logo_width = 188;
static const int logo_height = 35;
static const int logo_row_length = 24;
static const char logo_image[] =
{
this->getPhysicsWorld()->setDebugDraw(true);
return true;
}
#else
return TestScene::init();
#endif
15,-16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,-64,15,63,-32,-2,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,31,-64,15,127,-125,-1,-128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,127,-64,15,127,15,-1,-64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,-1,-64,15,-2,
31,-1,-64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,-1,-64,0,-4,63,-1,-32,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,1,-1,-64,15,-8,127,-1,-32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,-1,-64,0,-8,-15,-1,-32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,-31,-1,-64,15,-8,-32,
-1,-32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,-15,-1,-64,9,-15,-32,-1,-32,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,31,-15,-1,-64,0,-15,-32,-1,-32,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,63,-7,-1,-64,9,-29,-32,127,-61,-16,63,15,-61,-1,-8,31,-16,15,-8,126,7,-31,
-8,31,-65,-7,-1,-64,9,-29,-32,0,7,-8,127,-97,-25,-1,-2,63,-8,31,-4,-1,15,-13,
-4,63,-1,-3,-1,-64,9,-29,-32,0,7,-8,127,-97,-25,-1,-2,63,-8,31,-4,-1,15,-13,
-2,63,-1,-3,-1,-64,9,-29,-32,0,7,-8,127,-97,-25,-1,-1,63,-4,63,-4,-1,15,-13,
-2,63,-33,-1,-1,-32,9,-25,-32,0,7,-8,127,-97,-25,-1,-1,63,-4,63,-4,-1,15,-13,
-1,63,-33,-1,-1,-16,9,-25,-32,0,7,-8,127,-97,-25,-1,-1,63,-4,63,-4,-1,15,-13,
-1,63,-49,-1,-1,-8,9,-57,-32,0,7,-8,127,-97,-25,-8,-1,63,-2,127,-4,-1,15,-13,
-1,-65,-49,-1,-1,-4,9,-57,-32,0,7,-8,127,-97,-25,-8,-1,63,-2,127,-4,-1,15,-13,
-1,-65,-57,-1,-1,-2,9,-57,-32,0,7,-8,127,-97,-25,-8,-1,63,-2,127,-4,-1,15,-13,
-1,-1,-57,-1,-1,-1,9,-57,-32,0,7,-1,-1,-97,-25,-8,-1,63,-1,-1,-4,-1,15,-13,-1,
-1,-61,-1,-1,-1,-119,-57,-32,0,7,-1,-1,-97,-25,-8,-1,63,-1,-1,-4,-1,15,-13,-1,
-1,-61,-1,-1,-1,-55,-49,-32,0,7,-1,-1,-97,-25,-8,-1,63,-1,-1,-4,-1,15,-13,-1,
-1,-63,-1,-1,-1,-23,-49,-32,127,-57,-1,-1,-97,-25,-1,-1,63,-1,-1,-4,-1,15,-13,
-1,-1,-63,-1,-1,-1,-16,-49,-32,-1,-25,-1,-1,-97,-25,-1,-1,63,-33,-5,-4,-1,15,
-13,-1,-1,-64,-1,-9,-1,-7,-49,-32,-1,-25,-8,127,-97,-25,-1,-1,63,-33,-5,-4,-1,
15,-13,-1,-1,-64,-1,-13,-1,-32,-49,-32,-1,-25,-8,127,-97,-25,-1,-2,63,-49,-13,
-4,-1,15,-13,-1,-1,-64,127,-7,-1,-119,-17,-15,-1,-25,-8,127,-97,-25,-1,-2,63,
-49,-13,-4,-1,15,-13,-3,-1,-64,127,-8,-2,15,-17,-1,-1,-25,-8,127,-97,-25,-1,
-8,63,-49,-13,-4,-1,15,-13,-3,-1,-64,63,-4,120,0,-17,-1,-1,-25,-8,127,-97,-25,
-8,0,63,-57,-29,-4,-1,15,-13,-4,-1,-64,63,-4,0,15,-17,-1,-1,-25,-8,127,-97,
-25,-8,0,63,-57,-29,-4,-1,-1,-13,-4,-1,-64,31,-2,0,0,103,-1,-1,-57,-8,127,-97,
-25,-8,0,63,-57,-29,-4,-1,-1,-13,-4,127,-64,31,-2,0,15,103,-1,-1,-57,-8,127,
-97,-25,-8,0,63,-61,-61,-4,127,-1,-29,-4,127,-64,15,-8,0,0,55,-1,-1,-121,-8,
127,-97,-25,-8,0,63,-61,-61,-4,127,-1,-29,-4,63,-64,15,-32,0,0,23,-1,-2,3,-16,
63,15,-61,-16,0,31,-127,-127,-8,31,-1,-127,-8,31,-128,7,-128,0,0};
return false;
static inline int get_pixel(int x, int y)
{
return (logo_image[(x>>3) + y*logo_row_length]>>(~x&0x7)) & 1;
}
static inline float frand(void)
{
return rand()/RAND_MAX;
}
}
void PhysicsTestScene::runThisTest()
Node* PhysicsDemoLogoSmash::makeBall(float x, float y)
{
auto layer = new PhysicsTestLayer();
layer->setScene(this);
addChild(layer);
layer->release();
auto ball = Sprite::createWithTexture(_ball->getTexture());
ball->setScale(0.1);
Director::getInstance()->replaceScene(this);
auto body = PhysicsBody::createCircle(0.95, PhysicsMaterial(1, 0, 0));
body->setMass(1.0);
body->setAngularDamping(PHYSICS_INFINITY);
//body->setDynamic(false);
ball->setPhysicsBody(body);
ball->setPosition(Point(x, y));
return ball;
}
void PhysicsDemoLogoSmash::onEnter()
{
PhysicsDemo::onEnter();
_scene->getPhysicsWorld()->setGravity(Point(0, 0));
_ball = SpriteBatchNode::create("Images/ball.png", sizeof(logo_image)/sizeof(logo_image[0]));
addChild(_ball);
for (int y = 0; y < logo_height; ++y)
{
for (int x = 0; x < logo_width; ++x)
{
if (get_pixel(x, y))
{
float x_jitter = 0.05*frand();
float y_jitter = 0.05*frand();
_ball->addChild(makeBall(2*(x - logo_width/2 + x_jitter) + VisibleRect::getVisibleRect().size.width/2,
2*(logo_height-y + y_jitter) + VisibleRect::getVisibleRect().size.height/2 - logo_height/2));
}
}
}
auto bullet = Sprite::createWithTexture(_ball->getTexture());
bullet->setScale(0.5);
auto body = PhysicsBody::createCircle(8, PhysicsMaterial(PHYSICS_INFINITY, 0, 0));
body->setVelocity(Point(400, 0));
bullet->setPhysicsBody(body);
bullet->setPosition(Point(-1000, VisibleRect::getVisibleRect().size.height/2));
_ball->addChild(bullet);
}
std::string PhysicsDemoLogoSmash::title()
{
return "Logo Smash";
}
void PhysicsDemoPyramidStack::onEnter()
{
PhysicsDemo::onEnter();
auto node = Node::create();
node->setPhysicsBody(PhysicsBody::createEdgeSegment(VisibleRect::leftBottom() + Point(0, 50), VisibleRect::rightBottom() + Point(0, 50)));
this->addChild(node);
auto ball = Sprite::create("Images/ball.png");
ball->setScale(1);
ball->setPhysicsBody(PhysicsBody::createCircle(10));
ball->setPosition(VisibleRect::bottom() + Point(0, 60));
this->addChild(ball);
for(int i=0; i<14; i++)
{
for(int j=0; j<=i; j++)
{
addGrossiniAtPosition(VisibleRect::bottom() + Point((i/2 - j) * 11, (14 - i) * 23 + 100), 0.2);
}
}
}
std::string PhysicsDemoPyramidStack::title()
{
return "Pyramid Stack";
}
void PhysicsDemoPlink::onEnter()
{
PhysicsDemo::onEnter();
auto node = Node::create();
auto body = PhysicsBody::create();
body->setDynamic(false);
node->setPhysicsBody(body);
Point tris[] = { Point(-15, -15), Point(0, 10), Point(15, -15) };
auto rect = VisibleRect::getVisibleRect();
for (int i = 0; i < 9; ++i)
{
for (int j = 0; j < 4; ++j)
{
body->addShape(PhysicsShapePolygon::create(tris, 3, PHYSICSSHAPE_MATERIAL_DEFAULT, Point(rect.origin.x + rect.size.width/9*i + (j%2)*40 - 20, rect.origin.y + j*70)));
}
}
addChild(node);
}
std::string PhysicsDemoPlink::title()
{
return "Plink";
}

View File

@ -3,30 +3,79 @@
#include "cocos2d.h"
#include "../testBasic.h"
#include "../BaseTest.h"
class PhysicsTestLayer : public Layer
{
Texture2D* _spriteTexture; // weak ref
Scene* _scene;
public:
PhysicsTestLayer();
~PhysicsTestLayer();
void createResetButton();
inline void setScene(Scene* scene) { _scene = scene; }
void toggleDebugCallback(Object* sender);
void addNewSpriteAtPosition(Point p);
virtual void onTouchesEnded(const std::vector<Touch*>& touches, Event* event) override;
virtual void onAcceleration(Acceleration* acc, Event* event) override;
} ;
class PhysicsTestScene : public TestScene
{
public:
virtual bool initTest() override;
virtual void runThisTest();
void toggleDebug();
private:
static bool _debugDraw;
};
class PhysicsDemo : public BaseTest
{
protected:
PhysicsTestScene* _scene;
public:
PhysicsDemo();
virtual ~PhysicsDemo();
virtual void onEnter() override;
virtual std::string title() override;
virtual std::string subtitle() override;
void restartCallback(Object* sender);
void nextCallback(Object* sender);
void backCallback(Object* sender);
void toggleDebugCallback(Object* sender);
void addGrossiniAtPosition(Point p, float scale = 1.0);
private:
Texture2D* _spriteTexture; // weak ref
};
class PhysicsDemoClickAdd : public PhysicsDemo
{
public:
void onEnter() override;
std::string subtitle() override;
void onTouchesEnded(const std::vector<Touch*>& touches, Event* event) override;
void onAcceleration(Acceleration* acc, Event* event) override;
};
class PhysicsDemoLogoSmash : public PhysicsDemo
{
public:
void onEnter() override;
std::string title() override;
Node* makeBall(float x, float y);
private:
SpriteBatchNode* _ball;
};
class PhysicsDemoPyramidStack : public PhysicsDemo
{
public:
void onEnter() override;
std::string title() override;
};
class PhysicsDemoPlink : public PhysicsDemo
{
public:
void onEnter() override;
std::string title() override;
};
#endif