繁体   English   中英

重构:使游戏引擎更加模块化以及如何实现

[英]Refactoring: Making a game engine more modular and how

我的游戏引擎由一系列松散耦合的模块组成,可以加载和卸载。

一些示例是:基本模块,处理窗口管理和响应OS事件,实体管理器,Lua管理器,物理管理器。

现在,这些模块被组织为命名空间,它们的状态通过相应源文件中的局部变量来定义。 每个命名空间都有一个Open(),Close()和Update()函数。

现在,我真的不喜欢名称空间的解决方案了。

  • 它不够灵活

  • 即使在现实中可能不需要它,具有创建模块的多个实例的简单能力似乎是正确的

  • 好像我在这里没有使用OOP - 一个带有虚拟Update()成员函数的模块基类听起来更合理

  • 当模块关闭并重新打开时,更难以确保所有变量也将被重置(具有构造函数和析构函数的类将更容易)

  • 如果没有显式调用Open(),Close()和Update(),就无法正确管理模块

所以,我的想法会一直使用为每个模块,从模块基类派生。 模块类实例将由ModuleManager类处理,后者会更新它们。

但是OOP的解决方案带来了模块应该如何通信的问题。 现在,基础模块告诉控制台模块通过console::print()打印一些东西

  • 如何解决这个问题而不必使用像g_ModuleManager.GetConsoleModule()->print()

  • 这个模块管理器怎么能详细工作?

我的最后一个问题是:

  • 对于使用OOP用C ++编写模块化游戏引擎这个主题,你有什么进一步的提示吗?

  • 是否有任何设计模式可以帮助我在这种情况下,甚至可能是具体的阅读材料?

命名空间很快变得非常灵活。
保持松散耦合的一种方法是通过中央消息调度程序使用消息传递; 而不是说console::print你会说messenger->sendMessage(PRINT_MESSAGE, stuffToPrint)
控制台会将自己注册为PRINT_MESSAGE的监听器,并以其想要的方式运行。 发送者不需要关心某人是否在监听,每个消息甚至可能有几个监听器(对调试很有用)。

关于阅读材料,杰森格雷戈里的“游戏引擎架构”非常好,讨论了几种架构的优缺点。

首先作为一般提醒,只记得使用继承来代替可替代性,而不是代码重用。 粗略地说,这意味着从您的基础模块继承的任何东西都需要支持(大部分)相同的操作,并且如果用户说任何模块上的opencloseupdate ,它将提供预期的结果。

你真的想要一个模块经理吗? 可能更好的是绘制不同类/模块之间关系的图表,并在那里创建链接而不是顶级经理。 然后应用程序的主循环将知道一个或多个高级模块并直接调用它们上的相应方法。 如果需要,甚至可以有一个高级模块来管理这种高级别的授权。

对于您的控制台示例,假设您不想支持多个控制台,您可能最好只保留命名空间:它使您能够直接引用您正在连接的单个控制台。 或者,您可以要求将“父控制台”传递给创建的每个模块,并使用该关联控制台根据需要执行其I / O. 这为您提供了更大的灵活性,但需要确保您必须在基础模块中维护控制台。

g_ModuleManager.GetConsoleModule()->print()

很简单,如前所述,你很可能不得不重构很多东西来利用OOP。 你希望每个班级都有一个独特的关系,而不是所有人都在平等的竞争环境中进行管理。 告诉ConsoleModule要打印的人应该有自己的打印功能,告诉ConsoleModule打印。 这样你就说print()

也认为在“有一个”的组成和“是一个”的继承。 我会阅读整个第8节: http//www.learncpp.com/cpp-tutorial/81-welcome-to-object-oriented-programming/

作为我当前项目的一个例子:我有一块“有” beatleswallsapples的板子。 每个“都是” icon

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM