我的(基本)Pacman游戏的OO设计

时间:2011-02-20 18:34:06

标签: oop design-patterns

我正在尝试用C ++创建一个基本的Pacman游戏(我将在这个问题中使用Java语法,因为这更容易演示),但我找不到一个好的设计选项。

到目前为止,我有4个班级:
- 怪物:可以为特定于怪物的行为进行子类化,并包含怪物的所有逻辑 - 玩家:包含玩家逻辑
- Map:包含表示地图的二维数组。该数组指定哪些位置是墙壁或吃豆子食物
- 游戏:包含玩家,地图和怪物列表。

为了简单起见:

public class Game {
  Player player;
  Map map;
  ArrayList<Monster> monsters;

  public Game() {
    player = new Player();
    map = new Map();
    monsters = new ArrayList<Monster();
    monsters.add(new ScaryMonster());
    monsters.add(new DumpMonster());
  }

  public void update() {
    player.update();
    map.update();

    for (Monster monster: monsters) {
      monster.update();
    }

  public void draw() {
    map.draw();
    player.draw();

    for (Monster monster: monsters) {
      monster.draw();
  }
}

所以我现在要做的就是每次创建一个Game对象并在其上调用update()和draw()。非常简单。但它不起作用。

假设我在玩家对象上调用update()并且玩家(这是Pacman ofcourse)命中食物。在这种情况下,应该通知地图对象(和位置)以从2d阵列中移除食物。假设玩家杀死一个怪物,怪物的位置应该改变(怪物类有一个“位置场”)。你可以想象出更多这些情况。

一个选项是将map和monster对象作为参数传递给player对象的update()和draw()方法。并在地图的方法调用中将玩家和怪物对象作为参数传递。但这肯定听起来不像是一个好的OO设计。

解决这个问题的好方法是什么?我正在考虑使用Observer模式(因此Game是主题,玩家,地图和怪物都是观察者),但这没有任何意义:观察者必须让主体知道任何变化,这是显然不是使用它的正确方法。

非常欢迎任何提示。

非常感谢:)

1 个答案:

答案 0 :(得分:4)

为什么不尝试映射操作?

每一个动作都有反应。所以,让我们说pacman打食物。这是一个动作,&#34;击中食物&#34;,反过来又有反应(通知地图,食物,或任何你喜欢的食物),食物不再存在。

现在想象一下,pacman击中了一个怪物,这是另一个动作......对此会有什么反应?好吧,它可能导致怪物死亡(调用BeDeath方法:P)或者它可能导致pacman死亡......无论它是什么,它允许你将动作链接到游戏中的反应。

这意味着游戏的逻辑,规则将在游戏类中,谁还知道所需的所有元素,并且可以与每个元素进行通信。

编辑:一个简单的例子(非常简单,因为游戏越来越复杂,你需要更好地思考行动和反应结构)

public void IGameInfo
{
  List<Monster> Monsters {get;}
  Pacman Pacman {get;}
  Map Map {get;}
}

public void ComputeReactions()
{
  foreach (actionChecker in Actions)
  {
    actionChecker.Check(gameInfo);
  }
}

public void ComputeDotEaten(IGameInfo gameInfo)
{
  foreach (dot in gameInfo.Map.Dots)
    if (pacman.location == dot.location)
      dot.MarkEaten();
}

public void ComputeMonsterEaten(IGameInfo gameInfo)
{
  foreach (Monster in gameInfo.monsters)
    if (gameInfo.pacman.location == gameInfo.monster.location &&
        gameInfo.pacman.Invulnerable)
      monster.MarkDeath();
    else
      Game.EndGame();
}

或者,如果你愿意,你也可以映射反应

public void ComputeDotEaten(IGameInfo gameInfo)
{
  foreach (dot in gameInfo.Map.Dots)
    if (pacman.location == dot.location)
      Reactions["DotEaten"].Execute(dot);
}

请注意,要使其工作,所有反应都必须共享一个共同的签名(即,将一组对象转换为预期的参数)