15 std::random_device s_randomDevice;
21 return s_randomDevice();
36 std::uniform_int_distribution<int> dist(a, b);
42 std::uniform_real_distribution<double> dist(a, b);
53 #pragma region AsyncLoadScene 55 AsyncLoadScene::~AsyncLoadScene()
62 void AsyncLoadScene::update()
68 void AsyncLoadScene::startLoadThread()
70 if (m_future.valid()) {
71 throwTrace<std::logic_error>(
"Async task is already running");
74 m_future = std::async(std::launch::async, [
this]() {
76 loadOnSubThread(m_cancel);
80 void AsyncLoadScene::updateLoadStatus()
82 if (m_future.valid()) {
83 auto status = m_future.wait_for(std::chrono::seconds(0));
85 case std::future_status::ready:
91 case std::future_status::timeout:
100 bool AsyncLoadScene::isLoading()
const 102 return m_future.valid();
112 const WCHAR *cmdline = ::GetCommandLineW();
117 WCHAR **tmpArgv = ::CommandLineToArgvW(cmdline, &argc);
121 auto del = [](WCHAR **ptr) {
124 std::unique_ptr<WCHAR *[], decltype(del)> argv(tmpArgv, del);
126 std::vector<std::wstring> result(&argv[0], &argv[argc]);
133 #pragma region ResourceManager 136 m_texMapVec(resSetCount),
137 m_fontMapVec(resSetCount),
138 m_seMapVec(resSetCount),
139 m_bgmMapVec(resSetCount)
144 template <
class T,
class U>
145 void addResource(ResourceManager::ResMapVec<T> *targetMapVec,
bool locked,
146 size_t setId,
const char * resId, std::function<U> loadFunc)
149 throwTrace<std::logic_error>(
"Resource is not allowed to be added now");
154 std::unordered_map<IdString, Resource<T>> &map =
155 targetMapVec->at(setId);
156 if (map.count(fixedResId) != 0) {
157 throwTrace<std::invalid_argument>(std::string(
"Resource ID already exists: ") + resId);
161 map.emplace(std::piecewise_construct,
162 std::forward_as_tuple(fixedResId),
163 std::forward_as_tuple(loadFunc));
171 addResource(&m_texMapVec, m_sealed, setId, resId, loadFunc);
177 addResource(&m_fontMapVec, m_sealed, setId, resId, loadFunc);
183 addResource(&m_seMapVec, m_sealed, setId, resId, loadFunc);
189 addResource(&m_bgmMapVec, m_sealed, setId, resId, loadFunc);
205 void loadAll(ResourceManager::ResMapVec<T> *targetMapVec,
size_t setId, std::atomic_bool &cancel)
207 for (
auto &elem : targetMapVec->at(setId)) {
216 void unloadAll(ResourceManager::ResMapVec<T> *targetMapVec,
size_t setId)
218 for (
auto &elem : targetMapVec->at(setId)) {
219 elem.second.unload();
227 loadAll(&m_texMapVec, setId, cancel);
228 loadAll(&m_fontMapVec, setId, cancel);
229 loadAll(&m_seMapVec, setId, cancel);
230 loadAll(&m_bgmMapVec, setId, cancel);
235 unloadAll(&m_texMapVec, setId);
236 unloadAll(&m_fontMapVec, setId);
237 unloadAll(&m_seMapVec, setId);
238 unloadAll(&m_bgmMapVec, setId);
246 size_t setId,
const char *resId)
250 auto &map = mapVec.at(setId);
251 if (map.count(fixedResId) == 0) {
252 throwTrace<std::invalid_argument>(std::string(
"Resource ID not found: ") + resId);
254 return map.at(fixedResId).getPtr();
260 size_t setId,
const char *resId)
const 262 return getResource(m_texMapVec, setId, resId);
266 size_t setId,
const char *resId)
const 268 return getResource(m_fontMapVec, setId, resId);
272 size_t setId,
const char *resId)
const 274 return getResource(m_seMapVec, setId, resId);
278 size_t setId,
const char *resId)
const 280 return getResource(m_bgmMapVec, setId, resId);
288 #pragma region FrameControl 292 inline int64_t getTimeCounter()
295 BOOL b = ::QueryPerformanceCounter(&cur);
303 m_skipCount(skipCount),
308 BOOL b = ::QueryPerformanceFrequency(&freq);
310 m_freq = freq.QuadPart;
314 m_counterPerFrame = m_freq / fps;
319 return m_frameCount != 0;
329 int64_t target = m_base + m_counterPerFrame;
330 int64_t cur = getTimeCounter();
335 else if (cur < target) {
337 while (cur < target) {
339 cur = getTimeCounter();
351 m_frameCount = (m_frameCount + 1) % (1 + m_skipCount);
355 if (m_fpsCount >= m_fpsPeriod) {
356 double sec =
static_cast<double>(cur - m_fpsBase) / m_freq;
357 m_fps = m_fpsFrameAcc / sec;
375 #pragma region Application 379 size_t resSetCount) :
381 m_resMgr(resSetCount),
383 m_graphParam(graphParam),
384 m_frameCtrl(graphParam.refreshRate, appParam.frameSkip)
388 m_graphParam.
hWnd = m_hWnd;
401 void Application::initializeWindow()
406 WNDCLASSEX cls = { 0 };
407 cls.cbSize =
sizeof(WNDCLASSEX);
409 cls.lpfnWndProc = wndProc;
413 cls.hIcon = m_param.
hIcon;
414 cls.hCursor = LoadCursor(NULL, IDC_ARROW);
415 cls.hbrBackground =
reinterpret_cast<HBRUSH
>(COLOR_BTNFACE + 1);
416 cls.lpszMenuName =
nullptr;
421 const DWORD wndStyle = WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX;
423 RECT rc = { 0, 0, m_graphParam.
w, m_graphParam.
h };
425 "AdjustWindowRect() failed");
428 CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top,
429 nullptr,
nullptr, m_param.
hInstance,
this);
433 ::SetTimer(m_hWnd, TimerEventId, 1,
nullptr);
437 while (::ShowCursor(TRUE) < 0);
440 while (::ShowCursor(FALSE) >= 0);
449 if (m_hWnd !=
nullptr) {
450 ::DestroyWindow(m_hWnd);
455 LRESULT CALLBACK Application::wndProc(HWND hWnd, UINT
msg, WPARAM wParam, LPARAM lParam)
457 if (msg == WM_CREATE) {
459 void *userData =
reinterpret_cast<LPCREATESTRUCT
>(lParam)->lpCreateParams;
460 ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(userData));
463 LONG_PTR user = ::GetWindowLongPtr(hWnd, GWLP_USERDATA);
471 return self->onSize(hWnd, msg, wParam, lParam);
473 self->m_hWnd =
nullptr;
477 return ::DefWindowProc(hWnd, msg, wParam, lParam);
480 LRESULT Application::onSize(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
482 return m_dg->onSize(hWnd, msg, wParam, lParam);
487 void Application::onIdle()
496 wchar_t buf[256] = { 0 };
497 swprintf_s(buf, L
"%s fps=%.2f (%d)", m_param.
title,
499 ::SetWindowText(m_hWnd, buf);
502 void Application::updateInternal()
504 m_ds->processFrame();
505 m_di->processFrame();
510 void Application::renderInternal()
529 ::ShowWindow(m_hWnd, m_param.
nCmdShow);
530 ::UpdateWindow(m_hWnd);
533 while (msg.message != WM_QUIT) {
534 if (::PeekMessage(&msg,
nullptr, 0, 0, PM_REMOVE)) {
535 ::TranslateMessage(&msg);
536 ::DispatchMessage(&msg);
543 return static_cast<int>(msg.wParam);
549 std::wstring pathCopy(path);
550 m_resMgr.
addTexture(setId, resId, [
this, pathCopy]() {
552 return m_dg->loadTexture(pathCopy.c_str());
557 const wchar_t *fontName, uint32_t startChar, uint32_t endChar,
558 uint32_t w, uint32_t h)
560 std::wstring fontNameCopy(fontName);
561 m_resMgr.
addFont(setId, resId, [
this, fontNameCopy, startChar, endChar, w, h]() {
563 return m_dg->loadFont(fontNameCopy.c_str(), startChar, endChar, w, h);
569 std::wstring pathCopy(path);
572 return m_ds->loadSoundEffect(pathCopy.c_str());
578 std::wstring pathCopy(path);
579 m_resMgr.
addBgm(setId, resId, [
this, pathCopy]() {
581 return m_ds->loadBgm(pathCopy.c_str());
600 size_t setId,
const char *resId)
const 606 size_t setId,
const char *resId)
const 608 return m_resMgr.
getFont(setId, resId);
612 size_t setId,
const char *resId)
const 618 size_t setId,
const char *resId)
const 620 return m_resMgr.
getBgm(setId, resId);
HINSTANCE hInstance
hInstance from WinMain.
int run()
Start main loop.
void addTextureResource(size_t setId, const char *resId, const wchar_t *path)
Register texture image resource.
HICON hIcon
hIcon for window class.
void addFontResource(size_t setId, const char *resId, const wchar_t *fontName, uint32_t startChar, uint32_t endChar, uint32_t w, uint32_t h)
Register font image resource.
const sound::XAudio2::SeResourcePtr getSoundEffect(size_t setId, const char *resId) const
int nextInt(int a, int b)
Get next int random number.
std::shared_ptr< BgmResource > BgmResourcePtr
const sound::XAudio2::SeResourcePtr getSoundEffect(size_t setId, const char *resId) const
Get sound effect resource pointer.
double nextDouble(double a, double b)
Get next double random number.
void createFixedString(std::array< char, N > *out, const char *src)
Create yappy::util::IdString from C-style string.
virtual void render()=0
Process rendering.
ResourceManager(size_t resSetCount=1)
const sound::XAudio2::BgmResourcePtr getBgm(size_t setId, const char *resId) const
void addBgmResource(size_t setId, const char *resId, const wchar_t *path)
Register BGM resource.
void setSeed(unsigned int seed)
Set random seed.
Game application main framework classes.
void writef(const wchar_t *fmt,...) noexcept
Write debug message using format string like printf.
bool showCursor
Whether shows cursor or not.
void loadResourceSet(size_t setId, std::atomic_bool &cancel)
void addBgm(size_t setId, const char *resId, std::function< sound::XAudio2::BgmResourcePtr()> loadFunc)
const sound::XAudio2::BgmResourcePtr getBgm(size_t setId, const char *resId) const
Get BGM resource pointer.
unsigned int nextRawUInt32()
Get next uint32 random number.
virtual void init()=0
User initialization code.
bool shouldSkipFrame() const
void addSeResource(size_t setId, const char *resId, const wchar_t *path)
Register sound effect resource.
const graphics::DGraphics::FontResourcePtr getFont(size_t setId, const char *resId) const
#define ASSERT(x)
Assertion which uses debug framework.
void addFont(size_t setId, const char *resId, std::function< graphics::DGraphics::FontResourcePtr()> loadFunc)
void sealResource(bool seal)
Set the lock state of resources.
uint32_t frameSkip
Frame skip count.
void writeLine(const wchar_t *str=L"") noexcept
Write debug string and new line.
std::shared_ptr< FontResource > FontResourcePtr
std::shared_ptr< SeResource > SeResourcePtr
virtual void update()=0
Process frame.
void unloadResourceSet(size_t setId)
int nCmdShow
nCmdShow from WinMain.
char msg[LINE_DATA_SIZE-sizeof(LARGE_INTEGER)-sizeof(uint32_t)]
void addTexture(size_t setId, const char *resId, std::function< graphics::DGraphics::TextureResourcePtr()> loadFunc)
FrameControl(uint32_t fps, uint32_t skipCount)
unsigned int generateRandomSeed()
Generate nondeterministic random number for seed.
const graphics::DGraphics::FontResourcePtr getFont(size_t setId, const char *resId) const
Get font resource pointer.
std::shared_ptr< T > PtrType
std::shared_ptr< TextureResource > TextureResourcePtr
void unloadResourceSet(size_t setId)
Unload resources by resource set ID.
std::vector< std::wstring > parseCommandLine()
Command line utility.
void checkWin32Result(bool cond, const std::string &msg)
util::IdString IdString
Resource ID is fixed-length string; char[16].
void addSoundEffect(size_t setId, const char *resId, std::function< sound::XAudio2::SeResourcePtr()> loadFunc)
const graphics::DGraphics::TextureResourcePtr getTexture(size_t setId, const char *resId) const
Get texture resource pointer.
const wchar_t * title
Window title string.
void loadResourceSet(size_t setId, std::atomic_bool &cancel)
Load resources by resource set ID.
Application(const AppParam &appParam, const graphics::GraphicsParam &graphParam, size_t resSetCount)
Constructor.
const wchar_t * wndClsName
Window class name.
void setSealed(bool sealed)
double getFramePerSec() const
virtual ~Application()
Destructor.
User application base, which manages a window and DirectX objects.
HICON hIconSm
hIconSm for window class.
const graphics::DGraphics::TextureResourcePtr getTexture(size_t setId, const char *resId) const