Я всегда был довольно знаком с C. Я решил использовать C с Visual Studio 2017, чтобы сделать небольшую windows игру для промежуточного проекта в моем классе AP по информатике в этом году. Конечно, он использует winapi, но я использую библиотеку wingdi для рендеринга простой 2d игры; использование wingdi, возможно, не лучший метод, но в целях экономии времени и простоты я решил сделать это, поскольку у меня действительно есть всего пара дней, чтобы завершить sh this.
Игра загружает среды в что вы можете перемещаться по персонажу вокруг него, и когда я закончил тестировать простую физику двумерных столкновений, которую я реализовал для движения персонажа и стен, я понял, что когда я оставлял приложение работающим в режиме отладки, казалось, что оно перестало рисовать зеленые границы стен для среды Demo, вскоре после этого маленький прямоугольник для хитбокса персонажа исчез, а когда я изменил размер окна, вся верхняя панель исчезла и была заменена на коричневый цвет фона, для которого я установил hbrBackground окна .
Я прочитал пост о ком-то, у кого также были проблемы с рисованием wingdi, и люди предположили, что это утечка памяти, но мое приложение значительно меньше, и я действительно не вижу ничего, что могло бы быть памятью. утечка в моем с Ода, насколько мне известно ...
Я установил таймер с USER_TIMER_MINIMUM, чтобы вызывать InvalidateRect, чтобы экран можно было постоянно обновлять, поскольку персонаж должен иметь возможность перемещаться.
В WM_PAINT я был уверен, что начать с BeginPaint и закрыть с EndPaint. Вот мой код, который на самом деле имеет дело с wingdi:
source. c:
int DEMO_ROOM[] =
{
0, 0, 500, 10,
0, 0, 10, 500,
490, 0, 500, 500,
0, 490, 500, 500
};
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch (msg)
{
case WM_CREATE:
RunTrack1();
TITLE_IMAGE = LoadBitmapA(PROGRAM, MAKEINTRESOURCE(IDB_PNG1));
char_pos.X = 250;
char_pos.Y = 250;
SetTimer(hwnd, 1, USER_TIMER_MINIMUM, NULL);
break;
case WM_TIMER:
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
LoadRoom(hdc, hwnd, &DEMO_ROOM, sizeof(DEMO_ROOM));
LoadChar(hdc, hwnd, char_pos.X, char_pos.Y);
EndPaint(hwnd, &ps);
break;
case WM_KEYDOWN:
switch (wParam)
{
case 0x57: //W
MoveChar
(
&char_pos,
char_pos.X,
char_pos.Y - 5,
&DEMO_ROOM,
sizeof(DEMO_ROOM)
);
break;
case 0x41: //A
MoveChar
(
&char_pos,
char_pos.X - 5,
char_pos.Y,
&DEMO_ROOM,
sizeof(DEMO_ROOM)
);
break;
case 0x53: //S
MoveChar
(
&char_pos,
char_pos.X,
char_pos.Y + 5,
&DEMO_ROOM,
sizeof(DEMO_ROOM)
);
break;
case 0x44: //D
MoveChar
(
&char_pos,
char_pos.X + 5,
char_pos.Y,
&DEMO_ROOM,
sizeof(DEMO_ROOM)
);
break;
default:
break;
}
break;
case WM_KEYUP:
break;
case WM_GETMINMAXINFO:
((LPMINMAXINFO)lParam)->ptMinTrackSize.x = GetSystemMetrics(SM_CXSCREEN) / 2;
((LPMINMAXINFO)lParam)->ptMinTrackSize.y = GetSystemMetrics(SM_CYSCREEN) / 2;
break;
case WM_DESTROY:
//KillTimer(hwnd, 1);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
GameLibrary.h:
GameCoordinate GameSpaceToWindowSpace(HWND hwnd, int X, int Y, int MAX)
{
RECT w;
GameCoordinate pos;
if (GetWindowRect(hwnd, &w))
{
int width = (w.right - w.left) - 20;
int height = (w.bottom - w.top) - 43;
float XRatio = (float)X / (float)MAX;
float YRatio = (float)Y / (float)MAX;
float XWindowPos = XRatio * (float)width;
float YWindowPos = YRatio * (float)height;
pos.X = (int)XWindowPos;
pos.Y = (int)YWindowPos;
}
return pos;
}
void LoadRoom(HDC hdc, HWND hwnd, int * ROOM_DATA, unsigned int R_SIZE)
{
for (unsigned int i = 0; i < (R_SIZE / 16); i++)
{
int left = ROOM_DATA[i * 4];
int top = ROOM_DATA[(i * 4) + 1];
int right = ROOM_DATA[(i * 4) + 2];
int bottom = ROOM_DATA[(i * 4) + 3];
GameCoordinate C1 = GameSpaceToWindowSpace(hwnd, left, top, 500);
GameCoordinate C2 = GameSpaceToWindowSpace(hwnd, right, bottom, 500);
RECT obj;
obj.left = C1.X;
obj.top = C1.Y;
obj.right = C2.X;
obj.bottom = C2.Y;
FillRect(hdc, &obj, CreateSolidBrush(RGB(22, 110, 18)));
}
}
void LoadChar(HDC hdc, HWND hwnd, int x, int y)
{
GameCoordinate windowPos = GameSpaceToWindowSpace(hwnd, x, y, 500);
Rectangle(hdc, windowPos.X - 1, windowPos.Y - 1, windowPos.X + 1, windowPos.Y + 1);
}
Это не было действительно необходимо для чтобы я включил функцию GameSpaceToWindowSpace в код, но я решил, просто чтобы избежать путаницы с моей маленькой пользовательской системой координат.
Этот код пока что в значительной степени моя игра, за исключением двух функций столкновения, моего WinMain и пара глобальных переменных.
Вот изображение того, как должно выглядеть окно, маленькая точка с синим кружком вокруг нее представляет координату персонажа, а зеленые стены вокруг окна должны быть пограничными стенами, чтобы помочь мне проверить столкновения:
Вот что происходит с окном примерно через 30 секунд:
Иногда прямоугольник символа также исчезает, и это последнее изображение представляет собой представление, показывающее, что по какой-то причине оно больше не будет рисовать, или refre sh окно; как у меня было окно развернуто, а затем свернуло его, чтобы показать, что прямоугольники границы не изменили свой размер и положение с окном:
To В заключение, я определенно новичок в wingdi, но с моим знакомством с winapi я решил, что лучше всего будет создать простую графику для простой 2D-игры за короткий промежуток времени. Однако, когда мое приложение выполняется в течение немного продолжительного времени, процесс рисования кажется неудачным, и он больше не может обновлять и обновлять sh содержимое окна. Я действительно не уверен, что проблема здесь, и при этом я не знаю, как я мог бы должным образом решить это. Я не думаю, что это утечка памяти из-за небольшого размера моей программы в настоящее время, однако я также в значительной степени нуб из-за wingdi, так что я могу быть очень неправ, и это вполне может быть утечка памяти, но в любом случае я не знаю, как go решить эту проблему, и буду признателен за более опытное понимание проблемы.
Спасибо всем за ваше время и опыт.