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);
}
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()
{
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_);
if (shape)
{
return Fixture(this, shape, prop);
return Fixture::Create(this, shape, density, friction, restitution);
}
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)
@ -120,6 +124,24 @@ namespace kiwano
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)
{
body_ = body;

View File

@ -30,6 +30,7 @@ namespace kiwano
class World;
// 먼竟
KGE_DECLARE_SMART_PTR(Body);
class KGE_API Body
: public ObjectBase
{
@ -43,16 +44,17 @@ namespace kiwano
Body();
Body(b2Body* body, Actor* actor);
Body(World* world, Actor* actor);
virtual ~Body();
static BodyPtr Create(World* world, Actor* actor);
// 警속近榴
Fixture AddShape(Shape* shape, Fixture::Property const& prop = Fixture::Property());
Fixture AddCircleShape(float radius, Fixture::Property const& prop = Fixture::Property());
Fixture AddBoxShape(Vec2 const& size, Fixture::Property const& prop = Fixture::Property());
Fixture AddPolygonShape(Vector<Point> const& vertexs, Fixture::Property const& prop = Fixture::Property());
Fixture AddEdgeShape(Point const& p1, Point const& p2, Fixture::Property const& prop = Fixture::Property());
Fixture AddChainShape(Vector<Point> const& vertexs, bool loop = false, 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, float density = 0.f);
Fixture AddBoxShape(Vec2 const& size, float density = 0.f);
Fixture AddPolygonShape(Vector<Point> const& vertexs, float density = 0.f);
Fixture AddEdgeShape(Point const& p1, Point const& p2, float density = 0.f);
Fixture AddChainShape(Vector<Point> const& vertexs, bool loop, float density = 0.f);
// 삿혤셸야죗깊
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()); }
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_; }
void SetIgnoreRotation(bool ignore_rotation) { ignore_rotation_ = ignore_rotation; }
@ -91,7 +98,5 @@ namespace kiwano
World* world_;
b2Body* body_;
};
KGE_DECLARE_SMART_PTR(Body);
}
}

View File

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

View File

@ -32,34 +32,16 @@ namespace kiwano
class Fixture
{
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(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;
Fixture GetNext() const;
bool IsValid() const { return !!fixture_; }
b2Fixture* GetB2Fixture() { return fixture_; }
const b2Fixture* GetB2Fixture() const { return 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
};
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(b2Joint* joint);
Joint(World* world, b2JointDef* joint_def);
@ -67,5 +76,32 @@ namespace kiwano
World* world_;
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 body = new Body(this, actor);
BodyPtr body = Body::Create(this, actor);
bodies_.push_back(body.get());
return body;
}
@ -156,13 +156,25 @@ namespace kiwano
{
Stage::Update(dt);
world_.Step(dt.Seconds(), vel_iter_, pos_iter_);
b2Body* b2body = world_.GetBodyList();
while (b2body)
{
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();
}

View File

@ -108,7 +108,7 @@ namespace kiwano
{
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 Color Color::Transparent = Color(0.f, 0.f, 0.f, 0.f);
Color::Color()
: r(0)
, g(0)
@ -72,4 +74,4 @@ namespace kiwano
, a(alpha)
{
}
}
}

View File

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