issue #2771: add physics pump demo and fix bugs

This commit is contained in:
boyu0 2013-10-29 17:31:35 +08:00
parent 66d1bbd89f
commit cae9a3e54f
17 changed files with 529 additions and 98 deletions

View File

@ -57,7 +57,6 @@ namespace
{
static const float MASS_DEFAULT = 1.0;
static const float MOMENT_DEFAULT = 200;
static float GROUP_INDEX = 0;
}
PhysicsBody::PhysicsBody()
@ -81,6 +80,7 @@ PhysicsBody::PhysicsBody()
, _categoryBitmask(UINT_MAX)
, _collisionBitmask(UINT_MAX)
, _contactTestBitmask(0)
, _group(0)
{
}
@ -273,7 +273,6 @@ bool PhysicsBody::init()
_shapes->retain();
_info->body = cpBodyNew(PhysicsHelper::float2cpfloat(_mass), PhysicsHelper::float2cpfloat(_moment));
_info->group = ++GROUP_INDEX;
CC_BREAK_IF(_info->body == nullptr);
@ -321,10 +320,10 @@ void PhysicsBody::setGravityEnable(bool enable)
{
if (enable)
{
applyForce(_world->getGravity());
applyForce(_world->getGravity() * _mass);
}else
{
applyForce(-_world->getGravity());
applyForce(-_world->getGravity() * _mass);
}
}
}
@ -351,9 +350,9 @@ float PhysicsBody::getRotation() const
return -PhysicsHelper::cpfloat2float(cpBodyGetAngle(_info->body) / 3.14f * 180.0f);
}
void PhysicsBody::addShape(PhysicsShape* shape)
PhysicsShape* PhysicsBody::addShape(PhysicsShape* shape)
{
if (shape == nullptr) return;
if (shape == nullptr) return nullptr;
// add shape to body
if (_shapes->getIndexOfObject(shape) == UINT_MAX)
@ -372,9 +371,16 @@ void PhysicsBody::addShape(PhysicsShape* shape)
}
_shapes->addObject(shape);
if (_group != CP_NO_GROUP && shape->getGroup() == CP_NO_GROUP)
{
shape->setGroup(_group);
}
}
return shape;
}
void PhysicsBody::applyForce(Point force)
{
applyForce(force, Point::ZERO);
@ -676,6 +682,54 @@ void PhysicsBody::update(float delta)
}
}
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)));
}
//Clonable* PhysicsBody::clone() const
//{
// PhysicsBody* body = new PhysicsBody();

View File

@ -87,7 +87,7 @@ public:
*/
static PhysicsBody* createEdgeChain(Point* points, int count, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT, float border = 1);
virtual void addShape(PhysicsShape* shape);
virtual PhysicsShape* addShape(PhysicsShape* shape);
/**
* @brief Applies a immediate force to body.
@ -154,13 +154,16 @@ public:
*/
inline Node* getOwner() const { return _owner; }
inline void setCategoryBitmask(int bitmask) { _categoryBitmask = bitmask; }
void setCategoryBitmask(int bitmask);
void setContactTestBitmask(int bitmask);
void setCollisionBitmask(int bitmask);
inline int getCategoryBitmask() const { return _categoryBitmask; }
inline void setContactTestBitmask(int bitmask) { _contactTestBitmask = bitmask; }
inline int getContactTestBitmask() const { return _contactTestBitmask; }
inline void setCollisionBitmask(int bitmask) { _collisionBitmask = bitmask; }
inline int getCollisionBitmask() const { return _collisionBitmask; }
void setGroup(int group);
inline int getGroup() { return _group; }
/*
* @brief get the body position.
*/
@ -246,6 +249,8 @@ public:
inline int getTag() { return _tag; }
inline void setTag(int tag) { _tag = tag; }
Point world2Local(const Point& point);
Point local2World(const Point& point);
protected:
@ -283,6 +288,7 @@ protected:
int _categoryBitmask;
int _collisionBitmask;
int _contactTestBitmask;
int _group;
friend class PhysicsWorld;
friend class PhysicsShape;

View File

@ -144,6 +144,16 @@ PhysicsJointLimit::~PhysicsJointLimit()
}
PhysicsJointDistance::PhysicsJointDistance()
{
}
PhysicsJointDistance::~PhysicsJointDistance()
{
}
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
PhysicsBodyInfo* PhysicsJoint::bodyInfo(PhysicsBody* body) const
{
@ -343,6 +353,39 @@ void PhysicsJointLimit::setMax(float max)
cpSlideJointSetMax(_info->joints.front(), PhysicsHelper::float2cpfloat(max));
}
PhysicsJointDistance* PhysicsJointDistance::create(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2)
{
PhysicsJointDistance* joint = new PhysicsJointDistance();
if (joint && joint->init(a, b, anchr1, anchr2))
{
return joint;
}
CC_SAFE_DELETE(joint);
return nullptr;
}
bool PhysicsJointDistance::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2)
{
do
{
CC_BREAK_IF(!PhysicsJoint::init(a, b));
cpConstraint* joint = cpPinJointNew(bodyInfo(a)->body,
bodyInfo(b)->body,
PhysicsHelper::point2cpv(anchr1), PhysicsHelper::point2cpv(anchr2));
CC_BREAK_IF(joint == nullptr);
_info->add(joint);
return true;
} while (false);
return false;
}
#elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
#endif

View File

@ -165,6 +165,20 @@ protected:
virtual ~PhysicsJointPin();
};
class PhysicsJointDistance : public PhysicsJoint
{
public:
static PhysicsJointDistance* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2);
protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2);
protected:
PhysicsJointDistance();
virtual ~PhysicsJointDistance();
};
NS_CC_END
#endif // __CCPHYSICS_JOINT_H__

View File

@ -50,6 +50,10 @@ PhysicsShape::PhysicsShape()
, _mass(0)
, _moment(0)
, _tag(0)
, _categoryBitmask(UINT_MAX)
, _collisionBitmask(UINT_MAX)
, _contactTestBitmask(0)
, _group(0)
{
}
@ -777,6 +781,17 @@ int PhysicsShapeEdgeChain::getPointsCount()
return _info->shapes.size() + 1;
}
void PhysicsShape::setGroup(int group)
{
if (group < 0)
{
for (auto shape : _info->shapes)
{
cpShapeSetGroup(shape, (cpGroup)group);
}
}
}
#elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
#endif

View File

@ -102,6 +102,16 @@ public:
static Point* recenterPoints(Point* points, int count, Point center = Point::ZERO);
static Point getPolyonCenter(Point* points, int count);
inline void setCategoryBitmask(int bitmask) { _categoryBitmask = bitmask; }
inline int getCategoryBitmask() const { return _categoryBitmask; }
inline void setContactTestBitmask(int bitmask) { _contactTestBitmask = bitmask; }
inline int getContactTestBitmask() const { return _contactTestBitmask; }
inline void setCollisionBitmask(int bitmask) { _collisionBitmask = bitmask; }
inline int getCollisionBitmask() const { return _collisionBitmask; }
void setGroup(int group);
inline int getGroup() { return _group; }
protected:
bool init(Type type);
@ -125,6 +135,10 @@ protected:
float _moment;
PhysicsMaterial _material;
int _tag;
int _categoryBitmask;
int _collisionBitmask;
int _contactTestBitmask;
int _group;
friend class PhysicsWorld;
friend class PhysicsBody;

View File

@ -181,9 +181,9 @@ bool PhysicsWorld::init()
{
_info = new PhysicsWorldInfo();
CC_BREAK_IF(_info == nullptr);
_bodys = Array::create();
CC_BREAK_IF(_bodys == nullptr);
_bodys->retain();
_bodies = Array::create();
CC_BREAK_IF(_bodies == nullptr);
_bodies->retain();
cpSpaceSetGravity(_info->space, PhysicsHelper::point2cpv(_gravity));
@ -253,7 +253,7 @@ void PhysicsWorld::removeAllJoints()
_joints.clear();
}
void PhysicsWorld::addShape(PhysicsShape* shape)
PhysicsShape* PhysicsWorld::addShape(PhysicsShape* shape)
{
for (auto cps : shape->_info->shapes)
{
@ -270,9 +270,11 @@ void PhysicsWorld::addShape(PhysicsShape* shape)
cpSpaceAddShape(_info->space, cps);
}
}
return shape;
}
void PhysicsWorld::addBody(PhysicsBody* body)
PhysicsBody* PhysicsWorld::addBody(PhysicsBody* body)
{
CCASSERT(body != nullptr, "the body can not be nullptr");
@ -304,7 +306,9 @@ void PhysicsWorld::addBody(PhysicsBody* body)
}
}
_bodys->addObject(body);
_bodies->addObject(body);
return body;
}
void PhysicsWorld::removeBody(PhysicsBody* body)
@ -341,12 +345,12 @@ void PhysicsWorld::removeBody(PhysicsBody* body)
}
body->_world = nullptr;
_bodys->removeObject(body);
_bodies->removeObject(body);
}
void PhysicsWorld::removeBodyByTag(int tag)
{
for (Object* obj : *_bodys)
for (Object* obj : *_bodies)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
if (body->getTag() == tag)
@ -357,9 +361,9 @@ void PhysicsWorld::removeBodyByTag(int tag)
}
}
void PhysicsWorld::removeAllBodys()
void PhysicsWorld::removeAllBodies()
{
for (Object* obj : *_bodys)
for (Object* obj : *_bodies)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
@ -390,8 +394,8 @@ void PhysicsWorld::removeAllBodys()
body->_world = nullptr;
}
_bodys->removeAllObjects();
CC_SAFE_RELEASE(_bodys);
_bodies->removeAllObjects();
CC_SAFE_RELEASE(_bodies);
}
void PhysicsWorld::removeShape(PhysicsShape* shape)
@ -407,7 +411,7 @@ void PhysicsWorld::removeShape(PhysicsShape* shape)
void PhysicsWorld::update(float delta)
{
for (auto body : *_bodys)
for (auto body : *_bodies)
{
body->update(delta);
}
@ -428,11 +432,11 @@ void PhysicsWorld::update(float delta)
void PhysicsWorld::debugDraw()
{
if (_debugDraw && _bodys != nullptr)
if (_debugDraw && _bodies != nullptr)
{
_drawNode= DrawNode::create();
for (Object* obj : *_bodys)
for (Object* obj : *_bodies)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
@ -442,6 +446,11 @@ void PhysicsWorld::debugDraw()
}
}
for (auto joint : _joints)
{
drawWithJoint(_drawNode, joint);
}
if (_scene)
{
_scene->addChild(_drawNode);
@ -454,6 +463,58 @@ void PhysicsWorld::setScene(Scene *scene)
_scene = scene;
}
void PhysicsWorld::drawWithJoint(DrawNode* node, PhysicsJoint* joint)
{
for (auto it = joint->_info->joints.begin(); it != joint->_info->joints.end(); ++it)
{
cpConstraint *constraint = *it;
cpBody *body_a = constraint->a;
cpBody *body_b = constraint->b;
const cpConstraintClass *klass = constraint->klass_private;
if(klass == cpPinJointGetClass()){
cpPinJoint *joint = (cpPinJoint *)constraint;
cpVect a = cpvadd(body_a->p, cpvrotate(joint->anchr1, body_a->rot));
cpVect b = cpvadd(body_b->p, cpvrotate(joint->anchr2, body_b->rot));
node->drawSegment(PhysicsHelper::cpv2point(a), PhysicsHelper::cpv2point(b), 1, Color4F(0.0f, 0.0f, 1.0f, 1.0f));
node->drawDot(PhysicsHelper::cpv2point(a), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
node->drawDot(PhysicsHelper::cpv2point(b), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
} else if(klass == cpSlideJointGetClass()){
cpSlideJoint *joint = (cpSlideJoint *)constraint;
cpVect a = cpvadd(body_a->p, cpvrotate(joint->anchr1, body_a->rot));
cpVect b = cpvadd(body_b->p, cpvrotate(joint->anchr2, body_b->rot));
node->drawSegment(PhysicsHelper::cpv2point(a), PhysicsHelper::cpv2point(b), 1, Color4F(0.0f, 0.0f, 1.0f, 1.0f));
node->drawDot(PhysicsHelper::cpv2point(a), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
node->drawDot(PhysicsHelper::cpv2point(b), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
} else if(klass == cpPivotJointGetClass()){
cpPivotJoint *joint = (cpPivotJoint *)constraint;
cpVect a = cpvadd(body_a->p, cpvrotate(joint->anchr1, body_a->rot));
cpVect b = cpvadd(body_b->p, cpvrotate(joint->anchr2, body_b->rot));
node->drawDot(PhysicsHelper::cpv2point(a), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
node->drawDot(PhysicsHelper::cpv2point(b), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
} else if(klass == cpGrooveJointGetClass()){
cpGrooveJoint *joint = (cpGrooveJoint *)constraint;
cpVect a = cpvadd(body_a->p, cpvrotate(joint->grv_a, body_a->rot));
cpVect b = cpvadd(body_a->p, cpvrotate(joint->grv_b, body_a->rot));
cpVect c = cpvadd(body_b->p, cpvrotate(joint->anchr2, body_b->rot));
node->drawSegment(PhysicsHelper::cpv2point(a), PhysicsHelper::cpv2point(b), 1, Color4F(0.0f, 0.0f, 1.0f, 1.0f));
node->drawDot(PhysicsHelper::cpv2point(c), 2, Color4F(0.0f, 1.0f, 0.0f, 1.0f));
} else if(klass == cpDampedSpringGetClass()){
}
}
}
void PhysicsWorld::drawWithShape(DrawNode* node, PhysicsShape* shape)
{
for (auto it = shape->_info->shapes.begin(); it != shape->_info->shapes.end(); ++it)
@ -510,8 +571,10 @@ void PhysicsWorld::drawWithShape(DrawNode* node, PhysicsShape* shape)
int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact)
{
bool ret = true;
PhysicsBody* bodyA = contact.getShapeA()->getBody();
PhysicsBody* bodyB = contact.getShapeB()->getBody();
PhysicsShape* shapeA = contact.getShapeA();
PhysicsShape* shapeB = contact.getShapeB();
PhysicsBody* bodyA = shapeA->getBody();
PhysicsBody* bodyB = shapeB->getBody();
std::vector<PhysicsJoint*> jointsA = bodyA->getJoints();
// check the joint is collision enable or not
@ -534,18 +597,25 @@ int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact)
}
}
// bitmask check
if ((bodyA->getCategoryBitmask() & bodyB->getContactTestBitmask()) == 0
|| (bodyB->getContactTestBitmask() & bodyA->getCategoryBitmask()) == 0)
if ((shapeA->getCategoryBitmask() & shapeB->getContactTestBitmask()) == 0
|| (shapeB->getContactTestBitmask() & shapeA->getCategoryBitmask()) == 0)
{
contact.setNotify(false);
}
if ((bodyA->getCategoryBitmask() & bodyB->getCollisionBitmask()) == 0
|| (bodyB->getCategoryBitmask() & bodyA->getCollisionBitmask()) == 0)
if (shapeA->getGroup() != 0 && shapeA->getGroup() == shapeB->getGroup())
{
ret = shapeA->getGroup() > 0;
}else
{
if ((shapeA->getCategoryBitmask() & shapeB->getCollisionBitmask()) == 0
|| (shapeB->getCategoryBitmask() & shapeA->getCollisionBitmask()) == 0)
{
ret = false;
}
}
if (contact.getNotify() && _listener && _listener->onContactBegin)
{
@ -614,9 +684,9 @@ void PhysicsWorld::collisionSeparateCallback(PhysicsContact& contact)
void PhysicsWorld::setGravity(Point gravity)
{
if (_bodys != nullptr)
if (_bodies != nullptr)
{
for (auto child : *_bodys)
for (auto child : *_bodies)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(child);
@ -694,9 +764,22 @@ PhysicsShape* PhysicsWorld::getShapeAtPoint(Point point)
return shape == nullptr ? nullptr : PhysicsShapeInfo::map.find(shape)->second->shape;
}
Array* PhysicsWorld::getAllBody() const
Array* PhysicsWorld::getAllBodies() const
{
return _bodys;
return _bodies;
}
PhysicsBody* PhysicsWorld::getBodyByTag(int tag)
{
for (auto body : *_bodies)
{
if (((PhysicsBody*)body)->getTag() == tag)
{
return (PhysicsBody*)body;
}
}
return nullptr;
}
#elif (CC_PHYSICS_ENGINE == CC_PHYSICS_BOX2D)
@ -720,7 +803,7 @@ PhysicsWorld::PhysicsWorld()
, _speed(1.0f)
, _info(nullptr)
, _listener(nullptr)
, _bodys(nullptr)
, _bodies(nullptr)
, _scene(nullptr)
, _debugDraw(false)
, _drawNode(nullptr)
@ -730,7 +813,7 @@ PhysicsWorld::PhysicsWorld()
PhysicsWorld::~PhysicsWorld()
{
removeAllBodys();
removeAllBodies();
removeAllJoints();
CC_SAFE_DELETE(_info);
}

View File

@ -97,7 +97,8 @@ public:
void rectQuery(PhysicsRectQueryCallback& callback, Rect rect, void* data);
Array* getShapesAtPoint(Point point);
PhysicsShape* getShapeAtPoint(Point point);
Array* getAllBody() const;
Array* getAllBodies() const;
PhysicsBody* getBodyByTag(int tag);
/** Register a listener to receive contact callbacks*/
inline void registerContactListener(PhysicsContactListener* delegate) { _listener = delegate; }
@ -116,7 +117,7 @@ public:
virtual void removeBody(PhysicsBody* body);
virtual void removeBodyByTag(int tag);
virtual void removeAllBodys();
virtual void removeAllBodies();
protected:
static PhysicsWorld* create();
@ -124,13 +125,14 @@ protected:
void setScene(Scene* scene);
virtual void addBody(PhysicsBody* body);
virtual void addShape(PhysicsShape* shape);
virtual PhysicsBody* addBody(PhysicsBody* body);
virtual PhysicsShape* addShape(PhysicsShape* shape);
virtual void removeShape(PhysicsShape* shape);
virtual void update(float delta);
virtual void debugDraw();
virtual void drawWithShape(DrawNode* node, PhysicsShape* shape);
virtual void drawWithJoint(DrawNode* node, PhysicsJoint* joint);
virtual int collisionBeginCallback(PhysicsContact& contact);
@ -145,7 +147,7 @@ protected:
PhysicsContactListener* _listener;
Array* _bodys;
Array* _bodies;
std::list<PhysicsJoint*> _joints;
Scene* _scene;

View File

@ -28,7 +28,6 @@ NS_CC_BEGIN
PhysicsBodyInfo::PhysicsBodyInfo()
: body(nullptr)
, group(CP_NO_GROUP)
{
}

View File

@ -22,11 +22,11 @@
THE SOFTWARE.
****************************************************************************/
#include "../CCPhysicsSetting.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#ifndef __CCPHYSICS_BODY_INFO_H__
#define __CCPHYSICS_BODY_INFO_H__
#include "../CCPhysicsSetting.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#include "chipmunk.h"
#include "CCPlatformMacros.h"
#include "CCObject.h"
@ -37,7 +37,6 @@ class PhysicsBodyInfo : public Clonable
{
public:
cpBody* body;
cpGroup group;
private:
PhysicsBodyInfo();

View File

@ -22,11 +22,11 @@
THE SOFTWARE.
****************************************************************************/
#include "../CCPhysicsSetting.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#ifndef __CCPHYSICS_CONTACT_INFO_H__
#define __CCPHYSICS_CONTACT_INFO_H__
#include "../CCPhysicsSetting.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#include "chipmunk.h"
#include "CCPlatformMacros.h"
NS_CC_BEGIN

View File

@ -22,12 +22,12 @@
THE SOFTWARE.
****************************************************************************/
#include "../CCPhysicsSetting.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#ifndef __CCPHYSICS_HELPER_H__
#define __CCPHYSICS_HELPER_H__
#include "../CCPhysicsSetting.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#include "chipmunk.h"
#include "CCPlatformMacros.h"
#include "CCGeometry.h"

View File

@ -22,11 +22,11 @@
THE SOFTWARE.
****************************************************************************/
#include "../CCPhysicsSetting.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#ifndef __CCPHYSICS_JOINT_INFO_H__
#define __CCPHYSICS_JOINT_INFO_H__
#include "../CCPhysicsSetting.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#include "chipmunk.h"
#include "CCPlatformMacros.h"
#include <vector>

View File

@ -22,12 +22,12 @@
THE SOFTWARE.
****************************************************************************/
#include "../CCPhysicsSetting.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#ifndef __CCPHYSICS_SHAPE_INFO_H__
#define __CCPHYSICS_SHAPE_INFO_H__
#include "../CCPhysicsSetting.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#include <vector>
#include <map>
#include "chipmunk.h"

View File

@ -22,11 +22,11 @@
THE SOFTWARE.
****************************************************************************/
#include "../CCPhysicsSetting.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#ifndef __CCPHYSICS_WORLD_INFO_H__
#define __CCPHYSICS_WORLD_INFO_H__
#include "../CCPhysicsSetting.h"
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
#include "chipmunk.h"
#include "CCPlatformMacros.h"
NS_CC_BEGIN

View File

@ -11,6 +11,8 @@ namespace
CL(PhysicsDemoClickAdd),
CL(PhysicsDemoRayCast),
CL(PhysicsDemoJoints),
CL(PhysicsDemoActions),
CL(PhysicsDemoPump),
};
static int sceneIdx=-1;
@ -52,7 +54,7 @@ namespace
}
static const Color4F STATIC_COLOR(1.0f, 0.0f, 0.0f, 1.0f);
static const int DRAG_BODYS_TAG = 100;
static const int DRAG_BODYS_TAG = 0x80;
}
@ -314,7 +316,7 @@ namespace
}
}
Sprite* PhysicsDemo::makeBall(float x, float y, float radius, PhysicsMaterial material)
Sprite* PhysicsDemo::makeBall(Point point, float radius, PhysicsMaterial material)
{
Sprite* ball = nullptr;
if (_ball != nullptr)
@ -329,12 +331,12 @@ Sprite* PhysicsDemo::makeBall(float x, float y, float radius, PhysicsMaterial ma
auto body = PhysicsBody::createCircle(radius, material);
ball->setPhysicsBody(body);
ball->setPosition(Point(x, y));
ball->setPosition(Point(point.x, point.y));
return ball;
}
Sprite* PhysicsDemo::makeBox(float x, float y, Size size, PhysicsMaterial material)
Sprite* PhysicsDemo::makeBox(Point point, Size size, PhysicsMaterial material)
{
auto box = CCRANDOM_0_1() > 0.5f ? Sprite::create("Images/YellowSquare.png") : Sprite::create("Images/CyanSquare.png");
@ -343,12 +345,12 @@ Sprite* PhysicsDemo::makeBox(float x, float y, Size size, PhysicsMaterial materi
auto body = PhysicsBody::createBox(size);
box->setPhysicsBody(body);
box->setPosition(Point(x, y));
box->setPosition(Point(point.x, point.y));
return box;
}
Sprite* PhysicsDemo::makeTriangle(float x, float y, Size size, PhysicsMaterial material)
Sprite* PhysicsDemo::makeTriangle(Point point, Size size, PhysicsMaterial material)
{
auto triangle = CCRANDOM_0_1() > 0.5f ? Sprite::create("Images/YellowTriangle.png") : Sprite::create("Images/CyanTriangle.png");
@ -365,7 +367,7 @@ Sprite* PhysicsDemo::makeTriangle(float x, float y, Size size, PhysicsMaterial m
auto body = PhysicsBody::createPolygon(vers, 3);
triangle->setPhysicsBody(body);
triangle->setPosition(Point(x, y));
triangle->setPosition(Point(point.x, point.y));
return triangle;
}
@ -380,7 +382,7 @@ bool PhysicsDemo::onTouchBegan(Touch* touch, Event* event)
{
shape = dynamic_cast<PhysicsShape*>(obj);
if (shape->getTag() == DRAG_BODYS_TAG)
if ((shape->getTag() & DRAG_BODYS_TAG) != 0)
{
break;
}
@ -395,7 +397,7 @@ bool PhysicsDemo::onTouchBegan(Touch* touch, Event* event)
mouse->setPosition(location);
this->addChild(mouse);
PhysicsJointPin* joint = PhysicsJointPin::create(mouse->getPhysicsBody(), shape->getBody(), location);
joint->setMaxForce(5000.0f);
joint->setMaxForce(5000.0f * shape->getBody()->getMass());
_scene->getPhysicsWorld()->addJoint(joint);
_mouses.insert(std::make_pair(touch->getID(), mouse));
@ -445,9 +447,9 @@ void PhysicsDemoLogoSmash::onEnter()
float x_jitter = 0.05*frand();
float y_jitter = 0.05*frand();
Node* ball = 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,
0.95f, PhysicsMaterial(1.0f, 0.0f, 0.0f));
Node* ball = makeBall(Point(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),
0.95f, PhysicsMaterial(0.01f, 0.0f, 0.0f));
ball->getPhysicsBody()->setMass(1.0);
ball->getPhysicsBody()->setMoment(PHYSICS_INFINITY);
@ -459,7 +461,7 @@ void PhysicsDemoLogoSmash::onEnter()
}
auto bullet = makeBall(400, 0, 10, PhysicsMaterial(PHYSICS_INFINITY, 0, 0));
auto bullet = makeBall(Point(400, 0), 10, PhysicsMaterial(PHYSICS_INFINITY, 0, 0));
bullet->getPhysicsBody()->setVelocity(Point(400, 0));
bullet->setPosition(Point(-1000, VisibleRect::getVisibleRect().size.height/2));
@ -727,13 +729,13 @@ void PhysicsDemoRayCast::onTouchesEnded(const std::vector<Touch*>& touches, Even
if (r < 1.0f/3.0f)
{
addChild(makeBall(location.x, location.y, 5 + CCRANDOM_0_1()*10));
addChild(makeBall(location, 5 + CCRANDOM_0_1()*10));
}else if(r < 2.0f/3.0f)
{
addChild(makeBox(location.x, location.y, Size(10 + CCRANDOM_0_1()*15, 10 + CCRANDOM_0_1()*15)));
addChild(makeBox(location, Size(10 + CCRANDOM_0_1()*15, 10 + CCRANDOM_0_1()*15)));
}else
{
addChild(makeTriangle(location.x, location.y, Size(10 + CCRANDOM_0_1()*20, 10 + CCRANDOM_0_1()*20)));
addChild(makeTriangle(location, Size(10 + CCRANDOM_0_1()*20, 10 + CCRANDOM_0_1()*20)));
}
}
}
@ -743,12 +745,6 @@ std::string PhysicsDemoRayCast::title()
return "Ray Cast";
}
PhysicsDemoJoints::PhysicsDemoJoints()
{
}
void PhysicsDemoJoints::onEnter()
{
PhysicsDemo::onEnter();
@ -780,9 +776,9 @@ void PhysicsDemoJoints::onEnter()
{
case 0:
{
auto sp1 = makeBall(offset.x - 30, offset.y, 10);
auto sp1 = makeBall(offset - Point(30, 0), 10);
sp1->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
auto sp2 = makeBall(offset.x + 30, offset.y, 10);
auto sp2 = makeBall(offset + Point(30, 0), 10);
sp2->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
PhysicsJointPin* joint = PhysicsJointPin::create(sp1->getPhysicsBody(), sp2->getPhysicsBody(), offset);
@ -795,9 +791,9 @@ void PhysicsDemoJoints::onEnter()
case 1:
{
auto sp1 = makeBall(offset.x - 30, offset.y, 10);
auto sp1 = makeBall(offset - Point(30, 0), 10);
sp1->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
auto sp2 = makeBox(offset.x + 30, offset.y, Size(30, 10));
auto sp2 = makeBox(offset + Point(30, 0), Size(30, 10));
sp2->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
PhysicsJointFixed* joint = PhysicsJointFixed::create(sp1->getPhysicsBody(), sp2->getPhysicsBody(), offset);
@ -818,3 +814,192 @@ std::string PhysicsDemoJoints::title()
{
return "Joints";
}
void PhysicsDemoActions::onEnter()
{
PhysicsDemo::onEnter();
setTouchEnabled(true);
setTouchMode(Touch::DispatchMode::ONE_BY_ONE);
auto node = Node::create();
node->setPhysicsBody(PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size));
node->setPosition(VisibleRect::center());
this->addChild(node);
Sprite* sp1 = addGrossiniAtPosition(VisibleRect::center());
Sprite* sp2 = addGrossiniAtPosition(VisibleRect::left() + Point(50, 0));
Sprite* sp3 = addGrossiniAtPosition(VisibleRect::right() - Point(20, 0));
Sprite* sp4 = addGrossiniAtPosition(VisibleRect::leftTop() + Point(50, -50));
sp4->getPhysicsBody()->setGravityEnable(false);
auto actionTo = JumpTo::create(2, Point(100,100), 50, 4);
auto actionBy = JumpBy::create(2, Point(300,0), 50, 4);
auto actionUp = JumpBy::create(2, Point(0,50), 80, 4);
auto actionByBack = actionBy->reverse();
sp1->runAction(RepeatForever::create(actionUp));
sp2->runAction(RepeatForever::create(Sequence::create(actionBy, actionByBack, NULL)));
sp3->runAction(actionTo);
sp4->runAction(RepeatForever::create(Sequence::create(actionBy->clone(), actionByBack->clone(), NULL)));
}
std::string PhysicsDemoActions::title()
{
return "Actions";
}
void PhysicsDemoPump::onEnter()
{
PhysicsDemo::onEnter();
_distance = 0.0f;
_rotationV = 0.0f;
setTouchEnabled(true);
setTouchMode(Touch::DispatchMode::ONE_BY_ONE);
scheduleUpdate();
auto node = Node::create();
auto body = PhysicsBody::create();
body->setDynamic(false);
PhysicsMaterial staticMaterial(PHYSICS_INFINITY, 0, 0.5f);
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(50, 0), VisibleRect::leftTop() + Point(50, -130), staticMaterial, 2.0f));
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(190, 0), VisibleRect::leftTop() + Point(100, -50), staticMaterial, 2.0f));
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(100, -50), VisibleRect::leftTop() + Point(100, -90), staticMaterial, 2.0f));
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(50, -130), VisibleRect::leftTop() + Point(100, -145), staticMaterial, 2.0f));
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(100, -145), VisibleRect::leftBottom() + Point(100, 80), staticMaterial, 2.0f));
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(150, -80), VisibleRect::leftBottom() + Point(150, 80), staticMaterial, 2.0f));
body->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Point(150, -80), VisibleRect::rightTop() + Point(-100, -150), staticMaterial, 2.0f));
body->setCategoryBitmask(0x01);
// balls
for (int i = 0; i < 6; ++i)
{
auto ball = makeBall(VisibleRect::leftTop() + Point(75 + CCRANDOM_0_1() * 90, 0), 22, PhysicsMaterial(0.5f, 0.0f, 0.1f));
ball->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
addChild(ball);
}
node->setPhysicsBody(body);
this->addChild(node);
Point vec[4] =
{
VisibleRect::leftTop() + Point(102, -146),
VisibleRect::leftTop() + Point(148, -159),
VisibleRect::leftBottom() + Point(148, 20),
VisibleRect::leftBottom() + Point(102, 20)
};
auto _world = _scene->getPhysicsWorld();
// small gear
auto sgear = Node::create();
auto sgearB = PhysicsBody::createCircle(50);
sgear->setPhysicsBody(sgearB);
sgear->setPosition(VisibleRect::leftBottom() + Point(125, 0));
this->addChild(sgear);
sgearB->setCategoryBitmask(0x04);
sgearB->setCollisionBitmask(0x04);
sgearB->setTag(1);
_world->addJoint(PhysicsJointPin::create(body, sgearB, sgearB->getPosition()));
// big gear
auto bgear = Node::create();
auto bgearB = PhysicsBody::createCircle(100);
bgear->setPhysicsBody(bgearB);
bgear->setPosition(VisibleRect::leftBottom() + Point(275, 0));
this->addChild(bgear);
bgearB->setCategoryBitmask(0x04);
_world->addJoint(PhysicsJointPin::create(body, bgearB, bgearB->getPosition()));
// pump
auto pump = Node::create();
pump->setPosition(PhysicsShape::getPolyonCenter(vec, 4));
auto pumpB = PhysicsBody::createPolygon(PhysicsShape::recenterPoints(vec, 4), 4);
pump->setPhysicsBody(pumpB);
this->addChild(pump);
pumpB->setCategoryBitmask(0x02);
pumpB->setGravityEnable(false);
_world->addJoint(PhysicsJointDistance::create(pumpB, sgearB, Point(0, 0), Point(0, -50)));
// plugger
Point seg[] = {VisibleRect::leftTop() + Point(75, -120), VisibleRect::leftBottom() + Point(75, -100)};
Point segCenter = (seg[1] + seg[0])/2;
seg[1] -= segCenter;
seg[0] -= segCenter;
auto plugger = Node::create();
auto pluggerB = PhysicsBody::createEdgeSegment(seg[0], seg[1], PhysicsMaterial(0.01f, 0.0f, 0.5f), 20);
pluggerB->setDynamic(true);
pluggerB->setMass(30);
pluggerB->setMoment(100000);
plugger->setPhysicsBody(pluggerB);
plugger->setPosition(segCenter);
this->addChild(plugger);
pluggerB->setCategoryBitmask(0x02);
sgearB->setCollisionBitmask(0x04 | 0x01);
_world->addJoint(PhysicsJointPin::create(body, pluggerB, VisibleRect::leftBottom() + Point(75, -90)));
_world->addJoint(PhysicsJointDistance::create(pluggerB, sgearB, pluggerB->world2Local(VisibleRect::leftBottom() + Point(75, 0)), Point(50, 0)));
}
void PhysicsDemoPump::update(float delta)
{
for (auto obj : *_scene->getPhysicsWorld()->getAllBodies())
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
if (body->getTag() == DRAG_BODYS_TAG && body->getPosition().y < 0.0f)
{
body->getOwner()->setPosition(VisibleRect::leftTop() + Point(75 + CCRANDOM_0_1() * 90, 0));
body->setVelocity(Point(0, 0));
}
}
PhysicsBody* gear = _scene->getPhysicsWorld()->getBodyByTag(1);
if (gear != nullptr)
{
if (_distance != 0.0f)
{
_rotationV += _distance/2500.0f;
if (_rotationV > 30) _rotationV = 30.0f;
if (_rotationV < -30) _rotationV = -30.0f;
}
gear->setAngularVelocity(_rotationV);
_rotationV *= 0.995;
}
}
bool PhysicsDemoPump::onTouchBegan(Touch* touch, Event* event)
{
PhysicsDemo::onTouchBegan(touch, event);
_distance = touch->getLocation().x - VisibleRect::center().x;
return true;
}
void PhysicsDemoPump::onTouchMoved(Touch* touch, Event* event)
{
PhysicsDemo::onTouchMoved(touch, event);
_distance = touch->getLocation().x - VisibleRect::center().x;
}
void PhysicsDemoPump::onTouchEnded(Touch* touch, Event* event)
{
PhysicsDemo::onTouchEnded(touch, event);
_distance = 0;
}
std::string PhysicsDemoPump::title()
{
return "Pump";
}

View File

@ -39,9 +39,9 @@ public:
void toggleDebugCallback(Object* sender);
Sprite* addGrossiniAtPosition(Point p, float scale = 1.0);
Sprite* makeBall(float x, float y, float radius, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
Sprite* makeBox(float x, float y, Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
Sprite* makeTriangle(float x, float y, Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
Sprite* makeBall(Point point, float radius, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
Sprite* makeBox(Point point, Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
Sprite* makeTriangle(Point point, Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
bool onTouchBegan(Touch* touch, Event* event) override;
void onTouchMoved(Touch* touch, Event* event) override;
@ -107,14 +107,31 @@ private:
class PhysicsDemoJoints : public PhysicsDemo
{
public:
PhysicsDemoJoints();
void onEnter() override;
std::string title() override;
};
class PhysicsDemoActions : public PhysicsDemo
{
public:
void onEnter() override;
std::string title() override;
};
class PhysicsDemoPump : public PhysicsDemo
{
public:
void onEnter() override;
std::string title() override;
void update(float delta) override;
bool onTouchBegan(Touch* touch, Event* event) override;
void onTouchMoved(Touch* touch, Event* event) override;
void onTouchEnded(Touch* touch, Event* event) override;
private:
PhysicsShape* _touchesShape;
float _distance;
float _rotationV;
};
#endif