上图为美术绘制的「击中音符」的动效。
仍然是游戏创作的课程项目,这次是音游。
就像上一篇所说的,我这次实现并应用了一套更灵活的框架。 它支持基本的场景调度,这允许我将不同场景的逻辑与元素分别写在不同的文件里,例如:
// Scenes/level.cpp
// Register the level-choosing scene.
Scene level_scene("level", &level_init, {
{ WM_KEYDOWN, { (EventHandler::Handler)&level_keydown } },
{ WM_PAINT, { (EventHandler::Handler)&level_paint } },
});
// main.cpp
using namespace Win32GameEngine;
LRESULT init(HWND hWnd) {
// ...
// Switch to the above-defined scene on start.
Scene::switchTo("level", hWnd, nullptr);
return 0;
}
开始选歌菜单。
这样我就能把更多时间花在具体的游戏逻辑的开发上去。 下面是一段游戏内主要游玩部分的绘制代码:
// Scenes/play.cpp
Bitmap background((wstring(textures_dir) + L"background.bmp").c_str());
// Define the content area.
PureColor vinner(0, { 512, 192 });
LRESULT paint(HWND hWnd, WPARAM, LPARAM) {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
background.paintOn(vscreen.hdc, { 0, 0 });
background.paintOn(vinner.hdc, { -64, -84 });
// Get the current time since level (music track) started.
LONGLONG const progress = getCurrentProgress();
// And then render the note tracks regarding the process.
tr_top.paint(vinner.hdc, progress);
tr_bottom.paint(vinner.hdc, progress);
vinner.paintOn(vscreen.hdc, { 64, 84 });
// Lastly, render the HP bar.
RECT health_bar{ 0, 0, (long)(vwidth * health / 100.0), 8 };
FillRect(vscreen.hdc, &health_bar, (HBRUSH)GetStockObject(WHITE_BRUSH));
vscreen.paintOn(hdc, { 0, 0 });
EndPaint(hWnd, &ps);
return 0;
}
最后的游戏界面看起来像这样。
虽然肉眼可见地还未成功与 Win32 API 解耦,但整体的框架设计已经在朝着预想的方向发展了! 现在的游戏框架本体已经做到了与应用逻辑解耦。 这意味着后面的游创作业都可以用此框架来开发!
游戏框架与游戏本体的项目均已上传至 GitHub,欢迎自行下载编译。
注意:后者的工程依赖于前者,下载后请手动索引。