Создание игры на C ++ с использованием параллельной обработки - PullRequest
2 голосов
/ 16 сентября 2008

Я хотел «эмулировать» популярную флеш-игру Chrontron на C ++, и мне нужна была помощь для начала работы. (ПРИМЕЧАНИЕ: не для релиза, просто тренируюсь для себя)

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).

Итак, это как-то объясняет, как работает игра. Вы должны играть немного, чтобы действительно понять в чем моя проблема.

Я думаю, что хороший способ решить эту проблему - использовать связанные списки для хранения каждого состояния, которая, вероятно, будет либо хэш-картой, основанной на времени, либо связанным списком, который выполняет итерации основанный на времени. Я все еще не уверен.

АКТУАЛЬНЫЙ ВОПРОС:

Теперь, когда у меня есть приблизительные характеристики, мне нужна помощь в определении того, какие структуры данных использовать для этого и почему. Кроме того, я хочу знать, какой графический API / слой мне следует использовать для этого: SDL, OpenGL или DirectX (мой текущий выбор - SDL). И как бы я пошел о реализации параллельных состояний? С параллельными нитями?

РЕДАКТИРОВАТЬ (чтобы уточнить больше):
ОС - Windows (так как это хобби-проект, возможно, позже это сделают в Linux)
Графика - 2D Язык - C ++ (должен быть C ++ - это практика для курса в следующем семестре)

Q-Без ответа: SDL: OpenGL: Direct X
Ответ на вопрос: Избегайте параллельной обработки
Вопрос-ответ: Используйте 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).

Подходя к вопросу, я раньше в основном использовал C #, PHP и Java, поэтому я бы не назвал себя программистом. Какие специфические знания C ++ помогут мне сделать этот проект легче? (т. е. векторы?)

Ответы [ 7 ]

6 голосов
/ 16 сентября 2008

Что вы должны сделать, это сначала прочитать и понять игровой цикл с «фиксированным временным шагом» (Вот хорошее объяснение: http://www.gaffer.org/game-physics/fix-your-timestep).

Тогда вы должны вести список списка пар счетчика кадров и действия. Пример STL:

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

Или, может быть, вектор списков пар. Чтобы создать состояние, для каждого действия (взаимодействия с игроком) вы сохраняете номер кадра и выполняемое действие. Скорее всего, вы получите наилучшие результаты, если просто выполнить действие «клавиша нажата» или «клавиша отпущена» «:

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, поскольку это, пожалуй, самая простая вещь для начала. Вы всегда можете использовать OpenGL из SDL позже, если хотите перейти в 3D.

5 голосов
/ 16 сентября 2008

Это звучит очень похоже на Braid . Вы действительно не хотите параллельной обработки для этого - параллельное программирование - сложное , и для чего-то подобного производительность не должна быть проблемой.

Поскольку вектор состояния игры будет расти очень быстро (вероятно, порядка нескольких килобайт в секунду, в зависимости от частоты кадров и объема хранимых данных), вам не нужен связанный список, который имеет много накладные расходы с точки зрения пространства (и могут привести к большим потерям производительности из-за пропусков кеша, если он плохо спланирован). Для каждой параллельной временной шкалы вам нужна векторная структура данных. Вы можете хранить каждую параллельную временную шкалу в связанном списке. Каждый график знает, в какое время он начался.

Чтобы запустить игру, вы перебираете все активные временные шкалы и выполняете действия по одному кадру для каждого из них в режиме блокировки. Нет необходимости в параллельной обработке.

1 голос
/ 16 сентября 2008

Я играл в эту игру раньше. Я не обязательно думаю, что параллельная обработка - это путь. У вас есть общие объекты в игре (рычаги, ящики, лифты и т. Д.), Которые нужно будет разделять между процессами, возможно, с каждой дельтой, что снижает эффективность параллелизма.

Лично я бы просто вел список действий, а затем для каждой последующей итерации начинал их чередовать. Например, если список имеет формат <[iteration.action]>, то в третий раз выполняются действия 1.1, 2.1, 3.1, 1.2, 2.2, 3.3 и т. Д.

0 голосов
/ 16 сентября 2008

Если вы не отчаянно хотите использовать C ++ для своего образования, вам непременно стоит взглянуть на XNA для вашей игровой и графической среды (в ней используется C #). Он абсолютно бесплатный, он многое для вас делает, и вскоре вы сможете продавать свою игру на Xbox Live.

Чтобы ответить на ваш главный вопрос, ничто из того, что вы уже можете сделать во Flash, никогда не должно использовать более одного потока. Просто сохраните список позиций в массиве и выполните цикл с различным смещением для каждого робота.

0 голосов
/ 16 сентября 2008

Параллельная обработка не является ответом. Вы должны просто «записать» действия игроков, а затем воспроизвести их для «предыдущих действий»

Итак, вы создаете вектор (односвязный список) векторов, который содержит действия. Просто сохраните номер кадра, в котором было выполнено действие (или дельта), и выполните это действие на «фиктивном боте», который представляет игрока в этом конкретном случае. Вы просто переключаетесь между состояниями и запускаете их одно за другим.

Вы получаете побочный эффект от легкого «взлома» игры, когда парадокс состояния происходит просто потому, что следующее действие проваливается.

0 голосов
/ 16 сентября 2008

Очень интересная идея игры. Я думаю, вы правы, что парреллел-вычисления будут полезны для этого дизайна, но не более, чем любая другая программа с высокими ресурсами.

Вопрос немного двусмысленный. Я вижу, что вы собираетесь написать это на C ++, но для какой ОС вы это кодируете? Планируете ли вы, чтобы он был кроссплатформенным и какую графику вы бы хотели, например, 3D, 2D, high end, веб-интерфейс.

Так что в основном нам нужно гораздо больше информации.

0 голосов
/ 16 сентября 2008

После краткого описания описания, я думаю, у вас есть правильная идея, у меня будет объект состояния, который содержит данные о состоянии, и помещу их в связанный список ... Я не думаю, что вам нужны параллельные потоки. ..

Что касается графического API, я использовал только opengl и могу сказать, что он довольно мощный и имеет хороший C / C ++ API, opengl также будет более кроссплатформенным, так как вы можете использовать библиотеку messa в * Nix. компьютеры.

...