我正在尝试使用C ++创建一个Breakout克隆,因此有几个对象(如ball,paddle,powerupicon,block等)。我知道将它们放在全局范围内是不好的做法,所以它们在main()中初始化。问题在于需要从其他函数(如redraw()或reset_game())中对这些对象进行处理。我能想到的唯一方法就是将对象的引用传递给每个函数,但我不确定这是否是最好的方法。
基本上,从函数中处理这些对象的最佳方法是什么?通过参考传递它们?使它们全局但在命名空间内?还是完全不同的东西?
答案 0 :(得分:2)
一种简单的(不一定是灵活的或强大的)方法是定义一个基类game_object
类,用于定义与游戏对象的接口,并存储它们。你的对象继承它。:
class game_object
{
public:
virtual ~game_object() {}
virtual void update() = 0;
virtual void draw() = 0;
// get and set position
virtual vector3 position() = 0;
virtual void position(const vector3&) = 0;
// etc...
};
class ball : public game_object
{
public:
void update() { /* update the ball */ }
void draw() { /* draw the ball */ }
// etc
};
// etc
现在您有一种使用游戏对象的常用方法。接下来,您可以将它们存储在地图中(如果您有Boost,TR1或C ++ 0x),最好将其存储在unordered_map
中,并使该地图全局可用:
// game_object_manager.h
typedef std::map<std::string, game_object*> game_object_manager;
extern game_object_manager manager;
您可以在某处翻译单元(main.cpp
或game_object_manager.cpp
)中对此进行定义。最后,您可以通过按名称插入内容来使用它:
// somewhere, add the ball
manager.insert(std::make_pair("ball", new ball()));
并使用它:
game_object* b = manager["ball"];
if (!b) /* there is no ball object */
// use b as ball */
同样,这是一个简单的解决方案,不一定是健壮的,最佳实践或灵活的。但对于第一场比赛,它会很好。 (为了改进它,你想要研究异常安全,智能指针和其他东西(游戏书籍)。我建议你在尝试制作游戏之前这样做。)
答案 1 :(得分:1)
引自cppreference:
static 关键字可以通过四种不同的方式使用:
还有其他例子。
void foo()
{
static int counter = 0;
cout << "foo has been called " << ++counter << " times\n";
}
int main()
{
for( int i = 0; i < 10; ++i )
foo();
}
答案 2 :(得分:0)
如果它正在初始化您担心的顺序,您可以在全局范围内指向它们,可能在命名空间中,并在main中为它们分配内存。
答案 3 :(得分:0)
游戏编程模式中Singletons的章节可以帮助您,特别是"What We Can Do Instead"部分。
答案 4 :(得分:-1)
我会创建一个包含所有这些信息的管理器对象。就像有Game
成员paddle
,bricks
,items
等的成绩Game
一样。然后你可以让currentGame
有一个类方法class Game {
public:
Paddle *paddle;
vector<Brick> *bricks;
vector<Item> *items;
static Game *currentGame();
static void setCurrentGame(Game *newGame);
private:
static Game *currentGameInstance;
}
static Game *Game::currentGame() {
return currentGameInstance;
}
static void Game::setCurrentGame(Game *newGame) {
currentGameInstance = newGame;
}
返回当前游戏实例。这有点像在“全球范围”,但更多的OOP方式。
E.g:
Game::currentGame()->paddle
(我对C ++非常生疏,希望语法正确)
这样你可以随心所欲地{{1}}。
答案 5 :(得分:-1)
“最好”有点主观;您已经命名了标准方法(即:命名空间中的全局或有效等效,或传递给每个函数)。
我倾向于在设计方面做的是通过逻辑分组将组对象放在一起(例如:“游戏状态”对象中的某些内容,“UI资源”对象内的其他内容等),然后生效这些对象的全局实例。我建议总是为对象提供一个有效的命名空间:这可以是字面意思,或者像单例或命名实例工厂范例。通常,对象越“本地”,我越倾向于将它们明确地传递给使用/操纵它们的函数;对象越“应用程序级别”,我就越倾向于使它们成为有效的全局变量。
希望有所帮助。