issue #2771: add PhysicsMaterial

This commit is contained in:
boyu0 2013-10-09 17:53:12 +08:00
parent 4747e37acf
commit 381f904cd4
8 changed files with 268 additions and 163 deletions

View File

@ -43,6 +43,7 @@ Scene::Scene()
Scene::~Scene()
{
CC_SAFE_DELETE(_physicsWorld);
}
bool Scene::init()

View File

@ -92,12 +92,12 @@ PhysicsBody::~PhysicsBody()
}
}
PhysicsBody* PhysicsBody::createCircle(float radius, float density)
PhysicsBody* PhysicsBody::createCircle(float radius, PhysicsMaterial material)
{
PhysicsBody* body = new PhysicsBody();
if (body && body->init())
{
body->addShape(PhysicsShapeCircle::create(radius, density));
body->addShape(PhysicsShapeCircle::create(radius, material));
body->autorelease();
return body;
}
@ -106,12 +106,12 @@ PhysicsBody* PhysicsBody::createCircle(float radius, float density)
return nullptr;
}
PhysicsBody* PhysicsBody::createBox(Size size, float density)
PhysicsBody* PhysicsBody::createBox(Size size, PhysicsMaterial material)
{
PhysicsBody* body = new PhysicsBody();
if (body && body->init())
{
body->addShape(PhysicsShapeBox::create(size, density));
body->addShape(PhysicsShapeBox::create(size, material));
body->autorelease();
return body;
}
@ -120,12 +120,12 @@ PhysicsBody* PhysicsBody::createBox(Size size, float density)
return nullptr;
}
PhysicsBody* PhysicsBody::createPolygon(Point* points, int count, float density)
PhysicsBody* PhysicsBody::createPolygon(Point* points, int count, PhysicsMaterial material)
{
PhysicsBody* body = new PhysicsBody();
if (body && body->init())
{
body->addShape(PhysicsShapePolygon::create(points, count, density));
body->addShape(PhysicsShapePolygon::create(points, count, material));
body->autorelease();
return body;
}
@ -134,12 +134,12 @@ PhysicsBody* PhysicsBody::createPolygon(Point* points, int count, float density)
return nullptr;
}
PhysicsBody* PhysicsBody::createEdgeSegment(Point a, Point b, float border/* = 1*/)
PhysicsBody* PhysicsBody::createEdgeSegment(Point a, Point b, PhysicsMaterial material, float border/* = 1*/)
{
PhysicsBody* body = new PhysicsBody();
if (body && body->init())
{
body->addShape(PhysicsShapeEdgeSegment::create(a, b, border));
body->addShape(PhysicsShapeEdgeSegment::create(a, b, material, border));
body->_dynamic = false;
body->autorelease();
return body;
@ -149,12 +149,12 @@ PhysicsBody* PhysicsBody::createEdgeSegment(Point a, Point b, float border/* = 1
return nullptr;
}
PhysicsBody* PhysicsBody::createEdgeBox(Size size, float border/* = 1*/)
PhysicsBody* PhysicsBody::createEdgeBox(Size size, PhysicsMaterial material, float border/* = 1*/)
{
PhysicsBody* body = new PhysicsBody();
if (body && body->init())
{
body->addShape(PhysicsShapeEdgeBox::create(size, border));
body->addShape(PhysicsShapeEdgeBox::create(size, material, border));
body->_dynamic = false;
body->autorelease();
return body;
@ -165,12 +165,12 @@ PhysicsBody* PhysicsBody::createEdgeBox(Size size, float border/* = 1*/)
return nullptr;
}
PhysicsBody* PhysicsBody::createEdgePolygon(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->init())
{
body->addShape(PhysicsShapePolygon::create(points, count, border));
body->addShape(PhysicsShapeEdgePolygon::create(points, count, material, border));
body->_dynamic = false;
body->autorelease();
return body;
@ -181,12 +181,12 @@ PhysicsBody* PhysicsBody::createEdgePolygon(Point* points, int count, float bord
return nullptr;
}
PhysicsBody* PhysicsBody::createEdgeChain(Point* points, int count, float border/* = 1*/)
PhysicsBody* PhysicsBody::createEdgeChain(Point* points, int count, PhysicsMaterial material, float border/* = 1*/)
{
PhysicsBody* body = new PhysicsBody();
if (body && body->init())
{
body->addShape(PhysicsShapeEdgeChain::create(points, count, border));
body->addShape(PhysicsShapeEdgeChain::create(points, count, material, border));
body->_dynamic = false;
body->autorelease();
return body;
@ -311,9 +311,18 @@ void PhysicsBody::addShape(PhysicsShape* shape)
if (shape->getAngularDumping() > 0)
{
_angularDamping = (_angularDampingDefault ? 0 : _angularDamping) + shape->getAngularDumping();
_angularDampingDefault = false;
cpBodySetMoment(_info->body, _angularDamping);
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);

View File

@ -30,15 +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 PhysicsBodyInfo;
const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT = {0.0f, 1.0f, 1.0f};
/**
* A body affect by physics.
* it can attach one or more shapes.
@ -49,33 +55,33 @@ public:
/**
* @brief Create a body contains a circle shape.
*/
static PhysicsBody* createCircle(float radius, float density = 1);
static PhysicsBody* createCircle(float radius, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
/**
* @brief Create a body contains a box shape.
*/
static PhysicsBody* createBox(Size size, float density = 1);
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, float density = 1);
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);
virtual void addShape(PhysicsShape* shape);

View File

@ -49,7 +49,6 @@ PhysicsShape::PhysicsShape()
, _area(0)
, _mass(0)
, _angularDamping(0)
, _density(0)
, _tag(0)
, _enable(true)
{
@ -61,12 +60,13 @@ PhysicsShape::~PhysicsShape()
CC_SAFE_DELETE(_info);
}
bool PhysicsShape::init(Type type)
bool PhysicsShape::init(Type type, PhysicsMaterial material/* = MaterialDefault*/)
{
_info = new PhysicsShapeInfo(this);
if (_info == nullptr) return false;
_type = type;
_material = material;
return true;
}
@ -183,6 +183,14 @@ 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)
{
@ -201,10 +209,10 @@ void PhysicsShape::setFriction(float friction)
}
// PhysicsShapeCircle
PhysicsShapeCircle* PhysicsShapeCircle::create(float radius, float density/* = 0*/, 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(radius, density, offset))
if (shape && shape->init(radius, material, offset))
{
shape->autorelease();
return shape;
@ -214,23 +222,23 @@ PhysicsShapeCircle* PhysicsShapeCircle::create(float radius, float density/* = 0
return nullptr;
}
bool PhysicsShapeCircle::init(float radius, float density/* = 0*/, Point offset /*= Point(0, 0)*/)
bool PhysicsShapeCircle::init(float radius, PhysicsMaterial material/* = MaterialDefault*/, Point offset /*= Point(0, 0)*/)
{
do
{
CC_BREAK_IF(!PhysicsShape::init(Type::CIRCLE));
CC_BREAK_IF(!PhysicsShape::init(Type::CIRCLE, material));
cpShape* shape = cpCircleShapeNew(_info->shareBody, radius, PhysicsHelper::point2cpv(offset));
CC_BREAK_IF(shape == nullptr);
_density = density;
_area = PhysicsHelper::cpfloat2float(cpAreaForCircle(0, radius));
_mass = _density == PHYSICS_INFINITY ? PHYSICS_INFINITY : _density * _area;
_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);
@ -238,10 +246,10 @@ bool PhysicsShapeCircle::init(float radius, float density/* = 0*/, Point offset
}
// PhysicsShapeEdgeSegment
PhysicsShapeEdgeSegment* PhysicsShapeEdgeSegment::create(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(a, b, border))
if (shape && shape->init(a, b, material, border))
{
shape->autorelease();
return shape;
@ -251,11 +259,11 @@ PhysicsShapeEdgeSegment* PhysicsShapeEdgeSegment::create(Point a, Point b, float
return nullptr;
}
bool PhysicsShapeEdgeSegment::init(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(Type::EDGESEGMENT));
CC_BREAK_IF(!PhysicsShape::init(Type::EDGESEGMENT, material));
cpShape* shape = cpSegmentShapeNew(_info->shareBody,
PhysicsHelper::point2cpv(a),
@ -264,11 +272,13 @@ bool PhysicsShapeEdgeSegment::init(Point a, Point b, float border/* = 1*/)
CC_BREAK_IF(shape == nullptr);
_density = PHYSICS_INFINITY;
_mass = PHYSICS_INFINITY;
_angularDamping = PHYSICS_INFINITY;
_info->add(shape);
initEnd();
return true;
} while (false);
@ -276,10 +286,10 @@ bool PhysicsShapeEdgeSegment::init(Point a, Point b, float border/* = 1*/)
}
// PhysicsShapeBox
PhysicsShapeBox* PhysicsShapeBox::create(Size size, float density/* = 0*/, 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(size, density, offset))
if (shape && shape->init(size, material, offset))
{
shape->autorelease();
return shape;
@ -289,26 +299,24 @@ PhysicsShapeBox* PhysicsShapeBox::create(Size size, float density/* = 0*/, Point
return nullptr;
}
bool PhysicsShapeBox::init(Size size, float density/* = 0*/, Point offset /*= Point(0, 0)*/)
bool PhysicsShapeBox::init(Size size, PhysicsMaterial material/* = MaterialDefault*/, Point offset /*= Point(0, 0)*/)
{
do
{
CC_BREAK_IF(!PhysicsShape::init(Type::BOX));
CC_BREAK_IF(!PhysicsShape::init(Type::BOX, material));
cpShape* shape = cpBoxShapeNew(_info->shareBody, PhysicsHelper::float2cpfloat(size.width), PhysicsHelper::float2cpfloat(size.height));
CC_BREAK_IF(shape == nullptr);
_density = density;
_area = PhysicsHelper::cpfloat2float(cpAreaForPoly(4, ((cpPolyShape*)shape)->verts));
_mass = _density * _area;
if (_mass != 0)
{
_angularDamping = cpMomentForBox(_mass, PhysicsHelper::float2cpfloat(size.width), PhysicsHelper::float2cpfloat(size.height));
}
_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);
initEnd();
return true;
} while (false);
@ -316,10 +324,10 @@ bool PhysicsShapeBox::init(Size size, float density/* = 0*/, Point offset /*= Po
}
// PhysicsShapeCircle
PhysicsShapePolygon* PhysicsShapePolygon::create(Point* points, int count, float density/* = 0*/, 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(points, count, density, offset))
if (shape && shape->init(points, count, material, offset))
{
shape->autorelease();
return shape;
@ -329,11 +337,11 @@ PhysicsShapePolygon* PhysicsShapePolygon::create(Point* points, int count, float
return nullptr;
}
bool PhysicsShapePolygon::init(Point* points, int count, float density/* = 0*/, 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(Type::POLYGEN));
CC_BREAK_IF(!PhysicsShape::init(Type::POLYGEN, material));
cpVect* vecs = new cpVect[count];
PhysicsHelper::points2cpvs(points, vecs, count);
@ -342,16 +350,14 @@ bool PhysicsShapePolygon::init(Point* points, int count, float density/* = 0*/,
CC_BREAK_IF(shape == nullptr);
_density = density;
_area = PhysicsHelper::cpfloat2float(cpAreaForPoly(((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts));
_mass = _density * _area;
if (_mass != 0)
{
_angularDamping = cpMomentForPoly(_mass, ((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts, PhysicsHelper::point2cpv(offset));
}
_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);
initEnd();
return true;
} while (false);
@ -359,10 +365,10 @@ bool PhysicsShapePolygon::init(Point* points, int count, float density/* = 0*/,
}
// PhysicsShapeEdgeBox
PhysicsShapeEdgeBox* PhysicsShapeEdgeBox::create(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(size, border, offset))
if (shape && shape->init(size, material, border, offset))
{
shape->autorelease();
return shape;
@ -372,11 +378,11 @@ PhysicsShapeEdgeBox* PhysicsShapeEdgeBox::create(Size size, float border/* = 1*/
return nullptr;
}
bool PhysicsShapeEdgeBox::init(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(Type::EDGEBOX));
CC_BREAK_IF(!PhysicsShape::init(Type::EDGEBOX, material));
cpVect vec[4] = {};
vec[0] = PhysicsHelper::point2cpv(Point(-size.width/2+offset.x, -size.height/2+offset.y));
@ -390,8 +396,6 @@ bool PhysicsShapeEdgeBox::init(Size size, float border/* = 1*/, Point offset/*=
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);
@ -399,6 +403,8 @@ bool PhysicsShapeEdgeBox::init(Size size, float border/* = 1*/, Point offset/*=
_mass = PHYSICS_INFINITY;
_angularDamping = PHYSICS_INFINITY;
initEnd();
return true;
} while (false);
@ -406,10 +412,10 @@ bool PhysicsShapeEdgeBox::init(Size size, float border/* = 1*/, Point offset/*=
}
// PhysicsShapeEdgeBox
PhysicsShapeEdgePolygon* PhysicsShapeEdgePolygon::create(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(points, count, border))
if (shape && shape->init(points, count, material, border))
{
shape->autorelease();
return shape;
@ -419,12 +425,12 @@ PhysicsShapeEdgePolygon* PhysicsShapeEdgePolygon::create(Point* points, int coun
return nullptr;
}
bool PhysicsShapeEdgePolygon::init(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(Type::EDGEPOLYGEN));
CC_BREAK_IF(!PhysicsShape::init(Type::EDGEPOLYGEN, material));
vec = new cpVect[count];
PhysicsHelper::points2cpvs(points, vec, count);
@ -446,6 +452,8 @@ bool PhysicsShapeEdgePolygon::init(Point* points, int count, float border/* = 1*
_mass = PHYSICS_INFINITY;
_angularDamping = PHYSICS_INFINITY;
initEnd();
return true;
} while (false);
@ -455,10 +463,10 @@ bool PhysicsShapeEdgePolygon::init(Point* points, int count, float border/* = 1*
}
// PhysicsShapeEdgeChain
PhysicsShapeEdgeChain* PhysicsShapeEdgeChain::create(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(points, count, border))
if (shape && shape->init(points, count, material, border))
{
shape->autorelease();
return shape;
@ -468,12 +476,12 @@ PhysicsShapeEdgeChain* PhysicsShapeEdgeChain::create(Point* points, int count, f
return nullptr;
}
bool PhysicsShapeEdgeChain::init(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(Type::EDGECHAIN));
CC_BREAK_IF(!PhysicsShape::init(Type::EDGECHAIN, material));
vec = new cpVect[count];
PhysicsHelper::points2cpvs(points, vec, count);
@ -494,6 +502,8 @@ bool PhysicsShapeEdgeChain::init(Point* points, int count, float border/* = 1*/)
_mass = PHYSICS_INFINITY;
_angularDamping = PHYSICS_INFINITY;
initEnd();
return true;
} while (false);

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,11 +78,7 @@ public:
public:
inline PhysicsBody* getBody(){ return _body; }
inline Type getType() { return _type; }
inline float getMass() { return _mass; }
void setMass(float mass);
inline float getArea() { return _area; }
inline float getDensity() { return _density; }
void setDensity(float density);
inline float getAngularDumping() { return _angularDamping; }
void setAngularDumping(float angularDumping);
inline void setTag(int tag) { _tag = tag; }
@ -71,13 +87,16 @@ public:
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(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.
@ -97,7 +116,7 @@ protected:
float _area;
float _mass;
float _angularDamping;
float _density;
PhysicsMaterial _material;
int _tag;
bool _enable;
@ -109,10 +128,10 @@ protected:
class PhysicsShapeCircle : public PhysicsShape
{
public:
static PhysicsShapeCircle* create(float radius, float density = 0, Point offset = Point(0, 0));
static PhysicsShapeCircle* create(float radius, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
protected:
bool init(float radius, float density = 0, Point offset = Point(0, 0));
bool init(float radius, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
protected:
PhysicsShapeCircle();
@ -125,10 +144,10 @@ protected:
class PhysicsShapeBox : public PhysicsShape
{
public:
static PhysicsShapeBox* create(Size size, float density = 0, Point offset = Point(0, 0));
static PhysicsShapeBox* create(Size size, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
protected:
bool init(Size size, float density = 0, Point offset = Point(0, 0));
bool init(Size size, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
protected:
PhysicsShapeBox();
@ -141,10 +160,10 @@ protected:
class PhysicsShapePolygon : public PhysicsShape
{
public:
static PhysicsShapePolygon* create(Point* points, int count, float density = 0, Point offset = Point(0, 0));
static PhysicsShapePolygon* create(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
protected:
bool init(Point* points, int count, float density = 0, Point offset = Point(0, 0));
bool init(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, Point offset = Point(0, 0));
protected:
PhysicsShapePolygon();
@ -157,10 +176,10 @@ protected:
class PhysicsShapeEdgeSegment : public PhysicsShape
{
public:
static PhysicsShapeEdgeSegment* create(Point a, Point b, float border = 1);
static PhysicsShapeEdgeSegment* create(Point a, Point b, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
protected:
bool init(Point a, Point b, float border = 1);
bool init(Point a, Point b, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
protected:
PhysicsShapeEdgeSegment();
@ -173,10 +192,10 @@ protected:
class PhysicsShapeEdgeBox : public PhysicsShape
{
public:
static PhysicsShapeEdgeBox* create(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(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();
@ -189,10 +208,10 @@ protected:
class PhysicsShapeEdgePolygon : public PhysicsShape
{
public:
static PhysicsShapeEdgePolygon* create(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(Point* points, int count, float border = 1);
bool init(Point* points, int count, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
protected:
PhysicsShapeEdgePolygon();
@ -205,10 +224,10 @@ protected:
class PhysicsShapeEdgeChain : public PhysicsShape
{
public:
static PhysicsShapeEdgeChain* create(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(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

@ -286,7 +286,6 @@ void PhysicsWorld::debugDraw()
void PhysicsWorld::setScene(Scene *scene)
{
_scene = scene;
scene->retain();
}
void PhysicsWorld::drawWithShape(DrawNode* node, PhysicsShape* shape)
@ -413,7 +412,6 @@ PhysicsWorld::~PhysicsWorld()
{
CC_SAFE_DELETE(_info);
CC_SAFE_RELEASE(_bodys);
CC_SAFE_RELEASE(_scene);
}
NS_CC_END

View File

@ -6,6 +6,7 @@ namespace
{
static std::function<Layer*()> createFunctions[] = {
CL(PhysicsDemoLogoSmash),
CL(PhysicsDemoPyramidStack),
CL(PhysicsDemoClickAdd),
};
@ -48,10 +49,17 @@ namespace
}
}
bool PhysicsTestScene::_debugDraw = false;
bool PhysicsTestScene::initTest()
{
#ifdef CC_USE_PHYSICS
return TestScene::initWithPhysics();
if(TestScene::initWithPhysics())
{
this->getPhysicsWorld()->setDebugDraw(_debugDraw);
return true;
}
#else
return TestScene::init();
#endif
@ -70,6 +78,12 @@ void PhysicsTestScene::runThisTest()
#endif
}
void PhysicsTestScene::toggleDebug()
{
_debugDraw = !_debugDraw;
getPhysicsWorld()->setDebugDraw(_debugDraw);
}
PhysicsDemo::PhysicsDemo()
: _scene(nullptr)
{
@ -94,6 +108,7 @@ std::string PhysicsDemo::subtitle()
void PhysicsDemo::restartCallback(Object* sender)
{
auto s = new PhysicsTestScene();
s->initTest();
s->addChild( restart() );
Director::getInstance()->replaceScene(s);
s->release();
@ -102,6 +117,7 @@ void PhysicsDemo::restartCallback(Object* sender)
void PhysicsDemo::nextCallback(Object* sender)
{
auto s = new PhysicsTestScene();
s->initTest();
s->addChild( next() );
Director::getInstance()->replaceScene(s);
s->release();
@ -110,6 +126,7 @@ void PhysicsDemo::nextCallback(Object* sender)
void PhysicsDemo::backCallback(Object* sender)
{
auto s = new PhysicsTestScene();
s->initTest();
s->addChild( back() );
Director::getInstance()->replaceScene(s);
s->release();
@ -119,7 +136,10 @@ void PhysicsDemo::onEnter()
{
BaseTest::onEnter();
_scene = dynamic_cast<Scene*>(this->getParent());
_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);
@ -132,48 +152,7 @@ void PhysicsDemo::onEnter()
#endif
}
void PhysicsDemo::toggleDebugCallback(Object* sender)
{
#ifdef CC_USE_PHYSICS
if (_scene != nullptr)
{
_scene->getPhysicsWorld()->setDebugDraw(!_scene->getPhysicsWorld()->isDebugDraw());
}
#endif
}
void PhysicsDemoClickAdd::onEnter()
{
PhysicsDemo::onEnter();
#ifdef CC_USE_PHYSICS
setTouchEnabled(true);
setAccelerometerEnabled(true);
auto node = Node::create();
auto body = PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size);
node->setPhysicsBody(body);
node->setPosition(VisibleRect::center());
this->addChild(node);
auto parent = SpriteBatchNode::create("Images/grossini_dance_atlas.png", 100);
_spriteTexture = parent->getTexture();
addNewSpriteAtPosition(VisibleRect::center());
#else
auto label = LabelTTF::create("Should define CC_USE_BOX2D or CC_USE_CHIPMUNK\n to run this test case",
"Arial",
18);
auto size = Director::getInstance()->getWinSize();
label->setPosition(Point(size.width/2, size.height/2));
addChild(label);
#endif
}
void PhysicsDemoClickAdd::addNewSpriteAtPosition(Point p)
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);
@ -187,13 +166,50 @@ void PhysicsDemoClickAdd::addNewSpriteAtPosition(Point p)
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->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);
auto node = Node::create();
node->setPhysicsBody(PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size));
node->setPosition(VisibleRect::center());
this->addChild(node);
addGrossiniAtPosition(VisibleRect::center());
#else
auto label = LabelTTF::create("Should define CC_USE_BOX2D or CC_USE_CHIPMUNK\n to run this test case",
"Arial",
18);
auto size = Director::getInstance()->getWinSize();
label->setPosition(Point(size.width/2, size.height/2));
addChild(label);
#endif
}
std::string PhysicsDemoClickAdd::subtitle()
{
return "multi touch to add grossini";
@ -207,7 +223,7 @@ void PhysicsDemoClickAdd::onTouchesEnded(const std::vector<Touch*>& touches, Eve
{
auto location = touch->getLocation();
addNewSpriteAtPosition( location );
addGrossiniAtPosition( location );
}
}
@ -289,16 +305,13 @@ namespace
Node* PhysicsDemoLogoSmash::makeBall(float x, float y)
{
Sprite* ball = Sprite::create("Images/ball.png");
auto ball = Sprite::create("Images/ball.png");
ball->setScale(0.1);
PhysicsBody* body = PhysicsBody::createCircle(0.95);
auto body = PhysicsBody::createCircle(0.95, PhysicsMaterial(1, 0, 0));
body->setMass(1.0);
body->setAngularDamping(PHYSICS_INFINITY);
body->getShape()->setElasticity(0);
body->getShape()->setFriction(0);
//body->setDynamic(false);
ball->setPhysicsBody(body);
@ -310,7 +323,6 @@ Node* PhysicsDemoLogoSmash::makeBall(float x, float y)
void PhysicsDemoLogoSmash::onEnter()
{
PhysicsDemo::onEnter();
_draw = DrawNode::create();
_scene->getPhysicsWorld()->setGravity(Point(0, 0));
//addChild(makeBall(200, 200));
@ -330,13 +342,11 @@ void PhysicsDemoLogoSmash::onEnter()
}
Sprite* bullet = Sprite::create("Images/ball.png");
auto bullet = Sprite::create("Images/ball.png");
bullet->setScale(0.5);
PhysicsBody* body = PhysicsBody::createCircle(8, PHYSICS_INFINITY);
auto body = PhysicsBody::createCircle(8, PhysicsMaterial(PHYSICS_INFINITY, 0, 0));
body->setVelocity(Point(400, 0));
body->getShape()->setElasticity(0);
body->getShape()->setFriction(0);
bullet->setPhysicsBody(body);
bullet->setPosition(Point(-1000, VisibleRect::getVisibleRect().size.height/2));
@ -347,4 +357,40 @@ void PhysicsDemoLogoSmash::onEnter()
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();
}
std::string PhysicsDemoPlink::title()
{
return "Plink";
}

View File

@ -11,12 +11,17 @@ class PhysicsTestScene : public TestScene
public:
virtual bool initTest() override;
virtual void runThisTest();
void toggleDebug();
private:
static bool _debugDraw;
};
class PhysicsDemo : public BaseTest
{
protected:
Scene* _scene;
PhysicsTestScene* _scene;
public:
PhysicsDemo();
@ -30,6 +35,11 @@ public:
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
@ -38,13 +48,8 @@ public:
void onEnter() override;
std::string subtitle() override;
void addNewSpriteAtPosition(Point p);
void onTouchesEnded(const std::vector<Touch*>& touches, Event* event) override;
void onAcceleration(Acceleration* acc, Event* event) override;
private:
Texture2D* _spriteTexture; // weak ref
};
class PhysicsDemoLogoSmash : public PhysicsDemo
@ -54,9 +59,20 @@ public:
std::string title() override;
Node* makeBall(float x, float y);
private:
DrawNode* _draw;
};
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