Merge pull request #7234 from boyu0/iss5614_physics_transform

closed #5614: add transform support for physics
This commit is contained in:
minggo 2014-06-29 17:23:20 +08:00
commit 4f79176da2
9 changed files with 505 additions and 173 deletions

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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();

View File

@ -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);

View File

@ -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)

View File

@ -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;
};

View File

@ -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

View File

@ -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