你的位置:首页 > ASP.net教程

[ASP.net教程]《游戏编程模式》(2)

Chatper 2 命令模式

命令是一个具象化(实例化)的方法调用。

A command is a reified method call.

 

定义一个基类,命令的控制对象由参数传入

1 class Command2 {3 public:4  virtual ~Command() {}5  virtual void execute(GameActor& actor) = 0;6 };

 

为不同的游戏命令创建子类:

1 class JumpCommand : public Command2 {3 public:4  virtual void execute(GameActor& actor)5  {6   actor.jump();7  }8 };

 

在输入处理中,为每个按钮存储一个指针,绑定一个命令,且可以灵活替换新的命令

 1 class InputHandler 2 { 3 public: 4  void handleInput(); 5  6  // Methods to bind commands... 7  8 private: 9  Command* buttonX_;10  Command* buttonY_;11  Command* buttonA_;12  Command* buttonB_;13 };

 


现在,输入处理返回一个命令指针:

 1 Command* InputHandler::handleInput() 2 { 3  if (isPressed(BUTTON_X)) return buttonX_; 4  if (isPressed(BUTTON_Y)) return buttonY_; 5  if (isPressed(BUTTON_A)) return buttonA_; 6  if (isPressed(BUTTON_B)) return buttonB_; 7  8  // Nothing pressed, so do nothing. 9  return NULL;10 }

 


接收命令并让角色执行:

1 Command* command = inputHandler.handleInput();2 if (command)3 {4  command->execute(actor);5 }

对游戏中的AI对象也可以简单地提供命令对象以供执行。

空对象模式:在这里可以提供一个什么都不做的命令。

 

撤销和重做:

execute中记录上一次的位置:

 1 class Command 2 { 3 public: 4  virtual ~Command() {} 5  virtual void execute() = 0; 6  virtual void undo() = 0; 7 }; 8 class MoveUnitCommand : public Command 9 {10 public:11  MoveUnitCommand(Unit* unit, int x, int y)12  : unit_(unit),13   xBefore_(0),14   yBefore_(0),15   x_(x),16   y_(y)17  {}18 19  virtual void execute()20  {21   // Remember the unit's position before the move22   // so we can restore it.23   xBefore_ = unit_->x();24   yBefore_ = unit_->y();25 26   unit_->moveTo(x_, y_);27  }28 29  virtual void undo()30  {31   unit_->moveTo(xBefore_, yBefore_);32  }33 34 private:35  Unit* unit_;36  int xBefore_, yBefore_;37  int x_, y_;38 };

多次撤销可以维护一个命令列表和对当前命令的一个引用。

 

 

Chapter 3 享元模式

将数据对象切分成两种类型:

  1. 不属于单一实例对象并能被所有对象共享的数据;
  2. 对每个对象都是唯一的数据。

 

地形类:

 1 class Terrain 2 { 3 public: 4  Terrain(int movementCost, 5      bool isWater, 6      Texture texture) 7  : movementCost_(movementCost), 8   isWater_(isWater), 9   texture_(texture)10  {}11 12  int getMovementCost() const { return movementCost_; }13  bool isWater() const { return isWater_; }14  const Texture& getTexture() const { return texture_; }15 16 private:17  int movementCost_;18  bool isWater_;19  Texture texture_;20 };

 


使用指向地形对象的网格指针,相同地形的瓦片指向同一地形实例:

 1 class World 2 { 3 public: 4  World() 5  : grassTerrain_(1, false, GRASS_TEXTURE), 6   hillTerrain_(3, false, HILL_TEXTURE), 7   riverTerrain_(2, true, RIVER_TEXTURE) 8  {} 9 10 private:11  Terrain grassTerrain_;12  Terrain hillTerrain_;13  Terrain riverTerrain_;14 15 Terrain* tiles_[WIDTH][HEIGHT];16  // Other stuff...17 };

 


使用这些地形实例来绘制地面:

 1 void World::generateTerrain() 2 { 3  // Fill the ground with grass. 4  for (int x = 0; x < WIDTH; x++) 5  { 6   for (int y = 0; y < HEIGHT; y++) 7   { 8    // Sprinkle some hills. 9    if (random(10) == 0)10    {11     tiles_[x][y] = &hillTerrain_;12    }13    else14    {15     tiles_[x][y] = &grassTerrain_;16    }17   }18  }19 20  // Lay a river.21  int x = random(WIDTH);22  for (int y = 0; y < HEIGHT; y++) {23   tiles_[x][y] = &riverTerrain_;24  }25 }

 


获得(x,y)下的地形及属性:

1 const Terrain& World::getTile(int x, int y) const2 {3  return *tiles_[x][y];4 }5 int cost = world.getTile(2, 3).getMovementCost();

 

 

Chatper 4 观察者模式

观察者模式非常适合于一些不相关模块之间的通信(成就系统,新手引导)。

 

观察者:

 1 class Observer 2 { 3 public: 4  virtual ~Observer() {} 5  virtual void onNotify(const Entity& entity, Event event) = 0; 6 }; 7 class Achievements : public Observer 8 { 9 public:10  virtual void onNotify(const Entity& entity, Event event)11  {12   switch (event)13   {14   case EVENT_ENTITY_FELL:15    if (entity.isHero() && heroIsOnBridge_)16    {17     unlock(ACHIEVEMENT_FELL_OFF_BRIDGE);18    }19    break;20 21    // Handle other events, and update heroIsOnBridge_...22   }23  }24 25 private:26  void unlock(Achievement achievement)27  {28   // Unlock if not already unlocked...29  }30 31  bool heroIsOnBridge_;32 };

 


被观察者:

 1 class Subject 2 { 3 private: 4  Observer* observers_[MAX_OBSERVERS]; 5  int numObservers_; 6 }; 7 class Subject 8 { 9 public:10  void addObserver(Observer* observer)11  {12   // Add to array...13  }14 15  void removeObserver(Observer* observer)16  {17   // Remove from array...18  }19 20  // Other stuff...21 };22 class Subject23 {24 protected:25  void notify(const Entity& entity, Event event)26  {27   for (int i = 0; i < numObservers_; i++)28   {29    observers_[i]->onNotify(entity, event);30   }31  }32 33  // Other stuff...34 };

 

单链表写法(避免造成动态内存分配):

 1 class Subject 2 { 3  Subject() 4  : head_(NULL) 5  {} 6  7  // Methods... 8 private: 9  Observer* head_;10 };11 class Observer12 {13  friend class Subject;14 15 public:16  Observer()17  : next_(NULL)18  {}19 20  // Other stuff...21 private:22  Observer* next_;23 };24 void Subject::addObserver(Observer* observer)25 {26  observer->next_ = head_;27  head_ = observer;28 }29 void Subject::removeObserver(Observer* observer)30 {31  if (head_ == observer)32  {33   head_ = observer->next_;34   observer->next_ = NULL;35   return;36  }37 38  Observer* current = head_;39  while (current != NULL)40  {41   if (current->next_ == observer)42   {43    current->next_ = observer->next_;44    observer->next_ = NULL;45    return;46   }47 48   current = current->next_;49  }50 }51 void Subject::notify(const Entity& entity, Event event)52 {53  Observer* observer = head_;54  while (observer != NULL)55  {56   observer->onNotify(entity, event);57   observer = observer->next_;58  }59 }

C#:event关键字,观察者成为一个代理。