module; #include #include #include #include #include #include module MegaEngine; import Input; using namespace std; using namespace std::chrono; void Game::Run() { StartUp(); while (PeekMsg() && !Done()) { Update(); Render(); LaterUpdate(); } CleanUp(); } void Game::StartUp() { last = steady_clock::now(); CreateWnd(); Graphics::Init(hwnd); steve.OnStartUp(); } void Game::Update() { auto now = steady_clock::now(); delta = duration_cast>(now - last).count(); last = now; steve.OnUpdate(delta); } void Game::Render() { Graphics::BeginDraw(); Graphics::Clear(); steve.OnRender(); Graphics::Present(); } void Game::LaterUpdate() { steve.OnLaterUpdate(delta); } void Game::CleanUp() { steve.OnCleanUp(); Graphics::Finalize(); if (hwnd) DestroyWindow(hwnd); auto hInst = GetModuleHandleW(nullptr); UnregisterClassW(L"1mGameWnd", hInst); } void Game::CreateWnd() { auto hInst = GetModuleHandleW(nullptr); WNDCLASSEXW wc = { sizeof(WNDCLASSEXW), CS_CLASSDC, WndProcSetUp, 0, 0, hInst, LoadIconW(nullptr, IDI_APPLICATION), LoadCursorW(nullptr, IDC_ARROW), CreateSolidBrush(0x808080), nullptr, wndClassName, nullptr }; wc.lpszClassName = L"1mGameWnd"; RegisterClassExW(&wc); auto wnd_style = WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME;//WS_CAPTION | WS_SYSMENU; RECT client_rect{ 0, 0, wndWidth, wndHeight }; AdjustWindowRectEx(&client_rect, wnd_style, FALSE, 0u); hwnd = CreateWindowExW ( 0L, L"1mGameWnd", L"1mGame", wnd_style, CW_USEDEFAULT, CW_USEDEFAULT, client_rect.right - client_rect.left, client_rect.bottom - client_rect.top, nullptr, nullptr, hInst, (LPVOID)this ); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); } bool Game::PeekMsg() { MSG msg; while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) return false; DispatchMessageW(&msg); } return true; } bool Game::Done() { return done; } LRESULT CALLBACK Game::WndProcSetUp(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg == WM_NCCREATE) { ImmDisableIME(GetCurrentThreadId()); auto CreateData = reinterpret_cast(lParam); auto wnd_ptr = reinterpret_cast(CreateData->lpCreateParams); SetWindowLongPtrW(hWnd, GWLP_WNDPROC, reinterpret_cast(&Game::WndProcThunk)); SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast(wnd_ptr)); return wnd_ptr->WndProc(hWnd, msg, wParam, lParam); } return DefWindowProcW(hWnd, msg, wParam, lParam); } LRESULT CALLBACK Game::WndProcThunk(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { auto wnd_ptr = reinterpret_cast(GetWindowLongPtrW(hWnd, GWLP_USERDATA)); return wnd_ptr->WndProc(hWnd, msg, wParam, lParam); } LRESULT Game::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_KEYDOWN: KeyBoard::Update((char)wParam, true); break; case WM_KEYUP: KeyBoard::Update((char)wParam, false); break; case WM_CLOSE: done = true; DestroyWindow(hwnd); hwnd = nullptr; break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProcW(hWnd, msg, wParam, lParam); } return 0; }