我正在尝试用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是主题,玩家,地图和怪物都是观察者),但这没有任何意义:观察者必须让主体知道任何变化,这是显然不是使用它的正确方法。
非常欢迎任何提示。
非常感谢:)
答案 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);
}
请注意,要使其工作,所有反应都必须共享一个共同的签名(即,将一组对象转换为预期的参数)