2022-07-26 12:40:54 +08:00
|
|
|
module;
|
|
|
|
#include <Windows.h>
|
|
|
|
#include <windowsx.h>
|
|
|
|
#include <wincodec.h>
|
|
|
|
#include <iostream>
|
|
|
|
#include <chrono>
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2022-08-05 23:50:08 +08:00
|
|
|
status = Begin;
|
2022-07-26 12:40:54 +08:00
|
|
|
|
2022-08-05 23:50:08 +08:00
|
|
|
image = Texture::LoadFromFile(L"Steve.png");
|
|
|
|
|
|
|
|
steve.imge = image;
|
|
|
|
obs.imge = image;
|
|
|
|
score.imge = image;
|
|
|
|
background.imge = image;
|
2022-07-26 12:40:54 +08:00
|
|
|
|
2022-08-05 23:50:08 +08:00
|
|
|
steve.OnStartUp();
|
|
|
|
obs.OnStartUp();
|
|
|
|
score.OnStartUp();
|
|
|
|
background.OnStartUp();
|
|
|
|
}
|
|
|
|
bool vk_space_down = false;
|
2022-07-26 12:40:54 +08:00
|
|
|
void Game::Update()
|
|
|
|
{
|
|
|
|
auto now = steady_clock::now();
|
|
|
|
delta = duration_cast<duration<float>>(now - last).count();
|
|
|
|
last = now;
|
2022-08-05 23:50:08 +08:00
|
|
|
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);
|
|
|
|
{
|
2022-08-06 00:47:11 +08:00
|
|
|
auto s_r = steve.getRect();
|
|
|
|
auto o_r = obs.getRect();
|
|
|
|
if (isIntersection(s_r, o_r))
|
|
|
|
{
|
|
|
|
status = End;
|
|
|
|
steve.status = Steve::Dead;
|
|
|
|
steve.imge.rect = Steve::DeadRect;
|
|
|
|
steve.Size = steve.imge.rect.size();
|
|
|
|
}
|
2022-08-05 23:50:08 +08:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2022-07-26 12:40:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Game::Render()
|
|
|
|
{
|
|
|
|
Graphics::BeginDraw();
|
|
|
|
Graphics::Clear();
|
|
|
|
|
2022-08-05 23:50:08 +08:00
|
|
|
background.OnRender();
|
|
|
|
obs.OnRender();
|
2022-07-26 12:40:54 +08:00
|
|
|
steve.OnRender();
|
2022-08-05 23:50:08 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2022-07-26 12:40:54 +08:00
|
|
|
Graphics::Present();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Game::LaterUpdate()
|
|
|
|
{
|
2022-08-05 23:50:08 +08:00
|
|
|
if (status == Running)
|
|
|
|
{
|
|
|
|
steve.OnLaterUpdate(delta);
|
|
|
|
obs.OnLaterUpdate(delta);
|
|
|
|
background.speed = obs.speed;
|
|
|
|
background.OnLaterUpdate(delta);
|
|
|
|
score.OnLaterUpdate(delta);
|
|
|
|
}
|
|
|
|
KeyBoard::Flush();
|
2022-07-26 12:40:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Game::CleanUp()
|
|
|
|
{
|
|
|
|
steve.OnCleanUp();
|
2022-08-05 23:50:08 +08:00
|
|
|
obs.OnCleanUp();
|
|
|
|
score.OnCleanUp();
|
|
|
|
background.OnCleanUp();
|
2022-07-26 12:40:54 +08:00
|
|
|
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<CREATESTRUCTW*>(lParam);
|
|
|
|
auto wnd_ptr = reinterpret_cast<Game*>(CreateData->lpCreateParams);
|
|
|
|
|
|
|
|
SetWindowLongPtrW(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&Game::WndProcThunk));
|
|
|
|
SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(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<Game*>(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:
|
2022-08-05 23:50:08 +08:00
|
|
|
KeyBoard::OnKeyMsg((char)wParam, true);
|
2022-07-26 12:40:54 +08:00
|
|
|
break;
|
|
|
|
case WM_KEYUP:
|
2022-08-05 23:50:08 +08:00
|
|
|
KeyBoard::OnKeyMsg((char)wParam, false);
|
2022-07-26 12:40:54 +08:00
|
|
|
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;
|
|
|
|
}
|