mirror of https://github.com/axmolengine/axmol.git
Merge pull request #7234 from boyu0/iss5614_physics_transform
closed #5614: add transform support for physics
This commit is contained in:
commit
4f79176da2
|
@ -829,7 +829,7 @@ void RotateTo::update(float time)
|
|||
if (_target)
|
||||
{
|
||||
#if CC_USE_PHYSICS
|
||||
if (_target->getPhysicsBody() != nullptr && _startAngleX == _startAngleY && _diffAngleX == _diffAngleY)
|
||||
if (_startAngleX == _startAngleY && _diffAngleX == _diffAngleY)
|
||||
{
|
||||
_target->setRotation(_startAngleX + _diffAngleX * time);
|
||||
}
|
||||
|
@ -971,7 +971,7 @@ void RotateBy::update(float time)
|
|||
else
|
||||
{
|
||||
#if CC_USE_PHYSICS
|
||||
if (_target->getPhysicsBody() != nullptr && _startAngleZ_X == _startAngleZ_Y && _angleZ_X == _angleZ_Y)
|
||||
if (_startAngleZ_X == _startAngleZ_Y && _angleZ_X == _angleZ_Y)
|
||||
{
|
||||
_target->setRotation(_startAngleZ_X + _angleZ_X * time);
|
||||
}
|
||||
|
|
|
@ -116,6 +116,8 @@ Node::Node(void)
|
|||
, _componentContainer(nullptr)
|
||||
#if CC_USE_PHYSICS
|
||||
, _physicsBody(nullptr)
|
||||
, _physicsScaleStartX(1.0f)
|
||||
, _physicsScaleStartY(1.0f)
|
||||
#endif
|
||||
, _displayedOpacity(255)
|
||||
, _realOpacity(255)
|
||||
|
@ -283,10 +285,9 @@ void Node::setRotation(float rotation)
|
|||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
if (_physicsBody && !_physicsBody->_rotationResetTag)
|
||||
if (!_physicsBody || !_physicsBody->_rotationResetTag)
|
||||
{
|
||||
Scene* scene = _physicsBody->getWorld() != nullptr ? &_physicsBody->getWorld()->getScene() : nullptr;
|
||||
updatePhysicsBodyRotation(scene);
|
||||
updatePhysicsBodyRotation(getScene());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -377,15 +378,12 @@ void Node::setScale(float scale)
|
|||
if (_scaleX == scale && _scaleY == scale && _scaleZ == scale)
|
||||
return;
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
if (_physicsBody != nullptr)
|
||||
{
|
||||
CCLOG("Node WARNING: PhysicsBody doesn't support setScale");
|
||||
}
|
||||
#endif
|
||||
|
||||
_scaleX = _scaleY = _scaleZ = scale;
|
||||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
updatePhysicsBodyTransform(getScene());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// scaleX getter
|
||||
|
@ -400,16 +398,13 @@ void Node::setScale(float scaleX,float scaleY)
|
|||
if (_scaleX == scaleX && _scaleY == scaleY)
|
||||
return;
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
if (_physicsBody != nullptr)
|
||||
{
|
||||
CCLOG("Node WARNING: PhysicsBody doesn't support setScale");
|
||||
}
|
||||
#endif
|
||||
|
||||
_scaleX = scaleX;
|
||||
_scaleY = scaleY;
|
||||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
updatePhysicsBodyTransform(getScene());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// scaleX setter
|
||||
|
@ -418,15 +413,12 @@ void Node::setScaleX(float scaleX)
|
|||
if (_scaleX == scaleX)
|
||||
return;
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
if (_physicsBody != nullptr)
|
||||
{
|
||||
CCLOG("Node WARNING: PhysicsBody doesn't support setScaleX");
|
||||
}
|
||||
#endif
|
||||
|
||||
_scaleX = scaleX;
|
||||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
updatePhysicsBodyTransform(getScene());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// scaleY getter
|
||||
|
@ -464,15 +456,12 @@ void Node::setScaleY(float scaleY)
|
|||
if (_scaleY == scaleY)
|
||||
return;
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
if (_physicsBody != nullptr)
|
||||
{
|
||||
CCLOG("Node WARNING: PhysicsBody doesn't support setScaleY");
|
||||
}
|
||||
#endif
|
||||
|
||||
_scaleY = scaleY;
|
||||
_transformUpdated = _transformDirty = _inverseDirty = true;
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
updatePhysicsBodyTransform(getScene());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -493,10 +482,9 @@ void Node::setPosition(const Vec2& position)
|
|||
_usingNormalizedPosition = false;
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
if (_physicsBody != nullptr && !_physicsBody->_positionResetTag)
|
||||
if (!_physicsBody || !_physicsBody->_positionResetTag)
|
||||
{
|
||||
Scene* scene = _physicsBody->getWorld() != nullptr ? &_physicsBody->getWorld()->getScene() : nullptr;
|
||||
updatePhysicsBodyPosition(scene);
|
||||
updatePhysicsBodyPosition(getScene());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1020,14 +1008,11 @@ void Node::addChildHelper(Node* child, int localZOrder, int tag, const std::stri
|
|||
|
||||
#if CC_USE_PHYSICS
|
||||
// Recursive add children with which have physics body.
|
||||
for (Node* node = this; node != nullptr; node = node->getParent())
|
||||
Scene* scene = this->getScene();
|
||||
if (scene != nullptr && scene->getPhysicsWorld() != nullptr)
|
||||
{
|
||||
Scene* scene = dynamic_cast<Scene*>(node);
|
||||
if (scene != nullptr && scene->getPhysicsWorld() != nullptr)
|
||||
{
|
||||
scene->addChildToPhysicsWorld(child);
|
||||
break;
|
||||
}
|
||||
child->updatePhysicsBodyTransform(scene);
|
||||
scene->addChildToPhysicsWorld(child);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1870,6 +1855,12 @@ void Node::removeAllComponents()
|
|||
}
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
void Node::updatePhysicsBodyTransform(Scene* scene)
|
||||
{
|
||||
updatePhysicsBodyScale(scene);
|
||||
updatePhysicsBodyPosition(scene);
|
||||
updatePhysicsBodyRotation(scene);
|
||||
}
|
||||
|
||||
void Node::updatePhysicsBodyPosition(Scene* scene)
|
||||
{
|
||||
|
@ -1885,6 +1876,11 @@ void Node::updatePhysicsBodyPosition(Scene* scene)
|
|||
_physicsBody->setPosition(getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
for (Node* child : _children)
|
||||
{
|
||||
child->updatePhysicsBodyPosition(scene);
|
||||
}
|
||||
}
|
||||
|
||||
void Node::updatePhysicsBodyRotation(Scene* scene)
|
||||
|
@ -1905,6 +1901,39 @@ void Node::updatePhysicsBodyRotation(Scene* scene)
|
|||
_physicsBody->setRotation(_rotationZ_X);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto child : _children)
|
||||
{
|
||||
child->updatePhysicsBodyRotation(scene);
|
||||
child->updatePhysicsBodyPosition(scene);
|
||||
}
|
||||
}
|
||||
|
||||
void Node::updatePhysicsBodyScale(Scene* scene)
|
||||
{
|
||||
if (_physicsBody != nullptr)
|
||||
{
|
||||
if (scene != nullptr && scene->getPhysicsWorld() != nullptr)
|
||||
{
|
||||
float scaleX = _scaleX / _physicsScaleStartX;
|
||||
float scaleY = _scaleY / _physicsScaleStartY;
|
||||
for (Node* parent = _parent; parent != scene; parent = parent->getParent())
|
||||
{
|
||||
scaleX *= parent->getScaleX();
|
||||
scaleY *= parent->getScaleY();
|
||||
}
|
||||
_physicsBody->setScale(scaleX, scaleY);
|
||||
}
|
||||
else
|
||||
{
|
||||
_physicsBody->setScale(_scaleX / _physicsScaleStartX, _scaleY / _physicsScaleStartY);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto child : _children)
|
||||
{
|
||||
child->updatePhysicsBodyScale(scene);
|
||||
}
|
||||
}
|
||||
|
||||
void Node::setPhysicsBody(PhysicsBody* body)
|
||||
|
@ -1947,6 +1976,8 @@ void Node::setPhysicsBody(PhysicsBody* body)
|
|||
}
|
||||
|
||||
_physicsBody = body;
|
||||
_physicsScaleStartX = _scaleX;
|
||||
_physicsScaleStartY = _scaleY;
|
||||
|
||||
if (body != nullptr)
|
||||
{
|
||||
|
@ -1967,8 +1998,7 @@ void Node::setPhysicsBody(PhysicsBody* body)
|
|||
scene->getPhysicsWorld()->addBody(body);
|
||||
}
|
||||
|
||||
updatePhysicsBodyPosition(scene);
|
||||
updatePhysicsBodyRotation(scene);
|
||||
updatePhysicsBodyTransform(scene);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1500,8 +1500,10 @@ protected:
|
|||
bool doEnumerateRecursive(const Node* node, const std::string &name, std::function<bool (Node *)> callback) const;
|
||||
|
||||
#if CC_USE_PHYSICS
|
||||
void updatePhysicsBodyTransform(Scene* layer);
|
||||
virtual void updatePhysicsBodyPosition(Scene* layer);
|
||||
virtual void updatePhysicsBodyRotation(Scene* layer);
|
||||
virtual void updatePhysicsBodyScale(Scene* scene);
|
||||
#endif // CC_USE_PHYSICS
|
||||
|
||||
private:
|
||||
|
@ -1589,6 +1591,8 @@ protected:
|
|||
|
||||
#if CC_USE_PHYSICS
|
||||
PhysicsBody* _physicsBody; ///< the physicsBody the node have
|
||||
float _physicsScaleStartX; ///< the scale x value when setPhysicsBody
|
||||
float _physicsScaleStartY; ///< the scale y value when setPhysicsBody
|
||||
#endif
|
||||
|
||||
// opacity controls
|
||||
|
|
|
@ -355,6 +355,38 @@ void PhysicsBody::setRotation(float rotation)
|
|||
cpBodySetAngle(_info->getBody(), -PhysicsHelper::float2cpfloat((rotation + _rotationOffset) * (M_PI / 180.0f)));
|
||||
}
|
||||
|
||||
void PhysicsBody::setScale(float scale)
|
||||
{
|
||||
for (auto shape : _shapes)
|
||||
{
|
||||
shape->setScale(scale);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsBody::setScale(float scaleX, float scaleY)
|
||||
{
|
||||
for (auto shape : _shapes)
|
||||
{
|
||||
shape->setScale(scaleX, scaleY);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsBody::setScaleX(float scaleX)
|
||||
{
|
||||
for (auto shape : _shapes)
|
||||
{
|
||||
shape->setScaleX(scaleX);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsBody::setScaleY(float scaleY)
|
||||
{
|
||||
for (auto shape : _shapes)
|
||||
{
|
||||
shape->setScaleY(scaleY);
|
||||
}
|
||||
}
|
||||
|
||||
Vec2 PhysicsBody::getPosition() const
|
||||
{
|
||||
cpVect vec = cpBodyGetPos(_info->getBody());
|
||||
|
@ -763,8 +795,13 @@ void PhysicsBody::update(float delta)
|
|||
{
|
||||
if (_node != nullptr)
|
||||
{
|
||||
for (auto shape : _shapes)
|
||||
{
|
||||
shape->update(delta);
|
||||
}
|
||||
|
||||
Node* parent = _node->getParent();
|
||||
Scene* scene = &_world->getScene();
|
||||
Node* scene = &_world->getScene();
|
||||
|
||||
Vec2 position = parent != scene ? parent->convertToNodeSpace(scene->convertToWorldSpace(getPosition())) : getPosition();
|
||||
float rotation = getRotation();
|
||||
|
|
|
@ -303,6 +303,10 @@ protected:
|
|||
|
||||
virtual void setPosition(Vec2 position);
|
||||
virtual void setRotation(float rotation);
|
||||
virtual void setScale(float scale);
|
||||
virtual void setScale(float scaleX, float scaleY);
|
||||
virtual void setScaleX(float scaleX);
|
||||
virtual void setScaleY(float scaleY);
|
||||
|
||||
void update(float delta);
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <climits>
|
||||
|
||||
#include "chipmunk.h"
|
||||
#include "chipmunk_unsafe.h"
|
||||
|
||||
#include "physics/CCPhysicsBody.h"
|
||||
#include "physics/CCPhysicsWorld.h"
|
||||
|
@ -43,9 +44,14 @@ PhysicsShape::PhysicsShape()
|
|||
: _body(nullptr)
|
||||
, _info(nullptr)
|
||||
, _type(Type::UNKNOWN)
|
||||
, _area(0)
|
||||
, _mass(0)
|
||||
, _moment(0)
|
||||
, _area(0.0f)
|
||||
, _mass(0.0f)
|
||||
, _moment(0.0f)
|
||||
, _scaleX(1.0f)
|
||||
, _scaleY(1.0f)
|
||||
, _newScaleX(1.0f)
|
||||
, _newScaleY(1.0f)
|
||||
, _dirty(false)
|
||||
, _tag(0)
|
||||
, _categoryBitmask(UINT_MAX)
|
||||
, _collisionBitmask(UINT_MAX)
|
||||
|
@ -120,6 +126,52 @@ PhysicsBodyInfo* PhysicsShape::bodyInfo() const
|
|||
}
|
||||
}
|
||||
|
||||
void PhysicsShape::setScale(float scale)
|
||||
{
|
||||
setScaleX(scale);
|
||||
setScaleY(scale);
|
||||
}
|
||||
|
||||
void PhysicsShape::setScale(float scaleX, float scaleY)
|
||||
{
|
||||
setScaleX(scaleX);
|
||||
setScaleY(scaleY);
|
||||
}
|
||||
|
||||
void PhysicsShape::setScaleX(float scaleX)
|
||||
{
|
||||
if (_scaleX == scaleX)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_newScaleX = scaleX;
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
void PhysicsShape::setScaleY(float scaleY)
|
||||
{
|
||||
if (_scaleY == scaleY)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_newScaleY = scaleY;
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
void PhysicsShape::update(float delta)
|
||||
{
|
||||
CC_UNUSED_PARAM(delta);
|
||||
|
||||
if (_dirty)
|
||||
{
|
||||
_scaleX = _newScaleX;
|
||||
_scaleY = _newScaleY;
|
||||
_dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
PhysicsShapeCircle::PhysicsShapeCircle()
|
||||
{
|
||||
|
||||
|
@ -355,6 +407,66 @@ Vec2 PhysicsShapeCircle::getOffset()
|
|||
return PhysicsHelper::cpv2point(cpCircleShapeGetOffset(_info->getShapes().front()));
|
||||
}
|
||||
|
||||
void PhysicsShapeCircle::setScale(float scale)
|
||||
{
|
||||
if (_scaleX == scale)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_newScaleX = _newScaleY = scale;
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
void PhysicsShapeCircle::setScale(float scaleX, float scaleY)
|
||||
{
|
||||
if (scaleX != scaleY)
|
||||
{
|
||||
CCLOG("PhysicsShapeCircle WARNING: CANNOT support setScale with different x and y");
|
||||
}
|
||||
|
||||
if (_scaleX == scaleX)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_newScaleX = _newScaleY = scaleX;
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
void PhysicsShapeCircle::setScaleX(float scale)
|
||||
{
|
||||
CCLOG("PhysicsShapeCircle WARNING: CANNOT support setScaleX");
|
||||
|
||||
setScale(scale);
|
||||
}
|
||||
|
||||
void PhysicsShapeCircle::setScaleY(float scale)
|
||||
{
|
||||
CCLOG("PhysicsShapeCircle WARNING: CANNOT support setScaleY");
|
||||
|
||||
setScale(scale);
|
||||
}
|
||||
|
||||
void PhysicsShapeCircle::update(float delta)
|
||||
{
|
||||
|
||||
if (_dirty)
|
||||
{
|
||||
cpFloat factor = PhysicsHelper::float2cpfloat( _newScaleX / _scaleX );
|
||||
|
||||
cpShape* shape = _info->getShapes().front();
|
||||
cpVect v = cpCircleShapeGetOffset(shape);
|
||||
v = cpvmult(v, PhysicsHelper::float2cpfloat(factor));
|
||||
((cpCircleShape*)shape)->c = v;
|
||||
|
||||
cpCircleShapeSetRadius(shape, cpCircleShapeGetRadius(shape) * factor);
|
||||
}
|
||||
|
||||
PhysicsShape::update(delta);
|
||||
|
||||
}
|
||||
|
||||
// PhysicsShapeEdgeSegment
|
||||
PhysicsShapeEdgeSegment* PhysicsShapeEdgeSegment::create(const Vec2& a, const Vec2& b, const PhysicsMaterial& material/* = MaterialDefault*/, float border/* = 1*/)
|
||||
{
|
||||
|
@ -386,7 +498,6 @@ bool PhysicsShapeEdgeSegment::init(const Vec2& a, const Vec2& b, const PhysicsMa
|
|||
|
||||
_mass = PHYSICS_INFINITY;
|
||||
_moment = PHYSICS_INFINITY;
|
||||
_center = a.getMidpoint(b);
|
||||
|
||||
|
||||
setMaterial(material);
|
||||
|
@ -409,7 +520,29 @@ Vec2 PhysicsShapeEdgeSegment::getPointB() const
|
|||
|
||||
Vec2 PhysicsShapeEdgeSegment::getCenter()
|
||||
{
|
||||
return _center;
|
||||
Vec2 a = PhysicsHelper::cpv2point(cpSegmentShapeGetA(_info->getShapes().front()));
|
||||
Vec2 b = PhysicsHelper::cpv2point(cpSegmentShapeGetB(_info->getShapes().front()));
|
||||
return ( a + b ) / 2;
|
||||
}
|
||||
|
||||
void PhysicsShapeEdgeSegment::update(float delta)
|
||||
{
|
||||
if (_dirty)
|
||||
{
|
||||
cpFloat factorX = PhysicsHelper::float2cpfloat(_newScaleX / _scaleX);
|
||||
cpFloat factorY = PhysicsHelper::float2cpfloat(_newScaleY / _scaleY);
|
||||
|
||||
cpShape* shape = _info->getShapes().front();
|
||||
cpVect a = cpSegmentShapeGetA(shape);
|
||||
a.x *= factorX;
|
||||
a.y *= factorY;
|
||||
cpVect b = cpSegmentShapeGetB(shape);
|
||||
b.x *= factorX;
|
||||
b.y *= factorY;
|
||||
cpSegmentShapeSetEndpoints(shape, a, b);
|
||||
}
|
||||
|
||||
PhysicsShape::update(delta);
|
||||
}
|
||||
|
||||
// PhysicsShapeBox
|
||||
|
@ -444,7 +577,6 @@ bool PhysicsShapeBox::init(const Size& size, const PhysicsMaterial& material/* =
|
|||
|
||||
_info->add(shape);
|
||||
|
||||
_offset = offset;
|
||||
_area = calculateArea();
|
||||
_mass = material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : material.density * _area;
|
||||
_moment = calculateDefaultMoment();
|
||||
|
@ -457,50 +589,6 @@ bool PhysicsShapeBox::init(const Size& size, const PhysicsMaterial& material/* =
|
|||
return false;
|
||||
}
|
||||
|
||||
float PhysicsShapeBox::calculateArea(const Size& size)
|
||||
{
|
||||
cpVect wh = PhysicsHelper::size2cpv(size);
|
||||
cpVect vec[4] =
|
||||
{
|
||||
{-wh.x/2.0f, -wh.y/2.0f}, {-wh.x/2.0f, wh.y/2.0f}, {wh.x/2.0f, wh.y/2.0f}, {wh.x/2.0f, -wh.y/2.0f}
|
||||
};
|
||||
return PhysicsHelper::cpfloat2float(cpAreaForPoly(4, vec));
|
||||
}
|
||||
|
||||
float PhysicsShapeBox::calculateMoment(float mass, const Size& size, const Vec2& offset)
|
||||
{
|
||||
cpVect wh = PhysicsHelper::size2cpv(size);
|
||||
cpVect vec[4] =
|
||||
{
|
||||
{-wh.x/2.0f, -wh.y/2.0f}, {-wh.x/2.0f, wh.y/2.0f}, {wh.x/2.0f, wh.y/2.0f}, {wh.x/2.0f, -wh.y/2.0f}
|
||||
};
|
||||
|
||||
return mass == PHYSICS_INFINITY ? PHYSICS_INFINITY
|
||||
: PhysicsHelper::cpfloat2float(cpMomentForPoly(PhysicsHelper::float2cpfloat(mass),
|
||||
4,
|
||||
vec,
|
||||
PhysicsHelper::point2cpv(offset)));
|
||||
}
|
||||
|
||||
float PhysicsShapeBox::calculateArea()
|
||||
{
|
||||
cpShape* shape = _info->getShapes().front();
|
||||
return PhysicsHelper::cpfloat2float(cpAreaForPoly(((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts));
|
||||
}
|
||||
|
||||
float PhysicsShapeBox::calculateDefaultMoment()
|
||||
{
|
||||
cpShape* shape = _info->getShapes().front();
|
||||
return _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY
|
||||
: PhysicsHelper::cpfloat2float(cpMomentForPoly(_mass, ((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts, cpvzero));
|
||||
}
|
||||
|
||||
void PhysicsShapeBox::getPoints(Vec2* points) const
|
||||
{
|
||||
cpShape* shape = _info->getShapes().front();
|
||||
PhysicsHelper::cpvs2points(((cpPolyShape*)shape)->verts, points, ((cpPolyShape*)shape)->numVerts);
|
||||
}
|
||||
|
||||
Size PhysicsShapeBox::getSize() const
|
||||
{
|
||||
cpShape* shape = _info->getShapes().front();
|
||||
|
@ -540,7 +628,6 @@ bool PhysicsShapePolygon::init(const Vec2* points, int count, const PhysicsMater
|
|||
_area = calculateArea();
|
||||
_mass = material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : material.density * _area;
|
||||
_moment = calculateDefaultMoment();
|
||||
_center = PhysicsHelper::cpv2point(cpCentroidForPoly(((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts));
|
||||
|
||||
setMaterial(material);
|
||||
|
||||
|
@ -602,7 +689,37 @@ int PhysicsShapePolygon::getPointsCount() const
|
|||
|
||||
Vec2 PhysicsShapePolygon::getCenter()
|
||||
{
|
||||
return _center;
|
||||
return PhysicsHelper::cpv2point(cpCentroidForPoly(((cpPolyShape*)_info->getShapes().front())->numVerts, ((cpPolyShape*)_info->getShapes().front())->verts));
|
||||
}
|
||||
|
||||
void PhysicsShapePolygon::update(float delta)
|
||||
{
|
||||
if (_dirty)
|
||||
{
|
||||
cpFloat factorX = PhysicsHelper::float2cpfloat( _newScaleX / _scaleX );
|
||||
cpFloat factorY = PhysicsHelper::float2cpfloat( _newScaleY / _scaleY );
|
||||
|
||||
cpShape* shape = _info->getShapes().front();
|
||||
int count = cpPolyShapeGetNumVerts(shape);
|
||||
cpVect* vects = ((cpPolyShape*)shape)->verts;
|
||||
cpSplittingPlane* planes = ((cpPolyShape*)shape)->planes;
|
||||
|
||||
for (int i = 0; i < count ; ++i)
|
||||
{
|
||||
vects[i].x *= factorX;
|
||||
vects[i].y *= factorY;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
cpVect n = cpvnormalize(cpvperp(cpvsub(vects[i], vects[(i + 1) % count])));
|
||||
|
||||
planes[i].n = n;
|
||||
planes[i].d = cpvdot(n, vects[i]);
|
||||
}
|
||||
}
|
||||
|
||||
PhysicsShape::update(delta);
|
||||
}
|
||||
|
||||
// PhysicsShapeEdgeBox
|
||||
|
@ -641,7 +758,6 @@ bool PhysicsShapeEdgeBox::init(const Size& size, const PhysicsMaterial& material
|
|||
}
|
||||
CC_BREAK_IF(i < 4);
|
||||
|
||||
_offset = offset;
|
||||
_mass = PHYSICS_INFINITY;
|
||||
_moment = PHYSICS_INFINITY;
|
||||
|
||||
|
@ -653,15 +769,6 @@ bool PhysicsShapeEdgeBox::init(const Size& size, const PhysicsMaterial& material
|
|||
return false;
|
||||
}
|
||||
|
||||
void PhysicsShapeEdgeBox::getPoints(cocos2d::Vec2 *outPoints) const
|
||||
{
|
||||
int i = 0;
|
||||
for(auto shape : _info->getShapes())
|
||||
{
|
||||
outPoints[i++] = PhysicsHelper::cpv2point(((cpSegmentShape*)shape)->a);
|
||||
}
|
||||
}
|
||||
|
||||
// PhysicsShapeEdgeBox
|
||||
PhysicsShapeEdgePolygon* PhysicsShapeEdgePolygon::create(const Vec2* points, int count, const PhysicsMaterial& material/* = MaterialDefault*/, float border/* = 1*/)
|
||||
{
|
||||
|
@ -685,7 +792,6 @@ bool PhysicsShapeEdgePolygon::init(const Vec2* points, int count, const PhysicsM
|
|||
|
||||
vec = new cpVect[count];
|
||||
PhysicsHelper::points2cpvs(points, vec, count);
|
||||
_center = PhysicsHelper::cpv2point(cpCentroidForPoly(count, vec));
|
||||
|
||||
int i = 0;
|
||||
for (; i < count; ++i)
|
||||
|
@ -716,7 +822,18 @@ bool PhysicsShapeEdgePolygon::init(const Vec2* points, int count, const PhysicsM
|
|||
|
||||
Vec2 PhysicsShapeEdgePolygon::getCenter()
|
||||
{
|
||||
return _center;
|
||||
int count = (int)_info->getShapes().size();
|
||||
cpVect* points = new cpVect[count];
|
||||
int i = 0;
|
||||
for(auto shape : _info->getShapes())
|
||||
{
|
||||
points[i++] = ((cpSegmentShape*)shape)->a;
|
||||
}
|
||||
|
||||
Vec2 center = PhysicsHelper::cpv2point(cpCentroidForPoly(count, points));
|
||||
delete[] points;
|
||||
|
||||
return center;
|
||||
}
|
||||
|
||||
void PhysicsShapeEdgePolygon::getPoints(cocos2d::Vec2 *outPoints) const
|
||||
|
@ -730,7 +847,7 @@ void PhysicsShapeEdgePolygon::getPoints(cocos2d::Vec2 *outPoints) const
|
|||
|
||||
int PhysicsShapeEdgePolygon::getPointsCount() const
|
||||
{
|
||||
return static_cast<int>(_info->getShapes().size() + 1);
|
||||
return static_cast<int>(_info->getShapes().size());
|
||||
}
|
||||
|
||||
// PhysicsShapeEdgeChain
|
||||
|
@ -747,6 +864,28 @@ PhysicsShapeEdgeChain* PhysicsShapeEdgeChain::create(const Vec2* points, int cou
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void PhysicsShapeEdgePolygon::update(float delta)
|
||||
{
|
||||
if (_dirty)
|
||||
{
|
||||
cpFloat factorX = PhysicsHelper::float2cpfloat(_newScaleX / _scaleX);
|
||||
cpFloat factorY = PhysicsHelper::float2cpfloat(_newScaleY / _scaleY);
|
||||
|
||||
for(auto shape : _info->getShapes())
|
||||
{
|
||||
cpVect a = cpSegmentShapeGetA(shape);
|
||||
a.x *= factorX;
|
||||
a.y *= factorY;
|
||||
cpVect b = cpSegmentShapeGetB(shape);
|
||||
b.x *= factorX;
|
||||
b.y *= factorY;
|
||||
cpSegmentShapeSetEndpoints(shape, a, b);
|
||||
}
|
||||
}
|
||||
|
||||
PhysicsShape::update(delta);
|
||||
}
|
||||
|
||||
bool PhysicsShapeEdgeChain::init(const Vec2* points, int count, const PhysicsMaterial& material/* = MaterialDefault*/, float border/* = 1*/)
|
||||
{
|
||||
cpVect* vec = nullptr;
|
||||
|
@ -756,7 +895,6 @@ bool PhysicsShapeEdgeChain::init(const Vec2* points, int count, const PhysicsMat
|
|||
|
||||
vec = new cpVect[count];
|
||||
PhysicsHelper::points2cpvs(points, vec, count);
|
||||
_center = PhysicsHelper::cpv2point(cpCentroidForPoly(count, vec));
|
||||
|
||||
int i = 0;
|
||||
for (; i < count - 1; ++i)
|
||||
|
@ -786,7 +924,20 @@ bool PhysicsShapeEdgeChain::init(const Vec2* points, int count, const PhysicsMat
|
|||
|
||||
Vec2 PhysicsShapeEdgeChain::getCenter()
|
||||
{
|
||||
return _center;
|
||||
int count = (int)_info->getShapes().size() + 1;
|
||||
cpVect* points = new cpVect[count];
|
||||
int i = 0;
|
||||
for(auto shape : _info->getShapes())
|
||||
{
|
||||
points[i++] = ((cpSegmentShape*)shape)->a;
|
||||
}
|
||||
|
||||
points[i++] = ((cpSegmentShape*)_info->getShapes().back())->b;
|
||||
|
||||
Vec2 center = PhysicsHelper::cpv2point(cpCentroidForPoly(count, points));
|
||||
delete[] points;
|
||||
|
||||
return center;
|
||||
}
|
||||
|
||||
void PhysicsShapeEdgeChain::getPoints(Vec2* outPoints) const
|
||||
|
@ -797,7 +948,7 @@ void PhysicsShapeEdgeChain::getPoints(Vec2* outPoints) const
|
|||
outPoints[i++] = PhysicsHelper::cpv2point(((cpSegmentShape*)shape)->a);
|
||||
}
|
||||
|
||||
outPoints[i++] = PhysicsHelper::cpv2point(((cpSegmentShape*)_info->getShapes().back())->a);
|
||||
outPoints[i++] = PhysicsHelper::cpv2point(((cpSegmentShape*)_info->getShapes().back())->b);
|
||||
}
|
||||
|
||||
int PhysicsShapeEdgeChain::getPointsCount() const
|
||||
|
@ -805,6 +956,28 @@ int PhysicsShapeEdgeChain::getPointsCount() const
|
|||
return static_cast<int>(_info->getShapes().size() + 1);
|
||||
}
|
||||
|
||||
void PhysicsShapeEdgeChain::update(float delta)
|
||||
{
|
||||
if (_dirty)
|
||||
{
|
||||
cpFloat factorX = PhysicsHelper::float2cpfloat(_newScaleX / _scaleX);
|
||||
cpFloat factorY = PhysicsHelper::float2cpfloat(_newScaleY / _scaleY);
|
||||
|
||||
for(auto shape : _info->getShapes())
|
||||
{
|
||||
cpVect a = cpSegmentShapeGetA(shape);
|
||||
a.x *= factorX;
|
||||
a.y *= factorY;
|
||||
cpVect b = cpSegmentShapeGetB(shape);
|
||||
b.x *= factorX;
|
||||
b.y *= factorY;
|
||||
cpSegmentShapeSetEndpoints(shape, a, b);
|
||||
}
|
||||
}
|
||||
|
||||
PhysicsShape::update(delta);
|
||||
}
|
||||
|
||||
void PhysicsShape::setGroup(int group)
|
||||
{
|
||||
if (group < 0)
|
||||
|
|
|
@ -156,6 +156,12 @@ protected:
|
|||
/** calculate the area of this shape */
|
||||
virtual float calculateArea() { return 0.0f; }
|
||||
|
||||
virtual void setScale(float scale);
|
||||
virtual void setScale(float scaleX, float scaleY);
|
||||
virtual void setScaleX(float scaleX);
|
||||
virtual void setScaleY(float scaleY);
|
||||
virtual void update(float delta);
|
||||
|
||||
protected:
|
||||
PhysicsShape();
|
||||
virtual ~PhysicsShape() = 0;
|
||||
|
@ -167,6 +173,11 @@ protected:
|
|||
float _area;
|
||||
float _mass;
|
||||
float _moment;
|
||||
float _scaleX;
|
||||
float _scaleY;
|
||||
float _newScaleX;
|
||||
float _newScaleY;
|
||||
bool _dirty;
|
||||
PhysicsMaterial _material;
|
||||
int _tag;
|
||||
int _categoryBitmask;
|
||||
|
@ -192,42 +203,21 @@ public:
|
|||
|
||||
float getRadius() const;
|
||||
virtual Vec2 getOffset() override;
|
||||
|
||||
protected:
|
||||
bool init(float radius, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, const Vec2& offset = Vec2::ZERO);
|
||||
virtual float calculateArea() override;
|
||||
virtual void setScale(float scale) override;
|
||||
virtual void setScale(float scaleX, float scaleY) override;
|
||||
virtual void setScaleX(float scale) override;
|
||||
virtual void setScaleY(float scale) override;
|
||||
virtual void update(float delta) override;
|
||||
|
||||
protected:
|
||||
PhysicsShapeCircle();
|
||||
virtual ~PhysicsShapeCircle();
|
||||
};
|
||||
|
||||
/** A box shape */
|
||||
class PhysicsShapeBox : public PhysicsShape
|
||||
{
|
||||
public:
|
||||
static PhysicsShapeBox* create(const Size& size, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, const Vec2& offset = Vec2::ZERO);
|
||||
static float calculateArea(const Size& size);
|
||||
static float calculateMoment(float mass, const Size& size, const Vec2& offset = Vec2::ZERO);
|
||||
|
||||
virtual float calculateDefaultMoment() override;
|
||||
|
||||
void getPoints(Vec2* outPoints) const;
|
||||
int getPointsCount() const { return 4; }
|
||||
Size getSize() const;
|
||||
virtual Vec2 getOffset() override { return _offset; }
|
||||
|
||||
protected:
|
||||
bool init(const Size& size, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, const Vec2& offset = Vec2::ZERO);
|
||||
virtual float calculateArea() override;
|
||||
|
||||
protected:
|
||||
PhysicsShapeBox();
|
||||
virtual ~PhysicsShapeBox();
|
||||
|
||||
protected:
|
||||
Vec2 _offset;
|
||||
};
|
||||
|
||||
/** A polygon shape */
|
||||
class PhysicsShapePolygon : public PhysicsShape
|
||||
{
|
||||
|
@ -245,13 +235,28 @@ public:
|
|||
protected:
|
||||
bool init(const Vec2* points, int count, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, const Vec2& offset = Vec2::ZERO);
|
||||
float calculateArea() override;
|
||||
virtual void update(float delta) override;
|
||||
|
||||
protected:
|
||||
PhysicsShapePolygon();
|
||||
virtual ~PhysicsShapePolygon();
|
||||
};
|
||||
|
||||
/** A box shape */
|
||||
class PhysicsShapeBox : public PhysicsShapePolygon
|
||||
{
|
||||
public:
|
||||
static PhysicsShapeBox* create(const Size& size, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, const Vec2& offset = Vec2::ZERO);
|
||||
|
||||
Size getSize() const;
|
||||
virtual Vec2 getOffset() override { return getCenter(); }
|
||||
|
||||
protected:
|
||||
Vec2 _center;
|
||||
bool init(const Size& size, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, const Vec2& offset = Vec2::ZERO);
|
||||
|
||||
protected:
|
||||
PhysicsShapeBox();
|
||||
virtual ~PhysicsShapeBox();
|
||||
};
|
||||
|
||||
/** A segment shape */
|
||||
|
@ -266,36 +271,12 @@ public:
|
|||
|
||||
protected:
|
||||
bool init(const Vec2& a, const Vec2& b, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
|
||||
virtual void update(float delta) override;
|
||||
|
||||
protected:
|
||||
PhysicsShapeEdgeSegment();
|
||||
virtual ~PhysicsShapeEdgeSegment();
|
||||
|
||||
protected:
|
||||
Vec2 _center;
|
||||
|
||||
friend class PhysicsBody;
|
||||
};
|
||||
|
||||
/** An edge box shape */
|
||||
class PhysicsShapeEdgeBox : public PhysicsShape
|
||||
{
|
||||
public:
|
||||
static PhysicsShapeEdgeBox* create(const Size& size, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 0, const Vec2& offset = Vec2::ZERO);
|
||||
virtual Vec2 getOffset() override { return _offset; }
|
||||
void getPoints(Vec2* outPoints) const;
|
||||
int getPointsCount() const { return 4; }
|
||||
|
||||
protected:
|
||||
bool init(const Size& size, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1, const Vec2& offset = Vec2::ZERO);
|
||||
|
||||
protected:
|
||||
PhysicsShapeEdgeBox();
|
||||
virtual ~PhysicsShapeEdgeBox();
|
||||
|
||||
protected:
|
||||
Vec2 _offset;
|
||||
|
||||
friend class PhysicsBody;
|
||||
};
|
||||
|
||||
|
@ -310,15 +291,30 @@ public:
|
|||
|
||||
protected:
|
||||
bool init(const Vec2* points, int count, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
|
||||
virtual void update(float delta) override;
|
||||
|
||||
protected:
|
||||
PhysicsShapeEdgePolygon();
|
||||
virtual ~PhysicsShapeEdgePolygon();
|
||||
|
||||
friend class PhysicsBody;
|
||||
};
|
||||
|
||||
/** An edge box shape */
|
||||
class PhysicsShapeEdgeBox : public PhysicsShapeEdgePolygon
|
||||
{
|
||||
public:
|
||||
static PhysicsShapeEdgeBox* create(const Size& size, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 0, const Vec2& offset = Vec2::ZERO);
|
||||
virtual Vec2 getOffset() override { return getCenter(); }
|
||||
|
||||
protected:
|
||||
Vec2 _center;
|
||||
bool init(const Size& size, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1, const Vec2& offset = Vec2::ZERO);
|
||||
|
||||
protected:
|
||||
PhysicsShapeEdgeBox();
|
||||
virtual ~PhysicsShapeEdgeBox();
|
||||
|
||||
friend class PhysicsBody;
|
||||
};
|
||||
|
||||
/** a chain shape */
|
||||
|
@ -332,14 +328,12 @@ public:
|
|||
|
||||
protected:
|
||||
bool init(const Vec2* points, int count, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1);
|
||||
virtual void update(float delta) override;
|
||||
|
||||
protected:
|
||||
PhysicsShapeEdgeChain();
|
||||
virtual ~PhysicsShapeEdgeChain();
|
||||
|
||||
protected:
|
||||
Vec2 _center;
|
||||
|
||||
|
||||
friend class PhysicsBody;
|
||||
};
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace
|
|||
CL(PhysicsPositionRotationTest),
|
||||
CL(PhysicsSetGravityEnableTest),
|
||||
CL(Bug5482),
|
||||
CL(PhysicsTransformTest),
|
||||
#else
|
||||
CL(PhysicsDemoDisabled),
|
||||
#endif
|
||||
|
@ -1593,7 +1594,7 @@ void PhysicsPositionRotationTest::onEnter()
|
|||
auto leftBall = Sprite::create("Images/ball.png");
|
||||
leftBall->setPosition(-30, 0);
|
||||
leftBall->cocos2d::Node::setScale(2);
|
||||
leftBall->setPhysicsBody(PhysicsBody::createCircle(leftBall->getContentSize().width/4));
|
||||
leftBall->setPhysicsBody(PhysicsBody::createCircle(leftBall->getContentSize().width));
|
||||
leftBall->getPhysicsBody()->setTag(DRAG_BODYS_TAG);
|
||||
parent->addChild(leftBall);
|
||||
|
||||
|
@ -1734,4 +1735,81 @@ std::string Bug5482::subtitle() const
|
|||
return "change physics body to the other.";
|
||||
}
|
||||
|
||||
bool PhysicsTransformTest::onTouchBegan(Touch *touch, Event *event)
|
||||
{
|
||||
Node* child = this->getChildByTag(1);
|
||||
child->setPosition(this->convertTouchToNodeSpace(touch));
|
||||
return false;
|
||||
}
|
||||
|
||||
void PhysicsTransformTest::onEnter()
|
||||
{
|
||||
PhysicsDemo::onEnter();
|
||||
_scene->toggleDebug();
|
||||
_scene->getPhysicsWorld()->setGravity(Point::ZERO);
|
||||
|
||||
auto touchListener = EventListenerTouchOneByOne::create();
|
||||
touchListener->onTouchBegan = CC_CALLBACK_2(PhysicsTransformTest::onTouchBegan, this);
|
||||
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
|
||||
|
||||
auto wall = Node::create();
|
||||
wall->setPhysicsBody(PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size, PhysicsMaterial(0.1f, 1.0f, 0.0f)));
|
||||
wall->setPosition(VisibleRect::center());
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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)));
|
||||
|
||||
auto normal = Sprite::create("Images/YellowSquare.png");
|
||||
normal->setPosition(300, 100);
|
||||
normal->setScale(0.25, 0.5);
|
||||
auto size = parent->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);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
MoveBy* move = MoveBy::create(2.0, Vec2(100, 100));
|
||||
MoveBy* move2 = MoveBy::create(2.0, Vec2(-200, 0));
|
||||
MoveBy* move3 = MoveBy::create(2.0, Vec2(100, -100));
|
||||
ScaleTo* scale = ScaleTo::create(3.0, 0.3);
|
||||
ScaleTo* scale2 = ScaleTo::create(3.0, 1.0);
|
||||
|
||||
RotateBy* rotate = RotateBy::create(6.0, 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));
|
||||
}
|
||||
|
||||
std::string PhysicsTransformTest::title() const
|
||||
{
|
||||
return "Physics transform test";
|
||||
}
|
||||
|
||||
#endif // ifndef CC_USE_PHYSICS
|
||||
|
|
|
@ -255,6 +255,18 @@ private:
|
|||
bool _bodyInA;
|
||||
};
|
||||
|
||||
class PhysicsTransformTest : public PhysicsDemo
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(PhysicsTransformTest);
|
||||
|
||||
void onEnter() override;
|
||||
virtual std::string title() const override;
|
||||
|
||||
bool onTouchBegan(Touch* touch, Event* event);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue