issue #2771: edit physics effect with all bodies and fix some bugs

This commit is contained in:
boyu0 2013-10-28 16:17:19 +08:00
parent d0d8694091
commit 66d1bbd89f
13 changed files with 124 additions and 77 deletions

View File

@ -476,30 +476,6 @@ void Layer::onTouchesCancelled(const std::vector<Touch*>& pTouches, Event *pEven
CC_UNUSED_PARAM(pEvent); CC_UNUSED_PARAM(pEvent);
} }
#ifdef CC_USE_PHYSICS
void Layer::addChild(Node* child)
{
Node::addChild(child);
}
void Layer::addChild(Node* child, int zOrder)
{
Node::addChild(child, zOrder);
}
void Layer::addChild(Node* child, int zOrder, int tag)
{
Node::addChild(child, zOrder, tag);
if (this->getParent() &&
dynamic_cast<Scene*>(this->getParent()) != nullptr)
{
dynamic_cast<Scene*>(this->getParent())->addChildToPhysicsWorld(child);
}
}
#endif
// LayerRGBA // LayerRGBA
LayerRGBA::LayerRGBA() LayerRGBA::LayerRGBA()
: _displayedOpacity(255) : _displayedOpacity(255)

View File

@ -180,12 +180,6 @@ public:
*/ */
virtual void onEnterTransitionDidFinish() override; virtual void onEnterTransitionDidFinish() override;
#ifdef CC_USE_PHYSICS
virtual void addChild(Node* child) override;
virtual void addChild(Node* child, int zOrder) override;
virtual void addChild(Node* child, int zOrder, int tag) override;
#endif // CC_USE_PHYSICS
protected: protected:
void addTouchListener(); void addTouchListener();

View File

@ -43,6 +43,7 @@ THE SOFTWARE.
#include "CCEventDispatcher.h" #include "CCEventDispatcher.h"
#include "CCEvent.h" #include "CCEvent.h"
#include "CCEventTouch.h" #include "CCEventTouch.h"
#include "CCScene.h"
#ifdef CC_USE_PHYSICS #ifdef CC_USE_PHYSICS
#include "CCPhysicsBody.h" #include "CCPhysicsBody.h"
@ -627,6 +628,17 @@ void Node::addChild(Node *child, int zOrder, int tag)
this->insertChild(child, zOrder); this->insertChild(child, zOrder);
#ifdef CC_USE_PHYSICS
for (Node* node = this->getParent(); node != nullptr; node = node->getParent())
{
if (dynamic_cast<Scene*>(node) != nullptr)
{
(dynamic_cast<Scene*>(node))->addChildToPhysicsWorld(child);
break;
}
}
#endif
child->_tag = tag; child->_tag = tag;
child->setParent(this); child->setParent(this);
@ -1392,10 +1404,12 @@ void Node::setPhysicsBody(PhysicsBody* body)
{ {
if (_physicsBody != nullptr) if (_physicsBody != nullptr)
{ {
_physicsBody->_owner = nullptr;
_physicsBody->release(); _physicsBody->release();
} }
_physicsBody = body; _physicsBody = body;
_physicsBody->_owner = this;
_physicsBody->retain(); _physicsBody->retain();
_physicsBody->setPosition(getPosition()); _physicsBody->setPosition(getPosition());
_physicsBody->setRotation(getRotation()); _physicsBody->setRotation(getRotation());

View File

@ -136,14 +136,8 @@ void Scene::addChildToPhysicsWorld(Node* child)
std::function<void(Object*)> addToPhysicsWorldFunc = nullptr; std::function<void(Object*)> addToPhysicsWorldFunc = nullptr;
addToPhysicsWorldFunc = [this, &addToPhysicsWorldFunc](Object* child) -> void addToPhysicsWorldFunc = [this, &addToPhysicsWorldFunc](Object* child) -> void
{ {
if (dynamic_cast<SpriteBatchNode*>(child) != nullptr)
{ if (dynamic_cast<Node*>(child) != nullptr)
Object* subChild = nullptr;
CCARRAY_FOREACH((dynamic_cast<SpriteBatchNode*>(child))->getChildren(), subChild)
{
addToPhysicsWorldFunc(subChild);
}
}else if (dynamic_cast<Node*>(child) != nullptr)
{ {
Node* node = dynamic_cast<Node*>(child); Node* node = dynamic_cast<Node*>(child);
@ -151,20 +145,16 @@ void Scene::addChildToPhysicsWorld(Node* child)
{ {
_physicsWorld->addBody(node->getPhysicsBody()); _physicsWorld->addBody(node->getPhysicsBody());
} }
Object* subChild = nullptr;
CCARRAY_FOREACH(node->getChildren(), subChild)
{
addToPhysicsWorldFunc(subChild);
}
} }
}; };
if(dynamic_cast<Layer*>(child) != nullptr) addToPhysicsWorldFunc(child);
{
Object* subChild = nullptr;
CCARRAY_FOREACH(child->getChildren(), subChild)
{
addToPhysicsWorldFunc(subChild);
}
}else
{
addToPhysicsWorldFunc(child);
}
} }
} }

View File

@ -87,7 +87,7 @@ protected:
PhysicsWorld* _physicsWorld; PhysicsWorld* _physicsWorld;
#endif // CC_USE_PHYSICS #endif // CC_USE_PHYSICS
friend class Layer; friend class Node;
friend class SpriteBatchNode; friend class SpriteBatchNode;
}; };

View File

@ -182,17 +182,6 @@ void SpriteBatchNode::addChild(Node *child, int zOrder, int tag)
Node::addChild(child, zOrder, tag); Node::addChild(child, zOrder, tag);
appendChild(sprite); appendChild(sprite);
if (this->getParent() &&
dynamic_cast<Layer*>(this->getParent()) != nullptr)
{
if (this->getParent()->getParent() &&
dynamic_cast<Scene*>(this->getParent()->getParent()))
{
dynamic_cast<Scene*>(this->getParent()->getParent())->addChildToPhysicsWorld(child);
}
}
} }
// override reorderChild // override reorderChild

View File

@ -44,7 +44,7 @@ class PhysicsJoint;
class PhysicsBodyInfo; class PhysicsBodyInfo;
const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT(1.0f, 1.0f, 1.0f); const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT(0.01f, 0.5f, 0.5f);
/** /**
* A body affect by physics. * A body affect by physics.
@ -152,7 +152,7 @@ public:
/* /*
* @brief get the sprite the body set to. * @brief get the sprite the body set to.
*/ */
inline Sprite* getOwner() const { return _owner; } inline Node* getOwner() const { return _owner; }
inline void setCategoryBitmask(int bitmask) { _categoryBitmask = bitmask; } inline void setCategoryBitmask(int bitmask) { _categoryBitmask = bitmask; }
inline int getCategoryBitmask() const { return _categoryBitmask; } inline int getCategoryBitmask() const { return _categoryBitmask; }
@ -261,7 +261,7 @@ protected:
virtual ~PhysicsBody(); virtual ~PhysicsBody();
protected: protected:
Sprite* _owner; Node* _owner;
std::vector<PhysicsJoint*> _joints; std::vector<PhysicsJoint*> _joints;
Array* _shapes; Array* _shapes;
PhysicsWorld* _world; PhysicsWorld* _world;

View File

@ -41,6 +41,7 @@
#include "box2d/CCPhysicsShapeInfo.h" #include "box2d/CCPhysicsShapeInfo.h"
#include "chipmunk/CCPhysicsHelper.h" #include "chipmunk/CCPhysicsHelper.h"
#include "box2d/CCPhysicsHelper.h" #include "box2d/CCPhysicsHelper.h"
#include "CCNode.h"
NS_CC_BEGIN NS_CC_BEGIN
@ -149,6 +150,11 @@ PhysicsBodyInfo* PhysicsJoint::bodyInfo(PhysicsBody* body) const
return body->_info; return body->_info;
} }
Node* PhysicsJoint::bodyOwner(PhysicsBody* body) const
{
return body->_owner;
}
void PhysicsJoint::setCollisionEnable(bool enable) void PhysicsJoint::setCollisionEnable(bool enable)
{ {
@ -182,6 +188,9 @@ bool PhysicsJointFixed::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr)
{ {
CC_BREAK_IF(!PhysicsJoint::init(a, b)); CC_BREAK_IF(!PhysicsJoint::init(a, b));
bodyOwner(a)->setPosition(anchr);
bodyOwner(b)->setPosition(anchr);
// add a pivot joint to fixed two body together // add a pivot joint to fixed two body together
cpConstraint* joint = cpPivotJointNew(bodyInfo(a)->body, bodyInfo(b)->body, cpConstraint* joint = cpPivotJointNew(bodyInfo(a)->body, bodyInfo(b)->body,
PhysicsHelper::point2cpv(anchr)); PhysicsHelper::point2cpv(anchr));
@ -219,7 +228,6 @@ bool PhysicsJointPin::init(PhysicsBody *a, PhysicsBody *b, const Point& anchr)
do do
{ {
CC_BREAK_IF(!PhysicsJoint::init(a, b)); CC_BREAK_IF(!PhysicsJoint::init(a, b));
cpConstraint* joint = cpPivotJointNew(bodyInfo(a)->body, bodyInfo(b)->body, cpConstraint* joint = cpPivotJointNew(bodyInfo(a)->body, bodyInfo(b)->body,
PhysicsHelper::point2cpv(anchr)); PhysicsHelper::point2cpv(anchr));
@ -227,7 +235,7 @@ bool PhysicsJointPin::init(PhysicsBody *a, PhysicsBody *b, const Point& anchr)
_info->add(joint); _info->add(joint);
setCollisionEnable(false); //setCollisionEnable(false);
return true; return true;
} while (false); } while (false);
@ -235,6 +243,16 @@ bool PhysicsJointPin::init(PhysicsBody *a, PhysicsBody *b, const Point& anchr)
return false; return false;
} }
void PhysicsJointPin::setMaxForce(float force)
{
_info->joints.front()->maxForce = PhysicsHelper::float2cpfloat(force);
}
float PhysicsJointPin::getMaxForce()
{
return PhysicsHelper::cpfloat2float(_info->joints.front()->maxForce);
}
PhysicsJointSliding* PhysicsJointSliding::create(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr) PhysicsJointSliding* PhysicsJointSliding::create(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr)
{ {
PhysicsJointSliding* joint = new PhysicsJointSliding(); PhysicsJointSliding* joint = new PhysicsJointSliding();

View File

@ -63,6 +63,7 @@ protected:
* 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. * PhysicsShape is PhysicsBody's friend class, but all the subclasses isn't. so this method is use for subclasses to catch the bodyInfo from PhysicsBody.
*/ */
PhysicsBodyInfo* bodyInfo(PhysicsBody* body) const; PhysicsBodyInfo* bodyInfo(PhysicsBody* body) const;
Node* bodyOwner(PhysicsBody* body) const;
protected: protected:
PhysicsBody* _bodyA; PhysicsBody* _bodyA;
@ -82,7 +83,7 @@ protected:
class PhysicsJointFixed : public PhysicsJoint class PhysicsJointFixed : public PhysicsJoint
{ {
public: public:
PhysicsJointFixed* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr); static PhysicsJointFixed* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr);
protected: protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr); bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr);
@ -98,7 +99,7 @@ protected:
class PhysicsJointSliding : public PhysicsJoint class PhysicsJointSliding : public PhysicsJoint
{ {
public: public:
PhysicsJointSliding* create(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr); static PhysicsJointSliding* create(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr);
protected: protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr); bool init(PhysicsBody* a, PhysicsBody* b, const Point& grooveA, const Point& grooveB, const Point& anchr);
@ -153,6 +154,9 @@ class PhysicsJointPin : public PhysicsJoint
public: public:
static PhysicsJointPin* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr); static PhysicsJointPin* create(PhysicsBody* a, PhysicsBody* b, const Point& anchr);
void setMaxForce(float force);
float getMaxForce();
protected: protected:
bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr); bool init(PhysicsBody* a, PhysicsBody* b, const Point& anchr);

View File

@ -57,7 +57,7 @@ typedef struct PhysicsMaterial
{} {}
}PhysicsMaterial; }PhysicsMaterial;
const PhysicsMaterial PHYSICSSHAPE_MATERIAL_DEFAULT(0.0f, 1.0f, 1.0f); const PhysicsMaterial PHYSICSSHAPE_MATERIAL_DEFAULT(0.0f, 0.5f, 0.5f);
/** /**
* @brief A shape for body. You do not create PhysicsWorld objects directly, instead, you can view PhysicsBody to see how to create it. * @brief A shape for body. You do not create PhysicsWorld objects directly, instead, you can view PhysicsBody to see how to create it.

View File

@ -524,7 +524,7 @@ int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact)
if (!joint->isCollisionEnable()) if (!joint->isCollisionEnable())
{ {
PhysicsBody* body = joint->getBodyA() == bodyA ? bodyB : bodyA; PhysicsBody* body = joint->getBodyA() == bodyA ? joint->getBodyB() : joint->getBodyA();
if (body == bodyB) if (body == bodyB)
{ {

View File

@ -10,6 +10,7 @@ namespace
CL(PhysicsDemoPlink), CL(PhysicsDemoPlink),
CL(PhysicsDemoClickAdd), CL(PhysicsDemoClickAdd),
CL(PhysicsDemoRayCast), CL(PhysicsDemoRayCast),
CL(PhysicsDemoJoints),
}; };
static int sceneIdx=-1; static int sceneIdx=-1;
@ -51,6 +52,7 @@ namespace
} }
static const Color4F STATIC_COLOR(1.0f, 0.0f, 0.0f, 1.0f); static const Color4F STATIC_COLOR(1.0f, 0.0f, 0.0f, 1.0f);
static const int DRAG_BODYS_TAG = 100;
} }
@ -378,7 +380,7 @@ bool PhysicsDemo::onTouchBegan(Touch* touch, Event* event)
{ {
shape = dynamic_cast<PhysicsShape*>(obj); shape = dynamic_cast<PhysicsShape*>(obj);
if (shape->getTag() == 1) if (shape->getTag() == DRAG_BODYS_TAG)
{ {
break; break;
} }
@ -392,7 +394,8 @@ bool PhysicsDemo::onTouchBegan(Touch* touch, Event* event)
mouse->getPhysicsBody()->setDynamic(false); mouse->getPhysicsBody()->setDynamic(false);
mouse->setPosition(location); mouse->setPosition(location);
this->addChild(mouse); this->addChild(mouse);
PhysicsJoint* joint = PhysicsJointPin::create(mouse->getPhysicsBody(), shape->getBody(), location); PhysicsJointPin* joint = PhysicsJointPin::create(mouse->getPhysicsBody(), shape->getBody(), location);
joint->setMaxForce(5000.0f);
_scene->getPhysicsWorld()->addJoint(joint); _scene->getPhysicsWorld()->addJoint(joint);
_mouses.insert(std::make_pair(touch->getID(), mouse)); _mouses.insert(std::make_pair(touch->getID(), mouse));
@ -492,7 +495,7 @@ void PhysicsDemoPyramidStack::onEnter()
{ {
auto sp = addGrossiniAtPosition(VisibleRect::bottom() + Point((i/2 - j) * 11, (14 - i) * 23 + 100), 0.2f); auto sp = addGrossiniAtPosition(VisibleRect::bottom() + Point((i/2 - j) * 11, (14 - i) * 23 + 100), 0.2f);
sp->getPhysicsBody()->setTag(1); sp->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
} }
} }
} }
@ -741,15 +744,74 @@ std::string PhysicsDemoRayCast::title()
} }
PhysicsDemoJoints::PhysicsDemoJoints()
{
}
void PhysicsDemoJoints::onEnter() void PhysicsDemoJoints::onEnter()
{ {
PhysicsDemo::onEnter(); PhysicsDemo::onEnter();
setTouchEnabled(true); setTouchEnabled(true);
setTouchMode(Touch::DispatchMode::ONE_BY_ONE);
_scene->getPhysicsWorld()->setGravity(Point::ZERO); //_scene->getPhysicsWorld()->setGravity(Point::ZERO);
float width = (VisibleRect::getVisibleRect().size.width - 10) / 4;
float height = (VisibleRect::getVisibleRect().size.height - 50) / 4;
Node* node = Node::create();
PhysicsBody* box = PhysicsBody::create();
node->setPhysicsBody(box);
box->setDynamic(false);
node->setPosition(Point::ZERO);
this->addChild(node);
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
Point offset(VisibleRect::leftBottom().x + 5 + j * width + width/2, VisibleRect::leftBottom().y + 50 + i * height + height/2);
box->addShape(PhysicsShapeEdgeBox::create(Size(width, height), PHYSICSSHAPE_MATERIAL_DEFAULT, 1, offset));
switch (i*4 + j)
{
case 0:
{
auto sp1 = makeBall(offset.x - 30, offset.y, 10);
sp1->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
auto sp2 = makeBall(offset.x + 30, offset.y, 10);
sp2->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
PhysicsJointPin* joint = PhysicsJointPin::create(sp1->getPhysicsBody(), sp2->getPhysicsBody(), offset);
_scene->getPhysicsWorld()->addJoint(joint);
this->addChild(sp1);
this->addChild(sp2);
break;
}
case 1:
{
auto sp1 = makeBall(offset.x - 30, offset.y, 10);
sp1->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
auto sp2 = makeBox(offset.x + 30, offset.y, Size(30, 10));
sp2->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
PhysicsJointFixed* joint = PhysicsJointFixed::create(sp1->getPhysicsBody(), sp2->getPhysicsBody(), offset);
_scene->getPhysicsWorld()->addJoint(joint);
this->addChild(sp1);
this->addChild(sp2);
break;
}
default:
break;
}
}
}
} }
std::string PhysicsDemoJoints::title() std::string PhysicsDemoJoints::title()

View File

@ -39,9 +39,9 @@ public:
void toggleDebugCallback(Object* sender); void toggleDebugCallback(Object* sender);
Sprite* addGrossiniAtPosition(Point p, float scale = 1.0); Sprite* addGrossiniAtPosition(Point p, float scale = 1.0);
Sprite* makeBall(float x, float y, float radius, PhysicsMaterial material = PhysicsMaterial(1.0f, 1.0f, 1.0f)); Sprite* makeBall(float x, float y, float radius, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
Sprite* makeBox(float x, float y, Size size, PhysicsMaterial material = PhysicsMaterial(1.0f, 1.0f, 1.0f)); Sprite* makeBox(float x, float y, Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
Sprite* makeTriangle(float x, float y, Size size, PhysicsMaterial material = PhysicsMaterial(1.0f, 1.0f, 1.0f)); Sprite* makeTriangle(float x, float y, Size size, PhysicsMaterial material = PHYSICSBODY_MATERIAL_DEFAULT);
bool onTouchBegan(Touch* touch, Event* event) override; bool onTouchBegan(Touch* touch, Event* event) override;
void onTouchMoved(Touch* touch, Event* event) override; void onTouchMoved(Touch* touch, Event* event) override;