1

我目前正在开发一个游戏,其中我有几个类,每个类都处理自己的游戏对象。为了让这些类真正代表游戏中的某些东西,他们需要使用另一个类,即动画管理器。animation_manager 处理屏幕上对象的加载、绘制和移动,并在启动时创建。

将管理器传递给处理游戏对象的类的最聪明的方法是什么?

它应该由公共指针完成,通过将它分配给每个游戏对象继承的对象类中的静态指针,还是我应该简单地将它作为指针传递给游戏对象/对象类构造函数?

我正在使用 C++03,所以没有新的花哨修复:P

编辑1:

有很多好的建议,我对此表示感谢。现在我不会使用弱指针,因为我不需要对象处理程序来处理指针的删除,因为它从程序的开始到结束都存在。单身人士也不适合我的需求,因为我不希望任何班级都可以访问它。

阅读回复时想到的一件事是:为所有处理类继承的in做一个static referencefor the是个好主意吗?anim_handlerObject class

4

7 回答 7

0

我更喜欢构造函数的传递。

通过这种方式,您可以建立一个不变量(即经理始终存在),而稍后设置一个字段并不能确保它总是完成。

就像刚刚发布的 thomas 一样,您应该使用 ashared_ptr或类似的东西(如果不使用 C++11)。

我尽量不使用静态字段(常量除外),因为它会阻止您为每个游戏对象使用不同的管理器对象。(想想调试/日志管理器类,或另一个包装的管理器)。

于 2013-07-29T06:37:48.320 回答
0

我正在添加另一个答案,因为与以前的方法相比,它是一种完全不同的方法。首先我要澄清一下我在游戏编程方面没有经验!:) 无论如何,正如我在之前的评论中所建议的那样,也许我会采取不同的路线。想象一下,你有一个带有墙壁和其他静态元素的“游戏场”,以及一些“演员”,比如怪物、玩家改变自我等等……我可能会写一个祖先“演员”,子类化“玩家” " 和 "Enemy" 类,然后将 "Enemy" 子类化为 "Dragon"、"Zombie"、"Crocodile" 等等。也许 Actor 可以有很多共同的属性,比如“位置”、“速度”、“力量”、“能量”、“方向”、“

1) 从玩家那里获得输入

2)调用玩家actor对象的方法,例如:

player->move(east, fast);

3)循环遍历演员列表以更新其状态,例如:

for (int i(0); i < enemies.size(); i++) {
    // Checks the player position in the gamefield and setup a strategy to eat him
    enemies[i]->updateStatus(player, gamingField);
}

4) 在演员列表中循环并移动他们:

animator->animate(player);
for (int i(0); i < enemies.size(); i++) {
    animator->animate(enemies[i]);
}

5)检查是否发生了有趣的事情(玩家被鳄鱼吃掉了)

我的意思是:这是一种完全不同的方法,但我认为隔离参与者逻辑可能是一个好主意,您可以完全避免最初的问题。

于 2013-07-30T10:11:58.637 回答
0

如果您的 animator_manager 是一个独特的对象,另一种方法可能是将其定义为一个 signleton,最终消除了在游戏对象处理类中存储对它的任何引用并使用某种静态方法(如 animation_manager::getInstance() 来使用它)的需要.

通过减少对 getInstance() 方法的调用,可以轻松地将性能影响降至最低,但这实际上取决于您的设计,不能确定它是否适合。

于 2013-07-29T06:47:07.717 回答
0

你应该把它作为一个参考(如果可能的话,一个 const 的参考),而不是一个指针。仅当您拥有动画管理器的类层次结构时,指针(如果可能,指向 const)才有意义。在后一种情况下,您应该考虑使用 boost's shared_ptr。如果稍后移至 C++11,则对 C++11 的 shared_ptr 的更改很小。

从设计的角度来看,您可能还考虑使用观察者模式,因此动画管理器可以自行决定何时是渲染的正确时间,而无需太多样板代码。

于 2013-07-29T07:03:03.507 回答
0

您可以将此共享管理器对象保存在作为shared_ptr添加到 C++11(或者您可以使用 Boost 库)标准的共享指针中。

它具有引用计数机制,因此您不必担心相关对象的所有权和内存管理。

每个gameobject人都可以为您的animation_manager.

于 2013-07-29T06:33:42.087 回答
0

作为一名优秀的软件架构师,传递参考资料将是最有利的方式,因为它可以更轻松地进行测试和模拟。

然而,在我看来,游戏(引擎)是这样一种特殊的软件案例,其中“好的模式”有时会适得其反。您几乎总是会遇到到处都需要一些经理课程的情况。

您可能想查看上帝对象反模式,以使所有通用管理器在全球范围内可用。我使用一个(!)全局可访问的“应用程序”实例,其中包含一些引导代码和对最常见管理器类的引用,如下所示:

// application.h
class CApplication {
    void init(int argc, char **argv); // init managers & co here 
    void shutdown();
    void run();

    CMemoryManager * memory;
    CSystemManager * system;
    CAudioManager  * sound;
    CInputManager  * input;
};

// globals.h
CApplication * app;


// main.c
#include "globals.h"
int main(int argc, char ** argv) {
    app = new CApplication();
    app->init(argc, argv);
    app->run();
    app->shutdown();
    return 0;
}

// some_other_file.cpp
#include "globals.h"

void doSomething() {
    // ...
    app->input->keyDown(...);
    // ...
}

画风不好?大概。它有效吗?对我来说确实如此。也欢迎反馈作为评论!

于 2013-07-29T07:38:38.607 回答
0

在我看来,这个问题没有明确的答案,而是有多种方法,每个人都有自己的看法。如果其他人有同样的问题,我将在下面列出:

Shared_Pointer: 此方法将跟踪指向该地址的已使用指针的数量,如果该计数为零,则它将释放内存。在 C++11 和 boost 库中可用。共享指针可以像普通指针一样传递给其他对象。

由 ogni42 推荐

由构造函数传递: 可以在构造对象时将指针或引用传递给对象。使用引用的好处是程序员不会意外地delete在指针上使用。

Onur 的首选。

单例的使用 Singletons是一个独特的外部类,它包含一个指向可以通过函数访问的对象的指针。

这是阿尔伯特建议的

全局变量 简单的一个全局声明的变量。就我个人而言,我不推荐这些,因为即使从不需要它们的代码中也可以使用它们,因为它们可能会变得一团糟。

由 PanCake 爵士推荐

静态变量 这是我最终使用的。我这样做是为了只有从我的Object类继承的对象才能访问 anim_handler。我这样做的方法是声明Object我的 anim_handler 的朋友,然后我创建了静态变量来检索处理程序protected

总之谢谢大家的支持!我非常感谢它,我什至学到了一些新东西!:)

于 2013-08-02T08:00:10.440 回答