Обратные вызовы и основной игровой цикл. Это хорошая практика?

Я пишу игру, используя C ++. Интересно, как я могу оптимизировать свой игровой цикл? Например, у нас есть игра с основным циклом, которая выглядит так:

while ( gameContinue ) {
if ( SCENE == HELP_SCENE ) {
renderHelpScene();
} else if ( SCENE == SCORE_SCENE ) {
renderScoreScene();
} else if ( SCENE == MAIN_GAME_SCENE ) {
renderMainGameScene();
} // .... and many others scenes
}

Я думаю о том, как сделать этот код быстрее и легче. Я думаю об использовании обратных вызовов, поэтому нам не нужно много if-случаев. Что-то вроде этого:

typedef void (*callback_function)(void);
callback_function renderFunc;

void renderMainGameScene() {
renderFunc = renderScoreScene(); // set to another scene if we need this
}
void renderScoreScene() {
renderFunc = renderAnyAnotherSceneWeNeedNow();
}

renderFunc = renderMainGameScene();
while ( gameContinue ) {
renderFunc();
}

Что вы думаете об этом? Как вы организуете свои основные циклы?

1

Решение

Я лично начал использовать многопоточность. У меня есть нить для обновления объектов, нить для столкновения объектов и нить для рисования. Каждая нить зацикливается с while (GetMessage()) и потоки отправляют сообщения от одного к другому.

В каждом цикле (кадре) мой основной цикл отправляет сообщение каждому потоку:

  1. Рассчитать столкновения для измененных объектов
  2. Обновить объекты (движение, состояние и т. Д.)
  3. Нарисуйте обновленные объекты

Вот как я это делаю (по крайней мере, в моих играх GDI / GDI +). Не уверен, что лучший способ, но пока он работает как шарм :).

2

Другие решения

Полезные шаблоны для такого рода проблем являются Государственный Образец и Шаблон стратегии.
Как вы можете видеть, они оба похожи. Паттерн «Стратегия» немного проще, чем «Государство», но взамен «Шаблон паттерна» более мощный и, вероятно, лучше приспособлен для такого игрового движка. Вы также можете легко создать стек, например: начало игры -> меню -> запуск игры -> меню.
Если родительское состояние последнего меню — запуск игры, меню будет выглядеть по-другому (например, «Возврат игры» вместо «Начать игру» в первом меню). Состояния могут быть выскочил, и у вас есть легкая навигация.

1

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

Что касается преимуществ во время выполнения, они очень малы. Метод if-else не будет заметно замедлять вашу игру. В качестве альтернативы, есть также оператор switch, который предпочтительнее серии операторов if-else с точки зрения читабельности кода.

0
По вопросам рекламы [email protected]