重做了EApp的单例模式

This commit is contained in:
Nomango 2017-12-08 19:50:59 +08:00
parent c28b9653c5
commit 2e01f9cb1a
3 changed files with 204 additions and 220 deletions

View File

@ -8,71 +8,68 @@ int WINAPI WinMain(
int nCmdShow
)
{
EApp app;
if (!EApp::init(L"Easy2D Demo", 640, 480))
return -1;
if (app.init(L"Easy2D Demo", 640, 480))
{
float w = EApp::getWidth();
float h = EApp::getHeight();
auto scene = new EScene();
float w = EApp::getWidth();
float h = EApp::getHeight();
auto scene = new EScene();
auto text = new EText(L"中文测试中文测试中文测试中文测试中文测试中文测试中文测试", L"楷体");
text->setPos(EApp::getWidth() / 2, EApp::getHeight() / 2);
//text->setWordWrapping(true);
//text->setWordWrappingWidth(130);
text->setRotation(40);
//text->runAction(new EActionLoop(new EActionTwo(new EActionFadeOut(1), new EActionFadeIn(1))));
scene->add(text);
auto text = new EText(L"中文测试中文测试中文测试中文测试中文测试中文测试中文测试", L"楷体");
text->setPos(EApp::getWidth() / 2, EApp::getHeight() / 2);
//text->setWordWrapping(true);
//text->setWordWrappingWidth(130);
text->setRotation(40);
//text->runAction(new EActionLoop(new EActionTwo(new EActionFadeOut(1), new EActionFadeIn(1))));
scene->add(text);
auto listener = new EListenerKeyboardPress([=]() {
if (EKeyboardMsg::getKeyValue() == EKeyboardMsg::KEY::SPACE)
{
EApp::backScene(new ETransitionFade(0.5f, 0.5f));
}
});
listener->bindWith(scene);
auto listener = new EListenerKeyboardPress([=]() {
if (EKeyboardMsg::getKeyValue() == EKeyboardMsg::KEY::SPACE)
{
EApp::backScene(new ETransitionFade(0.5f, 0.5f));
}
});
listener->bindWith(scene);
auto scene2 = new EScene();
auto scene2 = new EScene();
auto bird = new ESprite();
auto animation = new EAnimation();
animation->addFrame(new ESpriteFrame(L"atlas.png", 5, 982, 34, 24));
animation->addFrame(new ESpriteFrame(L"atlas.png", 61, 982, 34, 24));
animation->addFrame(new ESpriteFrame(L"atlas.png", 117, 982, 34, 24));
animation->addFrame(new ESpriteFrame(L"atlas.png", 61, 982, 34, 24));
bird->runAction(new EActionLoop(animation));
bird->setPivot(0.5f, 0.5f);
bird->setPos(EApp::getWidth() / 2, EApp::getHeight() / 2);
scene2->add(bird);
auto bird = new ESprite(L"atlas.png", 5, 982, 34, 24);
auto animation = new EAnimation();
animation->addFrame(new ESpriteFrame(L"atlas.png", 5, 982, 34, 24));
animation->addFrame(new ESpriteFrame(L"atlas.png", 61, 982, 34, 24));
animation->addFrame(new ESpriteFrame(L"atlas.png", 117, 982, 34, 24));
animation->addFrame(new ESpriteFrame(L"atlas.png", 61, 982, 34, 24));
bird->runAction(new EActionLoop(animation));
bird->setPivot(0.5f, 0.5f);
bird->setPos(EApp::getWidth() / 2, EApp::getHeight() / 2);
scene2->add(bird);
auto btnStart = new ESprite(L"atlas.png", 702, 234, 116, 70);
auto btnStartSelected = new ESprite(L"atlas.png", 702, 234, 116, 70);
btnStartSelected->setPosY(5);
auto button = new EButton(btnStart, btnStartSelected, [=] {
if (EApp::isPaused())
{
EApp::resume();
}
else
{
EApp::pause();
}
//EApp::enterScene(scene, new ETransitionScaleEmerge(1, ETransitionScaleEmerge::BACK));
});
button->setPivot(0.5f, 0.5f);
button->setPos(EApp::getWidth() / 2, EApp::getHeight() / 2 + 100);
scene2->add(button);
auto btnStart = new ESprite(L"atlas.png", 702, 234, 116, 70);
auto btnStartSelected = new ESprite(L"atlas.png", 702, 234, 116, 70);
btnStartSelected->setPosY(5);
auto button = new EButton(btnStart, btnStartSelected, [=] {
if (EApp::isPaused())
{
EApp::resume();
}
else
{
EApp::pause();
}
//EApp::enterScene(scene, new ETransitionScaleEmerge(1, ETransitionScaleEmerge::BACK));
});
button->setPivot(0.5f, 0.5f);
button->setPos(EApp::getWidth() / 2, EApp::getHeight() / 2 + 100);
scene2->add(button);
scene2->runAction(new EActionSequence(5,
new EActionCallback([]() { EMusicUtils::playMusic(L"music.wav", -1); }),
new EActionDelay(3),
new EActionCallback([]() { EMusicUtils::pauseMusic(L"music.wav"); }),
new EActionDelay(3),
new EActionCallback([]() { EMusicUtils::resumeMusic(L"music.wav"); })));
scene2->runAction(new EActionSequence(5,
new EActionCallback([]() { EMusicUtils::playMusic(L"music.wav", -1); }),
new EActionDelay(3),
new EActionCallback([]() { EMusicUtils::pauseMusic(L"music.wav"); }),
new EActionDelay(10),
new EActionCallback([]() { EMusicUtils::resumeMusic(L"music.wav"); })));
app.enterScene(scene2, new ETransitionFade(0, 1));
app.run();
}
EApp::enterScene(scene2, new ETransitionFade(0, 1));
return 0;
return EApp::run();
}

View File

@ -33,27 +33,23 @@ e2d::EApp::EApp()
, m_pCurrentScene(nullptr)
, m_pNextScene(nullptr)
{
ASSERT(s_pInstance == nullptr, "EApp instance already exists!");
s_pInstance = this; // 保存实例对象
CoInitialize(NULL);
}
e2d::EApp::~EApp()
{
// 释放资源
SafeReleaseInterface(&GetSolidColorBrush());
SafeReleaseInterface(&GetRenderTarget());
SafeReleaseInterface(&GetFactory());
SafeReleaseInterface(&GetImagingFactory());
SafeReleaseInterface(&GetDirectWriteFactory());
CoUninitialize();
}
e2d::EApp * e2d::EApp::get()
e2d::EApp * e2d::EApp::getInstance()
{
ASSERT(s_pInstance != nullptr, "Nonexistent EApp instance.");
if (!s_pInstance)
{
s_pInstance = new EApp();
}
return s_pInstance; // 获取 EApp 的唯一实例
}
@ -64,6 +60,8 @@ bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height)
bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, EWindowStyle wStyle)
{
CoInitialize(NULL);
HRESULT hr;
// 注册窗口类
@ -122,19 +120,19 @@ bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, EWindowS
dwStyle |= WS_MINIMIZEBOX;
}
// 保存窗口是否置顶显示
m_bTopMost = wStyle.m_bTopMost;
EApp::getInstance()->m_bTopMost = wStyle.m_bTopMost;
// 保存窗口名称
m_sTitle = title;
EApp::getInstance()->m_sTitle = title;
// 创建窗口
GetHWnd() = CreateWindow(
L"Easy2DApp",
m_sTitle.c_str(),
title.c_str(),
dwStyle,
0, 0, width, height,
NULL,
NULL,
HINST_THISCOMPONENT,
this
NULL
);
hr = GetHWnd() ? S_OK : E_FAIL;
@ -142,9 +140,9 @@ bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, EWindowS
if (SUCCEEDED(hr))
{
// 禁用输入法
this->setKeyboardLayoutEnable(false);
EApp::setKeyboardLayoutEnable(false);
// 重设客户区大小
this->setWindowSize(width, height);
EApp::setWindowSize(width, height);
}
else
{
@ -159,18 +157,67 @@ bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, EWindowS
return SUCCEEDED(hr);
}
int e2d::EApp::run()
{
if (GetHWnd() == nullptr)
{
MessageBox(nullptr, L"Invalid window handle!", L"Error", MB_OK);
return -1;
}
EApp * pApp = EApp::getInstance();
// 进入第一个场景
pApp->_enterNextScene();
// 关闭控制台
if (!pApp->m_bShowConsole)
{
showConsole(false);
}
// 显示窗口
ShowWindow(GetHWnd(), SW_SHOWNORMAL);
UpdateWindow(GetHWnd());
// 设置窗口置顶
if (pApp->m_bTopMost)
{
SetWindowPos(GetHWnd(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
// 记录开始时间
s_tStart = steady_clock::now();
// 窗口消息
MSG msg;
while (!pApp->m_bEnd)
{
// 处理窗口消息
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// 执行主循环
pApp->_mainLoop();
}
// 关闭控制台
EApp::showConsole(false);
CoUninitialize();
return 0;
}
void e2d::EApp::pause()
{
EApp::get()->m_bManualPaused = true;
EApp::getInstance()->m_bManualPaused = true;
}
void e2d::EApp::resume()
{
if (isPaused())
{
EApp::get()->m_bPaused = false;
EApp::get()->m_bManualPaused = false;
EApp::_updateTime();
EApp::getInstance()->m_bPaused = false;
EApp::getInstance()->m_bManualPaused = false;
EApp::getInstance()->_updateTime();
}
}
@ -179,13 +226,18 @@ bool e2d::EApp::isPaused()
return s_pInstance->m_bPaused || s_pInstance->m_bManualPaused;
}
void e2d::EApp::quit()
{
getInstance()->m_bEnd = true; // 这个变量将控制游戏是否结束
}
void e2d::EApp::showConsole(bool show /* = true */)
{
static FILE * stdoutstream = nullptr;
static FILE * stdinstream = nullptr;
static FILE * stderrstream = nullptr;
EApp::get()->m_bShowConsole = show;
EApp::getInstance()->m_bShowConsole = show;
// 查找已存在的控制台句柄
HWND hwnd = GetConsoleWindow();
// 关闭控制台
@ -227,53 +279,6 @@ void e2d::EApp::showConsole(bool show /* = true */)
}
}
// 运行游戏
void e2d::EApp::run()
{
ASSERT(GetHWnd() != nullptr, "Cannot find Game Window.");
// 进入第一个场景
_enterNextScene();
// 关闭控制台
if (!m_bShowConsole)
{
showConsole(false);
}
// 显示窗口
ShowWindow(GetHWnd(), SW_SHOWNORMAL);
UpdateWindow(GetHWnd());
// 设置窗口置顶
if (m_bTopMost)
{
SetWindowPos(GetHWnd(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
// 记录开始时间
s_tStart = steady_clock::now();
// 窗口消息
MSG msg;
while (!m_bEnd)
{
// 处理窗口消息
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// 执行主循环
_mainLoop();
}
// 关闭控制台
EApp::showConsole(false);
}
void e2d::EApp::setFPS(UINT32 fps)
{
fps = min(max(fps, 30), 120);
s_pInstance->m_nAnimationInterval = 1000 / fps;
}
bool e2d::EApp::onActivate()
{
return true;
@ -419,12 +424,12 @@ void e2d::EApp::setWindowTitle(const EString &title)
// 设置窗口标题
SetWindowText(GetHWnd(), title.c_str());
// 保存当前标题,用于修改窗口大小时恢复标题
get()->m_sTitle = title;
getInstance()->m_sTitle = title;
}
e2d::EString e2d::EApp::getTitle()
{
return get()->m_sTitle;
return getInstance()->m_sTitle;
}
float e2d::EApp::getWidth()
@ -442,34 +447,29 @@ e2d::ESize e2d::EApp::getSize()
return ESize(GetRenderTarget()->GetSize().width, GetRenderTarget()->GetSize().height);
}
void e2d::EApp::enterScene(EScene * scene, bool saveCurrentScene /* = true */)
{
enterScene(scene, nullptr, saveCurrentScene);
}
void e2d::EApp::enterScene(EScene * scene, ETransition * transition, bool saveCurrentScene /* = true */)
void e2d::EApp::enterScene(EScene * scene, bool saveCurrentScene /* = true */, ETransition * transition /* = nullptr */)
{
scene->retain();
// 保存下一场景的指针
get()->m_pNextScene = scene;
getInstance()->m_pNextScene = scene;
// 切换场景时,是否保存当前场景
if (get()->m_pCurrentScene)
if (getInstance()->m_pCurrentScene)
{
get()->m_pCurrentScene->m_bWillSave = saveCurrentScene;
getInstance()->m_pCurrentScene->m_bWillSave = saveCurrentScene;
}
// 设置切换场景动画
if (transition)
{
get()->m_bTransitional = true;
getInstance()->m_bTransitional = true;
transition->_setTarget(
get()->m_pCurrentScene,
get()->m_pNextScene,
get()->m_bTransitional
getInstance()->m_pCurrentScene,
getInstance()->m_pNextScene,
getInstance()->m_bTransitional
);
}
else
{
get()->m_bTransitional = false;
getInstance()->m_bTransitional = false;
}
}
@ -480,30 +480,30 @@ void e2d::EApp::backScene(ETransition * transition /* = nullptr */)
if (s_SceneStack.size() == 0) return;
// 从栈顶取出场景指针,作为下一场景
get()->m_pNextScene = s_SceneStack.top();
getInstance()->m_pNextScene = s_SceneStack.top();
s_SceneStack.pop();
// 返回上一场景时,不保存当前场景
if (get()->m_pCurrentScene)
if (getInstance()->m_pCurrentScene)
{
get()->m_pCurrentScene->m_bWillSave = false;
getInstance()->m_pCurrentScene->m_bWillSave = false;
}
// 设置切换场景动画
if (transition)
{
get()->m_bTransitional = true;
getInstance()->m_bTransitional = true;
transition->_setTarget(
get()->m_pCurrentScene,
get()->m_pNextScene,
get()->m_bTransitional
getInstance()->m_pCurrentScene,
getInstance()->m_pNextScene,
getInstance()->m_bTransitional
);
}
else
{
// 把这个变量赋为 false场景将在下一帧画面
// 进行切换
get()->m_bTransitional = false;
getInstance()->m_bTransitional = false;
}
}
@ -518,26 +518,32 @@ void e2d::EApp::clearScene()
}
}
void e2d::EApp::setFPS(UINT32 fps)
{
fps = min(max(fps, 30), 120);
s_pInstance->m_nAnimationInterval = 1000 / fps;
}
e2d::EScene * e2d::EApp::getCurrentScene()
{
return get()->m_pCurrentScene;
return getInstance()->m_pCurrentScene;
}
void e2d::EApp::setAppName(const EString &appname)
{
get()->m_sAppName = appname;
getInstance()->m_sAppName = appname;
}
e2d::EString e2d::EApp::getAppName()
{
if (get()->m_sAppName.empty())
get()->m_sAppName = get()->m_sTitle;
return get()->m_sAppName;
if (getInstance()->m_sAppName.empty())
getInstance()->m_sAppName = getInstance()->m_sTitle;
return getInstance()->m_sAppName;
}
void e2d::EApp::setBkColor(UINT32 color)
{
get()->m_ClearColor = color;
getInstance()->m_ClearColor = color;
}
void e2d::EApp::setKeyboardLayoutEnable(bool value)
@ -581,17 +587,6 @@ void e2d::EApp::showWindow()
ShowWindow(GetHWnd(), SW_SHOWNORMAL);
}
void e2d::EApp::quit()
{
// 这个变量将控制游戏是否结束
get()->m_bEnd = true;
}
void e2d::EApp::end()
{
EApp::quit();
}
void e2d::EApp::_enterNextScene()
{
if (m_pNextScene == nullptr)
@ -709,29 +704,27 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam
// 窗口激活消息
case WM_ACTIVATE:
{
EScene * pCurrentScene = s_pInstance->getCurrentScene();
if (LOWORD(wParam) == WA_INACTIVE)
{
if (s_pInstance->getCurrentScene() &&
s_pInstance->getCurrentScene()->onInactive() &&
if (pCurrentScene &&
pCurrentScene->onInactive() &&
s_pInstance->onInactive())
{
s_pInstance->m_bPaused = true;
// 暂停音乐
EMusicUtils::pauseAllMusics();
}
}
else if (s_pInstance->m_bPaused)
{
if (s_pInstance->getCurrentScene() &&
s_pInstance->getCurrentScene()->onActivate() &&
if (pCurrentScene &&
pCurrentScene->onActivate() &&
s_pInstance->onActivate())
{
s_pInstance->m_bPaused = false;
if (!s_pInstance->m_bManualPaused)
{
EApp::_updateTime();
// 继续播放音乐
EMusicUtils::resumeAllMusics();
s_pInstance->_updateTime();
}
}
}
@ -742,17 +735,19 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam
// 窗口关闭消息
case WM_CLOSE:
{
if (!s_pInstance->getCurrentScene())
EScene * pCurrentScene = s_pInstance->getCurrentScene();
if (pCurrentScene)
{
if (s_pInstance->onCloseWindow())
if (pCurrentScene->onCloseWindow() &&
s_pInstance->onCloseWindow())
{
DestroyWindow(hWnd);
}
}
else
{
if (s_pInstance->getCurrentScene()->onCloseWindow() &&
s_pInstance->onCloseWindow())
if (s_pInstance->onCloseWindow())
{
DestroyWindow(hWnd);
}

View File

@ -19,19 +19,18 @@ class ETransition;
class EApp
{
public:
EApp();
virtual ~EApp();
// 获取程序实例
static EApp * getInstance();
// 初始化游戏界面
bool init(
static bool init(
const EString &title, /* 窗口标题 */
UINT32 width, /* 窗口宽度 */
UINT32 height /* 窗口高度 */
);
// 初始化游戏界面
bool init(
static bool init(
const EString &title, /* 窗口标题 */
UINT32 width, /* 窗口宽度 */
UINT32 height, /* 窗口高度 */
@ -39,19 +38,7 @@ public:
);
// 启动程序
void run();
// 重写这个函数,它将在窗口激活时执行
virtual bool onActivate();
// 重写这个函数,它将在窗口非激活时执行
virtual bool onInactive();
// 重写这个函数,它将在关闭窗口时执行
virtual bool onCloseWindow();
// 获取程序实例
static EApp * get();
static int run();
// 暂停游戏
static void pause();
@ -59,20 +46,14 @@ public:
// 继续游戏
static void resume();
// 游戏是否暂停
static bool isPaused();
// 结束游戏
static void quit();
// 切换场景
static void enterScene(
EScene * scene, /* 下一个场景的指针 */
bool saveCurrentScene = true /* 是否保存当前场景 */
);
// 切换场景
static void enterScene(
EScene * scene, /* 下一个场景的指针 */
ETransition * transition, /* 场景切换动画 */
bool saveCurrentScene = true /* 是否保存当前场景 */
EScene * scene, /* 下一个场景的指针 */
bool saveCurrentScene = true, /* 是否保存当前场景 */
ETransition * transition = nullptr /* 场景切换动画 */
);
// 返回上一场景
@ -94,11 +75,8 @@ public:
bool show = true
);
// 终止程序
static void quit();
// 终止程序
static void end();
// 游戏是否暂停
static bool isPaused();
// 获取窗口标题
static EString getTitle();
@ -155,7 +133,21 @@ public:
UINT32 fps
);
protected:
public:
// 重写这个函数,它将在窗口激活时执行
virtual bool onActivate();
// 重写这个函数,它将在窗口非激活时执行
virtual bool onInactive();
// 重写这个函数,它将在关闭窗口时执行
virtual bool onCloseWindow();
private:
EApp();
virtual ~EApp();
// 游戏主循环
void _mainLoop();
@ -169,7 +161,7 @@ protected:
void _enterNextScene();
// 刷新游戏时间
static void _updateTime();
void _updateTime();
// 窗口程序
static LRESULT CALLBACK WndProc(
@ -179,7 +171,7 @@ protected:
LPARAM lParam
);
protected:
private:
bool m_bEnd;
bool m_bPaused;
bool m_bManualPaused;