This commit is contained in:
革匊习习中 2022-08-05 23:50:08 +08:00
parent 47b32bf8a4
commit 7b1b5feaff
12 changed files with 470 additions and 31 deletions

View File

@ -56,6 +56,7 @@
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard> <LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -72,6 +73,7 @@
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard> <LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@ -85,13 +87,19 @@
<ClCompile Include="GameObject.ixx" /> <ClCompile Include="GameObject.ixx" />
<ClCompile Include="Graphics.cpp" /> <ClCompile Include="Graphics.cpp" />
<ClCompile Include="Graphics.ixx" /> <ClCompile Include="Graphics.ixx" />
<ClCompile Include="BackGround.ixx" />
<ClCompile Include="Input.ixx" /> <ClCompile Include="Input.ixx" />
<ClCompile Include="Math.ixx" /> <ClCompile Include="Math.ixx" />
<ClCompile Include="MegaEngine.cpp" /> <ClCompile Include="MegaEngine.cpp" />
<ClCompile Include="MegaEngine.ixx" /> <ClCompile Include="MegaEngine.ixx" />
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="Obstacle.ixx" />
<ClCompile Include="ScoreBoard.ixx" />
<ClCompile Include="Steve.ixx" /> <ClCompile Include="Steve.ixx" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Image Include="Steve.png" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>

View File

@ -42,5 +42,19 @@
<ClCompile Include="Steve.ixx"> <ClCompile Include="Steve.ixx">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Obstacle.ixx">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="ScoreBoard.ixx">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="BackGround.ixx">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Image Include="Steve.png">
<Filter>资源文件</Filter>
</Image>
</ItemGroup> </ItemGroup>
</Project> </Project>

69
BackGround.ixx Normal file
View File

@ -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);
}
};

View File

@ -36,12 +36,34 @@ public:
Vector2 Anch; Vector2 Anch;
Vector2 Size; 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() {} GameObject() {}
virtual void OnStartUp() = 0; virtual void OnStartUp() = 0;
virtual void OnCleanUp() = 0; virtual void OnCleanUp() = 0;
virtual void OnUpdate(float delta) = 0; virtual void OnUpdate(float delta) = 0;
virtual void OnLaterUpdate(float delta) = 0; virtual void OnLaterUpdate(float delta) = 0;
virtual void OnReset() {}
virtual void OnRender() virtual void OnRender()
{ {

View File

@ -9,8 +9,6 @@ module Graphics;
using namespace D2D1; using namespace D2D1;
using namespace ::Microsoft::WRL; using namespace ::Microsoft::WRL;
constexpr D2D1_RECT_F SteveRect{ 1678,2,1766,96 };
ComPtr<ID2D1HwndRenderTarget> Graphics::RT = nullptr; ComPtr<ID2D1HwndRenderTarget> Graphics::RT = nullptr;
ComPtr<IWICImagingFactory> Graphics::wic_factory = nullptr; ComPtr<IWICImagingFactory> Graphics::wic_factory = nullptr;
Vector2 Graphics::RtSize{}; Vector2 Graphics::RtSize{};

View File

@ -1,20 +1,35 @@
module; module;
#include <memory>
export module Input; export module Input;
export class KeyBoard export class KeyBoard
{ {
static bool KeyStatus[256]; static bool LastKeyStatus[256];
static bool CurrKeyStatus[256];
public: 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) 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]{}; bool KeyBoard::LastKeyStatus[256]{};
bool KeyBoard::CurrKeyStatus[256]{};

View File

@ -1,5 +1,6 @@
module; module;
#include <d2d1.h> #include <d2d1.h>
#include <concepts>
export module Math; export module Math;
@ -16,4 +17,19 @@ export
return { right - left, bottom - top }; 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);
}
} }

View File

@ -4,7 +4,6 @@ module;
#include <wincodec.h> #include <wincodec.h>
#include <iostream> #include <iostream>
#include <chrono> #include <chrono>
#include <thread>
module MegaEngine; module MegaEngine;
@ -34,16 +33,61 @@ void Game::StartUp()
CreateWnd(); CreateWnd();
Graphics::Init(hwnd); 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(); steve.OnStartUp();
obs.OnStartUp();
score.OnStartUp();
background.OnStartUp();
} }
bool vk_space_down = false;
void Game::Update() void Game::Update()
{ {
auto now = steady_clock::now(); auto now = steady_clock::now();
delta = duration_cast<duration<float>>(now - last).count(); delta = duration_cast<duration<float>>(now - last).count();
last = now; 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() void Game::Render()
@ -51,20 +95,41 @@ void Game::Render()
Graphics::BeginDraw(); Graphics::BeginDraw();
Graphics::Clear(); Graphics::Clear();
background.OnRender();
obs.OnRender();
steve.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(); Graphics::Present();
} }
void Game::LaterUpdate() 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() void Game::CleanUp()
{ {
steve.OnCleanUp(); steve.OnCleanUp();
obs.OnCleanUp();
score.OnCleanUp();
background.OnCleanUp();
Graphics::Finalize(); Graphics::Finalize();
if (hwnd) DestroyWindow(hwnd); if (hwnd) DestroyWindow(hwnd);
@ -163,10 +228,10 @@ LRESULT Game::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
switch (msg) switch (msg)
{ {
case WM_KEYDOWN: case WM_KEYDOWN:
KeyBoard::Update((char)wParam, true); KeyBoard::OnKeyMsg((char)wParam, true);
break; break;
case WM_KEYUP: case WM_KEYUP:
KeyBoard::Update((char)wParam, false); KeyBoard::OnKeyMsg((char)wParam, false);
break; break;
case WM_CLOSE: case WM_CLOSE:
done = true; done = true;

View File

@ -10,6 +10,9 @@ import Input;
import Graphics; import Graphics;
import GameObject; import GameObject;
import Steve; import Steve;
import Obstacle;
import ScoreBoard;
import BackGround;
using namespace std; using namespace std;
using namespace std::chrono; using namespace std::chrono;
@ -25,10 +28,16 @@ public:
void Run(); void Run();
private: private:
Texture image;
Steve steve; Steve steve;
Obstacle obs;
ScoreBoard score;
BackGround background;
steady_clock::time_point last; steady_clock::time_point last;
float delta; float delta;
enum Status { Begin, Running, End } status;
HWND hwnd = nullptr; HWND hwnd = nullptr;
bool done = false; bool done = false;
@ -44,6 +53,9 @@ private:
bool PeekMsg(); bool PeekMsg();
bool Done(); bool Done();
void GameOver();
void ReStart();
static LRESULT CALLBACK WndProcSetUp(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK WndProcSetUp(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK WndProcThunk(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); LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

93
Obstacle.ixx Normal file
View File

@ -0,0 +1,93 @@
module;
#include <random>
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();
}
};

100
ScoreBoard.ixx Normal file
View File

@ -0,0 +1,100 @@
module;
#include <vector>
#include <string>
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<Digit> digits;
virtual void OnStartUp()
{
Posi = { 900,400 };
}
virtual void OnCleanUp()
{
}
virtual void OnUpdate(float delta)
{
auto str = std::to_string(static_cast<int>(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;
}
};

View File

@ -9,31 +9,30 @@ import Input;
export struct Steve : GameObject export struct Steve : GameObject
{ {
static constexpr const float ground_height = 50; 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; float a, v, h;
bool jumping = false; bool jumping = false;
float time = 0.0f; float time = 0.0f;
Rect IdleRect = { 76, 2, 164, 96 }; static constexpr Rect IdleRect = { 76, 2, 164, 96 };
Rect NormalRect = { 1678, 2, 1766, 96 }; static constexpr Rect NormalRect = { 1678, 2, 1766, 96 };
Rect CloseEyeRect = { 1766, 2, 1854, 96 }; static constexpr Rect CloseEyeRect = { 1766, 2, 1854, 96 };
Rect RightRect = { 1854, 2, 1942, 96 }; static constexpr Rect RightRect = { 1854, 2, 1942, 96 };
Rect LeftRect = { 1942, 2, 2030, 96 }; static constexpr Rect LeftRect = { 1942, 2, 2030, 96 };
Rect BigEyeRect = { 2030, 2, 2118, 96 }; static constexpr Rect BigEyeRect = { 2030, 2, 2118, 96 };
Rect DeadRect = { 2122, 2, 2202, 96 }; static constexpr Rect DeadRect = { 2122, 2, 2202, 96 };
Rect CrawlingRightRect = { 2203, 2, 2321, 96 }; static constexpr Rect CrawlingRightRect = { 2203, 2, 2321, 96 };
Rect CrawlingLeftRect = { 2321, 2, 2439, 96 }; static constexpr Rect CrawlingLeftRect = { 2321, 2, 2439, 96 };
enum Status { Idle, Running, Jumping, Freefall, Crawling, Dead } status; enum Status { Idle, Running, Jumping, Freefall, Crawling, Dead } status;
virtual void OnStartUp() override virtual void OnStartUp() override
{ {
imge = Texture::LoadFromFile(L"steve.png");
imge.rect = IdleRect; imge.rect = IdleRect;
Posi = { y_pos, ground_height };
Anch = { 0.5f,0 }; Anch = { 0.5f,0 };
Size = { 88, 94 }; Posi = { x_pos, ground_height };
Size = imge.rect.size();
a = v = h = 0.0f; a = v = h = 0.0f;
} }
@ -43,12 +42,14 @@ export struct Steve : GameObject
} }
virtual void OnUpdate(float delta) override virtual void OnUpdate(float delta) override
{ {
if (isPaused) return;
time += delta; time += delta;
switch (status) switch (status)
{ {
case Steve::Idle: case Steve::Idle:
if (KeyBoard::GetKey(VK_SPACE)) status = Running; if (KeyBoard::GetKey(VK_SPACE)) status = Running;
imge.rect = IdleRect; imge.rect = IdleRect;
Size = imge.rect.size();
break; break;
case Steve::Running: case Steve::Running:
if (KeyBoard::GetKey(VK_SPACE)) if (KeyBoard::GetKey(VK_SPACE))
@ -56,10 +57,17 @@ export struct Steve : GameObject
status = Jumping; status = Jumping;
break; break;
} }
if (KeyBoard::GetKey(VK_DOWN))
{
status = Crawling;
break;
}
imge.rect = (int)(time / 0.1) % 2 ? LeftRect : RightRect; imge.rect = (int)(time / 0.1) % 2 ? LeftRect : RightRect;
Size = imge.rect.size();
break; break;
case Steve::Jumping: case Steve::Jumping:
imge.rect = NormalRect; imge.rect = NormalRect;
Size = imge.rect.size();
if ((h < 75 || KeyBoard::GetKey(VK_SPACE)) && h < 150.f) if ((h < 75 || KeyBoard::GetKey(VK_SPACE)) && h < 150.f)
{ {
v = 1000.f; v = 1000.f;
@ -84,8 +92,15 @@ export struct Steve : GameObject
} }
break; break;
case Steve::Crawling: case Steve::Crawling:
break; if (KeyBoard::GetKey(VK_DOWN))
case Steve::Dead: {
imge.rect = (int)(time / 0.1) % 2 ? CrawlingLeftRect : CrawlingRightRect;
Size = imge.rect.size();
}
else
{
status = Running;
}
break; break;
default: default:
break; break;
@ -93,5 +108,17 @@ export struct Steve : GameObject
} }
virtual void OnLaterUpdate(float delta) override 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;
} }
}; };