我目前正在制作一个游戏,我有几个类,每个类都处理自己的游戏对象。为了让这些类实际上代表游戏中的某些东西,他们需要使用另一个类,即animation_manager。 animation_manager处理在屏幕上加载,绘制和移动对象,并在启动时创建。
将经理传递给处理游戏对象的类最聪明的方法是什么?
是否应该通过公共指针完成,将其分配给每个游戏对象继承的对象类中的静态指针,或者我只是将其作为指向gameobjects / objects类构造函数的指针传递?
我正在使用C ++ 03,因此没有新的花哨修复:P
编辑1:
有很多好的建议,我很感激。 现在我不会使用弱指针,因为我不需要对象处理程序来处理指针的删除,因为它将从程序的开头到结尾存在。 单身人士不适合我的需要,因为我不希望任何课程有权使用它。
阅读回复时想到的一件事是:为所有处理类继承的static reference
中的anim_handler
创建Object class
是否是个好主意?
答案 0 :(得分:0)
您可以将此共享管理器对象保存在共享指针中,该指针将添加到C ++ 11(或者您可以使用Boost库)标准shared_ptr。
它有一个引用计数机制,这样您就不必担心相关对象的所有权和内存管理。
每个gameobject
都可以将共享指针成员保留到animation_manager
。
答案 1 :(得分:0)
我更喜欢传递构造函数。
这样你可以建立一个不变量(即经理总是存在),而后来设置一个字段并不能确保它始终完成。
就像刚发布的托马斯一样,你应该使用shared_ptr
或类似的东西(如果没有使用C ++ 11)。
我尽量不使用静态字段(常量除外),因为它会阻止您为每个游戏对象使用不同的管理器对象。 (想想一下调试/日志记录管理器类或其他包装管理器)。
答案 2 :(得分:0)
如果你的animator_manager是一个唯一的对象,另一种方法可能是将它定义为一个signleton,最终不需要在gameobjects处理类中存储对它的任何引用,并使用某种静态方法,如animation_manager :: getInstance()使用它。
通过减少对getInstance()方法的调用,可以轻松地降低性能影响,但这实际上取决于您的设计,不能确定它是否合适。
答案 3 :(得分:0)
你应该把它作为参考(如果可能的话,引用const),而不是指针。只有当你有一个动画管理器的类层次结构时,一个指针(如果可能的话const到const)才有意义。在后一种情况下,您应该考虑使用boost shared_ptr
。如果稍后转到C ++ 11,对C ++ 11的shared_ptr的更改是最小的。
从设计的角度来看,您可能还会考虑使用观察者模式,因此动画管理器可以在适当的时候进行渲染,而不需要太多的样板代码。
答案 4 :(得分:0)
在考虑成为优秀的软件架构师时,传递引用将是最有利的方式,因为它将允许更容易的测试和模拟。
然而,在我看来,游戏(引擎)是一个特殊的软件案例,其中“好的模式”有时会适得其反。几乎总是会遇到你需要一些经理课程的情况。
您可能希望查看神对象反模式,以使全球所有常见经理都可用。我使用一个(!)全局可访问的“Application”实例实例,它包含一些引导代码和对最常见管理器类的引用,如下所示:
// 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(...);
// ...
}
风格不好?大概。它有用吗?对我来说确实如此。反馈也欢迎评论!
答案 5 :(得分:0)
我正在添加另一个答案,因为与之前的方法相比,这是一种完全不同的方法。 首先,我应该澄清一点,我没有游戏编程的经验! :) 无论如何,正如我在之前的评论中所建议的那样,也许,我会采取不同的方式。想象你有一个带有墙壁和其他静态元素的“游戏场”,以及一些“演员”,如怪物,玩家改变自我等等...... 我可能会写一个祖先“演员”,主要是“玩家”和“敌人”类,然后将“敌人”子类化为“龙”,“僵尸”,“鳄鱼”等等。也许演员可以有一个共同的属性,如“位置”,“速度”,“强度”,“能量”,“方向”,“目的地”和状态,说“移动”,“睡觉”,“吃”玩家“,”被吃掉“...... 一个典型的游戏迭代,可能是这样的:
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)检查是否发生了有趣的事情(玩家被鳄鱼吃掉了)
我的意思是:这是一种完全不同的方法,但我认为隔离演员逻辑可能是一个好主意,你可以完全避免原来的问题。
答案 6 :(得分:0)
在我看来,这个问题没有明确的答案,而是多种方式,每个人都有自己的意见。 如果其他人有同样的问题,我将在下面列出:
<强> Shared_Pointer:强> 此方法将跟踪指向地址的已使用指针的数量,如果该计数达到零,则它将释放内存。可在C ++ 11和boost库中使用。 共享指针可以像普通指针一样传递给其他对象。
建议ogni42
由构造函数传递:
指针或引用可以在构造时传递给对象。使用引用的好处是程序员不会在指针上意外使用delete
。
首选Onur。
使用单身人士
Singletons
是一个唯一的extern类,它包含一个指向对象的指针,可以通过函数访问该对象。
这是由Albert
提出的全局变量 只是一个全局声明的变量。就个人而言,我不推荐这些,因为它们可能变得一团糟,因为它们甚至可以从您不需要它们的代码中获得。
PanCake先生建议
静态变量
这就是我最终使用的。我这样做只有从Object
类继承的对象才能访问anim_handler。我这样做的方法是声明Object
我的anim_handler的朋友,然后我创建静态变量来检索处理程序protected
无论如何,感谢大家的支持!我很欣赏它,我甚至学到了新东西! :)