A basic framwork and the jumping Steve.

This commit is contained in:
革匊习习中 2022-07-26 12:40:54 +08:00
parent f68a9f1019
commit 7f9985d5eb
14 changed files with 733 additions and 1 deletions

25
1mGame.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32526.322
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "1mGame", "1mGame.vcxproj", "{8E1FE2C8-6B0D-4DC7-AE36-026A1ED8D525}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8E1FE2C8-6B0D-4DC7-AE36-026A1ED8D525}.Debug|x64.ActiveCfg = Debug|x64
{8E1FE2C8-6B0D-4DC7-AE36-026A1ED8D525}.Debug|x64.Build.0 = Debug|x64
{8E1FE2C8-6B0D-4DC7-AE36-026A1ED8D525}.Release|x64.ActiveCfg = Release|x64
{8E1FE2C8-6B0D-4DC7-AE36-026A1ED8D525}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B82BAF57-C01C-4194-9774-CCE0AE107D86}
EndGlobalSection
EndGlobal

98
1mGame.vcxproj Normal file
View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{8e1fe2c8-6b0d-4dc7-ae36-026a1ed8d525}</ProjectGuid>
<RootNamespace>My1mGame</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)bin\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)bin\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Imm32.lib;d2d1.lib;Windowscodecs.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Imm32.lib;d2d1.lib;Windowscodecs.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="GameObject.ixx" />
<ClCompile Include="Graphics.cpp" />
<ClCompile Include="Graphics.ixx" />
<ClCompile Include="Input.ixx" />
<ClCompile Include="Math.ixx" />
<ClCompile Include="MegaEngine.cpp" />
<ClCompile Include="MegaEngine.ixx" />
<ClCompile Include="main.cpp" />
<ClCompile Include="Steve.ixx" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

46
1mGame.vcxproj.filters Normal file
View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="MegaEngine.ixx">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="MegaEngine.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Graphics.ixx">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Graphics.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Input.ixx">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="GameObject.ixx">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Math.ixx">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Steve.ixx">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>

57
GameObject.ixx Normal file
View File

@ -0,0 +1,57 @@
module;
#include <d2d1.h>
#include <wrl/client.h>
export module GameObject;
import Graphics;
import Math;
export struct Texture
{
using BitMap = ::Microsoft::WRL::ComPtr<ID2D1Bitmap>;
BitMap bitmap;
Vector2 size;
Rect rect;
static Texture LoadFromFile(LPCWSTR uri)
{
Texture tex;
tex.bitmap = Graphics::LoadImageFromFile(uri);
auto s = tex.bitmap->GetPixelSize();
tex.size = { (FLOAT)s.width, (FLOAT)s.height };
tex.rect = { 0.f, 0.f, tex.size.x, tex.size.y };
return tex;
}
};
export class GameObject
{
public:
Texture imge;
Vector2 Posi;
Vector2 Anch;
Vector2 Size;
GameObject() {}
virtual void OnStartUp() = 0;
virtual void OnCleanUp() = 0;
virtual void OnUpdate(float delta) = 0;
virtual void OnLaterUpdate(float delta) = 0;
void OnRender()
{
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);
}
};

114
Graphics.cpp Normal file
View File

@ -0,0 +1,114 @@
module;
#include <d2d1.h>
#include <wrl/client.h>
#include <wincodec.h>
#include <cassert>
module Graphics;
using namespace D2D1;
using namespace ::Microsoft::WRL;
constexpr D2D1_RECT_F SteveRect{ 1678,2,1766,96 };
ComPtr<ID2D1HwndRenderTarget> Graphics::RT = nullptr;
ComPtr<IWICImagingFactory> Graphics::wic_factory = nullptr;
Vector2 Graphics::RtSize{};
//ComPtr<IWICImagingFactory> Graphics::wic_factory = nullptr;
void Graphics::Init(HWND hwnd)
{
ComPtr<ID2D1Factory> Factory = nullptr;
auto hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, Factory.GetAddressOf());
assert(hr == S_OK);
RECT rc;
GetClientRect(hwnd, &rc);
hr = Factory->CreateHwndRenderTarget(
RenderTargetProperties(),
HwndRenderTargetProperties(hwnd, SizeU(rc.right-rc.left, rc.bottom-rc.top)),
&RT
);
assert(hr == S_OK);
RtSize = { (FLOAT)(rc.right - rc.left), (FLOAT)(rc.bottom - rc.top) };
hr = CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&wic_factory)
);
assert(hr == S_OK);
}
void Graphics::BeginDraw()
{
RT->BeginDraw();
}
void Graphics::Clear()
{
RT->Clear({ .r = 0.96862745f, .g = 0.96862745f, .b = 0.96862745f, .a = 1.0f });
}
void Graphics::Present()
{
RT->EndDraw();
}
void Graphics::Finalize()
{
}
void Graphics::DrawBitMap(const ComPtr<ID2D1Bitmap>& bitmap, D2D_RECT_F dst, D2D_RECT_F src)
{
if (!bitmap) return;
dst.top = RtSize.y - dst.top;
dst.bottom = RtSize.y - dst.bottom;
RT->DrawBitmap(bitmap.Get(), dst, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, src);
}
ComPtr<ID2D1Bitmap> Graphics::LoadImageFromFile(LPCWSTR uri)
{
ComPtr<ID2D1Bitmap> img = nullptr;
ComPtr<IWICBitmapDecoder> decoder = nullptr;
ComPtr<IWICBitmapFrameDecode> source = nullptr;
ComPtr<IWICFormatConverter> converter = nullptr;
auto hr = wic_factory->CreateDecoderFromFilename(
uri,
nullptr,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
&decoder
);
assert(hr == S_OK);
hr = decoder->GetFrame(0, &source);
assert(hr == S_OK);
hr = wic_factory->CreateFormatConverter(&converter);
assert(hr == S_OK);
hr = converter->Initialize(
source.Get(),
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.f,
WICBitmapPaletteTypeMedianCut
);
assert(hr == S_OK);
hr = RT->CreateBitmapFromWicBitmap(
converter.Get(),
nullptr,
&img
);
assert(hr == S_OK);
return img;
}

29
Graphics.ixx Normal file
View File

@ -0,0 +1,29 @@
module;
#include <d2d1.h>
#include <wrl/client.h>
#include <wincodec.h>
export module Graphics;
import Math;
export class Graphics
{
template <class T>
using ComPtr = ::Microsoft::WRL::ComPtr<T>;
public:
static void Init(HWND hwnd);
static void BeginDraw();
static void Clear();
static void Present();
static void Finalize();
static void DrawBitMap(const ComPtr<ID2D1Bitmap>& bitmap, D2D_RECT_F dst, D2D_RECT_F src);
static ComPtr<ID2D1Bitmap> LoadImageFromFile(LPCWSTR uri);
private:
static ComPtr<IWICImagingFactory> wic_factory;
static ComPtr<ID2D1HwndRenderTarget> RT;
static Vector2 RtSize;
};

20
Input.ixx Normal file
View File

@ -0,0 +1,20 @@
module;
export module Input;
export class KeyBoard
{
static bool KeyStatus[256];
public:
static void Update(char keycode, bool status)
{
KeyStatus[keycode] = status;
}
static bool GetKey(char keycode)
{
return KeyStatus[keycode];
}
};
bool KeyBoard::KeyStatus[256]{};

16
Math.ixx Normal file
View File

@ -0,0 +1,16 @@
module;
#include <d2d1.h>
export module Math;
export
{
struct Vector2 : D2D1_POINT_2F
{
};
struct Rect : D2D1_RECT_F
{
};
}

183
MegaEngine.cpp Normal file
View File

@ -0,0 +1,183 @@
module;
#include <Windows.h>
#include <windowsx.h>
#include <wincodec.h>
#include <iostream>
#include <chrono>
#include <thread>
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<duration<float>>(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<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:
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;
}

50
MegaEngine.ixx Normal file
View File

@ -0,0 +1,50 @@
module;
#include <Windows.h>
#include <vector>
#include <wrl/client.h>
#include <chrono>
export module MegaEngine;
import Input;
import Graphics;
import GameObject;
import Steve;
using namespace std;
using namespace std::chrono;
export class Game
{
public:
static constexpr LPCWSTR wndClassName = L"1mGameWnd";
static constexpr LPCWSTR gameTitle = L"1mGame";
static constexpr int wndHeight = 450;
static constexpr int wndWidth = 1050;
void Run();
private:
Steve steve;
steady_clock::time_point last;
float delta;
HWND hwnd = nullptr;
bool done = false;
void StartUp();
void Update();
void Render();
void LaterUpdate();
void CleanUp();
void CreateWnd();
bool PeekMsg();
bool Done();
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);
};

View File

@ -1,3 +1,3 @@
# MegaSteve
复刻Chrome的断网小游戏The Jumping Steve.
复刻Chrome的断网小游戏 Steve: The Jumping Dinosaur.

81
Steve.ixx Normal file
View File

@ -0,0 +1,81 @@
module;
#include <wrl/client.h>
export module Steve;
import GameObject;
import Input;
export struct Steve : GameObject
{
float a, v, h;
bool jumping = false;
enum Status { Idle, Running, Jumping, Freefall, Crawling, Dead } status;
virtual void OnStartUp() override
{
imge = Texture::LoadFromFile(L"steve.png");
imge.rect = { 1678, 2, 1766, 96 };
Posi = { 94, 100 };
Anch = { 0.5f,0 };
Size = { 88, 94 };
a = v = h = 0.0f;
}
virtual void OnCleanUp() override
{
imge.bitmap = nullptr;
}
virtual void OnUpdate(float delta) override
{
switch (status)
{
case Steve::Idle:
if (KeyBoard::GetKey(VK_SPACE)) status = Running;
break;
case Steve::Running:
if (KeyBoard::GetKey(VK_SPACE))
{
status = Jumping;
goto _jump_;
}
break;
case Steve::Jumping:
_jump_:
if ((h < 60 || KeyBoard::GetKey(VK_SPACE)) && h < 120.f)
{
v = 1000.f;
h += v * delta;
Posi.y = 100 + h;
}
else
{
status = Freefall;
}
break;
case Steve::Freefall:
a = -8000.f;
v += a * delta;
if (v < -1000) v = -1200;
h += v * delta;
Posi.y = 100 + h;
if (Posi.y <= 100)
{
status = Running;
Posi.y = 100;
}
break;
case Steve::Crawling:
break;
case Steve::Dead:
break;
default:
break;
}
}
virtual void OnLaterUpdate(float delta) override
{
}
};

BIN
Steve.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

13
main.cpp Normal file
View File

@ -0,0 +1,13 @@
#include <Windows.h>
import MegaEngine;
#ifdef NDEBUG
int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
#else
int main()
#endif // NDBUG
{
Game().Run();
return 0;
}