Modify some functions in class Game and Window

This commit is contained in:
Nomango 2018-04-13 00:39:27 +08:00
parent 48ae177f1d
commit c135168491
10 changed files with 287 additions and 274 deletions

View File

@ -8,11 +8,11 @@ static bool s_bEndGame = false;
static bool s_bPaused = false;
// 是否进行过初始化
static bool s_bInitialized = false;
// AppName
static e2d::String s_sAppName;
// 游戏名称
static e2d::String s_sGameName;
bool e2d::Game::init(String sTitle, UINT32 nWidth, UINT32 nHeight, LPCTSTR pIconID, String sAppname)
bool e2d::Game::init(String sGameName)
{
if (s_bInitialized)
{
@ -25,9 +25,6 @@ bool e2d::Game::init(String sTitle, UINT32 nWidth, UINT32 nHeight, LPCTSTR pIcon
// 初始化 COM 组件
CoInitializeEx(NULL, COINIT_MULTITHREADED);
// 设置 AppName
s_sAppName = sAppname;
// 创建设备无关资源
if (!Renderer::__createDeviceIndependentResources())
{
@ -36,7 +33,7 @@ bool e2d::Game::init(String sTitle, UINT32 nWidth, UINT32 nHeight, LPCTSTR pIcon
}
// 初始化窗口
if (!Window::__init(sTitle, nWidth, nHeight, pIconID))
if (!Window::__init())
{
WARN_IF(true, "Window::__init Failed!");
break;
@ -62,9 +59,8 @@ bool e2d::Game::init(String sTitle, UINT32 nWidth, UINT32 nHeight, LPCTSTR pIcon
WARN_IF(true, "MusicManager::__init Failed!");
break;
}
// 重设 Client 大小
Window::setSize(nWidth, nHeight);
// 保存游戏名称
s_sGameName = sGameName;
// 标志初始化成功
s_bInitialized = true;
@ -176,7 +172,28 @@ void e2d::Game::uninit()
s_bInitialized = false;
}
e2d::String e2d::Game::getAppName()
bool e2d::Game::createMutex(String sMutexName)
{
return s_sAppName;
// 创建进程互斥体
HANDLE m_hMutex = ::CreateMutex(NULL, TRUE, L"Easy2DApp-" + sMutexName);
if (m_hMutex == nullptr)
{
WARN_IF(true, "CreateMutex Failed!");
return true;
}
// 如果程序已经存在并且正在运行
if (::GetLastError() == ERROR_ALREADY_EXISTS)
{
// 关闭进程互斥体
::CloseHandle(m_hMutex);
return false;
}
return true;
}
e2d::String e2d::Game::getName()
{
return String();
}

View File

@ -9,13 +9,8 @@ static HWND s_HWnd = nullptr;
static bool s_bShowConsole = false;
bool e2d::Window::__init(const String& sTitle, UINT32 nWidth, UINT32 nHeight, LPCTSTR pIconID /*= nullptr*/)
bool e2d::Window::__init()
{
if (!Window::__initMutex(sTitle))
{
return false;
}
// 注册窗口类
WNDCLASSEX wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
@ -28,17 +23,7 @@ bool e2d::Window::__init(const String& sTitle, UINT32 nWidth, UINT32 nHeight, LP
wcex.lpszMenuName = NULL;
wcex.hCursor = LoadCursor(NULL, IDI_APPLICATION);
wcex.lpszClassName = L"Easy2DApp";
// 设置程序图标
if (pIconID)
{
wcex.hIcon = (HICON)::LoadImage(
GetModuleHandle(NULL),
pIconID,
IMAGE_ICON,
0,
0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
}
wcex.hIcon = NULL;
RegisterClassEx(&wcex);
@ -49,8 +34,8 @@ bool e2d::Window::__init(const String& sTitle, UINT32 nWidth, UINT32 nHeight, LP
// 工厂将返回当前的系统 DPI这个值也将用来创建窗口
Renderer::getID2D1Factory()->GetDesktopDpi(&dpiX, &dpiY);
nWidth = static_cast<UINT>(ceil(nWidth * dpiX / 96.f));
nHeight = static_cast<UINT>(ceil(nHeight * dpiY / 96.f));
UINT nWidth = static_cast<UINT>(ceil(640 * dpiX / 96.f));
UINT nHeight = static_cast<UINT>(ceil(480 * dpiY / 96.f));
// 获取屏幕分辨率
UINT screenWidth = static_cast<UINT>(::GetSystemMetrics(SM_CXSCREEN));
@ -61,12 +46,22 @@ bool e2d::Window::__init(const String& sTitle, UINT32 nWidth, UINT32 nHeight, LP
nWidth = min(nWidth, screenWidth);
nHeight = min(nHeight, screenHeight);
// 计算窗口大小
DWORD dwStyle = WS_OVERLAPPEDWINDOW &~ WS_MAXIMIZEBOX;
RECT wr = { 0, 0, static_cast<LONG>(nWidth), static_cast<LONG>(nHeight) };
::AdjustWindowRectEx(&wr, dwStyle, FALSE, NULL);
// 获取新的宽高
nWidth = wr.right - wr.left;
nHeight = wr.bottom - wr.top;
// 创建窗口
s_HWnd = CreateWindow(
s_HWnd = ::CreateWindowEx(
NULL,
L"Easy2DApp",
sTitle,
WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX,
0, 0, nWidth, nHeight,
L"Easy2D Game",
dwStyle,
(screenWidth - nWidth) / 2, (screenHeight - nHeight) / 2,
nWidth, nHeight,
NULL,
NULL,
HINST_THISCOMPONENT,
@ -95,53 +90,17 @@ bool e2d::Window::__init(const String& sTitle, UINT32 nWidth, UINT32 nHeight, LP
}
else
{
UnregisterClass(L"Easy2DApp", HINST_THISCOMPONENT);
::UnregisterClass(L"Easy2DApp", HINST_THISCOMPONENT);
}
if (FAILED(hr))
{
MessageBox(nullptr, L"Create Window Failed!", L"Error", MB_OK);
::MessageBox(nullptr, L"Create Window Failed!", L"Error", MB_OK);
}
return SUCCEEDED(hr);
}
bool e2d::Window::__initMutex(const String& sTitle)
{
// 创建进程互斥体
HANDLE m_hMutex = ::CreateMutex(NULL, TRUE, L"Easy2DApp-" + sTitle);
if (m_hMutex == nullptr)
{
WARN_IF(true, "CreateMutex Failed!");
return true;
}
// 如果程序已经存在并且正在运行
if (::GetLastError() == ERROR_ALREADY_EXISTS)
{
// 获取窗口句柄
HWND hProgramWnd = ::FindWindow(L"Easy2DApp", sTitle);
if (hProgramWnd)
{
// 获取窗口显示状态
WINDOWPLACEMENT wpm;
::GetWindowPlacement(hProgramWnd, &wpm);
// 将运行的程序窗口还原成正常状态
wpm.showCmd = SW_SHOW;
::SetWindowPlacement(hProgramWnd, &wpm);
::SetWindowPos(hProgramWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
}
// 关闭进程互斥体
CloseHandle(m_hMutex);
m_hMutex = nullptr;
return false;
}
return true;
}
void e2d::Window::__uninit()
{
// 关闭控制台
@ -150,8 +109,11 @@ void e2d::Window::__uninit()
::FreeConsole();
}
// 关闭窗口
DestroyWindow(s_HWnd);
s_HWnd = nullptr;
if (s_HWnd)
{
::DestroyWindow(s_HWnd);
s_HWnd = nullptr;
}
}
void e2d::Window::__poll()
@ -167,18 +129,38 @@ void e2d::Window::__poll()
double e2d::Window::getWidth()
{
return Renderer::getRenderTarget()->GetSize().width;
if (s_HWnd)
{
// 获取客户区大小
tagRECT rcClient;
::GetClientRect(s_HWnd, &rcClient);
return rcClient.right - rcClient.left;
}
return 0;
}
double e2d::Window::getHeight()
{
return Renderer::getRenderTarget()->GetSize().height;
if (s_HWnd)
{
// 获取客户区大小
tagRECT rcClient;
::GetClientRect(s_HWnd, &rcClient);
return rcClient.bottom - rcClient.top;
}
return 0;
}
e2d::Size e2d::Window::getSize()
{
D2D1_SIZE_F size = Renderer::getRenderTarget()->GetSize();
return Size(size.width, size.height);
if (s_HWnd)
{
// 获取客户区大小
tagRECT rcClient;
::GetClientRect(s_HWnd, &rcClient);
return Size(rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
}
return Size();
}
HWND e2d::Window::getHWnd()
@ -188,18 +170,16 @@ HWND e2d::Window::getHWnd()
void e2d::Window::setSize(UINT32 width, UINT32 height)
{
// 计算窗口大小
DWORD dwStyle = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX;
RECT wr = { 0, 0, static_cast<LONG>(width), static_cast<LONG>(height) };
::AdjustWindowRectEx(&wr, dwStyle, FALSE, NULL);
// 获取新的宽高
width = wr.right - wr.left;
height = wr.bottom - wr.top;
// 获取屏幕分辨率
int screenWidth = ::GetSystemMetrics(SM_CXSCREEN);
int screenHeight = ::GetSystemMetrics(SM_CYSCREEN);
// 获取窗口大小(包含菜单栏)
tagRECT rcWindow;
::GetWindowRect(s_HWnd, &rcWindow);
// 获取客户区大小
tagRECT rcClient;
::GetClientRect(s_HWnd, &rcClient);
// 计算边框大小
width += (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left);
height += (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top);
// 修改窗口大小,并设置窗口在屏幕居中
::MoveWindow(s_HWnd, (screenWidth - width) / 2, (screenHeight - height) / 2, width, height, TRUE);
}
@ -210,6 +190,16 @@ void e2d::Window::setTitle(String title)
::SetWindowText(s_HWnd, title);
}
void e2d::Window::setIcon(LPCTSTR pIconID)
{
HINSTANCE hInstance = ::GetModuleHandle(NULL);
HICON hIcon = (HICON)::LoadImage(hInstance, pIconID, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
// 设置窗口的图标
::SendMessage(s_HWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
::SendMessage(s_HWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
}
e2d::String e2d::Window::getTitle()
{
wchar_t wszTitle[MAX_PATH] = { 0 };
@ -295,7 +285,8 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
// 目标适当。它可能会调用失败,但是这里可以忽略有可能的
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
Renderer::getRenderTarget()->Resize(D2D1::SizeU(width, height));
auto pRenderTarget = Renderer::getRenderTarget();
if (pRenderTarget) pRenderTarget->Resize(D2D1::SizeU(width, height));
}
break;

View File

@ -28,12 +28,14 @@ void e2d::TimerManager::__update()
}
}
void e2d::TimerManager::start(double timeOut, Function func)
e2d::Timer* e2d::TimerManager::start(double timeOut, Function func)
{
(new Timer(func, L"", timeOut, 1, false, true))->start();
auto t = new (std::nothrow) Timer(L"", func, timeOut, 1, false, true);
t->start();
return t;
}
void e2d::TimerManager::__add(Timer * pTimer)
void e2d::TimerManager::add(Timer * pTimer)
{
WARN_IF(pTimer == nullptr, "Timer NULL pointer exception!");

View File

@ -1,6 +1,6 @@
#include "..\etool.h"
static e2d::String s_sDefaultFileName = L"DefaultData.ini";
static e2d::String s_sDataFileName = L"DefaultData.ini";
void e2d::Data::saveInt(String key, int value, String field)
{
@ -53,12 +53,12 @@ void e2d::Data::setDataFileName(String fileName)
{
if (!fileName.isEmpty())
{
s_sDefaultFileName.clear();
s_sDefaultFileName << fileName << L".ini";
s_sDataFileName.clear();
s_sDataFileName << fileName << L".ini";
}
}
e2d::String e2d::Data::getDataFilePath()
{
return Path::getDefaultSavePath() + s_sDefaultFileName;
return Path::getDefaultSavePath() + s_sDataFileName;
}

View File

@ -46,16 +46,16 @@ e2d::String e2d::Path::getTempPath()
return path;
}
// »ñÈ¡ AppName
String sAppName = Game::getAppName();
if (!sAppName.isEmpty())
// »ñÈ¡ÓÎÏ·Ãû³Æ
String sGameName = Game::getName();
if (!sGameName.isEmpty())
{
// 创建文件夹
if (!Path::createFolder(tempFilePath + sAppName + L"\\"))
if (!Path::createFolder(tempFilePath + sGameName + L"\\"))
{
return std::move(tempFilePath);
}
tempFilePath << sAppName << L"\\";
tempFilePath << sGameName << L"\\";
}
return std::move(tempFilePath);
}
@ -78,16 +78,16 @@ e2d::String e2d::Path::getDefaultSavePath()
}
path << L"\\Easy2DGameData";
// »ñÈ¡ AppName
String sAppName = Game::getAppName();
if (!sAppName.isEmpty())
// »ñÈ¡ÓÎÏ·Ãû³Æ
String sGameName = Game::getName();
if (!sGameName.isEmpty())
{
// 创建文件夹
if (!Path::createFolder(path + L"\\" + sAppName))
if (!Path::createFolder(path + L"\\" + sGameName))
{
return std::move(path);
}
path << L"\\" << sAppName;
path << L"\\" << sGameName;
}
path << L"\\";

View File

@ -1,6 +1,6 @@
#include "..\etool.h"
std::default_random_engine &e2d::Random::getEngine()
std::default_random_engine &e2d::Random::__getEngine()
{
static std::random_device device;
static std::default_random_engine engine(device());

View File

@ -2,7 +2,7 @@
#include "..\enode.h"
#include "..\emanager.h"
e2d::Timer::Timer(Function func, String name, double interval /* = 0 */, int updateTimes /* = -1 */, bool atOnce /* = false */, bool autoRelease /* = false */)
e2d::Timer::Timer(String name, Function func, double interval /* = 0 */, int updateTimes /* = -1 */, bool atOnce /* = false */, bool autoRelease /* = false */)
: m_bRunning(false)
, m_nRunTimes(0)
, m_Callback(nullptr)
@ -19,7 +19,6 @@ e2d::Timer::Timer(Function func, String name, double interval /* = 0 */, int upd
this->setInterval(interval);
m_bAutoRelease = autoRelease;
m_bAtOnce = atOnce;
TimerManager::__add(this);
}
bool e2d::Timer::isRunning() const

View File

@ -14,11 +14,7 @@ class Game
public:
// 初始化游戏
static bool init(
String sTitle, /* 窗口标题 */
UINT32 nWidth = 640U, /* 窗口宽度 */
UINT32 nHeight = 480U, /* 窗口高度 */
LPCTSTR pIconID = nullptr, /* 窗口图标 */
String sAppname = L"" /* AppName */
String sGameName = L"E2DGame" /* 游戏英文名称 */
);
// 启动游戏
@ -39,8 +35,13 @@ public:
// 游戏是否暂停
static bool isPaused();
// 获取 AppName
static String getAppName();
// 创建进程互斥体
static bool createMutex(
String sMutexName /* 互斥体名称 */
);
// 获取游戏名称
static String getName();
};
@ -50,6 +51,22 @@ class Window
friend Game;
public:
// 修改窗口大小
static void setSize(
UINT32 nWidth, /* 窗口宽度 */
UINT32 nHeight /* 窗口高度 */
);
// 设置窗口标题
static void setTitle(
String sTitle /* 窗口标题 */
);
// 设置窗口图标
static void setIcon(
LPCTSTR pIconID
);
// 获取窗口标题
static String getTitle();
@ -65,17 +82,6 @@ public:
// 获取窗口句柄
static HWND getHWnd();
// 修改窗口大小
static void setSize(
UINT32 nWidth,
UINT32 nHeight
);
// 设置窗口标题
static void setTitle(
String sTitle
);
// 打开/隐藏控制台
static void showConsole(
bool bShow = true
@ -88,17 +94,7 @@ public:
private:
// 初始化窗口
static bool __init(
const String& sTitle,
UINT32 nWidth,
UINT32 nHeight,
LPCTSTR pIconID
);
// 创建进程互斥体
static bool __initMutex(
const String& sTitle
);
static bool __init();
// 重置窗口属性
static void __uninit();

View File

@ -94,8 +94,8 @@ class TimerManager
friend Timer;
public:
// 等待一段时间后执行指定函数
static void start(
// 启动一个新任务:等待一段时间后执行指定函数
static Timer* start(
double timeOut, /* 等待的时长(秒) */
Function func /* 执行的函数 */
);
@ -115,6 +115,11 @@ public:
String name
);
// 添加定时器
static void add(
Timer * pTimer
);
// 获取名称相同的定时器
static std::vector<Timer*> get(
String name
@ -136,11 +141,6 @@ private:
// 更新定时器
static void __update();
// 添加一个定时器
static void __add(
Timer * pTimer
);
// 重置定时器状态
static void __resetAllTimers();
@ -296,7 +296,7 @@ public:
#endif
private:
// 初始化 XAudio2
// 初始化音乐播放器
static bool __init();
// 回收相关资源

View File

@ -14,34 +14,149 @@ class ColliderManager;
class Random
{
public:
// 取得整型范围内的一个随机数
// 取得范围内的一个整型随机数
template<typename T>
static inline T range(T min, T max) { return e2d::Random::randomInt(min, max); }
// 取得浮点数范围内的一个随机数
static inline double range(float min, float max) { return e2d::Random::randomReal(min, max); }
// 取得浮点数范围内的一个随机数
static inline double range(double min, double max) { return e2d::Random::randomReal(min, max); }
// 取得整型范围内的一个随机数
template<typename T>
static T randomInt(T min, T max)
static inline T range(T min, T max)
{
std::uniform_int_distribution<T> dist(min, max);
return dist(getEngine());
return e2d::Random::__randomInt(min, max);
}
// 取得浮点数类型范围内的一个随机数
// 取得范围内的一个浮点数随机数
static inline double range(float min, float max)
{
return e2d::Random::__randomReal(min, max);
}
// 取得范围内的一个浮点数随机数
static inline double range(double min, double max)
{
return e2d::Random::__randomReal(min, max);
}
private:
template<typename T>
static T randomReal(T min, T max)
static T __randomInt(T min, T max)
{
std::uniform_int_distribution<T> dist(min, max);
return dist(Random::__getEngine());
}
template<typename T>
static T __randomReal(T min, T max)
{
std::uniform_real_distribution<T> dist(min, max);
return dist(getEngine());
return dist(Random::__getEngine());
}
// 获取随机数产生器
static std::default_random_engine &getEngine();
static std::default_random_engine &__getEngine();
};
// 音乐播放器
class Music :
public Object
{
friend MusicManager;
public:
Music();
Music(
String strFileName /* 音乐文件路径 */
);
virtual ~Music();
// 打开音乐文件
bool open(
String strFileName /* 音乐文件路径 */
);
// 播放
bool play(
int nLoopCount = 0 /* 重复播放次数,设置 -1 为循环播放 */
);
// 暂停
void pause();
// 继续
void resume();
// 停止
void stop();
// 关闭音乐文件
void close();
// 获取音乐播放状态
bool isPlaying() const;
// 获取音量
double getVolume() const;
// 获取频率比
double getFrequencyRatio() const;
// 设置音量
bool setVolume(
double fVolume /* 音量范围为 -224 ~ 224其中 0 是静音1 是正常音量 */
);
// 设置频率比
bool setFrequencyRatio(
double fFrequencyRatio /* 频率比范围为 1/1024.0f ~ 1024.0f,其中 1.0 为正常声调 */
);
#if HIGHER_THAN_VS2010
// 获取 IXAudio2SourceVoice 对象
IXAudio2SourceVoice* getIXAudio2SourceVoice() const;
protected:
bool _readMMIO();
bool _resetFile();
bool _read(
BYTE* pBuffer,
DWORD dwSizeToRead
);
bool _findMediaFileCch(
wchar_t* strDestPath,
int cchDest,
const wchar_t * strFilename
);
protected:
bool m_bOpened;
mutable bool m_bPlaying;
DWORD m_dwSize;
CHAR* m_pResourceBuffer;
BYTE* m_pbWaveData;
HMMIO m_hmmio;
MMCKINFO m_ck;
MMCKINFO m_ckRiff;
WAVEFORMATEX* m_pwfx;
IXAudio2SourceVoice* m_pSourceVoice;
#else
protected:
void _sendCommand(int nCommand, DWORD_PTR param1 = 0, DWORD_PTR parma2 = 0);
static LRESULT WINAPI MusicProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
protected:
MCIDEVICEID m_dev;
HWND m_wnd;
UINT m_nMusicID;
bool m_bPlaying;
int m_nRepeatTimes;
#endif
};
@ -53,8 +168,8 @@ class Timer :
public:
Timer(
Function func = nullptr, /* 定时器执行函数 */
String name = L"", /* 定时器名称 */
String name = L"", /* 任务名称 */
Function func = nullptr, /* 执行函数 */
double interval = 0, /* 时间间隔(秒) */
int times = -1, /* 执行次数(设 -1 为永久执行) */
bool atOnce = false, /* 是否立即执行 */
@ -326,111 +441,4 @@ public:
);
};
// 音乐播放器
class Music :
public Object
{
friend MusicManager;
public:
Music();
Music(
String strFileName /* 音乐文件路径 */
);
virtual ~Music();
// 打开音乐文件
bool open(
String strFileName /* 音乐文件路径 */
);
// 播放
bool play(
int nLoopCount = 0 /* 重复播放次数,设置 -1 为循环播放 */
);
// 暂停
void pause();
// 继续
void resume();
// 停止
void stop();
// 关闭音乐文件
void close();
// 获取音乐播放状态
bool isPlaying() const;
// 获取音量
double getVolume() const;
// 获取频率比
double getFrequencyRatio() const;
// 设置音量
bool setVolume(
double fVolume /* 音量范围为 -224 ~ 224其中 0 是静音1 是正常音量 */
);
// 设置频率比
bool setFrequencyRatio(
double fFrequencyRatio /* 频率比范围为 1/1024.0f ~ 1024.0f,其中 1.0 为正常声调 */
);
#if HIGHER_THAN_VS2010
// 获取 IXAudio2SourceVoice 对象
IXAudio2SourceVoice* getIXAudio2SourceVoice() const;
protected:
bool _readMMIO();
bool _resetFile();
bool _read(
BYTE* pBuffer,
DWORD dwSizeToRead
);
bool _findMediaFileCch(
wchar_t* strDestPath,
int cchDest,
const wchar_t * strFilename
);
protected:
bool m_bOpened;
mutable bool m_bPlaying;
DWORD m_dwSize;
CHAR* m_pResourceBuffer;
BYTE* m_pbWaveData;
HMMIO m_hmmio;
MMCKINFO m_ck;
MMCKINFO m_ckRiff;
WAVEFORMATEX* m_pwfx;
IXAudio2SourceVoice* m_pSourceVoice;
#else
protected:
void _sendCommand(int nCommand, DWORD_PTR param1 = 0, DWORD_PTR parma2 = 0);
static LRESULT WINAPI MusicProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
protected:
MCIDEVICEID m_dev;
HWND m_wnd;
UINT m_nMusicID;
bool m_bPlaying;
int m_nRepeatTimes;
#endif
};
}