N
N
Nikita Kargin2021-07-24 18:45:14
C++ / C#
Nikita Kargin, 2021-07-24 18:45:14

Why does the program freeze for half a second when two keys are pressed at the same time?

I am trying to write a simple tennis game.
If you press the A / Z, OEM_2 / OEM_7 keys, you can move the first and second paddle up and down, respectively.
The problem is that if I hold down one key and press another, then there is a slight delay. Let me explain with an example.
Let's say I move my left paddle up. At some point, I press a button that moves the right paddle down. In this case, everything stops for half a second and then continues as it should. How to get rid of this half second delay?

#include <windows.h>
const double PI = 3.141592653;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
char szClassName[] = "CG_WAPI_Template";
/////////////////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmd
{
HWND hWnd;
MSG lpMsg;
WNDCLASS wc;
// Заполняем структуру класса окна
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = (LPCWSTR)szClassName;
// Регистрируем класс окна
if (!RegisterClass(&wc))
{
MessageBox(NULL, (LPCWSTR)"Не могу зарегистрировать класс окна!", (LPCWSTR)"Ошибка", MB_O
return 0;
}
// Создаем основное окно приложения
hWnd = CreateWindow(
(LPCWSTR)szClassName, // Имя класса
L"Шаблон WinAPI приложения", // Текст заголовка
WS_OVERLAPPEDWINDOW, // Стиль окна
50, 50, // Позиция левого верхнего угла
600, 600, // Ширина и высота окна
(HWND) NULL, // Указатель на родительское окно NULL
(HMENU) NULL, // Используется меню класса окна
(HINSTANCE)hInstance, // Указатель на текущее приложение
NULL ); // Передается в качестве lParam в событие WM_CREATE
if (!hWnd)
{
MessageBox(NULL, (LPCWSTR)"Не удается создать главное окно!", (LPCWSTR)"Ошибка", MB_OK);
return 0;
}
// Показываем наше окно
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Выполняем цикл обработки сообщений до закрытия приложения
while (GetMessage(&lpMsg, NULL, 0, 0))
{
TranslateMessage(&lpMsg);
DispatchMessage(&lpMsg);
}
return (lpMsg.wParam);
}
/////////////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
RECT Rect;
Директива препроцессора #include <windows.h> открывает доступ к тысячам описаний констант,
структур, типов данных и функций Windows.
WinAPI приложение является в своей основе процедурным приложением и содержит два основных
модуля – функции WinMain и WndProc.
HDC hdc, hCmpDC;
HBITMAP hBmp;
switch (messg)
{
case WM_PAINT:
GetClientRect(hWnd, &Rect);
hdc = BeginPaint(hWnd, &ps);
// Создание теневого контекста для двойной буферизации
hCmpDC = CreateCompatibleDC(hdc);
hBmp = CreateCompatibleBitmap(hdc, Rect.right - Rect.left,
Rect.bottom - Rect.top);
SelectObject(hCmpDC, hBmp);
// Закраска фоновым цветом
LOGBRUSH br;
br.lbStyle = BS_SOLID;
br.lbColor = 0xEECCCC;
HBRUSH brush;
brush = CreateBrushIndirect(&br);
FillRect(hCmpDC, &Rect, brush);
DeleteObject(brush);
// Здесь рисуем на контексте hCmpDC
// Копируем изображение из теневого контекста на экран
SetStretchBltMode(hdc, COLORONCOLOR);
BitBlt(hdc, 0, 0, Rect.right - Rect.left, Rect.bottom - Rect.top,
hCmpDC, 0, 0, SRCCOPY);
// Удаляем ненужные системные объекты
DeleteDC(hCmpDC);
DeleteObject(hBmp);
hCmpDC = NULL;
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN: 		
speed=10; 		
if (GetAsyncKeyState(0x41)){ 
pos1+=speed; 				
if (pos1>320){ 					
pos1=320; 				
} 		
} 		
if (GetAsyncKeyState(0x5A)){ 			
pos1-=speed; 				
if (pos1<0){ 					
pos1=0; 				
} 		
} 		
if (GetAsyncKeyState(VK_OEM_7)){ 

pos2+=speed; 				
if (pos2>320){ 					
pos2=320; 				
} 		
} 		
if (GetAsyncKeyState(VK_OEM_2)){ 			

pos2-=speed;	
if (pos2<0){ 					
pos2=0; 				
} 		
}	 		
InvalidateRect(hWnd,0,false); 		
UpdateWindow(hWnd); 		
break;
default:
return (DefWindowProc(hWnd, messg, wParam, lParam));
}

Notes:
1. The template is not mine, I copied it. Originally it was called "winapi graphic application template"
2. This is my first winapi application. So don't judge too harshly
3. The draw function simply draws a horizontal line and a vertical line in the middle, and also draws paddles based on their position. I don't think it should be included here, but if it is, I'll attach it
Thanks in advance

Answer the question

In order to leave comments, you need to log in

1 answer(s)
N
Nikita Kargin, 2021-07-25
@Pakonigoosy

Found a solution to the problem. The bottom line is that in the WM_KEYDOWN block, set the values ​​of the boolean variables is1up_pressed, is1down_pressed, is2up_pressed, is2down_pressed, each of which is responsible for its own button. I also added a WM_KEYUP block where I check if the keys are released.
I change the position of the racket on a timer 25 times per second

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question