2

我想在 C++ 中“模拟”流行的 Flash 游戏 Chrontron,需要一些帮助才能开始。(注:不是为了释放,只是为自己练习)

基本:
玩家有一台时光机。在使用时间机器的每次迭代中,一个并行状态
被创建,与先前的状态共存。其中一个州必须完成所有
阶段结束前的关卡目标。此外,所有阶段必须能够
正常结束阶段,而不会引起状态悖论(他们应该有
能够正常完成阶段,但由于另一个状态的相互作用,
不是)。

所以,这解释了游戏是如何运作的。你应该玩一点才能真正理解我的问题是什么。

我在想一个解决这个问题的好方法是使用链表来存储每个状态,这可能是基于时间的哈希映射,或者是基于时间迭代的链表。我仍然不确定。

实际问题:

现在我有了一些粗略的规范,我需要一些帮助来决定使用哪些数据结构,以及为什么。另外,我想知道我应该使用什么图形 API/图层来执行此操作:SDL、OpenGL 或 DirectX(我目前的选择是 SDL)。我将如何实现并行状态?使用并行线程?

编辑(澄清更多):
操作系统——Windows(因为这是一个爱好项目,以后可能会在 Linux 中这样做)
图形——2D 语言——C++(必须是 C++——这是下学期课程的练习)

Q-Answered: SDL : OpenGL : Direct X
Q-Answered: Avoid Parallel Processing
Q-Answered: 使用 STL 实现时间步操作。

到目前为止,人们所说的,我应该:
1. 使用 STL 存储动作。
2. 基于时间步长迭代动作。
3. 忘记并行处理——句号。(但我仍然想要一些关于它如何
可以使用,在什么情况下应该使用,因为这是为了练习)。

附加到这个问题,我以前主要使用过 C#、PHP 和 Java,所以我不会将自己描述为一个能手的程序员。哪些 C++ 特定知识可以帮助我更轻松地完成这个项目?(即向量?)

4

7 回答 7

6

您应该首先阅读并理解“固定时间步长”游戏循环(这里有一个很好的解释:http ://www.gaffer.org/game-physics/fix-your-timestep )。

然后你要做的是保留帧计数器和动作对列表的列表。STL 示例:

std::list<std::list<std::pair<unsigned long, Action> > > state;

或者也许是对列表的向量。要创建状态,对于每个动作(玩家交互),您存储帧号和执行的动作,如果动作只是“按下 <X> 键”或“释放键 <X>”,您很可能会获得最佳结果“:

state.back().push_back(std::make_pair(currentFrame, VK_LEFT | KEY_PRESSED));

要回放之前的状态,您必须在玩家每次激活时间机器时重置帧计数器,然后遍历每个之前状态的状态列表,看看是否有任何匹配当前帧。如果存在,请针对该状态执行操作。为了优化,您可以将迭代器列表保留到您在每个先前状态列表中的位置。这是一些伪代码

typedef std::list<std::pair<unsigned long, Action> > StateList;
std::list<StateList::iterator> stateIteratorList;
//
foreach(it in stateIteratorList)
{
  if(it->first == currentFrame)
  {
    performAction(it->second);
    ++it;
  }
}

我希望你明白这个想法...

单独的线程只会使事情变得非常复杂,这样您每次都会得到相同的结果,您无法通过使用单独的线程(无法真正看到如何实现)或非固定时间步长游戏循环来保证这一点。

谈到图形 API,我会选择 SDL,因为它可能是最容易让您入门的东西。如果您想转为 3D,您以后可以随时使用 SDL 中的 OpenGL。

于 2008-09-16T15:25:19.173 回答
5

这听起来与Braid非常相似。你真的不希望并行处理 - 并行编程很难,对于这样的事情,性能应该不是问题。

由于游戏状态向量会增长得非常快(可能大约为每秒几千字节,具体取决于帧速率和存储的数据量),因此您不需要链表,因为链表的开销很大空间(如果布局不当,可能会由于缓存未命中而导致巨大的性能损失)。对于每个并行时间线,您需要一个矢量数据结构。您可以将每个并行时间线存储在链接列表中。每个时间线都知道它是从什么时间开始的。

要运行游戏,您需要遍历所有活动时间线,并以同步的方式从每个时间线执行一帧的动作。无需并行处理。

于 2008-09-16T15:06:15.053 回答
1

我以前玩过这个游戏。我不一定认为并行处理是要走的路。您在游戏中共享了需要在进程之间共享的对象(杠杆、盒子、电梯等),可能与每个增量共享,从而降低了并行性的有效性。

我个人只会保留一个动作列表,然后对于每个后续迭代开始将它们交错在一起。例如,如果列表的格式为 <[iteration.action]>,则第三次通过将执行动作 1.1、2.1、3.1、1.2、2.2、3.3 等。

于 2008-09-16T14:49:18.590 回答
0

在简要掩盖了描述之后,我认为您的想法是正确的,我将有一个包含状态数据的状态对象,并将其放入链表中...我认为您不需要并行线程...

至于图形API,我只用过opengl,可以说它很强大,并且有很好的C/C++ API,opengl也可以跨平台,因为你可以在*Nix电脑上使用messa库。

于 2008-09-16T14:49:54.767 回答
0

一个非常有趣的游戏创意。我认为你是对的,并行计算将有利于这种设计,但不比任何其他高资源程序。

这个问题有点模棱两可。我看到你打算用 C++ 编写这个,但你在为什么操作系统编写代码?您是否打算将其作为跨平台,您想要什么样的图形,即 3D、2D、高端、基于网络。

所以基本上我们需要更多的信息。

于 2008-09-16T14:51:41.970 回答
0

并行处理不是答案。您应该简单地“记录”玩家的动作,然后为“之前的动作”回放它们

因此,您创建了一个包含动作的向量(单链表)。只需存储执行该操作的帧号(或增量)并在该特定实例中代表玩家的“虚拟机器人”上完成该操作。您只需遍历状态并一个接一个地触发它们。

当状态悖论仅仅因为下一个动作失败而发生时,你会得到很容易“破坏”游戏的副作用。

于 2008-09-16T14:57:53.123 回答
0

除非您迫切希望将 C++ 用于自己的教育,否则您绝对应该将XNA用于您的游戏和图形框架(它使用 C#)。它完全免费,可以为您做很多事情,很快您就可以在 Xbox Live 上销售您的游戏。

要回答您的主要问题,您已经可以在 Flash 中执行的任何操作都不需要使用多个线程。只需将位置列表存储在数组中,然后为每个机器人使用不同的偏移量进行循环。

于 2008-09-16T15:03:56.807 回答