module; #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); status = Begin; image = Texture::LoadFromFile(L"Steve.png"); steve.imge = image; obs.imge = image; score.imge = image; background.imge = image; steve.OnStartUp(); obs.OnStartUp(); score.OnStartUp(); background.OnStartUp(); } bool vk_space_down = false; void Game::Update() { auto now = steady_clock::now(); delta = duration_cast>(now - last).count(); last = now; switch (status) { case Game::Begin: if (KeyBoard::GetKey(VK_SPACE)) status = Running; break; case Game::Running: steve.OnUpdate(delta); obs.OnUpdate(delta); background.OnUpdate(delta); score += obs.speed * delta; score.OnUpdate(delta); if (isIntersection(steve.getRect(), obs.getRect())) { status = End; steve.status = Steve::Dead; steve.imge.rect = Steve::DeadRect; steve.Size = steve.imge.rect.size(); } break; case Game::End: if (KeyBoard::GetKeyDown(VK_SPACE)) vk_space_down = true; if (vk_space_down && KeyBoard::GetKeyUp(VK_SPACE)) { vk_space_down = false; steve.OnReset(); obs.OnReset(); score.OnReset(); background.OnReset(); status = Begin; } break; default: break; } } void Game::Render() { Graphics::BeginDraw(); Graphics::Clear(); background.OnRender(); obs.OnRender(); steve.OnRender(); score.OnRender(); if (status == End) { Rect gameover_rect = { 1294,29,1675,50 }; auto size = gameover_rect.size(); size.x /= 2; size.y /= 2; Graphics::DrawBitMap(image.bitmap, { 525 - size.x,250 - size.y,525 + size.x,250+size.y }, gameover_rect); } Graphics::Present(); } void Game::LaterUpdate() { if (status == Running) { steve.OnLaterUpdate(delta); obs.OnLaterUpdate(delta); background.speed = obs.speed; background.OnLaterUpdate(delta); score.OnLaterUpdate(delta); } KeyBoard::Flush(); } void Game::CleanUp() { steve.OnCleanUp(); obs.OnCleanUp(); score.OnCleanUp(); background.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::OnKeyMsg((char)wParam, true); break; case WM_KEYUP: KeyBoard::OnKeyMsg((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; }