Я работаю над игрой на C ++ с использованием SDL. Я начал следовать учебникам Lazyfoo и собирал их в MacOS с использованием XCode. В эти выходные я смотрел, смогу ли я скомпилировать его на Windows в Visual Studio 2019. Я добился успеха, но не уверен насчет одного из изменений, которые мне пришлось сделать.
В игре используется ImageMagick (Magick ++) для рисования, которое затем сохраняется в виде текстуры в памяти видеокарты с использованием SDL (собственных функций рисования SDL недостаточно). Эта часть рисования очень медленная , но не должна происходить синхронно, поэтому я решил поместить этот процесс в свой собственный поток, который работал абсолютно нормально на моей Ma c.
Теперь у меня это работает на Windows, я видел случайные сбои, когда игра пыталась нарисовать нового персонажа. Я сузил это до SDL_CreateTextureFromSurface()
, который вызывается из потока и создает новую текстуру, используя поверхность, созданную из образа Magick ++. Это происходило только тогда, когда я использовал многопоточность, если я отключил это (и убивал мою частоту кадров, когда что-то рисовал), это работало нормально.
Я смотрел на мьютекс, но все рекомендации рекомендовали использовать join
в потоке, который заблокировал бы main()
на весь период розыгрыша и сделал бы это бессмысленным. Я думаю, что есть очень хороший шанс, что я неправильно понял это!
Вместо этого я установил два bool
в классе, который передается как ссылка на поток. Если для потока SDL_Thread_Waiting
установлено значение true
, игра l oop в main()
временно останавливается и устанавливает SDL_Main_Paused
в true
, что говорит потоку, что он может безопасно обращаться к средству визуализации. Затем поток устанавливает SDL_Main_Paused
на false
после завершения, и игра l oop продолжается.
Это означает, что ImageMagick может быть настолько медленным, насколько это необходимо для его собственного потока, но на последнем шаг, я могу сделать короткую паузу в основной игре, чтобы текстура сохранялась без сбоев.
Пример кода ниже. На данный момент игра довольно масштабная, но это должно показать, что я делаю:
// class.hpp
Class Game {
Public:
bool is_running;
bool SDL_Thread_Waiting = false;
bool SDL_Main_Paused = false;
// ...
}
// main.cpp
Game game;
int main(int argc, char* argv[]) {
game.is_running = true;
while (game.is_running) {
// Regular game stuff!
if (game.SDL_Thread_Waiting) {
game.SDL_Main_Paused = true;
while (game.SDL_Main_Paused) {
// do.. nothing?
}
}
}
// Threaded bits
void generate_character() {
std::thread th(make_texture, std::ref(game));
th.detach();
}
SDL_Texture* make_texture(Game& game) {
// Heavy lifting by ImageMagick goes here
SDL_Thread_Waiting = true;
while (!SDL_Main_Paused) {
std::this_thread::sleep_for(std::chrono::milliseconds(25));
}
// SDL_CreateTextureFromSurface()
SDL_Main_Paused = false;
SDL_Thread_Waiting = false;
return texture;
}
Является ли это подходящим способом на короткое время заблокировать основную игру l oop от отдельная тема? Я неправильно поняла mutex
и это было бы лучше здесь?
Я очень новичок в C ++ и SDL, прошу прощения, если весь мой вопрос основан на дальнейших недоразумениях!