Add physics::Joints
This commit is contained in:
parent
ae5d985238
commit
0484446bc1
|
|
@ -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
|
||||
{
|
||||
KGE_ASSERT(body_ && world_);
|
||||
|
|
|
|||
|
|
@ -65,6 +65,12 @@ namespace kiwano
|
|||
// »ñÈ¡ÖÊÁ¿
|
||||
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 GetWorldPoint(Point const& local) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ namespace kiwano
|
|||
world_ = world;
|
||||
if (world_)
|
||||
{
|
||||
world_->AddJoint(this);
|
||||
|
||||
b2Joint* joint = world_->GetB2World()->CreateJoint(joint_def);
|
||||
SetB2Joint(joint);
|
||||
}
|
||||
|
|
@ -92,11 +94,13 @@ namespace kiwano
|
|||
|
||||
DistanceJoint::DistanceJoint()
|
||||
: Joint()
|
||||
, raw_joint_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
DistanceJoint::DistanceJoint(World* world, b2DistanceJointDef* def)
|
||||
: Joint(world, def)
|
||||
, raw_joint_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -105,14 +109,279 @@ namespace kiwano
|
|||
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());
|
||||
def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body(), world->Stage2World(param.local_anchor_a), world->Stage2World(param.local_anchor_b));
|
||||
def.frequencyHz = param.frequency_hz;
|
||||
def.dampingRatio = param.damping_ratio;
|
||||
|
||||
DistanceJointPtr joint = new DistanceJoint(world, &def);
|
||||
joint->raw_joint_ = static_cast<b2DistanceJoint*>(joint->GetB2Joint());
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,14 @@ namespace kiwano
|
|||
namespace physics
|
||||
{
|
||||
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
|
||||
: public ObjectBase
|
||||
{
|
||||
|
|
@ -77,7 +85,8 @@ namespace kiwano
|
|||
Type type_;
|
||||
};
|
||||
|
||||
KGE_DECLARE_SMART_PTR(DistanceJoint);
|
||||
|
||||
// 固定距离关节
|
||||
class KGE_API DistanceJoint
|
||||
: public Joint
|
||||
{
|
||||
|
|
@ -86,15 +95,33 @@ namespace kiwano
|
|||
{
|
||||
Point local_anchor_a;
|
||||
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)
|
||||
, local_anchor_a(local_anchor_a)
|
||||
, 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(body_a.get(), body_b.get(), local_anchor_a, local_anchor_b)
|
||||
Param(
|
||||
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);
|
||||
|
||||
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_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,24 +24,56 @@ namespace kiwano
|
|||
{
|
||||
namespace physics
|
||||
{
|
||||
World::World()
|
||||
: world_(b2Vec2(0, 10))
|
||||
, vel_iter_(6)
|
||||
, pos_iter_(2)
|
||||
, global_scale_(100.f)
|
||||
namespace
|
||||
{
|
||||
const float DefaultGlobalScale = 100.f; // 100 pixels per meters
|
||||
}
|
||||
|
||||
class World::DestructionListener : public b2DestructionListener
|
||||
{
|
||||
World* world_;
|
||||
|
||||
public:
|
||||
DestructionListener(World* world)
|
||||
: world_(world)
|
||||
{
|
||||
}
|
||||
|
||||
World::World(Vec2 gravity)
|
||||
: world_(b2Vec2(gravity.x, gravity.y))
|
||||
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)
|
||||
, 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_.SetDestructionListener(nullptr);
|
||||
if (destruction_listener_)
|
||||
{
|
||||
delete destruction_listener_;
|
||||
destruction_listener_ = nullptr;
|
||||
}
|
||||
|
||||
// Make sure b2World was destroyed after b2Body
|
||||
RemoveAllChildren();
|
||||
RemoveAllBodies();
|
||||
|
|
@ -56,27 +88,13 @@ namespace kiwano
|
|||
BodyPtr World::CreateBody(Actor* actor)
|
||||
{
|
||||
BodyPtr body = Body::Create(this, actor);
|
||||
bodies_.push_back(body.get());
|
||||
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)
|
||||
{
|
||||
if (body)
|
||||
{
|
||||
auto iter = std::find(bodies_.begin(), bodies_.end(), body);
|
||||
if (iter != bodies_.end())
|
||||
{
|
||||
bodies_.erase(iter);
|
||||
}
|
||||
|
||||
if (body->GetB2Body())
|
||||
{
|
||||
world_.DestroyBody(body->GetB2Body());
|
||||
|
|
@ -96,7 +114,14 @@ namespace kiwano
|
|||
body = next;
|
||||
}
|
||||
}
|
||||
bodies_.clear();
|
||||
}
|
||||
|
||||
void World::AddJoint(Joint* joint)
|
||||
{
|
||||
if (joint)
|
||||
{
|
||||
joints_.push_back(joint);
|
||||
}
|
||||
}
|
||||
|
||||
void World::RemoveJoint(Joint* joint)
|
||||
|
|
@ -107,11 +132,13 @@ namespace kiwano
|
|||
if (iter != joints_.end())
|
||||
{
|
||||
joints_.erase(iter);
|
||||
}
|
||||
|
||||
if (joint->GetB2Joint())
|
||||
{
|
||||
removing_joint_ = true;
|
||||
world_.DestroyJoint(joint->GetB2Joint());
|
||||
removing_joint_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -119,6 +146,8 @@ namespace kiwano
|
|||
void World::RemoveAllJoints()
|
||||
{
|
||||
if (world_.GetJointCount())
|
||||
{
|
||||
removing_joint_ = true;
|
||||
{
|
||||
b2Joint* joint = world_.GetJointList();
|
||||
while (joint)
|
||||
|
|
@ -128,9 +157,28 @@ namespace kiwano
|
|||
joint = next;
|
||||
}
|
||||
}
|
||||
removing_joint_ = false;
|
||||
}
|
||||
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()
|
||||
{
|
||||
return &world_;
|
||||
|
|
|
|||
|
|
@ -36,17 +36,12 @@ namespace kiwano
|
|||
public:
|
||||
World();
|
||||
|
||||
World(Vec2 gravity);
|
||||
|
||||
virtual ~World();
|
||||
|
||||
// 创建刚体
|
||||
BodyPtr CreateBody(ActorPtr actor);
|
||||
BodyPtr CreateBody(Actor* actor);
|
||||
|
||||
// 创建关节
|
||||
JointPtr CreateJoint(b2JointDef* joint_def);
|
||||
|
||||
// 获取重力
|
||||
Vec2 GetGravity() const;
|
||||
|
||||
|
|
@ -67,10 +62,10 @@ namespace kiwano
|
|||
inline float Stage2World(float value) { return value / GetGlobalScale(); }
|
||||
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; }
|
||||
|
||||
// 设置位置迭代次数
|
||||
// 设置位置迭代次数, 默认为 2
|
||||
inline void SetPositionIterations(int pos_iter) { pos_iter_ = pos_iter; }
|
||||
|
||||
// 获取 Box2D 世界
|
||||
|
|
@ -86,21 +81,32 @@ namespace kiwano
|
|||
// 移除所有刚体
|
||||
void RemoveAllBodies();
|
||||
|
||||
// 添加关节
|
||||
void AddJoint(Joint* joint);
|
||||
|
||||
// 移除关节
|
||||
void RemoveJoint(Joint* joint);
|
||||
|
||||
// 移除所有关节
|
||||
void RemoveAllJoints();
|
||||
|
||||
// 关节被移除
|
||||
void JointRemoved(b2Joint* joint);
|
||||
|
||||
protected:
|
||||
void Update(Duration dt) override;
|
||||
|
||||
class DestructionListener;
|
||||
friend DestructionListener;
|
||||
|
||||
protected:
|
||||
b2World world_;
|
||||
int vel_iter_;
|
||||
int pos_iter_;
|
||||
float global_scale_;
|
||||
Vector<Body*> bodies_;
|
||||
DestructionListener* destruction_listener_;
|
||||
|
||||
bool removing_joint_;
|
||||
Vector<Joint*> joints_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -525,7 +525,7 @@ namespace kiwano
|
|||
return children;
|
||||
}
|
||||
|
||||
ActorPtr Actor::GetChild(String const& name) const
|
||||
Actor* Actor::GetChild(String const& name) const
|
||||
{
|
||||
size_t hash_code = std::hash<String>{}(name);
|
||||
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ namespace kiwano
|
|||
);
|
||||
|
||||
// 获取名称相同的子角色
|
||||
ActorPtr GetChild(
|
||||
Actor* GetChild(
|
||||
String const& name
|
||||
) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@ namespace kiwano
|
|||
}
|
||||
|
||||
Action* ActionManager::AddAction(ActionPtr action)
|
||||
{
|
||||
return AddAction(action.get());
|
||||
}
|
||||
|
||||
Action* ActionManager::AddAction(Action* action)
|
||||
{
|
||||
KGE_ASSERT(action && "AddAction failed, NULL pointer exception");
|
||||
|
||||
|
|
@ -50,10 +55,10 @@ namespace kiwano
|
|||
{
|
||||
actions_.push_back(action);
|
||||
}
|
||||
return action.get();
|
||||
return action;
|
||||
}
|
||||
|
||||
ActionPtr ActionManager::GetAction(String const & name)
|
||||
Action* ActionManager::GetAction(String const & name)
|
||||
{
|
||||
if (actions_.empty())
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -32,9 +32,13 @@ namespace kiwano
|
|||
Action* AddAction(
|
||||
ActionPtr action
|
||||
);
|
||||
// 添加动作
|
||||
Action* AddAction(
|
||||
Action* action
|
||||
);
|
||||
|
||||
// 获取动作
|
||||
ActionPtr GetAction(
|
||||
Action* GetAction(
|
||||
String const& name
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,11 @@ namespace kiwano
|
|||
}
|
||||
|
||||
EventListener* EventDispatcher::AddListener(EventListenerPtr listener)
|
||||
{
|
||||
return AddListener(listener.get());
|
||||
}
|
||||
|
||||
EventListener* EventDispatcher::AddListener(EventListener* listener)
|
||||
{
|
||||
KGE_ASSERT(listener && "AddListener failed, NULL pointer exception");
|
||||
|
||||
|
|
@ -48,7 +53,7 @@ namespace kiwano
|
|||
{
|
||||
listeners_.push_back(listener);
|
||||
}
|
||||
return listener.get();
|
||||
return listener;
|
||||
}
|
||||
|
||||
EventListener* EventDispatcher::AddListener(EventType type, EventListener::Callback callback, String const& name)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ namespace kiwano
|
|||
EventListenerPtr listener
|
||||
);
|
||||
|
||||
// 添加监听器
|
||||
EventListener* AddListener(
|
||||
EventListener* listener
|
||||
);
|
||||
|
||||
// 添加监听器
|
||||
EventListener* AddListener(
|
||||
EventType type,
|
||||
|
|
|
|||
Loading…
Reference in New Issue