diff --git a/cocos2dx/layers_scenes_transitions_nodes/CCScene.cpp b/cocos2dx/layers_scenes_transitions_nodes/CCScene.cpp index 50b67e50e0..9081c5c630 100644 --- a/cocos2dx/layers_scenes_transitions_nodes/CCScene.cpp +++ b/cocos2dx/layers_scenes_transitions_nodes/CCScene.cpp @@ -43,6 +43,7 @@ Scene::Scene() Scene::~Scene() { + CC_SAFE_DELETE(_physicsWorld); } bool Scene::init() diff --git a/cocos2dx/physics/CCPhysicsBody.cpp b/cocos2dx/physics/CCPhysicsBody.cpp index 44acb0c11f..4c2c1c65d7 100644 --- a/cocos2dx/physics/CCPhysicsBody.cpp +++ b/cocos2dx/physics/CCPhysicsBody.cpp @@ -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); diff --git a/cocos2dx/physics/CCPhysicsBody.h b/cocos2dx/physics/CCPhysicsBody.h index 580bec840d..505235de0a 100644 --- a/cocos2dx/physics/CCPhysicsBody.h +++ b/cocos2dx/physics/CCPhysicsBody.h @@ -30,15 +30,21 @@ #include "cocoa/CCObject.h" #include "cocoa/CCGeometry.h" + +#include "CCPhysicsShape.h" + #include 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); diff --git a/cocos2dx/physics/CCPhysicsShape.cpp b/cocos2dx/physics/CCPhysicsShape.cpp index 0b80d9ae68..b373e0710e 100644 --- a/cocos2dx/physics/CCPhysicsShape.cpp +++ b/cocos2dx/physics/CCPhysicsShape.cpp @@ -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); diff --git a/cocos2dx/physics/CCPhysicsShape.h b/cocos2dx/physics/CCPhysicsShape.h index aea4a9e36d..d754f6030b 100644 --- a/cocos2dx/physics/CCPhysicsShape.h +++ b/cocos2dx/physics/CCPhysicsShape.h @@ -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(); diff --git a/cocos2dx/physics/CCPhysicsWorld.cpp b/cocos2dx/physics/CCPhysicsWorld.cpp index 6f0fa1295c..fa0c245e5e 100644 --- a/cocos2dx/physics/CCPhysicsWorld.cpp +++ b/cocos2dx/physics/CCPhysicsWorld.cpp @@ -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 diff --git a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp index 3135e2481a..658cc606da 100644 --- a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp +++ b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp @@ -6,6 +6,7 @@ namespace { static std::function 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(this->getParent()); + _scene = dynamic_cast(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& 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"; } \ No newline at end of file diff --git a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h index cf63471998..c75431a852 100644 --- a/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h +++ b/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.h @@ -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& 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