mirror of https://github.com/axmolengine/axmol.git
Merge pull request #11379 from WenhaiLin/v3-physics-fix
Physics: Fixed position of physics body is wrong when the position of parent node changes
This commit is contained in:
commit
698d93a42b
|
@ -127,6 +127,8 @@ Node::Node(void)
|
||||||
, _physicsRotation(0.0f)
|
, _physicsRotation(0.0f)
|
||||||
, _physicsTransformDirty(true)
|
, _physicsTransformDirty(true)
|
||||||
, _updateTransformFromPhysics(true)
|
, _updateTransformFromPhysics(true)
|
||||||
|
, _physicsWorld(nullptr)
|
||||||
|
, _physicsBodyAssociatedWith(0)
|
||||||
#endif
|
#endif
|
||||||
, _displayedOpacity(255)
|
, _displayedOpacity(255)
|
||||||
, _realOpacity(255)
|
, _realOpacity(255)
|
||||||
|
@ -334,8 +336,9 @@ void Node::setRotation(float rotation)
|
||||||
_rotationZ_X = _rotationZ_Y = rotation;
|
_rotationZ_X = _rotationZ_Y = rotation;
|
||||||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
if (_physicsBody && _physicsBody->getWorld()) {
|
if (_physicsWorld && _physicsBodyAssociatedWith > 0)
|
||||||
_physicsBody->getWorld()->_updateBodyTransform = true;
|
{
|
||||||
|
_physicsWorld->_updateBodyTransform = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -475,8 +478,9 @@ void Node::setScale(float scale)
|
||||||
_scaleX = _scaleY = _scaleZ = scale;
|
_scaleX = _scaleY = _scaleZ = scale;
|
||||||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
if (_physicsBody && _physicsBody->getWorld()) {
|
if (_physicsWorld && _physicsBodyAssociatedWith > 0)
|
||||||
_physicsBody->getWorld()->_updateBodyTransform = true;
|
{
|
||||||
|
_physicsWorld->_updateBodyTransform = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -497,8 +501,9 @@ void Node::setScale(float scaleX,float scaleY)
|
||||||
_scaleY = scaleY;
|
_scaleY = scaleY;
|
||||||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
if (_physicsBody && _physicsBody->getWorld()) {
|
if (_physicsWorld && _physicsBodyAssociatedWith > 0)
|
||||||
_physicsBody->getWorld()->_updateBodyTransform = true;
|
{
|
||||||
|
_physicsWorld->_updateBodyTransform = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -512,8 +517,9 @@ void Node::setScaleX(float scaleX)
|
||||||
_scaleX = scaleX;
|
_scaleX = scaleX;
|
||||||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
if (_physicsBody && _physicsBody->getWorld()) {
|
if (_physicsWorld && _physicsBodyAssociatedWith > 0)
|
||||||
_physicsBody->getWorld()->_updateBodyTransform = true;
|
{
|
||||||
|
_physicsWorld->_updateBodyTransform = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -556,8 +562,9 @@ void Node::setScaleY(float scaleY)
|
||||||
_scaleY = scaleY;
|
_scaleY = scaleY;
|
||||||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
if (_physicsBody && _physicsBody->getWorld()) {
|
if (_physicsWorld && _physicsBodyAssociatedWith > 0)
|
||||||
_physicsBody->getWorld()->_updateBodyTransform = true;
|
{
|
||||||
|
_physicsWorld->_updateBodyTransform = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -592,8 +599,9 @@ void Node::setPosition(float x, float y)
|
||||||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||||
_usingNormalizedPosition = false;
|
_usingNormalizedPosition = false;
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
if (_physicsBody && _physicsBody->getWorld()) {
|
if (_physicsWorld && _physicsBodyAssociatedWith > 0)
|
||||||
_physicsBody->getWorld()->_updateBodyTransform = true;
|
{
|
||||||
|
_physicsWorld->_updateBodyTransform = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -661,8 +669,9 @@ void Node::setNormalizedPosition(const Vec2& position)
|
||||||
_normalizedPositionDirty = true;
|
_normalizedPositionDirty = true;
|
||||||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
if (_physicsBody && _physicsBody->getWorld()) {
|
if (_physicsWorld && _physicsBodyAssociatedWith > 0)
|
||||||
_physicsBody->getWorld()->_updateBodyTransform = true;
|
{
|
||||||
|
_physicsWorld->_updateBodyTransform = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1050,8 +1059,17 @@ void Node::addChildHelper(Node* child, int localZOrder, int tag, const std::stri
|
||||||
child->setOrderOfArrival(s_globalOrderOfArrival++);
|
child->setOrderOfArrival(s_globalOrderOfArrival++);
|
||||||
|
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
|
_physicsBodyAssociatedWith += child->_physicsBodyAssociatedWith;
|
||||||
|
auto parentNode = this;
|
||||||
|
while (parentNode->_parent)
|
||||||
|
{
|
||||||
|
parentNode = parentNode->_parent;
|
||||||
|
parentNode->_physicsBodyAssociatedWith += child->_physicsBodyAssociatedWith;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto scene = dynamic_cast<Scene*>(parentNode);
|
||||||
|
|
||||||
// Recursive add children with which have physics body.
|
// Recursive add children with which have physics body.
|
||||||
auto scene = this->getScene();
|
|
||||||
if (scene && scene->getPhysicsWorld())
|
if (scene && scene->getPhysicsWorld())
|
||||||
{
|
{
|
||||||
scene->addChildToPhysicsWorld(child);
|
scene->addChildToPhysicsWorld(child);
|
||||||
|
@ -2029,6 +2047,14 @@ void Node::setPhysicsBody(PhysicsBody* body)
|
||||||
_physicsBody->_node = nullptr;
|
_physicsBody->_node = nullptr;
|
||||||
_physicsBody->release();
|
_physicsBody->release();
|
||||||
_physicsBody = nullptr;
|
_physicsBody = nullptr;
|
||||||
|
|
||||||
|
_physicsBodyAssociatedWith--;
|
||||||
|
auto parentNode = this;
|
||||||
|
while (parentNode->_parent)
|
||||||
|
{
|
||||||
|
parentNode = parentNode->_parent;
|
||||||
|
parentNode->_physicsBodyAssociatedWith--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body)
|
if (body)
|
||||||
|
@ -2053,7 +2079,15 @@ void Node::setPhysicsBody(PhysicsBody* body)
|
||||||
_physicsScaleStartX = _scaleX;
|
_physicsScaleStartX = _scaleX;
|
||||||
_physicsScaleStartY = _scaleY;
|
_physicsScaleStartY = _scaleY;
|
||||||
|
|
||||||
auto scene = getScene();
|
_physicsBodyAssociatedWith++;
|
||||||
|
auto parentNode = this;
|
||||||
|
while (parentNode->_parent)
|
||||||
|
{
|
||||||
|
parentNode = parentNode->_parent;
|
||||||
|
parentNode->_physicsBodyAssociatedWith++;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto scene = dynamic_cast<Scene*>(parentNode);
|
||||||
if (scene && scene->getPhysicsWorld())
|
if (scene && scene->getPhysicsWorld())
|
||||||
{
|
{
|
||||||
_physicsTransformDirty = true;
|
_physicsTransformDirty = true;
|
||||||
|
@ -2095,6 +2129,7 @@ void Node::updateTransformFromPhysics(const Mat4& parentTransform, uint32_t pare
|
||||||
{
|
{
|
||||||
auto& newPosition = _physicsBody->getPosition();
|
auto& newPosition = _physicsBody->getPosition();
|
||||||
auto& recordedPosition = _physicsBody->_recordedPosition;
|
auto& recordedPosition = _physicsBody->_recordedPosition;
|
||||||
|
auto updateBodyTransform = _physicsWorld->_updateBodyTransform;
|
||||||
if (parentFlags || recordedPosition.x != newPosition.x || recordedPosition.y != newPosition.y)
|
if (parentFlags || recordedPosition.x != newPosition.x || recordedPosition.y != newPosition.y)
|
||||||
{
|
{
|
||||||
recordedPosition = newPosition;
|
recordedPosition = newPosition;
|
||||||
|
@ -2105,6 +2140,7 @@ void Node::updateTransformFromPhysics(const Mat4& parentTransform, uint32_t pare
|
||||||
}
|
}
|
||||||
_physicsRotation = _physicsBody->getRotation();
|
_physicsRotation = _physicsBody->getRotation();
|
||||||
setRotation(_physicsRotation - _parent->_physicsRotation);
|
setRotation(_physicsRotation - _parent->_physicsRotation);
|
||||||
|
_physicsWorld->_updateBodyTransform = updateBodyTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //CC_USE_PHYSICS
|
#endif //CC_USE_PHYSICS
|
||||||
|
|
|
@ -54,6 +54,7 @@ class GLProgram;
|
||||||
class GLProgramState;
|
class GLProgramState;
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
class PhysicsBody;
|
class PhysicsBody;
|
||||||
|
class PhysicsWorld;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1838,6 +1839,9 @@ protected:
|
||||||
float _physicsRotation;
|
float _physicsRotation;
|
||||||
bool _physicsTransformDirty;
|
bool _physicsTransformDirty;
|
||||||
bool _updateTransformFromPhysics;
|
bool _updateTransformFromPhysics;
|
||||||
|
|
||||||
|
PhysicsWorld* _physicsWorld; /** The PhysicsWorld associated with the node.*/
|
||||||
|
int _physicsBodyAssociatedWith; /** The count of PhysicsBody associated with the node and children.*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// opacity controls
|
// opacity controls
|
||||||
|
@ -1862,7 +1866,7 @@ private:
|
||||||
CC_DISALLOW_COPY_AND_ASSIGN(Node);
|
CC_DISALLOW_COPY_AND_ASSIGN(Node);
|
||||||
|
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
friend class Layer;
|
friend class Scene;
|
||||||
#endif //CC_USTPS
|
#endif //CC_USTPS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -227,6 +227,8 @@ void Scene::addChildToPhysicsWorld(Node* child)
|
||||||
std::function<void(Node*)> addToPhysicsWorldFunc = nullptr;
|
std::function<void(Node*)> addToPhysicsWorldFunc = nullptr;
|
||||||
addToPhysicsWorldFunc = [this, &addToPhysicsWorldFunc](Node* node) -> void
|
addToPhysicsWorldFunc = [this, &addToPhysicsWorldFunc](Node* node) -> void
|
||||||
{
|
{
|
||||||
|
node->_physicsWorld = _physicsWorld;
|
||||||
|
|
||||||
if (node->getPhysicsBody())
|
if (node->getPhysicsBody())
|
||||||
{
|
{
|
||||||
_physicsWorld->addBody(node->getPhysicsBody());
|
_physicsWorld->addBody(node->getPhysicsBody());
|
||||||
|
|
|
@ -1716,8 +1716,7 @@ std::string PhysicsFixedUpdate::subtitle() const
|
||||||
|
|
||||||
bool PhysicsTransformTest::onTouchBegan(Touch *touch, Event *event)
|
bool PhysicsTransformTest::onTouchBegan(Touch *touch, Event *event)
|
||||||
{
|
{
|
||||||
Node* child = this->getChildByTag(1);
|
_parentSprite->setPosition(_rootLayer->convertTouchToNodeSpace(touch));
|
||||||
child->setPosition(this->convertTouchToNodeSpace(touch));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1731,46 +1730,49 @@ void PhysicsTransformTest::onEnter()
|
||||||
touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsTransformTest::onTouchBegan, this);
|
touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsTransformTest::onTouchBegan, this);
|
||||||
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
|
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
|
||||||
|
|
||||||
|
_rootLayer = Layer::create();
|
||||||
|
addChild(_rootLayer);
|
||||||
|
|
||||||
auto wall = Node::create();
|
auto wall = Node::create();
|
||||||
wall->setPhysicsBody(PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size, PhysicsMaterial(0.1f, 1.0f, 0.0f)));
|
wall->setPhysicsBody(PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size, PhysicsMaterial(0.1f, 1.0f, 0.0f)));
|
||||||
wall->setPosition(VisibleRect::center());
|
wall->setPosition(VisibleRect::center());
|
||||||
addChild(wall);
|
_rootLayer->addChild(wall);
|
||||||
|
|
||||||
//parent test
|
//parent test
|
||||||
auto parent = Sprite::create("Images/YellowSquare.png");
|
_parentSprite = Sprite::create("Images/YellowSquare.png");
|
||||||
parent->setPosition(200, 100);
|
_parentSprite->setPosition(200, 100);
|
||||||
parent->setScale(0.25);
|
_parentSprite->setScale(0.25);
|
||||||
parent->setPhysicsBody(PhysicsBody::createBox(parent->getContentSize()*parent->getScale(), PhysicsMaterial(0.1f, 1.0f, 0.0f)));
|
_parentSprite->setPhysicsBody(PhysicsBody::createBox(_parentSprite->getContentSize()*_parentSprite->getScale(), PhysicsMaterial(0.1f, 1.0f, 0.0f)));
|
||||||
parent->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
|
_parentSprite->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
|
||||||
parent->setTag(1);
|
_parentSprite->setTag(1);
|
||||||
addChild(parent);
|
_rootLayer->addChild(_parentSprite);
|
||||||
|
|
||||||
auto leftBall = Sprite::create("Images/ball.png");
|
auto leftBall = Sprite::create("Images/ball.png");
|
||||||
leftBall->setPosition(-30, 0);
|
leftBall->setPosition(-30, 0);
|
||||||
leftBall->cocos2d::Node::setScale(2);
|
leftBall->cocos2d::Node::setScale(2);
|
||||||
leftBall->setPhysicsBody(PhysicsBody::createCircle(leftBall->getContentSize().width, PhysicsMaterial(0.1f, 1.0f, 0.0f)));
|
leftBall->setPhysicsBody(PhysicsBody::createCircle(leftBall->getContentSize().width, PhysicsMaterial(0.1f, 1.0f, 0.0f)));
|
||||||
leftBall->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
|
leftBall->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
|
||||||
parent->addChild(leftBall);
|
_parentSprite->addChild(leftBall);
|
||||||
|
|
||||||
ScaleTo* scaleTo = ScaleTo::create(2.0, 0.5);
|
ScaleTo* scaleTo = ScaleTo::create(2.0, 0.5);
|
||||||
ScaleTo* scaleBack = ScaleTo::create(2.0, 1.0);
|
ScaleTo* scaleBack = ScaleTo::create(2.0, 1.0);
|
||||||
parent->runAction(RepeatForever::create(Sequence::create(scaleTo, scaleBack, nullptr)));
|
_parentSprite->runAction(RepeatForever::create(Sequence::create(scaleTo, scaleBack, nullptr)));
|
||||||
|
|
||||||
auto normal = Sprite::create("Images/YellowSquare.png");
|
auto normal = Sprite::create("Images/YellowSquare.png");
|
||||||
normal->setPosition(300, 100);
|
normal->setPosition(300, 100);
|
||||||
normal->setScale(0.25, 0.5);
|
normal->setScale(0.25, 0.5);
|
||||||
auto size = parent->getContentSize();
|
auto size = _parentSprite->getContentSize();
|
||||||
size.width *= normal->getScaleX();
|
size.width *= normal->getScaleX();
|
||||||
size.height *= normal->getScaleY();
|
size.height *= normal->getScaleY();
|
||||||
normal->setPhysicsBody(PhysicsBody::createBox(size, PhysicsMaterial(0.1f, 1.0f, 0.0f)));
|
normal->setPhysicsBody(PhysicsBody::createBox(size, PhysicsMaterial(0.1f, 1.0f, 0.0f)));
|
||||||
normal->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
|
normal->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
|
||||||
addChild(normal);
|
_rootLayer->addChild(normal);
|
||||||
|
|
||||||
auto bullet = Sprite::create("Images/ball.png");
|
auto bullet = Sprite::create("Images/ball.png");
|
||||||
bullet->setPosition(200, 200);
|
bullet->setPosition(200, 200);
|
||||||
bullet->setPhysicsBody(PhysicsBody::createCircle(bullet->getContentSize().width/2, PhysicsMaterial(0.1f, 1.0f, 0.0f)));
|
bullet->setPhysicsBody(PhysicsBody::createCircle(bullet->getContentSize().width/2, PhysicsMaterial(0.1f, 1.0f, 0.0f)));
|
||||||
bullet->getPhysicsBody()->setVelocity(Vect(100, 100));
|
bullet->getPhysicsBody()->setVelocity(Vect(100, 100));
|
||||||
this->addChild(bullet);
|
_rootLayer->addChild(bullet);
|
||||||
|
|
||||||
|
|
||||||
MoveBy* move = MoveBy::create(2.0f, Vec2(100, 100));
|
MoveBy* move = MoveBy::create(2.0f, Vec2(100, 100));
|
||||||
|
@ -1781,9 +1783,9 @@ void PhysicsTransformTest::onEnter()
|
||||||
|
|
||||||
RotateBy* rotate = RotateBy::create(6.0f, 360);
|
RotateBy* rotate = RotateBy::create(6.0f, 360);
|
||||||
|
|
||||||
this->runAction(RepeatForever::create(Sequence::create(move, move2, move3, nullptr)));
|
_rootLayer->runAction(RepeatForever::create(Sequence::create(move, move2, move3, nullptr)));
|
||||||
this->runAction(RepeatForever::create(Sequence::create(scale, scale2, nullptr)));
|
_rootLayer->runAction(RepeatForever::create(Sequence::create(scale, scale2, nullptr)));
|
||||||
this->runAction(RepeatForever::create(rotate));
|
_rootLayer->runAction(RepeatForever::create(rotate));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PhysicsTransformTest::title() const
|
std::string PhysicsTransformTest::title() const
|
||||||
|
|
|
@ -259,6 +259,9 @@ public:
|
||||||
|
|
||||||
bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
|
bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
cocos2d::Sprite* _parentSprite;
|
||||||
|
cocos2d::Layer* _rootLayer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PhysicsIssue9959 : public PhysicsDemo
|
class PhysicsIssue9959 : public PhysicsDemo
|
||||||
|
|
Loading…
Reference in New Issue