#define _CRT_SECURE_NO_WARNINGS #ifdef _MSC_VER #pragma comment(lib, "opengl32.lib") #pragma comment(lib, "glu32.lib") #endif #include "Global.h" #include "Utils.h" #include "Render.h" #include "Physics.h" #include "RESOURCE.H" #include "Logger.hpp" #include "fabula.hpp" // Deklaracje funkcji lokalnych w Main LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); BOOL APIENTRY AboutDlgProc(HWND hDlg, UINT message, UINT wParam, LONG lParam); // Zmienne globalne tylko dla okna static LPCTSTR lpszAppName = "grafikaKBT"; static HINSTANCE hInstance; static const int targetFPS = 144; int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { CreateConsole(); DisableQuickEdit(); AsyncLogger::getInstance().start(); MSG msg; WNDCLASS wc{}; HWND hWnd; hInstance = hInst; wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU); wc.lpszClassName = lpszAppName; if (RegisterClass(&wc) == 0) return FALSE; int screenWidth = GetSystemMetrics(SM_CXSCREEN); int screenHeight = GetSystemMetrics(SM_CYSCREEN); // 2. Utwórz okno z pełnym zestawem przycisków (WS_OVERLAPPEDWINDOW) hWnd = CreateWindow( lpszAppName, lpszAppName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, // Pozycja startowa (lewy górny róg) screenWidth, screenHeight, // Rozmiar (wstępnie cały ekran) NULL, NULL, hInstance, NULL); if (hWnd == NULL) return FALSE; HDC hDC = GetDC(hWnd); const WORD ID_TIMER = 1; SetTimer(hWnd, ID_TIMER, 100, NULL); ShowWindow(hWnd, SW_SHOWMAXIMIZED); UpdateWindow(hWnd); ZeroMemory(&msg, sizeof(msg)); auto lastFrameTime = std::chrono::high_resolution_clock::now(); while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { auto currentFrameTime = std::chrono::high_resolution_clock::now(); std::chrono::duration timeSpan = currentFrameTime - lastFrameTime; deltaTime = timeSpan.count(); lastFrameTime = currentFrameTime; RenderScene(); SwapBuffers(hDC); GAME_LOG("Klatka wyrenderowana. FPS: " << fpsCounter.getFPS()); LimitFPS(targetFPS); } } ReleaseDC(hWnd, hDC); return msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HGLRC hRC; static HDC hDC; switch (message) { case WM_CREATE: hDC = GetDC(hWnd); SetDCPixelFormat(hDC); GetOpenGLPalette(hDC); hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); SetupRC(); // Ładowanie tekstur (uproszczone dla czytelności, można wydzielić funkcję LoadTextures) { GLfloat fLargest; glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest); glGenTextures(4, &texture[0]); // Tutaj możesz przenieść logikę ładowania tekstur do np. Utils.cpp -> LoadAllTextures() // Aby nie zaśmiecać WndProc. const char* texFiles[] = { "res/img/woodenTextureHighExposure.bmp", "res/img/grass02.bmp", "res/img/barnroof.bmp", "res/img/brickwall.bmp" }; for (int i = 0; i < 4; i++) { bitmapData = LoadBitmapFile((char*)texFiles[i], &bitmapInfoHeader); if (bitmapData) { glBindTexture(GL_TEXTURE_2D, texture[i]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); // lub GL_CLAMP zależnie od idx glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeight, GL_RGB, GL_UNSIGNED_BYTE, bitmapData); free(bitmapData); } } glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } break; case WM_DESTROY: user.unload(); wglMakeCurrent(hDC, NULL); wglDeleteContext(hRC); PostQuitMessage(0); AsyncLogger::getInstance().stop(); break; case WM_SIZE: ChangeSize(LOWORD(lParam), HIWORD(lParam)); break; case WM_MOUSEWHEEL: { int zDelta = GET_WHEEL_DELTA_WPARAM(wParam); CameraHeight -= (float)zDelta * 0.1f; if (CameraHeight < 20.0f) CameraHeight = 20.0f; // Stała MinDistance if (CameraHeight > 1000.0f) CameraHeight = 1000.0f; // Stała MaxDistance } break; case WM_KEYUP: switch (wParam) { case 'W': keyWPressed = false; break; case 'S': keySPressed = false; break; case 'A': keyAPressed = false; break; case 'D': keyDPressed = false; break; case 112: // F1 fpv_view = !fpv_view; if (fpv_view) panoramic_view = false; break; case 'N': dayNight.toggle(); break; } break; case WM_KEYDOWN: switch (wParam) { case VK_UP: xRot -= 5.0f; break; case VK_DOWN: xRot += 5.0f; break; case VK_LEFT: yRot -= 5.0f; break; case VK_RIGHT: yRot += 5.0f; break; case 'Q': zRot += 5.0f; break; case 'E': zRot -= 5.0f; break; case 'R': xRot = yRot = zRot = 0; break; case ' ': polygonmode = !polygonmode; break; case 'K': Kolizja = !Kolizja; break; case 'W': keyWPressed = true; break; case 'S': keySPressed = true; break; case 'A': keyAPressed = true; break; case 'D': keyDPressed = true; break; case 116: // F5 case 16: // Shift panoramic_view = !panoramic_view; break; case 8: // Backspace nadpiszNowaSiatke(biezacy_wzor); // Zakładam, że ta zmienna jest w fabula.hpp break; } break; case WM_COMMAND: switch (LOWORD(wParam)) { case ID_FILE_EXIT: DestroyWindow(hWnd); break; case ID_HELP_ABOUT: DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG_ABOUT), hWnd, (DLGPROC)AboutDlgProc); break; } break; default: return (DefWindowProc(hWnd, message, wParam, lParam)); } return (0L); } BOOL APIENTRY AboutDlgProc(HWND hDlg, UINT message, UINT wParam, LONG lParam) { if (message == WM_INITDIALOG) { // ... (Kod dialogu bez zmian, ewentualnie dodaj include gluGetString) return TRUE; } if (message == WM_COMMAND && LOWORD(wParam) == IDOK) EndDialog(hDlg, TRUE); if (message == WM_CLOSE) EndDialog(hDlg, TRUE); return FALSE; }