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 (_physicsBody)
|
||||
{
|
||||
_physicsBody->setPosition(position);
|
||||
Node* parent = getParent();
|
||||
Point pos = parent != nullptr ? parent->convertToWorldSpace(getPosition()) : getPosition();
|
||||
_physicsBody->setPosition(pos);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -534,6 +536,14 @@ const Point& Node::getAnchorPoint() const
|
|||
|
||||
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))
|
||||
{
|
||||
_anchorPoint = point;
|
||||
|
@ -719,6 +729,11 @@ void Node::addChild(Node *child, int zOrder, int tag)
|
|||
this->insertChild(child, zOrder);
|
||||
|
||||
#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())
|
||||
{
|
||||
if (dynamic_cast<Scene*>(node) != nullptr)
|
||||
|
@ -1511,6 +1526,14 @@ void Node::setPhysicsBody(PhysicsBody* body)
|
|||
{
|
||||
body->_node = this;
|
||||
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)
|
||||
|
@ -1529,7 +1552,9 @@ void Node::setPhysicsBody(PhysicsBody* body)
|
|||
_physicsBody = body;
|
||||
if (body != nullptr)
|
||||
{
|
||||
_physicsBody->setPosition(getPosition());
|
||||
Node* parent = getParent();
|
||||
Point pos = parent != nullptr ? parent->convertToWorldSpace(getPosition()) : getPosition();
|
||||
_physicsBody->setPosition(pos);
|
||||
_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.
|
||||
* 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.
|
||||
* @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.
|
||||
*/
|
||||
|
@ -1432,6 +1433,7 @@ public:
|
|||
#if CC_USE_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);
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ PhysicsBody::PhysicsBody()
|
|||
, _group(0)
|
||||
, _positionResetTag(false)
|
||||
, _rotationResetTag(false)
|
||||
, _rotationOffset(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -347,7 +348,7 @@ void PhysicsBody::setPosition(Point position)
|
|||
{
|
||||
if (!_positionResetTag)
|
||||
{
|
||||
cpBodySetPos(_info->getBody(), PhysicsHelper::point2cpv(position));
|
||||
cpBodySetPos(_info->getBody(), PhysicsHelper::point2cpv(position + _positionOffset));
|
||||
}
|
||||
_positionResetTag = false;
|
||||
}
|
||||
|
@ -356,7 +357,7 @@ void PhysicsBody::setRotation(float rotation)
|
|||
{
|
||||
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;
|
||||
|
@ -365,12 +366,12 @@ void PhysicsBody::setRotation(float rotation)
|
|||
Point PhysicsBody::getPosition() const
|
||||
{
|
||||
cpVect vec = cpBodyGetPos(_info->getBody());
|
||||
return PhysicsHelper::cpv2point(vec);
|
||||
return PhysicsHelper::cpv2point(vec) - _positionOffset;
|
||||
}
|
||||
|
||||
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*/)
|
||||
|
@ -767,27 +768,18 @@ void PhysicsBody::setResting(bool rest) const
|
|||
|
||||
void PhysicsBody::update(float delta)
|
||||
{
|
||||
if (_node != nullptr && _dynamic && !isResting())
|
||||
if (_node != nullptr)
|
||||
{
|
||||
cpVect pos = cpBodyGetPos(_info->getBody());
|
||||
cpVect prePos = _info->getPosition();
|
||||
cpVect rot = cpBodyGetRot(_info->getBody());
|
||||
cpVect preRot = _info->getRotation();
|
||||
Node* parent = _node->getParent();
|
||||
|
||||
// only reset the node position when body position/rotation changed.
|
||||
if (std::abs(pos.x - prePos.x) >= 0.3f || std::abs(pos.y - prePos.y) >= 0.3f
|
||||
|| std::abs(rot.x - preRot.x) >= 0.01f || std::abs(rot.y - preRot.y) >= 0.01f)
|
||||
{
|
||||
_positionResetTag = true;
|
||||
_rotationResetTag = true;
|
||||
_node->setPosition(getPosition());
|
||||
_info->setPosition(pos);
|
||||
_node->setRotation(getRotation());
|
||||
_info->setRotation(rot);
|
||||
}
|
||||
Point position = parent != nullptr ? parent->convertToNodeSpace(getPosition()) : getPosition();
|
||||
_positionResetTag = true;
|
||||
_rotationResetTag = true;
|
||||
_node->setPosition(position);
|
||||
_node->setRotation(getRotation());
|
||||
|
||||
// damping compute
|
||||
if (_isDamping)
|
||||
if (_isDamping && _dynamic && !isResting())
|
||||
{
|
||||
_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);
|
||||
|
@ -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)
|
||||
{
|
||||
return PhysicsHelper::cpv2point(cpBodyWorld2Local(_info->getBody(), PhysicsHelper::point2cpv(point)));
|
||||
|
|
|
@ -192,6 +192,15 @@ public:
|
|||
/** get the body rotation. */
|
||||
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.
|
||||
* 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 _rotationResetTag; /// To avoid reset the body rotation when body invoke Node::setRotation().
|
||||
Point _positionOffset;
|
||||
float _rotationOffset;
|
||||
|
||||
friend class PhysicsWorld;
|
||||
friend class PhysicsShape;
|
||||
|
|
Loading…
Reference in New Issue