帮助程序设计

时间:2010-11-23 17:45:59

标签: java class-design loose-coupling cohesion

我目前正在创建一个简单的基于控制台的游戏,玩家可以在不同的房间之间移动,拿起和使用物品,以及吃食物。在游戏的当前状态是关于它的。

我需要帮助的是:

为我的游戏创建一个好的“事件”类。我希望它的工作方式是每个项目和房间都应该能够与一个事件相关联。

由于我是新手,我会欣赏与此类程序相关的任何阅读材料,或者建议考虑以下几点如何最好地设置我的课程,或者只是如何解决这类问题(在决定如何设置类时遇到问题)

我希望能够创建不同类型的事件,例如:

  • 输出一些文字,然后向玩家提问。如果玩家给出了正确答案,请做点什么。

  • 输出一些文字,然后从播放器的广告资源中删除一个项目,然后将播放器移到另一个房间。

我想避免的事情:

  • 游戏的重点是练习良好的课堂设计,因此责任驱动设计,凝聚力和耦合等方面都是重要的方面。因此,我希望它尽可能简单,可重复和独立。

  • 必须对每个事件进行硬编码,以便项目或房间只调用Event类中的特定方法。

目前我在想什么:

创建一些子类,以便我可以使用以下方法创建新事件(并将它们关联起来): itemObject.setEvent(new Event(new Question(“introText”,“outroText”,“correctAnswer”)));

如果需要更多信息,请与我们联系! 谢谢!

4 个答案:

答案 0 :(得分:2)

我要考虑的一件事是将输入文本的解析与底层域模型的输出文本生成分开。你的问题似乎将两者混合在一起,而我会将问题的文本部分视为表示层。

例如,您的域可以包含以下接口:

public enum Action { HIT, TALK_TO, EAT, USE };

public interface GameEntity {
  /**
   * Performs the specified action on this GameEntity, passing in zero or
   * more other GameEntity instances as parameters.
   */
  void applyAction(Action action, GameEntity... params);    
}

public interface Item extends GameEntity { }
public interface Person extends GameEntity { }

此外,您可以定义一个TextParser类,它将处理输入字符串并对域图层进行调用,或者返回默认响应:“我不明白。”。例如,输入短语“门上的使用键”将导致方法调用:

key.applyAction(Action.USE, door);

答案 1 :(得分:2)

游戏编程宝石书很棒......虽然有点贵。

您可以在GameDev's Article list上找到相关的一两篇文章,而their forums

中可能存在一些好东西。

对于Event类,您几乎肯定需要一个具有一定数量子类的基类(MoveEvent,InventoryEvent等)。如果你真的想要避免硬编码,你应该在数据文件中定义你的游戏。房间,物品和活动......以及您稍后再提出的任何其他内容。用于定义事物的格式完全取决于您。我推荐一些能给你实际经验的东西,因为这是一个学习练习:例如你没有用过的XML解析器。不是最有效的解析格式,但这是一个控制台游戏,所以这不是一个问题。

我对Event子类的一个建议是可以将其他事件链接在一起的建议。界面不会改变,它允许你做一些事情,比如“将它添加到玩家的库存中,把它拿走,然后将它们移到这里”。

答案 2 :(得分:2)

在谈到事件时,我会想到observer pattern 。您可以将您的游戏视为由多个状态机内部呈现(您也可以在维基百科上查看,我不能自己添加第二个链接,因为它是SO的新手)。从一个阶段到另一个阶段的每次转换都是一个事件,可以传达给该事件的注册观察员。

例如:

锁定时使用钥匙:触发钥匙和门的开启;在没有额外的用户交互(开门)的情况下隐含地“级联”到下一个事件:触发房间有额外的退出等。

答案 3 :(得分:1)

我最近实现了类似于你所描述的内容。我首先创建了一个具有“发布”和“订阅”方法的EventManager类。当系统启动时,它会扫描所有已加载的程序集(库)以查找实现IEventListener接口的类:

/// <summary>
/// A class that intends to listen for specific events to be published by an
/// event manager.
/// <see cref="EventManager"/>
/// </summary>
public interface IEventListener
{
    /// <summary>
    /// Subscribes to the event types that this listener wishes to listen for.
    /// </summary>
    /// <param name="eventManager"></param>
    void RegisterSubscriptions(EventManager eventManager);
}

...并在每个上调用RegisterSubscriptions方法。 (EventManager中只有一个实例可以在任何地方使用;我使用依赖注入将其绑定为单例实例。)

RegisterSubscriptions将简单地为每个事件类型和给定类要处理的处理程序调用Subscribe方法。 (我正在使用.NET,因此事件和处理程序更容易使用,但您可以使用匿名子类在Java中执行相同的操作。)

典型的事件可能类似于RoomEntered,与此事件相关联的参数将包括房间ID以及房间的其他一些属性。当用户进入房间时,游戏引擎发布此事件,为该房间提供适当的事件参数,然后EventManager类负责调用已订阅该事件类型的每个处理程序。此事件的一个处理程序可能是“HandleEnterRoomWithMonsters”,它会检查房间是否有怪物,并相应地执行操作。

这总体上有意义吗?您对此方法有任何疑问吗?