diff --git a/1mGame.vcxproj b/1mGame.vcxproj index 30df8b9..9aed699 100644 --- a/1mGame.vcxproj +++ b/1mGame.vcxproj @@ -56,6 +56,7 @@ WIN32_LEAN_AND_MEAN;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 + stdc17 Console @@ -72,6 +73,7 @@ WIN32_LEAN_AND_MEAN;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 + stdc17 Windows @@ -85,13 +87,19 @@ + + + + + + diff --git a/1mGame.vcxproj.filters b/1mGame.vcxproj.filters index 2c7b4ff..46ee765 100644 --- a/1mGame.vcxproj.filters +++ b/1mGame.vcxproj.filters @@ -42,5 +42,19 @@ 源文件 + + 源文件 + + + 源文件 + + + 源文件 + + + + + 资源文件 + \ No newline at end of file diff --git a/BackGround.ixx b/BackGround.ixx new file mode 100644 index 0000000..b2d7da7 --- /dev/null +++ b/BackGround.ixx @@ -0,0 +1,69 @@ +module; + + +export module BackGround; +import GameObject; +import Graphics; + +export struct BackGround : GameObject +{ + static constexpr Rect GroundRect{ 2,104,2402,130 }; + static constexpr Rect CloudRect{ 166,2,258,29 }; + float speed = -500.f; + Vector2 CloudPosi; + virtual void OnStartUp() + { + imge.rect = GroundRect; + Posi = { 0,50 }; + CloudPosi = { 1050,200 }; + Size = imge.rect.size(); + } + virtual void OnCleanUp() + { + + } + virtual void OnUpdate(float delta) + { + Posi.x += speed * delta; + CloudPosi.x += speed * delta * 0.5f; + } + virtual void OnLaterUpdate(float delta) + { + if (Posi.x <= -Size.x) + { + Posi.x += Size.x; + } + if (CloudPosi.x <= 0 - CloudRect.size().x) + { + CloudPosi.x = 1050; + } + } + virtual void OnReset() override + { + Posi.x = 0; + } + virtual void OnRender() override + { + Rect dst = + { + Posi.x - Size.x * Anch.x, + Posi.y + Size.y * (1.f - Anch.y), + Posi.x + Size.x * (1.f - Anch.x), + Posi.y - Size.y * Anch.y, + }; + Graphics::DrawBitMap(imge.bitmap, dst, imge.rect); + dst.left += Size.x; + dst.right += Size.x; + Graphics::DrawBitMap(imge.bitmap, dst, imge.rect); + + auto cloud_size = CloudRect.size(); + Rect cloud_dst = + { + CloudPosi.x, + CloudPosi.y + cloud_size.y, + CloudPosi.x + cloud_size.x, + CloudPosi.y, + }; + Graphics::DrawBitMap(imge.bitmap, dst, CloudRect); + } +}; \ No newline at end of file diff --git a/GameObject.ixx b/GameObject.ixx index 7d697e4..680a0e9 100644 --- a/GameObject.ixx +++ b/GameObject.ixx @@ -36,12 +36,34 @@ public: Vector2 Anch; Vector2 Size; + Rect getRect() const + { + return + { + Posi.x - Size.x * Anch.x, + Posi.y - Size.y * Anch.y, + Posi.x + Size.x * (1.f - Anch.x), + Posi.y + Size.y * (1.f - Anch.y), + }; + } + + bool isPaused = false; + void Pause() + { + isPaused = true; + } + void Resume() + { + isPaused = false; + } + GameObject() {} virtual void OnStartUp() = 0; virtual void OnCleanUp() = 0; virtual void OnUpdate(float delta) = 0; virtual void OnLaterUpdate(float delta) = 0; + virtual void OnReset() {} virtual void OnRender() { diff --git a/Graphics.cpp b/Graphics.cpp index 504667d..a4d0ca3 100644 --- a/Graphics.cpp +++ b/Graphics.cpp @@ -9,8 +9,6 @@ module Graphics; using namespace D2D1; using namespace ::Microsoft::WRL; -constexpr D2D1_RECT_F SteveRect{ 1678,2,1766,96 }; - ComPtr Graphics::RT = nullptr; ComPtr Graphics::wic_factory = nullptr; Vector2 Graphics::RtSize{}; diff --git a/Input.ixx b/Input.ixx index 1b3fc98..29d2898 100644 --- a/Input.ixx +++ b/Input.ixx @@ -1,20 +1,35 @@ module; +#include export module Input; export class KeyBoard { - static bool KeyStatus[256]; + static bool LastKeyStatus[256]; + static bool CurrKeyStatus[256]; public: - static void Update(char keycode, bool status) + static void OnKeyMsg(char keycode, bool status) { - KeyStatus[keycode] = status; + CurrKeyStatus[keycode] = status; } static bool GetKey(char keycode) { - return KeyStatus[keycode]; + return CurrKeyStatus[keycode]; + } + static bool GetKeyUp(char keycode) + { + return LastKeyStatus[keycode] && !CurrKeyStatus[keycode]; + } + static bool GetKeyDown(char keycode) + { + return !LastKeyStatus[keycode] && CurrKeyStatus[keycode]; + } + static void Flush() + { + memcpy(LastKeyStatus, CurrKeyStatus, sizeof(CurrKeyStatus)); } }; -bool KeyBoard::KeyStatus[256]{}; \ No newline at end of file +bool KeyBoard::LastKeyStatus[256]{}; +bool KeyBoard::CurrKeyStatus[256]{}; \ No newline at end of file diff --git a/Math.ixx b/Math.ixx index 9b4227e..c8381e3 100644 --- a/Math.ixx +++ b/Math.ixx @@ -1,5 +1,6 @@ module; #include +#include export module Math; @@ -16,4 +17,19 @@ export return { right - left, bottom - top }; } }; + + inline bool isIntersection(const Rect& lhs, const Rect& rhs) + { + auto ox1 = (lhs.left + lhs.right) * 0.5f; + auto oy1 = (lhs.top + lhs.bottom) * 0.5f; + auto ox2 = (rhs.left + rhs.right) * 0.5f; + auto oy2 = (rhs.top + rhs.bottom) * 0.5f; + + auto rx1 = abs(lhs.right - lhs.left) * 0.5f; + auto ry1 = abs(lhs.top - lhs.bottom) * 0.5f; + auto rx2 = abs(rhs.right - rhs.left) * 0.5f; + auto ry2 = abs(rhs.top - rhs.bottom) * 0.5f; + + return ((abs(ox1 - ox2) - (rx1 + rx2)) < -20.f) && ((abs(oy1 - oy2) - (ry1 + ry2)) < -20.f); + } } \ No newline at end of file diff --git a/MegaEngine.cpp b/MegaEngine.cpp index f5ef46e..f99f70a 100644 --- a/MegaEngine.cpp +++ b/MegaEngine.cpp @@ -4,7 +4,6 @@ module; #include #include #include -#include module MegaEngine; @@ -34,16 +33,61 @@ void Game::StartUp() 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; - steve.OnUpdate(delta); + 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() @@ -51,20 +95,41 @@ 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() { - steve.OnLaterUpdate(delta); + 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); @@ -163,10 +228,10 @@ LRESULT Game::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) switch (msg) { case WM_KEYDOWN: - KeyBoard::Update((char)wParam, true); + KeyBoard::OnKeyMsg((char)wParam, true); break; case WM_KEYUP: - KeyBoard::Update((char)wParam, false); + KeyBoard::OnKeyMsg((char)wParam, false); break; case WM_CLOSE: done = true; diff --git a/MegaEngine.ixx b/MegaEngine.ixx index 56608b1..74ed1c9 100644 --- a/MegaEngine.ixx +++ b/MegaEngine.ixx @@ -10,6 +10,9 @@ import Input; import Graphics; import GameObject; import Steve; +import Obstacle; +import ScoreBoard; +import BackGround; using namespace std; using namespace std::chrono; @@ -25,10 +28,16 @@ public: void Run(); private: + Texture image; Steve steve; + Obstacle obs; + ScoreBoard score; + BackGround background; steady_clock::time_point last; float delta; + enum Status { Begin, Running, End } status; + HWND hwnd = nullptr; bool done = false; @@ -44,6 +53,9 @@ private: bool PeekMsg(); bool Done(); + void GameOver(); + void ReStart(); + static LRESULT CALLBACK WndProcSetUp(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK WndProcThunk(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); diff --git a/Obstacle.ixx b/Obstacle.ixx new file mode 100644 index 0000000..d658c8d --- /dev/null +++ b/Obstacle.ixx @@ -0,0 +1,93 @@ +module; + +#include + +export module Obstacle; + +import GameObject; + +export struct Obstacle : GameObject +{ + static constexpr Rect ObstacleRectList[] + { + //Small Cactus + { 446,2,480,72 }, + { 480,2,514,72 }, + { 514,2,548,72 }, + { 548,2,582,72 }, + { 582,2,616,72 }, + { 616,2,650,72 }, + //Giant Cactus + { 652,2,702,102 }, + { 702,2,750,102 }, + { 752,2,802,102 }, + { 802,2,850,102 }, + //Double Giant Cactus + { 652,2,750,102 }, + { 752,2,850,102 }, + //Tirple Giant Cactus + { 850,2,952,102 }, + //Qradro Giant Cactus + { 802,2,952,102 }, + // + { 260,2,352,82 }, + { 352,2,444,82 }, + }; + + float speed = -500.f; + float time = 0.f; + bool isCactus = true; + virtual void OnStartUp() override + { + imge.rect = ObstacleRectList[0]; + Size = imge.rect.size(); + Posi = { 1200, 50 }; + Anch = { 0.5f,0 }; + Reset(); + } + virtual void OnCleanUp() override + { + + } + virtual void OnUpdate(float delta) override + { + time += delta; + Posi.x += speed * delta; + imge.rect = (int)(time / 0.3) % 2 ? ObstacleRectList[14] : ObstacleRectList[15]; + } + virtual void OnLaterUpdate(float delta) override + { + if (Posi.x <= -100.f) Reset(); + } + void Start() + { + + } + std::mt19937 random{std::random_device()()}; + void Reset() + { + int index = 14;// random() % 15; + if (index == 14) + { + isCactus = false; + Posi.y = 125; + } + else + { + isCactus = true; + Posi.y = 50; + } + imge.rect = ObstacleRectList[index]; + Size = imge.rect.size(); + speed += -1.f; + Posi.x = 1200.f; + } + virtual void OnReset() override + { + imge.rect = ObstacleRectList[0]; + Size = imge.rect.size(); + Posi = { 1200, 50 }; + Anch = { 0.5f,0 }; + Reset(); + } +}; \ No newline at end of file diff --git a/ScoreBoard.ixx b/ScoreBoard.ixx new file mode 100644 index 0000000..71f430b --- /dev/null +++ b/ScoreBoard.ixx @@ -0,0 +1,100 @@ +module; + +#include +#include + +export module ScoreBoard; + +import GameObject; +import Math; + +struct Digit : GameObject +{ + static constexpr Rect DigitsRectList[] + { + { 1294,2,1314,23 }, + { 1314,2,1334,23 }, + { 1334,2,1354,23 }, + { 1354,2,1374,23 }, + { 1374,2,1394,23 }, + { 1394,2,1414,23 }, + { 1414,2,1434,23 }, + { 1434,2,1454,23 }, + { 1454,2,1474,23 }, + { 1474,2,1494,23 }, + }; + + char value; + + virtual void OnStartUp() + { + + } + virtual void OnCleanUp() + { + + } + virtual void OnUpdate(float delta) + { + + } + virtual void OnLaterUpdate(float delta) + { + + } +}; + +export struct ScoreBoard : GameObject +{ + float score = 0; + std::vector digits; + virtual void OnStartUp() + { + Posi = { 900,400 }; + } + virtual void OnCleanUp() + { + + } + virtual void OnUpdate(float delta) + { + auto str = std::to_string(static_cast(score/100.f)); + digits.resize(str.size()); + for (size_t i = 0; i < digits.size(); i++) + { + auto& digit = digits[i]; + digit.value = str[i] - '0'; + digit.imge = imge; + digit.imge.rect = Digit::DigitsRectList[digit.value]; + digit.Size = digit.imge.rect.size(); + digit.Posi = { Posi.x + i * digit.Size.x, Posi.y }; + } + } + virtual void OnLaterUpdate(float delta) + { + + } + virtual void OnRender() override + { + for (auto& digit : digits) + { + digit.OnRender(); + } + } + virtual void OnReset() override + { + score = 0; + digits.resize(1); + + auto& digit = digits[0]; + digit.value = 0; + digit.imge = imge; + digit.imge.rect = Digit::DigitsRectList[digit.value]; + digit.Size = digit.imge.rect.size(); + digit.Posi = Posi; + } + void operator+=(float value) + { + score += value; + } +}; \ No newline at end of file diff --git a/Steve.ixx b/Steve.ixx index bf421b8..3314db6 100644 --- a/Steve.ixx +++ b/Steve.ixx @@ -9,31 +9,30 @@ import Input; export struct Steve : GameObject { static constexpr const float ground_height = 50; - static constexpr const float y_pos = 100; + static constexpr const float x_pos = 100; float a, v, h; bool jumping = false; float time = 0.0f; - Rect IdleRect = { 76, 2, 164, 96 }; - Rect NormalRect = { 1678, 2, 1766, 96 }; - Rect CloseEyeRect = { 1766, 2, 1854, 96 }; - Rect RightRect = { 1854, 2, 1942, 96 }; - Rect LeftRect = { 1942, 2, 2030, 96 }; - Rect BigEyeRect = { 2030, 2, 2118, 96 }; - Rect DeadRect = { 2122, 2, 2202, 96 }; - Rect CrawlingRightRect = { 2203, 2, 2321, 96 }; - Rect CrawlingLeftRect = { 2321, 2, 2439, 96 }; + static constexpr Rect IdleRect = { 76, 2, 164, 96 }; + static constexpr Rect NormalRect = { 1678, 2, 1766, 96 }; + static constexpr Rect CloseEyeRect = { 1766, 2, 1854, 96 }; + static constexpr Rect RightRect = { 1854, 2, 1942, 96 }; + static constexpr Rect LeftRect = { 1942, 2, 2030, 96 }; + static constexpr Rect BigEyeRect = { 2030, 2, 2118, 96 }; + static constexpr Rect DeadRect = { 2122, 2, 2202, 96 }; + static constexpr Rect CrawlingRightRect = { 2203, 2, 2321, 96 }; + static constexpr Rect CrawlingLeftRect = { 2321, 2, 2439, 96 }; enum Status { Idle, Running, Jumping, Freefall, Crawling, Dead } status; virtual void OnStartUp() override { - imge = Texture::LoadFromFile(L"steve.png"); imge.rect = IdleRect; - Posi = { y_pos, ground_height }; Anch = { 0.5f,0 }; - Size = { 88, 94 }; + Posi = { x_pos, ground_height }; + Size = imge.rect.size(); a = v = h = 0.0f; } @@ -43,12 +42,14 @@ export struct Steve : GameObject } virtual void OnUpdate(float delta) override { + if (isPaused) return; time += delta; switch (status) { case Steve::Idle: if (KeyBoard::GetKey(VK_SPACE)) status = Running; imge.rect = IdleRect; + Size = imge.rect.size(); break; case Steve::Running: if (KeyBoard::GetKey(VK_SPACE)) @@ -56,10 +57,17 @@ export struct Steve : GameObject status = Jumping; break; } + if (KeyBoard::GetKey(VK_DOWN)) + { + status = Crawling; + break; + } imge.rect = (int)(time / 0.1) % 2 ? LeftRect : RightRect; + Size = imge.rect.size(); break; case Steve::Jumping: imge.rect = NormalRect; + Size = imge.rect.size(); if ((h < 75 || KeyBoard::GetKey(VK_SPACE)) && h < 150.f) { v = 1000.f; @@ -84,8 +92,15 @@ export struct Steve : GameObject } break; case Steve::Crawling: - break; - case Steve::Dead: + if (KeyBoard::GetKey(VK_DOWN)) + { + imge.rect = (int)(time / 0.1) % 2 ? CrawlingLeftRect : CrawlingRightRect; + Size = imge.rect.size(); + } + else + { + status = Running; + } break; default: break; @@ -93,5 +108,17 @@ export struct Steve : GameObject } virtual void OnLaterUpdate(float delta) override { + if (isPaused) return; + } + virtual void OnReset() override + { + imge.rect = IdleRect; + status = Idle; + + Anch = { 0.5f,0 }; + Posi = { x_pos, ground_height }; + Size = imge.rect.size(); + + a = v = h = 0.0f; } }; \ No newline at end of file