欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

游戏开发模式一:组件模式(Component)

发布时间:2025/3/15 42 豆豆
生活随笔 收集整理的这篇文章主要介绍了 游戏开发模式一:组件模式(Component) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

软件设计模式告诉我们,程序中不同的领域要保持隔离,也就是解耦。所以,我们不希望AI,物理引擎,渲染引擎,声音引擎,还有其他的事情影响到彼此,不能把他们放到同一个类里。

下面是一个反例:

if (collidingWithFloor() && (getRenderState() != INVISIBLE)) {playSound(HIT_FLOOR); }

如果有人要修改这段代码,那么他就需要查看物理,绘图,和声音的代码以保证不会出错。更糟糕的情况是,你可能需要修改其他部分的代码!

 

解决的办法:

我们可以吧不同的领域分割城不同的组件,谈后需要的时候持有这些组件的实例,例如 InputComponent。

 

再看一个难一点的例子:

class Bjorn { public:void update(World& world, Graphics& graphics){// Apply user input to hero's velocity.switch (Controller::getJoystickDirection()){case DIR_LEFT: velocity_ -= WALK_ACCELERATION; break;case DIR_RIGHT: velocity_ += WALK_ACCELERATION; break;}// Modify position by velocity.x_ += velocity_;world.resolveCollision(volume_, x_, y_, velocity_);// Draw the appropriate sprite.Sprite* sprite = &spriteStand_;if (velocity_ < 0) sprite = &spriteWalkLeft_;else if (velocity_ > 0) sprite = &spriteWalkRight_;graphics.draw(*sprite, x_, y_);}private:static const int WALK_ACCELERATION = 1;int velocity_;int x_, y_;Volume volume_;Sprite spriteStand_;Sprite spriteWalkLeft_;Sprite spriteWalkRight_; };

Bjorn 有一个 update()方法每一帧被调用一次。它获取determine来决定方向,谈后他用物理引擎来处理位置,最后,它把Bjørn绘制到屏幕上。可以看到这里其实只做了很少的事情,但是却显得很复杂。

 

分割不同的领域:

首先让我们把input分离:

class InputComponent { public:void update(Bjorn& bjorn){switch (Controller::getJoystickDirection()){case DIR_LEFT: bjorn.velocity -= WALK_ACCELERATION; break;case DIR_RIGHT: bjorn.velocity += WALK_ACCELERATION; break;}}private:static const int WALK_ACCELERATION = 1; };

Bjorn的变化:

class Bjorn { public:int velocity;int x, y;virtual void update(World& world, Graphics& graphics){input_.update(*this);// Modify position by velocity.x += velocity;world.resolveCollision(volume_, x, y, velocity);// Draw the appropriate sprite.Sprite* sprite = &spriteStand_;if (velocity < 0) sprite = &spriteWalkLeft_;else if (velocity > 0) sprite = &spriteWalkRight_;graphics.draw(*sprite, x, y);}private:InputComponent input_;Volume volume_;Sprite spriteStand_;Sprite spriteWalkLeft_;Sprite spriteWalkRight_; };

  然后我们把其他的组件都分离:

class PhysicsComponent { public:void update(Bjorn& bjorn, World& world){bjorn.x += bjorn.velocity;world.resolveCollision(volume_, bjorn.x, bjorn.y, bjorn.velocity);}private:Volume volume_; };

  

class GraphicsComponent { public:void update(Bjorn& bjorn, Graphics& graphics){Sprite* sprite = &spriteStand_;if (bjorn.velocity < 0) sprite = &spriteWalkLeft_;else if (bjorn.velocity > 0) sprite = &spriteWalkRight_;graphics.draw(*sprite, bjorn.x, bjorn.y);}private:Sprite spriteStand_;Sprite spriteWalkLeft_;Sprite spriteWalkRight_; };

  现在Bjorn变得很简洁:

class Bjorn { public:int velocity;int x, y;virtual void update(World& world, Graphics& graphics){input_.update(*this);physics_.update(*this, world);graphics_.update(*this, graphics);}private:InputComponent input_;PhysicsComponent physics_;GraphicsComponent graphics_; };

  

现在我们已经把不同的组件都分开了,但是Bjorn依然知道这些行为的具体实现。我们将把我们的组件隐藏在借口背后,这样就需要把InputComponent变成一个抽象类:

class InputComponent { public:virtual void update(Bjorn& bjorn) = 0; };

  然后实现它:

class PlayerInputComponent : public InputComponent { public:virtual void update(Bjorn& bjorn){switch (Controller::getJoystickDirection()){case DIR_LEFT: bjorn.velocity -= WALK_ACCELERATION; break;case DIR_RIGHT: bjorn.velocity += WALK_ACCELERATION; break;}}private:static const int WALK_ACCELERATION = 1; };

我们将持有一个InputComponent的指针,

class Bjorn { public:int velocity;int x, y;Bjorn(InputComponent* input): input_(input){}virtual void update(World& world, Graphics& graphics){input_->update(*this);physics_.update(*this, world);graphics_.update(*this, graphics);}private:InputComponent* input_;PhysicsComponent physics_;GraphicsComponent graphics_; };

  现在我们可以传入一个InputComponent来实例化Bjorn:

Bjorn* bjorn = new Bjorn(new PlayerInputComponent());

  来看看InputComponent的另一个实现:

class DemoInputComponent : public InputComponent { public:virtual void update(Bjorn& bjorn){// AI to automatically control Bjorn...} };

  

 

好了,最后让我们看看最简介的一般实现:

我们有两个component:

class PhysicsComponent { public:virtual void update(GameObject& obj, World& world) = 0; };class GraphicsComponent { public:virtual void update(GameObject& obj, Graphics& graphics) = 0; };

  一个GameObject:

class GameObject { public:int velocity;int x, y;GameObject(InputComponent* input,PhysicsComponent* physics,GraphicsComponent* graphics): input_(input),physics_(physics),graphics_(graphics){}virtual void update(World& world, Graphics& graphics){input_->update(*this);physics_->update(*this, world);graphics_->update(*this, graphics);}private:InputComponent* input_;PhysicsComponent* physics_;GraphicsComponent* graphics_; };

  

 

 

 

 

 

 

转载于:https://www.cnblogs.com/shangdahao/archive/2013/04/02/2995051.html

总结

以上是生活随笔为你收集整理的游戏开发模式一:组件模式(Component)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。