使用并行处理在C ++中制作游戏

时间:2022-01-22 12:03:56

I wanted to "emulate" a popular flash game, Chrontron, in C++ and needed some help getting started. (NOTE: Not for release, just practicing for myself)

我想用C ++“模仿”流行的Flash游戏Chrontron,需要一些帮助才能开始。 (注意:不是为了发布,只为我自己练习)

Basics:
Player has a time machine. On each iteration of using the time machine, a parallel state
is created, co-existing with a previous state. One of the states must complete all the
objectives of the level before ending the stage. In addition, all the stages must be able
to end the stage normally, without causing a state paradox (wherein they should have
been able to finish the stage normally but, due to the interactions of another state,
were not).

So, that sort of explains how the game works. You should play it a bit to really understand what my problem is.

所以,这种解释了游戏的运作方式。你应该玩一点来真正理解我的问题是什么。

I'm thinking a good way to solve this would be to use linked lists to store each state, which will probably either be a hash map, based on time, or a linked list that iterates based on time. I'm still unsure.

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

ACTUAL QUESTION:

Now that I have some rough specs, I need some help deciding on which data structures to use for this, and why. Also, I want to know what Graphics API/Layer I should use to do this: SDL, OpenGL, or DirectX (my current choice is SDL). And how would I go about implementing parallel states? With parallel threads?

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

EDIT (To clarify more):
OS -- Windows (since this is a hobby project, may do this in Linux later)
Graphics -- 2D Language -- C++ (must be C++ -- this is practice for a course next semester)

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

Q-Unanswered: SDL : OpenGL : Direct X
Q-Answered: Avoid Parallel Processing
Q-Answered: Use STL to implement time-step actions.

Q-Unanswered:SDL:OpenGL:Direct X Q-Answered:避免并行处理Q-Answered:使用STL实现时间步骤操作。

So far from what people have said, I should:
1. Use STL to store actions.
2. Iterate through actions based on time-step.
3. Forget parallel processing -- period. (But I'd still like some pointers as to how it
could be used and in what cases it should be used, since this is for practice).

Appending to the question, I've mostly used C#, PHP, and Java before so I wouldn't describe myself as a hotshot programmer. What C++ specific knowledge would help make this project easier for me? (ie. Vectors?)

回答这个问题,我之前主要使用C#,PHP和Java,因此我不会将自己描述为一个热门的程序员。哪些C ++特定知识有助于我更轻松地完成这个项目? (即矢量?)

7 个解决方案

#1


6  

What you should do is first to read and understand the "fixed time-step" game loop (Here's a good explanation: http://www.gaffer.org/game-physics/fix-your-timestep).

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

Then what you do is to keep a list of list of pairs of frame counter and action. STL example:

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

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

Or maybe a vector of lists of pairs. To create the state, for every action (player interaction) you store the frame number and what action is performed, most likely you'd get the best results if action simply was "key <X> pressed" or "key <X> released":

或者可能是对列表的向量。要创建状态,对于每个操作(玩家互动),您存储帧编号和执行的操作,如果操作只是“按下 按下”或“键 发布,则很可能获得最佳结果“:

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

To play back the previous states, you'd have to reset the frame counter every time the player activates the time machine and then iterate through the state list for each previous state and see if any matches the current frame. If there is, perform the action for that state. To optimize you could keep a list of iterators to where you are in each previous state-list. Here's some pseudo-code for that:

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

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;
  }
}

I hope you get the idea...

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

Separate threads would simply complicate the matter greatly, this way you get the same result every time, which you cannot guarantee by using separate threads (can't really see how that would be implemented) or a non-fixed time-step game loop.

单独的线程会使问题变得非常复杂,这样每次都会得到相同的结果,这是你无法保证使用单独的线程(无法真正看到如何实现)或非固定的时间步游戏循环。

When it comes to graphics API, I'd go with SDL as it's probably the easiest thing to get you started. You can always use OpenGL from SDL later on if you want to go 3D.

说到图形API,我会选择SDL,因为它可能是让你入门的最简单方法。如果您想要3D,您可以随后从SDL使用OpenGL。

#2


5  

This sounds very similar to Braid. You really don't want parallel processing for this - parallel programming is hard, and for something like this, performance should not be an issue.

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

Since the game state vector will grow very quickly (probably on the order of several kilobytes per second, depending on the frame rate and how much data you store), you don't want a linked list, which has a lot of overhead in terms of space (and can introduce big performance penalties due to cache misses if it is laid out poorly). For each parallel timeline, you want a vector data structure. You can store each parallel timeline in a linked list. Each timeline knows at what time it began.

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

To run the game, you iterate through all active timelines and perform one frame's worth of actions from each of them in lockstep. No need for parallel processing.

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

#3


1  

I have played this game before. I don't necessarily think parallel processing is the way to go. You have shared objects in the game (levers, boxes, elevators, etc) that will need to be shared between processes, possibly with every delta, thereby reducing the effectiveness of the parallelism.

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

I would personally just keep a list of actions, then for each subsequent iteration start interleaving them together. For example, if the list is in the format of <[iteration.action]> then the 3rd time thru would execute actions 1.1, 2.1, 3.1, 1.2, 2.2, 3.3, etc.

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

#4


0  

After briefly glossing over the description, I think you have the right idea, I would have a state object that holds the state data, and place this into a linked list...I don't think you need parallel threads...

在简要介绍了描述之后,我认为你有正确的想法,我会有一个状态对象来保存状态数据,并把它放到一个链表...我不认为你需要并行线程...

as far as the graphics API, I have only used opengl, and can say that it is pretty powerful and has a good C / C++ API, opengl would also be more cross platform as you can use the messa library on *Nix computers.

至于图形API,我只使用了opengl,并且可以说它非常强大且具有良好的C / C ++ API,opengl也可以更加跨平台,因为你可以使用* Nix计算机上的messa库。

#5


0  

A very interesting game idea. I think you are right that parrellel computing would be benefical to this design, but no more then any other high resource program.

一个非常有趣的游戏理念。我认为,对于这种设计而言,parrellel计算将是有益的,但不会超过任何其他高资源计划。

The question is a bit ambigous. I see that you are going to write this in C++ but what OS are you coding it for? Do you intend on it being cross platform and what kind of graphics would you like, ie 3D, 2D, high end, web based.

问题有点模糊。我看到你要用C ++编写这个,但你编写的是什么操作系统?您是否打算跨平台以及您想要什么样的图形,即3D,2D,高端,基于Web。

So basically we need a lot more information.

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

#6


0  

Parallel processing isn't the answer. You should simply "record" the players actions then play them back for the "previous actions"

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

So you create a vector (singly linked list) of vectors that holds the actions. Simply store the frame number that the action was taken (or the delta) and complete that action on the "dummy bot" that represents the player during that particular instance. You simply loop through the states and trigger them one after another.

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

You get a side effect of easily "breaking" the game when a state paradox happens simply because the next action fails.

当一个状态悖论发生时,你会因为下一个动作失败而轻易“打破”游戏。

#7


0  

Unless you're desperate to use C++ for your own education, you should definitely look at XNA for your game & graphics framework (it uses C#). It's completely free, it does a lot of things for you, and soon you'll be able to sell your game on Xbox Live.

除非你不顾一切地使用C ++进行自己的教育,否则你应该看看XNA的游戏和图形框架(它使用C#)。它是完全免费的,它为你做了很多事情,很快你就可以在Xbox Live上出售你的游戏了。

To answer your main question, nothing that you can already do in Flash would ever need to use more than one thread. Just store a list of positions in an array and loop through with a different offset for each robot.

要回答你的主要问题,你在Flash中已经做过的任何事都不需要使用多个线程。只需在阵列中存储位置列表,然后使用每个机器人的不同偏移量进行循环。

#1


6  

What you should do is first to read and understand the "fixed time-step" game loop (Here's a good explanation: http://www.gaffer.org/game-physics/fix-your-timestep).

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

Then what you do is to keep a list of list of pairs of frame counter and action. STL example:

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

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

Or maybe a vector of lists of pairs. To create the state, for every action (player interaction) you store the frame number and what action is performed, most likely you'd get the best results if action simply was "key <X> pressed" or "key <X> released":

或者可能是对列表的向量。要创建状态,对于每个操作(玩家互动),您存储帧编号和执行的操作,如果操作只是“按下 按下”或“键 发布,则很可能获得最佳结果“:

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

To play back the previous states, you'd have to reset the frame counter every time the player activates the time machine and then iterate through the state list for each previous state and see if any matches the current frame. If there is, perform the action for that state. To optimize you could keep a list of iterators to where you are in each previous state-list. Here's some pseudo-code for that:

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

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;
  }
}

I hope you get the idea...

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

Separate threads would simply complicate the matter greatly, this way you get the same result every time, which you cannot guarantee by using separate threads (can't really see how that would be implemented) or a non-fixed time-step game loop.

单独的线程会使问题变得非常复杂,这样每次都会得到相同的结果,这是你无法保证使用单独的线程(无法真正看到如何实现)或非固定的时间步游戏循环。

When it comes to graphics API, I'd go with SDL as it's probably the easiest thing to get you started. You can always use OpenGL from SDL later on if you want to go 3D.

说到图形API,我会选择SDL,因为它可能是让你入门的最简单方法。如果您想要3D,您可以随后从SDL使用OpenGL。

#2


5  

This sounds very similar to Braid. You really don't want parallel processing for this - parallel programming is hard, and for something like this, performance should not be an issue.

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

Since the game state vector will grow very quickly (probably on the order of several kilobytes per second, depending on the frame rate and how much data you store), you don't want a linked list, which has a lot of overhead in terms of space (and can introduce big performance penalties due to cache misses if it is laid out poorly). For each parallel timeline, you want a vector data structure. You can store each parallel timeline in a linked list. Each timeline knows at what time it began.

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

To run the game, you iterate through all active timelines and perform one frame's worth of actions from each of them in lockstep. No need for parallel processing.

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

#3


1  

I have played this game before. I don't necessarily think parallel processing is the way to go. You have shared objects in the game (levers, boxes, elevators, etc) that will need to be shared between processes, possibly with every delta, thereby reducing the effectiveness of the parallelism.

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

I would personally just keep a list of actions, then for each subsequent iteration start interleaving them together. For example, if the list is in the format of <[iteration.action]> then the 3rd time thru would execute actions 1.1, 2.1, 3.1, 1.2, 2.2, 3.3, etc.

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

#4


0  

After briefly glossing over the description, I think you have the right idea, I would have a state object that holds the state data, and place this into a linked list...I don't think you need parallel threads...

在简要介绍了描述之后,我认为你有正确的想法,我会有一个状态对象来保存状态数据,并把它放到一个链表...我不认为你需要并行线程...

as far as the graphics API, I have only used opengl, and can say that it is pretty powerful and has a good C / C++ API, opengl would also be more cross platform as you can use the messa library on *Nix computers.

至于图形API,我只使用了opengl,并且可以说它非常强大且具有良好的C / C ++ API,opengl也可以更加跨平台,因为你可以使用* Nix计算机上的messa库。

#5


0  

A very interesting game idea. I think you are right that parrellel computing would be benefical to this design, but no more then any other high resource program.

一个非常有趣的游戏理念。我认为,对于这种设计而言,parrellel计算将是有益的,但不会超过任何其他高资源计划。

The question is a bit ambigous. I see that you are going to write this in C++ but what OS are you coding it for? Do you intend on it being cross platform and what kind of graphics would you like, ie 3D, 2D, high end, web based.

问题有点模糊。我看到你要用C ++编写这个,但你编写的是什么操作系统?您是否打算跨平台以及您想要什么样的图形,即3D,2D,高端,基于Web。

So basically we need a lot more information.

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

#6


0  

Parallel processing isn't the answer. You should simply "record" the players actions then play them back for the "previous actions"

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

So you create a vector (singly linked list) of vectors that holds the actions. Simply store the frame number that the action was taken (or the delta) and complete that action on the "dummy bot" that represents the player during that particular instance. You simply loop through the states and trigger them one after another.

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

You get a side effect of easily "breaking" the game when a state paradox happens simply because the next action fails.

当一个状态悖论发生时,你会因为下一个动作失败而轻易“打破”游戏。

#7


0  

Unless you're desperate to use C++ for your own education, you should definitely look at XNA for your game & graphics framework (it uses C#). It's completely free, it does a lot of things for you, and soon you'll be able to sell your game on Xbox Live.

除非你不顾一切地使用C ++进行自己的教育,否则你应该看看XNA的游戏和图形框架(它使用C#)。它是完全免费的,它为你做了很多事情,很快你就可以在Xbox Live上出售你的游戏了。

To answer your main question, nothing that you can already do in Flash would ever need to use more than one thread. Just store a list of positions in an array and loop through with a different offset for each robot.

要回答你的主要问题,你在Flash中已经做过的任何事都不需要使用多个线程。只需在阵列中存储位置列表,然后使用每个机器人的不同偏移量进行循环。