C ++ / OOP游戏设计

时间:2012-12-02 18:15:08

标签: c++ sfml

我正在通过使用SFML和OpenGL制作一款小游戏来练习我的新手c ++技能。编程部分在大多数情况下都很好,但我对实际的代码/类设计有疑问。

我有一个类,MainLoop,它包含游戏循环并拥有以下每个类的一个实例:事件,图形,命令,游戏和UI。我最初希望所有这些都是一个单独的类(在不同的.cpp文件中分隔函数),但被告知这是OOP / C ++的错误方法。然而,虽然我可以看到分离它们的好方面(封装,模块化,调试),但我似乎也遇到了很多不好的东西。让我举一个用户按下UI按钮的例子。

首先,MainLoop从SFML的窗口类中获取事件。 MainLoop将它发送到我自己的Event类,该类解释事件并将其发送到UI类以检查它是否“命中”了任何按钮。如果为true,则UI类将其发送到Command类,该类解释按钮命令。然后,最后,命令类将其发送到Game类或其他任何需要去的地方。

这对我来说似乎非常苛刻,并且至少我此刻一直在做的方式,还需要很多前瞻性声明(在我了解到那些我最终以大量的循环依赖)。我怀疑它对性能有好处。

无论如何,这里有一些我不知道的伎俩吗?这些课程应该如何联系,他们应该如何沟通?我应该如何将命令从事件类转发到UI类?我是否真的应该在任何地方都有前瞻性声明,包含和内容,这不会破坏模块化吗?我是否应该通过MainLoop类运行并使用不需要声明的整数/浮点数/字符转发返回值?我在这里有点不知所措。

2 个答案:

答案 0 :(得分:4)

我可以建议你在开发游戏时使用的一些设计,虽然它们并不是什么好东西但是我从来没有遇到过很多问题。我会简短地告诉你这个想法。

首先,你需要一个视图管理器,这个管理器应该管理游戏的当前视图,这可以作为一堆视图或其他任何东西来实现。因此,您将拥有一个ViewManager课程,该课程了解您游戏的所有视图,并能够将内容发送到当前的视图。

然后你需要一个抽象类GameView,它应该提供来自外部的基本界面,如:

  • drawMe(),用于绘制视图
  • receivedMouseEvent(Event e),将接收鼠标事件
  • activate()deactivate()执行在视图管理器中推送或弹出视图时应执行的操作

现在有了这个抽象类,您应该实现游戏的任何特定视图或视图的一部分,以便您可以在视图堆栈中推送它们。

一个好处是让子类来管理UI元素,例如,类ActiveArea响应点击,Button继承自ActiveArea,它也能够提供两个状态图形。这些元素应包含在可点击元素列表中,这些元素存储在抽象视图中,以便每个具体视图都可以将其按钮添加到常见实现中而不必担心。通过这种方式,您可以获得类似(元代码)

的内容
void AbstractView::receiveEvent(Event e) {
  for (ActiveArea *area in areas)
    if (area.isInside(e)) {
      area->action();
      return;
    }

  innerReceiveEvent(e); //which should be a pure virtual function that will call a method specified in concrete views
}

通过这种方式,您将拥有管理自己状态的每个视图,以及负责绘制和管理事件的视图管理器,例如

void ViewManager::draw() {
  for (AbstractView *view in views) // from top to bottom of the stack
    view.draw();
}

答案 1 :(得分:3)

我可以想象它似乎很重,但这是正确的方法。请注意,函数调用根本不重,它确实使整个事情更容易阅读。或者至少它应该。 ; - )

每个类都应该有一个包含类定义的头文件,但不包含其成员函数的实现。任何文件都应该能够包含任何类头文件。只有当您使用模板(实现必须在头文件中)时,可能存在循环依赖关系,但从您的描述中我不认为您拥有它们。标题不需要包含彼此。如果需要在函数参数中传递指针或引用其他类,可以在头文件的开头转发声明其他类。您应该能够在源文件的顶部包含任何包含。如果没有,请提供更多信息,说明您认为在您的案例中需要这样做的原因。