У меня для школьного задания создана небольшая игра, она делится на 2 разных проекта, один проект с формой и один с DLL файлом, содержащим игру.
Игровой цикл очень прост и выглядит следующим образом:
private void GameLoop(Graphics g)
{
int lastTick = Kernel32.GetTickCount();
do
{
if (terminated)
break;
while ((lastTick + 50) > Kernel32.GetTickCount())
Application.DoEvents();
while (gamePaused)
Application.DoEvents();
g.FillRectangle(new SolidBrush(Color.White), 0, 0, 800, 640);
DrawWalls(g);
MoveMonsters();
DrawMonsters(g);
lastTick = Kernel32.GetTickCount();
}
while (true);
gameRunning = false;
}
Он работает по назначению и перерисовывает панель на странице формы. На странице формы у меня есть кнопка для выхода из текущей игры, это делается просто с помощью основной формы, вызывающей команду game.dll TerminateGame(), которая заканчивается на true, это также работает по назначению. Теперь моя проблема в том, что пользователь нажимает кнопку закрытия формы или нажимает F4.
Затем я попытался сделать то же самое:
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (game.IsRunning)
game.TerminateGame();
}
Но я продолжаю получать эту ошибку: Общая ошибка произошла в GDI +. и он указывает на эту строку: g.FillRectangle(новый SolidBrush (Color.White), 0, 0, 800, 640);
Я понятия не имею, почему это работает, когда я нажимаю кнопку, которая просто завершает игру и почему ее не работает, когда форма закрывается, ее же вызов метода.
Форма закрывается отлично, если я сначала нажимаю кнопку, а затем нажимаю F4, это просто, когда я просто нажимаю F4, что я все время получаю это.
Любые идеи?
Ваша основная ошибка (IMO) создает игровой цикл самостоятельно и вызывает Application.DoEvents
. Вместо этого вы должны запускать сам цикл событий обычного пользовательского интерфейса (через Application.Run(form)
и добавлять таймеры для анимации и т.д. WinForms предназначен для запуска по событию.
Причина неудачи в том, что вы пытаетесь рисовать после того, как форма фактически была закрыта - т.е. вы используете недействительный дескриптор Graphics
. Когда нажата кнопка "Остановить", я предполагаю, что вы фактически не закрываете форму, а следовательно, и отсутствие проблемы.
Быстрый и грязный взлом должен был бы добавить другое:
if (terminated)
break;
после последнего вызова Application.DoEvents
, прежде чем вы попытаетесь нарисовать Graphics
, но не решаете более фундаментальный способ, которым вы эффективно пытаетесь использовать WinForms таким образом, чтобы он не был предназначен для.
Вам нужно дождаться окончания галлупа. Если вы этого не сделаете, тогда код будет выполнен после того, как уже будут установлены различные графические объекты, которые выдают исключение, которое вы получаете. Чтобы исправить это, дождитесь окончания цикла игры, а затем прекратите выполнение вашего приложения.
Как
if (game.IsRunning)
game.TerminateGame();
while (game.IsRunning)
Continue;