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