mirror of https://github.com/axmolengine/axmol.git
issue #4150: Correct body position with the node has a parent. Add set/getPosition/Rotation method.
This commit is contained in:
parent
ab9f030b11
commit
a934d29c57
|
@ -419,7 +419,9 @@ void Node::setPosition(const Point& position)
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
if (_physicsBody)
|
if (_physicsBody)
|
||||||
{
|
{
|
||||||
_physicsBody->setPosition(position);
|
Node* parent = getParent();
|
||||||
|
Point pos = parent != nullptr ? parent->convertToWorldSpace(getPosition()) : getPosition();
|
||||||
|
_physicsBody->setPosition(pos);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -534,6 +536,14 @@ const Point& Node::getAnchorPoint() const
|
||||||
|
|
||||||
void Node::setAnchorPoint(const Point& point)
|
void Node::setAnchorPoint(const Point& point)
|
||||||
{
|
{
|
||||||
|
#if CC_USE_PHYSICS
|
||||||
|
if (_physicsBody != nullptr && point.equals(Point::ANCHOR_MIDDLE))
|
||||||
|
{
|
||||||
|
CCLOG("Node warning: This node has a physics body, the anchor must be in the middle, you cann't change this to other value.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if( ! point.equals(_anchorPoint))
|
if( ! point.equals(_anchorPoint))
|
||||||
{
|
{
|
||||||
_anchorPoint = point;
|
_anchorPoint = point;
|
||||||
|
@ -719,6 +729,11 @@ void Node::addChild(Node *child, int zOrder, int tag)
|
||||||
this->insertChild(child, zOrder);
|
this->insertChild(child, zOrder);
|
||||||
|
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
|
if (child->getPhysicsBody() != nullptr)
|
||||||
|
{
|
||||||
|
child->getPhysicsBody()->setPosition(this->convertToWorldSpace(child->getPosition()));
|
||||||
|
}
|
||||||
|
|
||||||
for (Node* node = this->getParent(); node != nullptr; node = node->getParent())
|
for (Node* node = this->getParent(); node != nullptr; node = node->getParent())
|
||||||
{
|
{
|
||||||
if (dynamic_cast<Scene*>(node) != nullptr)
|
if (dynamic_cast<Scene*>(node) != nullptr)
|
||||||
|
@ -1511,6 +1526,14 @@ void Node::setPhysicsBody(PhysicsBody* body)
|
||||||
{
|
{
|
||||||
body->_node = this;
|
body->_node = this;
|
||||||
body->retain();
|
body->retain();
|
||||||
|
|
||||||
|
// physics rotation based on body position, but node rotation based on node anthor point
|
||||||
|
// it cann't support both of them, so I clear the anthor point to default.
|
||||||
|
if (!getAnchorPoint().equals(Point::ANCHOR_MIDDLE))
|
||||||
|
{
|
||||||
|
CCLOG("Node warning: setPhysicsBody sets anchor point to Point::ANCHOR_MIDDLE.");
|
||||||
|
setAnchorPoint(Point::ANCHOR_MIDDLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_physicsBody != nullptr)
|
if (_physicsBody != nullptr)
|
||||||
|
@ -1529,7 +1552,9 @@ void Node::setPhysicsBody(PhysicsBody* body)
|
||||||
_physicsBody = body;
|
_physicsBody = body;
|
||||||
if (body != nullptr)
|
if (body != nullptr)
|
||||||
{
|
{
|
||||||
_physicsBody->setPosition(getPosition());
|
Node* parent = getParent();
|
||||||
|
Point pos = parent != nullptr ? parent->convertToWorldSpace(getPosition()) : getPosition();
|
||||||
|
_physicsBody->setPosition(pos);
|
||||||
_physicsBody->setRotation(getRotation());
|
_physicsBody->setRotation(getRotation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -449,6 +449,7 @@ public:
|
||||||
* The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner.
|
* The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner.
|
||||||
* But you can use values higher than (1,1) and lower than (0,0) too.
|
* But you can use values higher than (1,1) and lower than (0,0) too.
|
||||||
* The default anchorPoint is (0.5,0.5), so it starts in the center of the node.
|
* The default anchorPoint is (0.5,0.5), so it starts in the center of the node.
|
||||||
|
* @note If node has a physics body, the anchor must be in the middle, you cann't change this to other value.
|
||||||
*
|
*
|
||||||
* @param anchorPoint The anchor point of node.
|
* @param anchorPoint The anchor point of node.
|
||||||
*/
|
*/
|
||||||
|
@ -1432,6 +1433,7 @@ public:
|
||||||
#if CC_USE_PHYSICS
|
#if CC_USE_PHYSICS
|
||||||
/**
|
/**
|
||||||
* set the PhysicsBody that let the sprite effect with physics
|
* set the PhysicsBody that let the sprite effect with physics
|
||||||
|
* @note This method will set anchor point to Point::ANCHOR_MIDDLE if body not null, and you cann't change anchor point if node has a physics body.
|
||||||
*/
|
*/
|
||||||
void setPhysicsBody(PhysicsBody* body);
|
void setPhysicsBody(PhysicsBody* body);
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,7 @@ PhysicsBody::PhysicsBody()
|
||||||
, _group(0)
|
, _group(0)
|
||||||
, _positionResetTag(false)
|
, _positionResetTag(false)
|
||||||
, _rotationResetTag(false)
|
, _rotationResetTag(false)
|
||||||
|
, _rotationOffset(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,7 +348,7 @@ void PhysicsBody::setPosition(Point position)
|
||||||
{
|
{
|
||||||
if (!_positionResetTag)
|
if (!_positionResetTag)
|
||||||
{
|
{
|
||||||
cpBodySetPos(_info->getBody(), PhysicsHelper::point2cpv(position));
|
cpBodySetPos(_info->getBody(), PhysicsHelper::point2cpv(position + _positionOffset));
|
||||||
}
|
}
|
||||||
_positionResetTag = false;
|
_positionResetTag = false;
|
||||||
}
|
}
|
||||||
|
@ -356,7 +357,7 @@ void PhysicsBody::setRotation(float rotation)
|
||||||
{
|
{
|
||||||
if (!_rotationResetTag)
|
if (!_rotationResetTag)
|
||||||
{
|
{
|
||||||
cpBodySetAngle(_info->getBody(), -PhysicsHelper::float2cpfloat(rotation * M_PI / 180.0f));
|
cpBodySetAngle(_info->getBody(), -PhysicsHelper::float2cpfloat((rotation + _rotationOffset) * (M_PI / 180.0f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
_rotationResetTag = false;
|
_rotationResetTag = false;
|
||||||
|
@ -365,12 +366,12 @@ void PhysicsBody::setRotation(float rotation)
|
||||||
Point PhysicsBody::getPosition() const
|
Point PhysicsBody::getPosition() const
|
||||||
{
|
{
|
||||||
cpVect vec = cpBodyGetPos(_info->getBody());
|
cpVect vec = cpBodyGetPos(_info->getBody());
|
||||||
return PhysicsHelper::cpv2point(vec);
|
return PhysicsHelper::cpv2point(vec) - _positionOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
float PhysicsBody::getRotation() const
|
float PhysicsBody::getRotation() const
|
||||||
{
|
{
|
||||||
return -PhysicsHelper::cpfloat2float(cpBodyGetAngle(_info->getBody()) / M_PI * 180.0f);
|
return -PhysicsHelper::cpfloat2float(cpBodyGetAngle(_info->getBody()) * (180.0f / M_PI)) - _rotationOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsShape* PhysicsBody::addShape(PhysicsShape* shape, bool addMassAndMoment/* = true*/)
|
PhysicsShape* PhysicsBody::addShape(PhysicsShape* shape, bool addMassAndMoment/* = true*/)
|
||||||
|
@ -767,27 +768,18 @@ void PhysicsBody::setResting(bool rest) const
|
||||||
|
|
||||||
void PhysicsBody::update(float delta)
|
void PhysicsBody::update(float delta)
|
||||||
{
|
{
|
||||||
if (_node != nullptr && _dynamic && !isResting())
|
if (_node != nullptr)
|
||||||
{
|
{
|
||||||
cpVect pos = cpBodyGetPos(_info->getBody());
|
Node* parent = _node->getParent();
|
||||||
cpVect prePos = _info->getPosition();
|
|
||||||
cpVect rot = cpBodyGetRot(_info->getBody());
|
|
||||||
cpVect preRot = _info->getRotation();
|
|
||||||
|
|
||||||
// only reset the node position when body position/rotation changed.
|
Point position = parent != nullptr ? parent->convertToNodeSpace(getPosition()) : getPosition();
|
||||||
if (std::abs(pos.x - prePos.x) >= 0.3f || std::abs(pos.y - prePos.y) >= 0.3f
|
_positionResetTag = true;
|
||||||
|| std::abs(rot.x - preRot.x) >= 0.01f || std::abs(rot.y - preRot.y) >= 0.01f)
|
_rotationResetTag = true;
|
||||||
{
|
_node->setPosition(position);
|
||||||
_positionResetTag = true;
|
_node->setRotation(getRotation());
|
||||||
_rotationResetTag = true;
|
|
||||||
_node->setPosition(getPosition());
|
|
||||||
_info->setPosition(pos);
|
|
||||||
_node->setRotation(getRotation());
|
|
||||||
_info->setRotation(rot);
|
|
||||||
}
|
|
||||||
|
|
||||||
// damping compute
|
// damping compute
|
||||||
if (_isDamping)
|
if (_isDamping && _dynamic && !isResting())
|
||||||
{
|
{
|
||||||
_info->getBody()->v.x *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f);
|
_info->getBody()->v.x *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f);
|
||||||
_info->getBody()->v.y *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f);
|
_info->getBody()->v.y *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f);
|
||||||
|
@ -834,6 +826,46 @@ void PhysicsBody::setGroup(int group)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicsBody::setPositionOffset(const Point& position)
|
||||||
|
{
|
||||||
|
if (!_positionOffset.equals(position))
|
||||||
|
{
|
||||||
|
Point pos = getPosition();
|
||||||
|
|
||||||
|
_positionOffset = position;
|
||||||
|
|
||||||
|
if (_node!= nullptr)
|
||||||
|
{
|
||||||
|
setPosition(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Point PhysicsBody::getPositionOffset()
|
||||||
|
{
|
||||||
|
return _positionOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsBody::setRotationOffset(float rotation)
|
||||||
|
{
|
||||||
|
if (std::abs(_rotationOffset - rotation) > 0.5f)
|
||||||
|
{
|
||||||
|
float rot = getRotation();
|
||||||
|
|
||||||
|
_rotationOffset = rotation;
|
||||||
|
|
||||||
|
if (_node != nullptr)
|
||||||
|
{
|
||||||
|
setRotation(rot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float PhysicsBody::getRotationOffset()
|
||||||
|
{
|
||||||
|
return _rotationOffset;
|
||||||
|
}
|
||||||
|
|
||||||
Point PhysicsBody::world2Local(const Point& point)
|
Point PhysicsBody::world2Local(const Point& point)
|
||||||
{
|
{
|
||||||
return PhysicsHelper::cpv2point(cpBodyWorld2Local(_info->getBody(), PhysicsHelper::point2cpv(point)));
|
return PhysicsHelper::cpv2point(cpBodyWorld2Local(_info->getBody(), PhysicsHelper::point2cpv(point)));
|
||||||
|
|
|
@ -192,6 +192,15 @@ public:
|
||||||
/** get the body rotation. */
|
/** get the body rotation. */
|
||||||
float getRotation() const;
|
float getRotation() const;
|
||||||
|
|
||||||
|
/** set body position offset, it's the position witch relative to node */
|
||||||
|
void setPositionOffset(const Point& position);
|
||||||
|
/** get body position offset. */
|
||||||
|
Point getPositionOffset();
|
||||||
|
/** set body rotation offset, it's the rotation witch relative to node */
|
||||||
|
void setRotationOffset(float rotation);
|
||||||
|
/** set the body rotation offset */
|
||||||
|
float getRotationOffset();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief test the body is dynamic or not.
|
* @brief test the body is dynamic or not.
|
||||||
* a dynamic body will effect with gravity.
|
* a dynamic body will effect with gravity.
|
||||||
|
@ -332,6 +341,8 @@ protected:
|
||||||
|
|
||||||
bool _positionResetTag; /// To avoid reset the body position when body invoke Node::setPosition().
|
bool _positionResetTag; /// To avoid reset the body position when body invoke Node::setPosition().
|
||||||
bool _rotationResetTag; /// To avoid reset the body rotation when body invoke Node::setRotation().
|
bool _rotationResetTag; /// To avoid reset the body rotation when body invoke Node::setRotation().
|
||||||
|
Point _positionOffset;
|
||||||
|
float _rotationOffset;
|
||||||
|
|
||||||
friend class PhysicsWorld;
|
friend class PhysicsWorld;
|
||||||
friend class PhysicsShape;
|
friend class PhysicsShape;
|
||||||
|
|
Loading…
Reference in New Issue