Update kiwano::physics

This commit is contained in:
Nomango 2019-10-23 16:49:34 +08:00
parent 2c4258c087
commit ae5d985238
10 changed files with 160 additions and 70 deletions

View File

@ -41,20 +41,6 @@ namespace kiwano
SetActor(actor); SetActor(actor);
} }
Body::Body(World* world, Actor* actor)
: Body()
{
world_ = world;
if (world_)
{
b2BodyDef def;
b2Body* body = world_->GetB2World()->CreateBody(&def);
SetB2Body(body);
}
SetActor(actor);
UpdateFromActor();
}
Body::~Body() Body::~Body()
{ {
if (world_) if (world_)
@ -63,40 +49,58 @@ namespace kiwano
} }
} }
Fixture Body::AddShape(Shape* shape, Fixture::Property const& prop) BodyPtr Body::Create(World* world, Actor* actor)
{
BodyPtr body = new Body;
if (body)
{
body->world_ = world;
if (world)
{
b2BodyDef def;
b2Body* b2body = world->GetB2World()->CreateBody(&def);
body->SetB2Body(b2body);
}
body->SetActor(actor);
body->UpdateFromActor();
}
return body;
}
Fixture Body::AddShape(Shape* shape, float density, float friction, float restitution)
{ {
KGE_ASSERT(body_ && world_); KGE_ASSERT(body_ && world_);
if (shape) if (shape)
{ {
return Fixture(this, shape, prop); return Fixture::Create(this, shape, density, friction, restitution);
} }
return Fixture(); return Fixture();
} }
Fixture Body::AddCircleShape(float radius, Fixture::Property const& prop) Fixture Body::AddCircleShape(float radius, float density)
{ {
return AddShape(&CircleShape(radius), prop); return AddShape(&CircleShape(radius), density);
} }
Fixture Body::AddBoxShape(Vec2 const& size, Fixture::Property const& prop) Fixture Body::AddBoxShape(Vec2 const& size, float density)
{ {
return AddShape(&BoxShape(size), prop); return AddShape(&BoxShape(size), density);
} }
Fixture Body::AddPolygonShape(Vector<Point> const& vertexs, Fixture::Property const& prop) Fixture Body::AddPolygonShape(Vector<Point> const& vertexs, float density)
{ {
return AddShape(&PolygonShape(vertexs), prop); return AddShape(&PolygonShape(vertexs), density);
} }
Fixture Body::AddEdgeShape(Point const& p1, Point const& p2, Fixture::Property const& prop) Fixture Body::AddEdgeShape(Point const& p1, Point const& p2, float density)
{ {
return AddShape(&EdgeShape(p1, p2), prop); return AddShape(&EdgeShape(p1, p2), density);
} }
Fixture Body::AddChainShape(Vector<Point> const& vertexs, bool loop, Fixture::Property const& prop) Fixture Body::AddChainShape(Vector<Point> const& vertexs, bool loop, float density)
{ {
return AddShape(&ChainShape(vertexs, loop), prop); return AddShape(&ChainShape(vertexs, loop), density);
} }
void Body::RemoveFixture(Fixture const& fixture) void Body::RemoveFixture(Fixture const& fixture)
@ -120,6 +124,24 @@ namespace kiwano
return world_->World2Stage(body_->GetWorldPoint(world_->Stage2World(local))); return world_->World2Stage(body_->GetWorldPoint(world_->Stage2World(local)));
} }
void Body::ApplyForce(Vec2 const& force, Point const& point, bool wake)
{
KGE_ASSERT(body_ && world_);
body_->ApplyForce(b2Vec2(force.x, force.y), world_->Stage2World(point), wake);
}
void Body::ApplyForceToCenter(Vec2 const& force, bool wake)
{
KGE_ASSERT(body_ && world_);
body_->ApplyForceToCenter(b2Vec2(force.x, force.y), wake);
}
void Body::ApplyTorque(float torque, bool wake)
{
KGE_ASSERT(body_ && world_);
body_->ApplyTorque(torque, wake);
}
void Body::SetB2Body(b2Body* body) void Body::SetB2Body(b2Body* body)
{ {
body_ = body; body_ = body;

View File

@ -30,6 +30,7 @@ namespace kiwano
class World; class World;
// 먼竟 // 먼竟
KGE_DECLARE_SMART_PTR(Body);
class KGE_API Body class KGE_API Body
: public ObjectBase : public ObjectBase
{ {
@ -43,16 +44,17 @@ namespace kiwano
Body(); Body();
Body(b2Body* body, Actor* actor); Body(b2Body* body, Actor* actor);
Body(World* world, Actor* actor);
virtual ~Body(); virtual ~Body();
static BodyPtr Create(World* world, Actor* actor);
// 警속近榴 // 警속近榴
Fixture AddShape(Shape* shape, Fixture::Property const& prop = Fixture::Property()); Fixture AddShape(Shape* shape, float density = 0.f, float friction = 0.2f, float restitution = 0.f);
Fixture AddCircleShape(float radius, Fixture::Property const& prop = Fixture::Property()); Fixture AddCircleShape(float radius, float density = 0.f);
Fixture AddBoxShape(Vec2 const& size, Fixture::Property const& prop = Fixture::Property()); Fixture AddBoxShape(Vec2 const& size, float density = 0.f);
Fixture AddPolygonShape(Vector<Point> const& vertexs, Fixture::Property const& prop = Fixture::Property()); Fixture AddPolygonShape(Vector<Point> const& vertexs, float density = 0.f);
Fixture AddEdgeShape(Point const& p1, Point const& p2, Fixture::Property const& prop = Fixture::Property()); Fixture AddEdgeShape(Point const& p1, Point const& p2, float density = 0.f);
Fixture AddChainShape(Vector<Point> const& vertexs, bool loop = false, Fixture::Property const& prop = Fixture::Property()); Fixture AddChainShape(Vector<Point> const& vertexs, bool loop, float density = 0.f);
// 삿혤셸야죗깊 // 삿혤셸야죗깊
Fixture GetFixture() const { KGE_ASSERT(body_); Fixture(body_->GetFixtureList()); } Fixture GetFixture() const { KGE_ASSERT(body_); Fixture(body_->GetFixtureList()); }
@ -69,6 +71,11 @@ namespace kiwano
Type GetType() const { KGE_ASSERT(body_); return Type(body_->GetType()); } Type GetType() const { KGE_ASSERT(body_); return Type(body_->GetType()); }
void SetType(Type type) { KGE_ASSERT(body_); body_->SetType(static_cast<b2BodyType>(type)); } void SetType(Type type) { KGE_ASSERT(body_); body_->SetType(static_cast<b2BodyType>(type)); }
void ApplyForce(Vec2 const& force, Point const& point, bool wake = true);
void ApplyForceToCenter(Vec2 const& force, bool wake = true);
void ApplyTorque(float torque, bool wake = true);
bool IsIgnoreRotation() const { return ignore_rotation_; } bool IsIgnoreRotation() const { return ignore_rotation_; }
void SetIgnoreRotation(bool ignore_rotation) { ignore_rotation_ = ignore_rotation; } void SetIgnoreRotation(bool ignore_rotation) { ignore_rotation_ = ignore_rotation; }
@ -91,7 +98,5 @@ namespace kiwano
World* world_; World* world_;
b2Body* body_; b2Body* body_;
}; };
KGE_DECLARE_SMART_PTR(Body);
} }
} }

View File

@ -38,8 +38,7 @@ namespace kiwano
SetB2Fixture(fixture); SetB2Fixture(fixture);
} }
Fixture::Fixture(Body* body, Shape* shape, Property const& prop) Fixture Fixture::Create(Body* body, Shape* shape, float density, float friction, float restitution)
: Fixture()
{ {
KGE_ASSERT(body); KGE_ASSERT(body);
@ -49,12 +48,14 @@ namespace kiwano
b2Body* b2body = body->GetB2Body(); b2Body* b2body = body->GetB2Body();
b2FixtureDef fd; b2FixtureDef fd;
fd.density = prop.density; fd.density = density;
fd.friction = prop.friction; fd.friction = friction;
fd.restitution = prop.restitution; fd.restitution = restitution;
fd.shape = shape->GetB2Shape(); fd.shape = shape->GetB2Shape();
fixture_ = b2body->CreateFixture(&fd); auto fixture = b2body->CreateFixture(&fd);
return Fixture(fixture);
} }
return Fixture();
} }
Shape Fixture::GetShape() const Shape Fixture::GetShape() const

View File

@ -32,34 +32,16 @@ namespace kiwano
class Fixture class Fixture
{ {
public: public:
struct Property
{
float density; // 密度 kg/m^2
float friction; // 摩擦系数 [0,1]
float restitution; // 弹性 [0,1]
Property()
: density(0.f)
, friction(0.2f)
, restitution(0.f)
{
}
Property(float density, float friction, float restitution)
: density(density)
, friction(friction)
, restitution(restitution)
{
}
};
Fixture(); Fixture();
Fixture(b2Fixture* fixture); Fixture(b2Fixture* fixture);
Fixture(Body* body, Shape* shape, Property const& prop);
static Fixture Create(Body* body, Shape* shape, float density = 0.f, float friction = 0.2f, float restitution = 0.f);
Shape GetShape() const; Shape GetShape() const;
Fixture GetNext() const; Fixture GetNext() const;
bool IsValid() const { return !!fixture_; }
b2Fixture* GetB2Fixture() { return fixture_; } b2Fixture* GetB2Fixture() { return fixture_; }
const b2Fixture* GetB2Fixture() const { return fixture_; } const b2Fixture* GetB2Fixture() const { return fixture_; }
void SetB2Fixture(b2Fixture* fixture) { fixture_ = fixture; } void SetB2Fixture(b2Fixture* fixture) { fixture_ = fixture; }

View File

@ -86,5 +86,33 @@ namespace kiwano
} }
} }
} //
// DistanceJoint
//
DistanceJoint::DistanceJoint()
: Joint()
{
}
DistanceJoint::DistanceJoint(World* world, b2DistanceJointDef* def)
: Joint(world, def)
{
}
DistanceJointPtr DistanceJoint::Create(World* world, Param const& param)
{
KGE_ASSERT(param.body_a && param.body_b);
b2DistanceJointDef def;
def.bodyA = param.body_a->GetB2Body();
def.bodyB = param.body_b->GetB2Body();
def.localAnchorA = world->Stage2World(param.local_anchor_a);
def.localAnchorB = world->Stage2World(param.local_anchor_b);
def.length = world->Stage2World((param.body_a->GetWorldPoint(param.local_anchor_a) - param.body_b->GetWorldPoint(param.local_anchor_b)).Length());
DistanceJointPtr joint = new DistanceJoint(world, &def);
return joint;
}
}
} }

View File

@ -47,6 +47,15 @@ namespace kiwano
Motor Motor
}; };
struct ParamBase
{
Body* body_a;
Body* body_b;
ParamBase(Body* body_a, Body* body_b) : body_a(body_a), body_b(body_b) {}
ParamBase(BodyPtr body_a, BodyPtr body_b) : body_a(body_a.get()), body_b(body_b.get()) {}
};
Joint(); Joint();
Joint(b2Joint* joint); Joint(b2Joint* joint);
Joint(World* world, b2JointDef* joint_def); Joint(World* world, b2JointDef* joint_def);
@ -67,5 +76,32 @@ namespace kiwano
World* world_; World* world_;
Type type_; Type type_;
}; };
KGE_DECLARE_SMART_PTR(DistanceJoint);
class KGE_API DistanceJoint
: public Joint
{
public:
struct Param : public Joint::ParamBase
{
Point local_anchor_a;
Point local_anchor_b;
Param(Body* body_a, Body* body_b, Point const& local_anchor_a, Point const& local_anchor_b)
: ParamBase(body_a, body_b)
, local_anchor_a(local_anchor_a)
, local_anchor_b(local_anchor_b)
{}
Param(BodyPtr body_a, BodyPtr body_b, Point const& local_anchor_a, Point const& local_anchor_b)
: Param(body_a.get(), body_b.get(), local_anchor_a, local_anchor_b)
{}
};
DistanceJoint();
DistanceJoint(World* world, b2DistanceJointDef* def);
static DistanceJointPtr Create(World* world, Param const& param);
};
} }
} }

View File

@ -55,7 +55,7 @@ namespace kiwano
BodyPtr World::CreateBody(Actor* actor) BodyPtr World::CreateBody(Actor* actor)
{ {
BodyPtr body = new Body(this, actor); BodyPtr body = Body::Create(this, actor);
bodies_.push_back(body.get()); bodies_.push_back(body.get());
return body; return body;
} }
@ -156,13 +156,25 @@ namespace kiwano
{ {
Stage::Update(dt); Stage::Update(dt);
world_.Step(dt.Seconds(), vel_iter_, pos_iter_);
b2Body* b2body = world_.GetBodyList(); b2Body* b2body = world_.GetBodyList();
while (b2body) while (b2body)
{ {
Body* body = static_cast<Body*>(b2body->GetUserData()); Body* body = static_cast<Body*>(b2body->GetUserData());
if (body) if (body && body->GetType() != Body::Type::Static)
{
body->UpdateFromActor();
}
b2body = b2body->GetNext();
}
world_.Step(dt.Seconds(), vel_iter_, pos_iter_);
b2body = world_.GetBodyList();
while (b2body)
{
Body* body = static_cast<Body*>(b2body->GetUserData());
if (body && body->GetType() != Body::Type::Static)
{ {
body->UpdateActor(); body->UpdateActor();
} }

View File

@ -108,7 +108,7 @@ namespace kiwano
{ {
PrepareRender(rt); PrepareRender(rt);
rt->DrawTexture(frame_->GetTexture(), &frame_->GetCropRect(), nullptr); rt->DrawTexture(frame_->GetTexture(), &frame_->GetCropRect(), &GetBounds());
} }
} }
} }

View File

@ -33,6 +33,8 @@ namespace kiwano
const uint32_t BLUE_MASK = 0xff << BLUE_SHIFT; const uint32_t BLUE_MASK = 0xff << BLUE_SHIFT;
} }
const Color Color::Transparent = Color(0.f, 0.f, 0.f, 0.f);
Color::Color() Color::Color()
: r(0) : r(0)
, g(0) , g(0)
@ -72,4 +74,4 @@ namespace kiwano
, a(alpha) , a(alpha)
{ {
} }
} }

View File

@ -112,6 +112,8 @@ namespace kiwano
YellowGreen = 0x9ACD32 YellowGreen = 0x9ACD32
}; };
static const Color Transparent;
public: public:
float r; float r;
float g; float g;