diff --git a/src/kiwano-physics/Body.cpp b/src/kiwano-physics/Body.cpp index e19b0c20..15e5e899 100644 --- a/src/kiwano-physics/Body.cpp +++ b/src/kiwano-physics/Body.cpp @@ -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_); diff --git a/src/kiwano-physics/Body.h b/src/kiwano-physics/Body.h index 3c0b8fde..3f1aca0d 100644 --- a/src/kiwano-physics/Body.h +++ b/src/kiwano-physics/Body.h @@ -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; diff --git a/src/kiwano-physics/Joint.cpp b/src/kiwano-physics/Joint.cpp index 7967c7a1..fc51719b 100644 --- a/src/kiwano-physics/Joint.cpp +++ b/src/kiwano-physics/Joint.cpp @@ -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(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(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(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(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(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(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(); + } + } } diff --git a/src/kiwano-physics/Joint.h b/src/kiwano-physics/Joint.h index f21bc1c2..96d093f0 100644 --- a/src/kiwano-physics/Joint.h +++ b/src/kiwano-physics/Joint.h @@ -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_; }; } } diff --git a/src/kiwano-physics/World.cpp b/src/kiwano-physics/World.cpp index 67fdb7f3..8bbe52e2 100644 --- a/src/kiwano-physics/World.cpp +++ b/src/kiwano-physics/World.cpp @@ -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 } - World::World(Vec2 gravity) - : world_(b2Vec2(gravity.x, gravity.y)) + class World::DestructionListener : public b2DestructionListener + { + 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) , 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()) - { - world_.DestroyJoint(joint->GetB2Joint()); + if (joint->GetB2Joint()) + { + removing_joint_ = true; + world_.DestroyJoint(joint->GetB2Joint()); + removing_joint_ = false; + } } } } @@ -120,17 +147,38 @@ namespace kiwano { if (world_.GetJointCount()) { - b2Joint* joint = world_.GetJointList(); - while (joint) + removing_joint_ = true; { - b2Joint* next = joint->GetNext(); - world_.DestroyJoint(joint); - joint = next; + b2Joint* joint = world_.GetJointList(); + while (joint) + { + b2Joint* next = joint->GetNext(); + world_.DestroyJoint(joint); + 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_; diff --git a/src/kiwano-physics/World.h b/src/kiwano-physics/World.h index a005dfbc..6fbb887d 100644 --- a/src/kiwano-physics/World.h +++ b/src/kiwano-physics/World.h @@ -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 bodies_; + DestructionListener* destruction_listener_; + + bool removing_joint_; Vector joints_; }; diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index 39a82b8c..78fb509e 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -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{}(name); diff --git a/src/kiwano/2d/Actor.h b/src/kiwano/2d/Actor.h index 47bbcf97..9795edef 100644 --- a/src/kiwano/2d/Actor.h +++ b/src/kiwano/2d/Actor.h @@ -325,7 +325,7 @@ namespace kiwano ); // 获取名称相同的子角色 - ActorPtr GetChild( + Actor* GetChild( String const& name ) const; diff --git a/src/kiwano/2d/action/ActionManager.cpp b/src/kiwano/2d/action/ActionManager.cpp index 6f2412d3..52b603f1 100644 --- a/src/kiwano/2d/action/ActionManager.cpp +++ b/src/kiwano/2d/action/ActionManager.cpp @@ -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; diff --git a/src/kiwano/2d/action/ActionManager.h b/src/kiwano/2d/action/ActionManager.h index 5b827198..e0ae6282 100644 --- a/src/kiwano/2d/action/ActionManager.h +++ b/src/kiwano/2d/action/ActionManager.h @@ -32,9 +32,13 @@ namespace kiwano Action* AddAction( ActionPtr action ); + // 添加动作 + Action* AddAction( + Action* action + ); // 获取动作 - ActionPtr GetAction( + Action* GetAction( String const& name ); diff --git a/src/kiwano/base/EventDispatcher.cpp b/src/kiwano/base/EventDispatcher.cpp index 3537c53c..91c715fd 100644 --- a/src/kiwano/base/EventDispatcher.cpp +++ b/src/kiwano/base/EventDispatcher.cpp @@ -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) diff --git a/src/kiwano/base/EventDispatcher.h b/src/kiwano/base/EventDispatcher.h index 4b59abca..75065de8 100644 --- a/src/kiwano/base/EventDispatcher.h +++ b/src/kiwano/base/EventDispatcher.h @@ -33,6 +33,11 @@ namespace kiwano EventListenerPtr listener ); + // 添加监听器 + EventListener* AddListener( + EventListener* listener + ); + // 添加监听器 EventListener* AddListener( EventType type,