Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > разработка игр, графический дизайн и моделирование > Gamedev - cоздание игр: Unity, OpenGL, DirectX
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.06.2012, 14:17   #1
_PROGRAMM_
Участник клуба
 
Аватар для _PROGRAMM_
 
Регистрация: 30.07.2009
Сообщений: 1,603
По умолчанию Подвисание игры при нажатии клавиш управления

Приветствую всех форумчан. Случилась такая неприятная ситуация. Начал делать игрушку. В ходе создания появилась проблема. В общем юнит(в данном случае танк) управляется не очень замысловатыми клавишами. Обычно у геймеров они стерты и продавлены(и не такое видел!). Это клавиши w,s,a,d. W и S заставляют двигаться танк вперед или назад параллельно направлению движения. A и D меняют направление движения(заставляют танк вращаться). Есть код обработки нажатий клавиш.
Цитата:
while(Run)
{
float SpeedRotate=1.5;
float y=1;
if ((keys[83]==true) ||(keys[87]==true))
y=1.5;
if (keys[68]==true) //d
{
int x = 1;
if (keys[83]==true)
x = -1;
if (User.kangle-SpeedRotate<0)
{
User.kangle=User.kangle-x*(SpeedRotate/y);
User.kangle=User.kangle+360;
}
else
{
User.kangle=User.kangle-x*(SpeedRotate/y);
}
User.kx=0.01*cos(DegToRad(User.kang le));
User.ky=0.01*sin(DegToRad(User.kang le));
}
if (keys[65]==true) //a
{
int x = 1;
if (keys[83]==true)
x = -1;
if (User.kangle-SpeedRotate>360)
{
User.kangle=User.kangle+x*(SpeedRot ate/y);
User.kangle=User.kangle-360;
}
else
{
User.kangle=User.kangle+x*(SpeedRot ate/y);
}
User.kx=0.01*cos(DegToRad(User.kang le));
User.ky=0.01*sin(DegToRad(User.kang le));
}

if (keys[87]==true) //s
{
if ((keys[65]==true) || (keys[68]==true) )
{
User.px=User.px-(User.kx/1.3);
User.py=User.py-(User.ky/1.3);
}
else
{
User.px=User.px-User.kx;
User.py=User.py-User.ky;
}
}
if (keys[83]==true) //s
{
if ((keys[65]==true) || (keys[68]==true) )
{
User.px=User.px+((User.kx/1.3)/2);
User.py=User.py+((User.ky/1.3)/2);
}
else
{
User.px=User.px+User.kx-(User.kx/2);
User.py=User.py+User.ky-(User.ky/2);
}
}
Sleep(20);
}
ExitThread(0);
Как видно из последней строки кода, он находится в потоке. Если копировать тело цикла(т.е. без while) и вставить в процедуру перерисовки, подвисания пропадают. Сами подвисания появляются при нажатии кнопок A или D (влево/вправо). Хотя сейчас пересмотрел и увидел, что и A, и D, и S, и W вызывают эти "глюки". Оба варианта представлены во вложениях.
Заранее спасибо.
P.S. в WinXP игра выбивает ошибку. Какую - я не знаю. Прошу сообщить.
ADD Забыл сказать, что если копировать в процедуру рисования еще и Sleep(20) ничего не меняется. Все нормально работает.
Вложения
Тип файла: rar Без подвисаний.rar (514.5 Кб, 12 просмотров)
Тип файла: rar С подвисаниеми.rar (514.5 Кб, 13 просмотров)
Тип файла: rar Проект Visual c++.rar (2.10 Мб, 10 просмотров)

В мире нет вечных двигателей, зато есть вечные тормоза...

Блог

Последний раз редактировалось _PROGRAMM_; 02.06.2012 в 14:27.
_PROGRAMM_ вне форума Ответить с цитированием
Старый 02.06.2012, 15:47   #2
Selestis
Форумчанин
 
Аватар для Selestis
 
Регистрация: 21.01.2009
Сообщений: 719
По умолчанию

Код:
if (PeekMessage(&message,NULL,NULL,0,PM_REMOVE))
Замените на while
Изобретатель велосипедов
Selestis вне форума Ответить с цитированием
Старый 02.06.2012, 16:11   #3
_PROGRAMM_
Участник клуба
 
Аватар для _PROGRAMM_
 
Регистрация: 30.07.2009
Сообщений: 1,603
По умолчанию

Цитата:
Замените на while
Ошибка во вложении
до
Код:
while(Run)
	{
	    
		if (PeekMessage(&message,NULL,NULL,0,PM_REMOVE))
		{
			if (message.message==WM_QUIT)
			{
				Run=false;
			}
			else
			{
				TranslateMessage(&message);
				DispatchMessage(&message);
			}
			
		}
	    else
		{
			if (keys[VK_ESCAPE])
			{
				Run=false;
			}
			else
			{
			DrawScene(Horres,Vertres);
			}
		}
	}
После.
Код:
	while(Run)
	{
	    
			if (message.message==WM_QUIT)
			{
				Run=false;
			}
			else
			{
				TranslateMessage(&message);
				DispatchMessage(&message);
			}
			
			if (keys[VK_ESCAPE])
			{
				Run=false;
			}
			else
			{
			DrawScene(Horres,Vertres);
			}
	}
И хотелось бы узнать, в чем, собственно, проблема?
Изображения
Тип файла: jpg Error.jpg (56.1 Кб, 132 просмотров)

В мире нет вечных двигателей, зато есть вечные тормоза...

Блог

Последний раз редактировалось _PROGRAMM_; 02.06.2012 в 16:13.
_PROGRAMM_ вне форума Ответить с цитированием
Старый 02.06.2012, 16:35   #4
Selestis
Форумчанин
 
Аватар для Selestis
 
Регистрация: 21.01.2009
Сообщений: 719
По умолчанию

Ээээ... Это совсем что-то не то: у вас перед этим циклом объявлена неинициализированная переменная
Код:
MSG message;
, разумеется всё свалится при попытке её использовать в условии...
Вы зачем убрали "if (PeekMessage(&message,NULL,NULL,0,P M_REMOVE))"? я имел в виду поменять в этой строчке if на while
Изобретатель велосипедов

Последний раз редактировалось Selestis; 02.06.2012 в 16:37.
Selestis вне форума Ответить с цитированием
Старый 02.06.2012, 18:58   #5
_PROGRAMM_
Участник клуба
 
Аватар для _PROGRAMM_
 
Регистрация: 30.07.2009
Сообщений: 1,603
По умолчанию

Код:
while(Run)
	{
		while (PeekMessage(&message,NULL,NULL,0,PM_REMOVE))
		{
			if (message.message==WM_QUIT)
			{
				Run=false;
			}
			else
			{
				TranslateMessage(&message);
				DispatchMessage(&message);
			}
		    if (keys[VK_ESCAPE])
			{
				Run=false;
			}
			else
			{
			DrawScene(Horres,Vertres);
			}
		}
	}
Так? Только теперь все запаздывает.

В мире нет вечных двигателей, зато есть вечные тормоза...

Блог
_PROGRAMM_ вне форума Ответить с цитированием
Старый 03.06.2012, 04:25   #6
Kostia
Участник клуба
 
Аватар для Kostia
 
Регистрация: 21.11.2007
Сообщений: 1,691
По умолчанию

Код:
	while(Run)
	{
		while (PeekMessage(&message,NULL,NULL,0,PM_REMOVE))
		{
			if (message.message==WM_QUIT)
			{
				Run=false;
			}
			else
			{
				TranslateMessage(&message);
				DispatchMessage(&message);
			}
			if (keys[VK_ESCAPE])
			{
				Run=false;
			}
		}
		DrawScene(Horres,Vertres);
		sleep(1); //или более точные варианты (nanosleep или usleep)
	}
Незабываем считать deltaTime для корректировки анимации
Kostia вне форума Ответить с цитированием
Старый 03.06.2012, 14:01   #7
_PROGRAMM_
Участник клуба
 
Аватар для _PROGRAMM_
 
Регистрация: 30.07.2009
Сообщений: 1,603
По умолчанию

Что-то я не пойму в чем все-таки проблема. Еще разок. Я хочу, чтобы в потоке находился обработчик кнопок(он у меня там и находится). Но при этом начинаются притормаживания. Если его поместить в процедуру перерисовки все работает нормально. Почему так? Просто списывать код не нравится.
Во вложениях результат переделанного кода. Как вычисляется deltaTime я посмотрю. Но все равно не понимаю, что делаю.
Вложения
Тип файла: rar Исходный код.rar (621.2 Кб, 9 просмотров)
Тип файла: rar Результат.rar (657.9 Кб, 9 просмотров)

В мире нет вечных двигателей, зато есть вечные тормоза...

Блог

Последний раз редактировалось _PROGRAMM_; 03.06.2012 в 14:04.
_PROGRAMM_ вне форума Ответить с цитированием
Старый 16.06.2012, 19:03   #8
_PROGRAMM_
Участник клуба
 
Аватар для _PROGRAMM_
 
Регистрация: 30.07.2009
Сообщений: 1,603
По умолчанию

Не могу я просто так оставить эту тему. Она мне спать спокойно не дает. Ответьте, пожалуйста, на предыдущий вопрос и на новые.
Для чего в цикле нужен Sleep(1)(Пост №6).
Наблюдаю следующее явление. Чем дольше держишь нажатой кнопку управления, тем дольше после того, как ее отпустишь, происходит самовольное движение объекта(в моем случае танка). Почему? Если не менять if на while, как советовали в посте №2, таких зависаний не наблюдается.

В мире нет вечных двигателей, зато есть вечные тормоза...

Блог
_PROGRAMM_ вне форума Ответить с цитированием
Старый 16.06.2012, 21:22   #9
Kostia
Участник клуба
 
Аватар для Kostia
 
Регистрация: 21.11.2007
Сообщений: 1,691
По умолчанию

Sleep(1) или Sleep(0) нужны чтобы ваша игра не скушала 100% процессорного времени.

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

Код приведенный в посте #5.
Цикл просмотра сообщений, если таковые имеются
while (PeekMessage(&message,NULL,NULL,0,P M_REMOVE))
Естественно если сообщений нет, то цикл ни разу не выполнится.
TranslateMessage(&message); Вы уверенны что вам это нужно?
Цитата:
Если не менять if на while, как советовали в посте №2, таких зависаний не наблюдается.
Очевидно if'ом обрабатывается только одно сообщение из очереди за один такт while, а while'ом обрабатываются все пришедшие сообщения(скопившиеся за время обработки предыдущих и время выполнения др. операций, например рендеринга кадра).

Вот думаю и все. Дальше гугл в помощь
Kostia вне форума Ответить с цитированием
Старый 17.06.2012, 11:01   #10
_PROGRAMM_
Участник клуба
 
Аватар для _PROGRAMM_
 
Регистрация: 30.07.2009
Сообщений: 1,603
По умолчанию

Цитата:
TranslateMessage(&message); Вы уверенны что вам это нужно?
Я где-то читал, что каждый процесс должен использовать эту функцию для обработки сообщений.
Цитата:
Очевидно if'ом обрабатывается только одно сообщение из очереди за один такт while, а while'ом обрабатываются все пришедшие сообщения(скопившиеся за время обработки предыдущих и время выполнения др. операций, например рендеринга кадра).
Получив интересующую меня информацию, все равно не могу понять как исправить ситуацию. Может есть более оптимальный вариант? Каким образом сделали бы Вы? Может я сам себе проблемы делаю?

В мире нет вечных двигателей, зато есть вечные тормоза...

Блог
_PROGRAMM_ вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Замена клавиш в чужом приложении при нажатии Ecosasha Win Api 4 25.12.2011 14:07
Как сделать чтобы программа не закрывалась при нажатии клавиш alt+f4 (Delphi) zig1 Помощь студентам 1 12.12.2011 06:18
при нажатии цифр поменять значение буквенных клавиш местами(Assembler) lexa123 Помощь студентам 1 16.12.2010 20:29
программа, выводящая сообщения о нажатии клавиш мыши Pljus1 Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 2 29.11.2010 04:49
Open GL. при нажатии клавиш Left, Ridth, Up и Down точка должна двигаться по форме Roof Gamedev - cоздание игр: Unity, OpenGL, DirectX 27 16.11.2007 01:33