Add physics::Joints

This commit is contained in:
Nomango 2019-10-28 17:25:06 +08:00
parent ae5d985238
commit 0484446bc1
12 changed files with 746 additions and 55 deletions

View File

@ -112,6 +112,12 @@ namespace kiwano
} }
} }
Point Body::GetPosition() const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetPosition());
}
Point Body::GetLocalPoint(Point const& world) const Point Body::GetLocalPoint(Point const& world) const
{ {
KGE_ASSERT(body_ && world_); KGE_ASSERT(body_ && world_);

View File

@ -65,6 +65,12 @@ namespace kiwano
// »ñÈ¡ÖÊÁ¿ // »ñÈ¡ÖÊÁ¿
float GetMass() const { KGE_ASSERT(body_); return body_->GetMass(); } float GetMass() const { KGE_ASSERT(body_); return body_->GetMass(); }
// »ñÈ¡Ðýת½Ç¶È
float GetRotation() const { KGE_ASSERT(body_); return math::Radian2Angle(body_->GetAngle()); }
// »ñȡλÖÃ
Point GetPosition() const;
Point GetLocalPoint(Point const& world) const; Point GetLocalPoint(Point const& world) const;
Point GetWorldPoint(Point const& local) const; Point GetWorldPoint(Point const& local) const;

View File

@ -48,6 +48,8 @@ namespace kiwano
world_ = world; world_ = world;
if (world_) if (world_)
{ {
world_->AddJoint(this);
b2Joint* joint = world_->GetB2World()->CreateJoint(joint_def); b2Joint* joint = world_->GetB2World()->CreateJoint(joint_def);
SetB2Joint(joint); SetB2Joint(joint);
} }
@ -92,11 +94,13 @@ namespace kiwano
DistanceJoint::DistanceJoint() DistanceJoint::DistanceJoint()
: Joint() : Joint()
, raw_joint_(nullptr)
{ {
} }
DistanceJoint::DistanceJoint(World* world, b2DistanceJointDef* def) DistanceJoint::DistanceJoint(World* world, b2DistanceJointDef* def)
: Joint(world, def) : Joint(world, def)
, raw_joint_(nullptr)
{ {
} }
@ -105,14 +109,279 @@ namespace kiwano
KGE_ASSERT(param.body_a && param.body_b); KGE_ASSERT(param.body_a && param.body_b);
b2DistanceJointDef def; b2DistanceJointDef def;
def.bodyA = param.body_a->GetB2Body(); def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body(), world->Stage2World(param.local_anchor_a), world->Stage2World(param.local_anchor_b));
def.bodyB = param.body_b->GetB2Body(); def.frequencyHz = param.frequency_hz;
def.localAnchorA = world->Stage2World(param.local_anchor_a); def.dampingRatio = param.damping_ratio;
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); DistanceJointPtr joint = new DistanceJoint(world, &def);
joint->raw_joint_ = static_cast<b2DistanceJoint*>(joint->GetB2Joint());
return joint; return joint;
} }
void DistanceJoint::SetLength(float length)
{
KGE_ASSERT(raw_joint_ && world_);
raw_joint_->SetLength(world_->Stage2World(length));
}
float DistanceJoint::GetLength() const
{
KGE_ASSERT(raw_joint_ && world_);
return world_->World2Stage(raw_joint_->GetLength());
}
//
// FrictionJoint
//
FrictionJoint::FrictionJoint()
: Joint()
, raw_joint_(nullptr)
{
}
FrictionJoint::FrictionJoint(World* world, b2FrictionJointDef* def)
: Joint(world, def)
, raw_joint_(nullptr)
{
}
FrictionJointPtr FrictionJoint::Create(World* world, Param const& param)
{
KGE_ASSERT(param.body_a && param.body_b);
b2FrictionJointDef def;
def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body(), world->Stage2World(param.anchor));
def.maxForce = param.max_force;
def.maxTorque = world->Stage2World(param.max_torque);
FrictionJointPtr joint = new FrictionJoint(world, &def);
joint->raw_joint_ = static_cast<b2FrictionJoint*>(joint->GetB2Joint());
return joint;
}
void FrictionJoint::SetMaxForce(float length)
{
KGE_ASSERT(raw_joint_);
raw_joint_->SetMaxForce(length);
}
float FrictionJoint::GetMaxForce() const
{
KGE_ASSERT(raw_joint_);
return raw_joint_->GetMaxForce();
}
void FrictionJoint::SetMaxTorque(float length)
{
KGE_ASSERT(raw_joint_ && world_);
raw_joint_->SetMaxTorque(world_->Stage2World(length));
}
float FrictionJoint::GetMaxTorque() const
{
KGE_ASSERT(raw_joint_ && world_);
return world_->World2Stage(raw_joint_->GetMaxTorque());
}
//
// GearJoint
//
GearJoint::GearJoint()
: Joint()
, raw_joint_(nullptr)
{
}
GearJoint::GearJoint(World* world, b2GearJointDef* def)
: Joint(world, def)
, raw_joint_(nullptr)
{
}
GearJointPtr GearJoint::Create(World* world, Param const& param)
{
KGE_ASSERT(param.joint_a && param.joint_b);
b2GearJointDef def;
def.joint1 = param.joint_a->GetB2Joint();
def.joint2 = param.joint_b->GetB2Joint();
def.ratio = param.ratio;
GearJointPtr joint = new GearJoint(world, &def);
joint->raw_joint_ = static_cast<b2GearJoint*>(joint->GetB2Joint());
return joint;
}
void GearJoint::SetRatio(float ratio)
{
KGE_ASSERT(raw_joint_);
raw_joint_->SetRatio(ratio);
}
float GearJoint::GetRatio() const
{
KGE_ASSERT(raw_joint_);
return raw_joint_->GetRatio();
}
//
// MotorJoint
//
MotorJoint::MotorJoint()
: Joint()
, raw_joint_(nullptr)
{
}
MotorJoint::MotorJoint(World* world, b2MotorJointDef* def)
: Joint(world, def)
, raw_joint_(nullptr)
{
}
MotorJointPtr MotorJoint::Create(World* world, Param const& param)
{
KGE_ASSERT(param.body_a && param.body_b);
b2MotorJointDef def;
def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body());
def.maxForce = param.max_force;
def.maxTorque = world->Stage2World(param.max_torque);
MotorJointPtr joint = new MotorJoint(world, &def);
joint->raw_joint_ = static_cast<b2MotorJoint*>(joint->GetB2Joint());
return joint;
}
void MotorJoint::SetMaxForce(float length)
{
KGE_ASSERT(raw_joint_);
raw_joint_->SetMaxForce(length);
}
float MotorJoint::GetMaxForce() const
{
KGE_ASSERT(raw_joint_);
return raw_joint_->GetMaxForce();
}
void MotorJoint::SetMaxTorque(float length)
{
KGE_ASSERT(raw_joint_ && world_);
raw_joint_->SetMaxTorque(world_->Stage2World(length));
}
float MotorJoint::GetMaxTorque() const
{
KGE_ASSERT(raw_joint_ && world_);
return world_->World2Stage(raw_joint_->GetMaxTorque());
}
//
// WheelJoint
//
WheelJoint::WheelJoint()
: Joint()
, raw_joint_(nullptr)
{
}
WheelJoint::WheelJoint(World* world, b2WheelJointDef* def)
: Joint(world, def)
, raw_joint_(nullptr)
{
}
WheelJointPtr WheelJoint::Create(World* world, Param const& param)
{
KGE_ASSERT(param.body_a && param.body_b);
b2WheelJointDef def;
def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body(), world->Stage2World(param.anchor), world->Stage2World(param.axis));
def.enableMotor = param.enable_motor;
def.maxMotorTorque = world->Stage2World(param.max_motor_torque);
def.motorSpeed = world->Stage2World(param.motor_speed);
def.frequencyHz = param.frequency_hz;
def.dampingRatio = param.damping_ratio;
WheelJointPtr joint = new WheelJoint(world, &def);
joint->raw_joint_ = static_cast<b2WheelJoint*>(joint->GetB2Joint());
return joint;
}
float WheelJoint::GetJointTranslation() const
{
KGE_ASSERT(raw_joint_ && world_);
return world_->World2Stage(raw_joint_->GetJointTranslation());
}
float WheelJoint::GetJointLinearSpeed() const
{
KGE_ASSERT(raw_joint_ && world_);
return world_->World2Stage(raw_joint_->GetJointLinearSpeed());
}
void WheelJoint::SetMaxMotorTorque(float torque)
{
KGE_ASSERT(raw_joint_ && world_);
raw_joint_->SetMaxMotorTorque(world_->Stage2World(torque));
}
float WheelJoint::GetMaxMotorTorque() const
{
KGE_ASSERT(raw_joint_ && world_);
return world_->World2Stage(raw_joint_->GetMaxMotorTorque());
}
//
// MouseJoint
//
MouseJoint::MouseJoint()
: Joint()
, raw_joint_(nullptr)
{
}
MouseJoint::MouseJoint(World* world, b2MouseJointDef* def)
: Joint(world, def)
, raw_joint_(nullptr)
{
}
MouseJointPtr MouseJoint::Create(World* world, Param const& param)
{
KGE_ASSERT(param.body_a && param.body_b);
KGE_ASSERT(param.body_a->GetWorld() && param.body_a->GetWorld() == param.body_b->GetWorld());
b2MouseJointDef def;
def.bodyA = param.body_a->GetB2Body();
def.bodyB = param.body_b->GetB2Body();
def.target = param.body_a->GetWorld()->Stage2World(param.target);
def.maxForce = param.max_force;
def.frequencyHz = param.frequency_hz;
def.dampingRatio = param.damping_ratio;
MouseJointPtr joint = new MouseJoint(world, &def);
joint->raw_joint_ = static_cast<b2MouseJoint*>(joint->GetB2Joint());
return joint;
}
void MouseJoint::SetMaxForce(float length)
{
KGE_ASSERT(raw_joint_);
raw_joint_->SetMaxForce(length);
}
float MouseJoint::GetMaxForce() const
{
KGE_ASSERT(raw_joint_);
return raw_joint_->GetMaxForce();
}
} }
} }

View File

@ -27,6 +27,14 @@ namespace kiwano
namespace physics namespace physics
{ {
KGE_DECLARE_SMART_PTR(Joint); KGE_DECLARE_SMART_PTR(Joint);
KGE_DECLARE_SMART_PTR(DistanceJoint);
KGE_DECLARE_SMART_PTR(FrictionJoint);
KGE_DECLARE_SMART_PTR(GearJoint);
KGE_DECLARE_SMART_PTR(MotorJoint);
KGE_DECLARE_SMART_PTR(WheelJoint);
KGE_DECLARE_SMART_PTR(MouseJoint);
// 关节
class KGE_API Joint class KGE_API Joint
: public ObjectBase : public ObjectBase
{ {
@ -77,7 +85,8 @@ namespace kiwano
Type type_; Type type_;
}; };
KGE_DECLARE_SMART_PTR(DistanceJoint);
// 固定距离关节
class KGE_API DistanceJoint class KGE_API DistanceJoint
: public Joint : public Joint
{ {
@ -86,15 +95,33 @@ namespace kiwano
{ {
Point local_anchor_a; Point local_anchor_a;
Point local_anchor_b; Point local_anchor_b;
float frequency_hz;
float damping_ratio;
Param(Body* body_a, Body* body_b, Point const& local_anchor_a, Point const& local_anchor_b) Param(
Body* body_a,
Body* body_b,
Point const& local_anchor_a,
Point const& local_anchor_b,
float frequency_hz = 0.f,
float damping_ratio = 0.f
)
: ParamBase(body_a, body_b) : ParamBase(body_a, body_b)
, local_anchor_a(local_anchor_a) , local_anchor_a(local_anchor_a)
, local_anchor_b(local_anchor_b) , local_anchor_b(local_anchor_b)
, frequency_hz(frequency_hz)
, damping_ratio(damping_ratio)
{} {}
Param(BodyPtr body_a, BodyPtr body_b, Point const& local_anchor_a, Point const& local_anchor_b) Param(
: Param(body_a.get(), body_b.get(), local_anchor_a, local_anchor_b) BodyPtr body_a,
BodyPtr body_b,
Point const& local_anchor_a,
Point const& local_anchor_b,
float frequency_hz = 0.f,
float damping_ratio = 0.f
)
: Param(body_a.get(), body_b.get(), local_anchor_a, local_anchor_b, frequency_hz, damping_ratio)
{} {}
}; };
@ -102,6 +129,316 @@ namespace kiwano
DistanceJoint(World* world, b2DistanceJointDef* def); DistanceJoint(World* world, b2DistanceJointDef* def);
static DistanceJointPtr Create(World* world, Param const& param); static DistanceJointPtr Create(World* world, Param const& param);
void SetLength(float length);
float GetLength() const;
// 设置弹簧阻尼器频率 [赫兹]
void SetFrequency(float hz) { KGE_ASSERT(raw_joint_); raw_joint_->SetFrequency(hz); }
float GetFrequency() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetFrequency(); }
// 设置阻尼比
void SetDampingRatio(float ratio) { KGE_ASSERT(raw_joint_); raw_joint_->SetDampingRatio(ratio); }
float GetDampingRatio() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetDampingRatio(); }
protected:
b2DistanceJoint* raw_joint_;
};
// 摩擦关节
class KGE_API FrictionJoint
: public Joint
{
public:
struct Param : public Joint::ParamBase
{
Point anchor;
float max_force;
float max_torque;
Param(
Body* body_a,
Body* body_b,
Point const& anchor,
float max_force = 0.f,
float max_torque = 0.f
)
: ParamBase(body_a, body_b)
, anchor(anchor)
, max_force(max_force)
, max_torque(max_torque)
{}
Param(
BodyPtr body_a,
BodyPtr body_b,
Point const& anchor,
float max_force = 0.f,
float max_torque = 0.f
)
: Param(body_a.get(), body_b.get(), anchor, max_force, max_torque)
{}
};
FrictionJoint();
FrictionJoint(World* world, b2FrictionJointDef* def);
static FrictionJointPtr Create(World* world, Param const& param);
// 设定最大摩擦力
void SetMaxForce(float force);
float GetMaxForce() const;
// 设定最大转矩
void SetMaxTorque(float torque);
float GetMaxTorque() const;
protected:
b2FrictionJoint* raw_joint_;
};
// 齿轮关节
class KGE_API GearJoint
: public Joint
{
public:
struct Param : public Joint::ParamBase
{
JointPtr joint_a;
JointPtr joint_b;
float ratio;
Param(
Joint* joint_a,
Joint* joint_b,
float ratio = 1.f
)
: ParamBase(nullptr, nullptr)
, joint_a(joint_a)
, joint_b(joint_b)
, ratio(ratio)
{}
Param(
JointPtr joint_a,
JointPtr joint_b,
float ratio = 1.f
)
: Param(joint_a.get(), joint_b.get(), ratio)
{}
};
GearJoint();
GearJoint(World* world, b2GearJointDef* def);
static GearJointPtr Create(World* world, Param const& param);
// 设定齿轮传动比
void SetRatio(float ratio);
float GetRatio() const;
protected:
b2GearJoint* raw_joint_;
};
// 马达关节
class KGE_API MotorJoint
: public Joint
{
public:
struct Param : public Joint::ParamBase
{
float max_force;
float max_torque;
float correction_factor;
Param(
Body* body_a,
Body* body_b,
float max_force = 1.f,
float max_torque = 100.f,
float correction_factor = 0.3f
)
: ParamBase(body_a, body_b)
, max_force(max_force)
, max_torque(max_torque)
, correction_factor(correction_factor)
{}
Param(
BodyPtr body_a,
BodyPtr body_b,
float max_force = 0.f,
float max_torque = 0.f,
float correction_factor = 0.3f
)
: Param(body_a.get(), body_b.get(), max_force, max_torque, correction_factor)
{}
};
MotorJoint();
MotorJoint(World* world, b2MotorJointDef* def);
static MotorJointPtr Create(World* world, Param const& param);
// 设定最大摩擦力
void SetMaxForce(float force);
float GetMaxForce() const;
// 设定最大转矩
void SetMaxTorque(float torque);
float GetMaxTorque() const;
protected:
b2MotorJoint* raw_joint_;
};
// 轮关节
class KGE_API WheelJoint
: public Joint
{
public:
struct Param : public Joint::ParamBase
{
Point anchor;
Vec2 axis;
bool enable_motor;
float max_motor_torque;
float motor_speed;
float frequency_hz;
float damping_ratio;
Param(
Body* body_a,
Body* body_b,
Point const& anchor,
Vec2 const& axis,
float frequency_hz = 2.0f,
float damping_ratio = 0.7f,
bool enable_motor = false,
float max_motor_torque = 0.0f,
float motor_speed = 0.0f
)
: ParamBase(body_a, body_b)
, anchor(anchor)
, axis(axis)
, enable_motor(enable_motor)
, max_motor_torque(max_motor_torque)
, motor_speed(motor_speed)
, frequency_hz(frequency_hz)
, damping_ratio(damping_ratio)
{}
Param(
BodyPtr body_a,
BodyPtr body_b,
Point const& anchor,
Vec2 const& axis,
float frequency_hz = 2.0f,
float damping_ratio = 0.7f,
bool enable_motor = false,
float max_motor_torque = 0.0f,
float motor_speed = 0.0f
)
: Param(body_a.get(), body_b.get(), anchor, axis, frequency_hz, damping_ratio, enable_motor, max_motor_torque, motor_speed)
{}
};
WheelJoint();
WheelJoint(World* world, b2WheelJointDef* def);
static WheelJointPtr Create(World* world, Param const& param);
float GetJointTranslation() const;
float GetJointLinearSpeed() const;
float GetJointAngle() const { KGE_ASSERT(raw_joint_); return math::Radian2Angle(raw_joint_->GetJointAngle()); }
float GetJointAngularSpeed() const { KGE_ASSERT(raw_joint_); return math::Radian2Angle(raw_joint_->GetJointAngularSpeed()); }
bool IsMotorEnabled() const { KGE_ASSERT(raw_joint_); return raw_joint_->IsMotorEnabled(); }
void EnableMotor(bool flag) { KGE_ASSERT(raw_joint_); raw_joint_->EnableMotor(flag); }
// 设置马达转速 [度/秒]
void SetMotorSpeed(float speed) { KGE_ASSERT(raw_joint_); raw_joint_->SetMotorSpeed(math::Angle2Radian(speed)); }
float GetMotorSpeed() const { KGE_ASSERT(raw_joint_); return math::Radian2Angle(raw_joint_->GetMotorSpeed()); }
// 设定最大马达转矩
void SetMaxMotorTorque(float torque);
float GetMaxMotorTorque() const;
void SetSpringFrequencyHz(float hz) { KGE_ASSERT(raw_joint_); raw_joint_->SetSpringFrequencyHz(hz); }
float GetSpringFrequencyHz() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetSpringFrequencyHz(); }
void SetSpringDampingRatio(float ratio) { KGE_ASSERT(raw_joint_); raw_joint_->SetSpringDampingRatio(ratio); }
float GetSpringDampingRatio() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetSpringDampingRatio(); }
protected:
b2WheelJoint* raw_joint_;
};
// 鼠标关节
// 用于使身体的某个点追踪世界上的指定点,例如让物体追踪鼠标位置
class KGE_API MouseJoint
: public Joint
{
public:
struct Param : public Joint::ParamBase
{
Point target;
float max_force;
float frequency_hz;
float damping_ratio;
Param(
Body* body_a,
Body* body_b,
Point const& target,
float max_force,
float frequency_hz = 5.0f,
float damping_ratio = 0.7f
)
: ParamBase(body_a, body_b)
, target(target)
, max_force(max_force)
, frequency_hz(frequency_hz)
, damping_ratio(damping_ratio)
{}
Param(
BodyPtr body_a,
BodyPtr body_b,
Point const& target,
float max_force,
float frequency_hz = 5.0f,
float damping_ratio = 0.7f
)
: Param(body_a.get(), body_b.get(), target, max_force, frequency_hz, damping_ratio)
{}
};
MouseJoint();
MouseJoint(World* world, b2MouseJointDef* def);
static MouseJointPtr Create(World* world, Param const& param);
// 设定最大摩擦力
void SetMaxForce(float force);
float GetMaxForce() const;
// 设置响应速度 [赫兹]
void SetFrequency(float hz) { KGE_ASSERT(raw_joint_); raw_joint_->SetFrequency(hz); }
float GetFrequency() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetFrequency(); }
// 设置阻尼比
void SetDampingRatio(float ratio) { KGE_ASSERT(raw_joint_); raw_joint_->SetDampingRatio(ratio); }
float GetDampingRatio() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetDampingRatio(); }
protected:
b2MouseJoint* raw_joint_;
}; };
} }
} }

View File

@ -24,24 +24,56 @@ namespace kiwano
{ {
namespace physics namespace physics
{ {
World::World() namespace
: world_(b2Vec2(0, 10))
, vel_iter_(6)
, pos_iter_(2)
, global_scale_(100.f)
{ {
const float DefaultGlobalScale = 100.f; // 100 pixels per meters
} }
World::World(Vec2 gravity) class World::DestructionListener : public b2DestructionListener
: world_(b2Vec2(gravity.x, gravity.y)) {
World* world_;
public:
DestructionListener(World* world)
: world_(world)
{
}
void SayGoodbye(b2Joint* joint) override
{
if (world_)
{
world_->JointRemoved(joint);
}
}
void SayGoodbye(b2Fixture* fixture) override
{
}
};
World::World()
: world_(b2Vec2(0, 10.0f))
, vel_iter_(6) , vel_iter_(6)
, pos_iter_(2) , pos_iter_(2)
, global_scale_(100.f) , global_scale_(DefaultGlobalScale)
, destruction_listener_(nullptr)
, removing_joint_(false)
{ {
destruction_listener_ = new DestructionListener(this);
world_.SetDestructionListener(destruction_listener_);
} }
World::~World() World::~World()
{ {
world_.SetDestructionListener(nullptr);
if (destruction_listener_)
{
delete destruction_listener_;
destruction_listener_ = nullptr;
}
// Make sure b2World was destroyed after b2Body // Make sure b2World was destroyed after b2Body
RemoveAllChildren(); RemoveAllChildren();
RemoveAllBodies(); RemoveAllBodies();
@ -56,27 +88,13 @@ namespace kiwano
BodyPtr World::CreateBody(Actor* actor) BodyPtr World::CreateBody(Actor* actor)
{ {
BodyPtr body = Body::Create(this, actor); BodyPtr body = Body::Create(this, actor);
bodies_.push_back(body.get());
return body; return body;
} }
JointPtr World::CreateJoint(b2JointDef* joint_def)
{
JointPtr joint = new Joint(this, joint_def);
joints_.push_back(joint.get());
return joint;
}
void World::RemoveBody(Body* body) void World::RemoveBody(Body* body)
{ {
if (body) if (body)
{ {
auto iter = std::find(bodies_.begin(), bodies_.end(), body);
if (iter != bodies_.end())
{
bodies_.erase(iter);
}
if (body->GetB2Body()) if (body->GetB2Body())
{ {
world_.DestroyBody(body->GetB2Body()); world_.DestroyBody(body->GetB2Body());
@ -96,7 +114,14 @@ namespace kiwano
body = next; body = next;
} }
} }
bodies_.clear(); }
void World::AddJoint(Joint* joint)
{
if (joint)
{
joints_.push_back(joint);
}
} }
void World::RemoveJoint(Joint* joint) void World::RemoveJoint(Joint* joint)
@ -107,11 +132,13 @@ namespace kiwano
if (iter != joints_.end()) if (iter != joints_.end())
{ {
joints_.erase(iter); joints_.erase(iter);
}
if (joint->GetB2Joint()) if (joint->GetB2Joint())
{ {
world_.DestroyJoint(joint->GetB2Joint()); removing_joint_ = true;
world_.DestroyJoint(joint->GetB2Joint());
removing_joint_ = false;
}
} }
} }
} }
@ -120,17 +147,38 @@ namespace kiwano
{ {
if (world_.GetJointCount()) if (world_.GetJointCount())
{ {
b2Joint* joint = world_.GetJointList(); removing_joint_ = true;
while (joint)
{ {
b2Joint* next = joint->GetNext(); b2Joint* joint = world_.GetJointList();
world_.DestroyJoint(joint); while (joint)
joint = next; {
b2Joint* next = joint->GetNext();
world_.DestroyJoint(joint);
joint = next;
}
} }
removing_joint_ = false;
} }
joints_.clear(); joints_.clear();
} }
void World::JointRemoved(b2Joint* joint)
{
if (!removing_joint_ && joint)
{
auto iter = std::find_if(
joints_.begin(),
joints_.end(),
[joint](Joint* j) -> bool { return j->GetB2Joint() == joint; }
);
if (iter != joints_.end())
{
joints_.erase(iter);
}
}
}
b2World* World::GetB2World() b2World* World::GetB2World()
{ {
return &world_; return &world_;

View File

@ -36,17 +36,12 @@ namespace kiwano
public: public:
World(); World();
World(Vec2 gravity);
virtual ~World(); virtual ~World();
// 创建刚体 // 创建刚体
BodyPtr CreateBody(ActorPtr actor); BodyPtr CreateBody(ActorPtr actor);
BodyPtr CreateBody(Actor* actor); BodyPtr CreateBody(Actor* actor);
// 创建关节
JointPtr CreateJoint(b2JointDef* joint_def);
// 获取重力 // 获取重力
Vec2 GetGravity() const; Vec2 GetGravity() const;
@ -67,10 +62,10 @@ namespace kiwano
inline float Stage2World(float value) { return value / GetGlobalScale(); } inline float Stage2World(float value) { return value / GetGlobalScale(); }
inline b2Vec2 Stage2World(const Point& pos) { return b2Vec2(Stage2World(pos.x), Stage2World(pos.y)); } inline b2Vec2 Stage2World(const Point& pos) { return b2Vec2(Stage2World(pos.x), Stage2World(pos.y)); }
// 设置速度迭代次数 // 设置速度迭代次数, 默认为 6
inline void SetVelocityIterations(int vel_iter) { vel_iter_ = vel_iter; } inline void SetVelocityIterations(int vel_iter) { vel_iter_ = vel_iter; }
// 设置位置迭代次数 // 设置位置迭代次数, 默认为 2
inline void SetPositionIterations(int pos_iter) { pos_iter_ = pos_iter; } inline void SetPositionIterations(int pos_iter) { pos_iter_ = pos_iter; }
// 获取 Box2D 世界 // 获取 Box2D 世界
@ -86,21 +81,32 @@ namespace kiwano
// 移除所有刚体 // 移除所有刚体
void RemoveAllBodies(); void RemoveAllBodies();
// 添加关节
void AddJoint(Joint* joint);
// 移除关节 // 移除关节
void RemoveJoint(Joint* joint); void RemoveJoint(Joint* joint);
// 移除所有关节 // 移除所有关节
void RemoveAllJoints(); void RemoveAllJoints();
// 关节被移除
void JointRemoved(b2Joint* joint);
protected: protected:
void Update(Duration dt) override; void Update(Duration dt) override;
class DestructionListener;
friend DestructionListener;
protected: protected:
b2World world_; b2World world_;
int vel_iter_; int vel_iter_;
int pos_iter_; int pos_iter_;
float global_scale_; float global_scale_;
Vector<Body*> bodies_; DestructionListener* destruction_listener_;
bool removing_joint_;
Vector<Joint*> joints_; Vector<Joint*> joints_;
}; };

View File

@ -525,7 +525,7 @@ namespace kiwano
return children; return children;
} }
ActorPtr Actor::GetChild(String const& name) const Actor* Actor::GetChild(String const& name) const
{ {
size_t hash_code = std::hash<String>{}(name); size_t hash_code = std::hash<String>{}(name);

View File

@ -325,7 +325,7 @@ namespace kiwano
); );
// 获取名称相同的子角色 // 获取名称相同的子角色
ActorPtr GetChild( Actor* GetChild(
String const& name String const& name
) const; ) const;

View File

@ -43,6 +43,11 @@ namespace kiwano
} }
Action* ActionManager::AddAction(ActionPtr action) Action* ActionManager::AddAction(ActionPtr action)
{
return AddAction(action.get());
}
Action* ActionManager::AddAction(Action* action)
{ {
KGE_ASSERT(action && "AddAction failed, NULL pointer exception"); KGE_ASSERT(action && "AddAction failed, NULL pointer exception");
@ -50,10 +55,10 @@ namespace kiwano
{ {
actions_.push_back(action); actions_.push_back(action);
} }
return action.get(); return action;
} }
ActionPtr ActionManager::GetAction(String const & name) Action* ActionManager::GetAction(String const & name)
{ {
if (actions_.empty()) if (actions_.empty())
return nullptr; return nullptr;

View File

@ -32,9 +32,13 @@ namespace kiwano
Action* AddAction( Action* AddAction(
ActionPtr action ActionPtr action
); );
// 添加动作
Action* AddAction(
Action* action
);
// 获取动作 // 获取动作
ActionPtr GetAction( Action* GetAction(
String const& name String const& name
); );

View File

@ -41,6 +41,11 @@ namespace kiwano
} }
EventListener* EventDispatcher::AddListener(EventListenerPtr listener) EventListener* EventDispatcher::AddListener(EventListenerPtr listener)
{
return AddListener(listener.get());
}
EventListener* EventDispatcher::AddListener(EventListener* listener)
{ {
KGE_ASSERT(listener && "AddListener failed, NULL pointer exception"); KGE_ASSERT(listener && "AddListener failed, NULL pointer exception");
@ -48,7 +53,7 @@ namespace kiwano
{ {
listeners_.push_back(listener); listeners_.push_back(listener);
} }
return listener.get(); return listener;
} }
EventListener* EventDispatcher::AddListener(EventType type, EventListener::Callback callback, String const& name) EventListener* EventDispatcher::AddListener(EventType type, EventListener::Callback callback, String const& name)

View File

@ -33,6 +33,11 @@ namespace kiwano
EventListenerPtr listener EventListenerPtr listener
); );
// 添加监听器
EventListener* AddListener(
EventListener* listener
);
// 添加监听器 // 添加监听器
EventListener* AddListener( EventListener* AddListener(
EventType type, EventType type,