修复多个bug

This commit is contained in:
Nomango 2017-10-31 17:19:13 +08:00
parent db64bf8e8d
commit 56464a36e2
31 changed files with 430 additions and 430 deletions

View File

@ -8,7 +8,7 @@ e2d::EActionLoop::EActionLoop(EAction * action) :
e2d::EActionLoop::~EActionLoop() e2d::EActionLoop::~EActionLoop()
{ {
SafeReleaseAndClear(&m_Action); SafeRelease(&m_Action);
} }
e2d::EActionLoop * e2d::EActionLoop::clone() const e2d::EActionLoop * e2d::EActionLoop::clone() const

View File

@ -25,7 +25,7 @@ e2d::EActionSequence::~EActionSequence()
{ {
for (auto action : m_vActions) for (auto action : m_vActions)
{ {
SafeReleaseAndClear(&action); SafeRelease(&action);
} }
} }

View File

@ -10,8 +10,8 @@ e2d::EActionTwo::EActionTwo(EAction * actionFirst, EAction * actionSecond) :
e2d::EActionTwo::~EActionTwo() e2d::EActionTwo::~EActionTwo()
{ {
SafeReleaseAndClear(&m_pFirstAction); SafeRelease(&m_pFirstAction);
SafeReleaseAndClear(&m_pSecondAction); SafeRelease(&m_pSecondAction);
} }
e2d::EActionTwo * e2d::EActionTwo::clone() const e2d::EActionTwo * e2d::EActionTwo::clone() const

View File

@ -10,8 +10,8 @@ e2d::EActionTwoAtSameTime::EActionTwoAtSameTime(EAction * actionFirst, EAction *
e2d::EActionTwoAtSameTime::~EActionTwoAtSameTime() e2d::EActionTwoAtSameTime::~EActionTwoAtSameTime()
{ {
SafeReleaseAndClear(&m_pFirstAction); SafeRelease(&m_pFirstAction);
SafeReleaseAndClear(&m_pSecondAction); SafeRelease(&m_pSecondAction);
} }
e2d::EActionTwoAtSameTime * e2d::EActionTwoAtSameTime::clone() const e2d::EActionTwoAtSameTime * e2d::EActionTwoAtSameTime::clone() const

View File

@ -19,7 +19,7 @@ e2d::EAnimation::~EAnimation()
{ {
for (auto frame : m_vFrames) for (auto frame : m_vFrames)
{ {
SafeReleaseAndClear(&frame); SafeRelease(&frame);
} }
} }

View File

@ -25,6 +25,7 @@ e2d::EApp::EApp()
, m_bManualPaused(false) , m_bManualPaused(false)
, m_bTransitional(false) , m_bTransitional(false)
, m_bTopMost(false) , m_bTopMost(false)
, m_bShowConsole(false)
, nAnimationInterval(17LL) , nAnimationInterval(17LL)
, m_ClearColor(EColor::BLACK) , m_ClearColor(EColor::BLACK)
, m_pCurrentScene(nullptr) , m_pCurrentScene(nullptr)
@ -33,7 +34,7 @@ e2d::EApp::EApp()
ASSERT(s_pInstance == nullptr, "EApp instance already exists!"); ASSERT(s_pInstance == nullptr, "EApp instance already exists!");
s_pInstance = this; // 保存实例对象 s_pInstance = this; // 保存实例对象
CoInitializeEx(NULL, COINIT_MULTITHREADED); CoInitialize(NULL);
} }
e2d::EApp::~EApp() e2d::EApp::~EApp()
@ -54,104 +55,101 @@ e2d::EApp * e2d::EApp::get()
return s_pInstance; // 获取 EApp 的唯一实例 return s_pInstance; // 获取 EApp 的唯一实例
} }
bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, bool showConsole /* = false */) bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height)
{ {
return init(title, width, height, EWindowStyle(), showConsole); return init(title, width, height, EWindowStyle());
} }
bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, EWindowStyle wStyle, bool showConsole /* = false */) bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, EWindowStyle wStyle)
{ {
HRESULT hr; HRESULT hr;
// 显示或关闭控制台 // 注册窗口类
EApp::showConsole(showConsole); WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = EApp::WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = HINST_THISCOMPONENT;
wcex.hbrBackground = (HBRUSH)(GetStockObject(BLACK_BRUSH));
wcex.lpszMenuName = NULL;
wcex.hCursor = LoadCursor(NULL, IDI_APPLICATION);
wcex.lpszClassName = L"Easy2DApp";
// 设置窗口是否有关闭按钮
if (wStyle.m_bNoClose)
{
wcex.style |= CS_NOCLOSE;
}
// 设置程序图标
if (wStyle.m_pIconID)
{
wcex.hIcon = (HICON)::LoadImage(
GetModuleHandle(NULL),
wStyle.m_pIconID,
IMAGE_ICON,
0,
0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
}
// 创建设备无关资源 RegisterClassEx(&wcex);
hr = _createDeviceIndependentResources();
// 因为 CreateWindow 函数使用的是像素大小,获取系统的 DPI 以使它
// 适应窗口缩放
FLOAT dpiX, dpiY;
// 工厂将返回当前的系统 DPI这个值也将用来创建窗口
GetFactory()->GetDesktopDpi(&dpiX, &dpiY);
width = static_cast<UINT>(ceil(width * dpiX / 96.f));
height = static_cast<UINT>(ceil(height * dpiY / 96.f));
// 获取屏幕分辨率
UINT screenWidth = static_cast<UINT>(GetSystemMetrics(SM_CXSCREEN));
UINT screenHeight = static_cast<UINT>(GetSystemMetrics(SM_CYSCREEN));
// 当输入的窗口大小比分辨率大时,给出警告
WARN_IF(screenWidth < width || screenHeight < height, "The window is larger than screen!");
// 取最小值
width = min(width, screenWidth);
height = min(height, screenHeight);
// 创建窗口样式
DWORD dwStyle = WS_OVERLAPPED | WS_SYSMENU;
if (!wStyle.m_bNoMiniSize)
{
dwStyle |= WS_MINIMIZEBOX;
}
// 保存窗口是否置顶显示
m_bTopMost = wStyle.m_bTopMost;
// 保存窗口名称
m_sTitle = title;
// 创建窗口
GetHWnd() = CreateWindow(
L"Easy2DApp",
m_sTitle.c_str(),
dwStyle,
0,
0,
width,
height,
NULL,
NULL,
HINST_THISCOMPONENT,
this
);
hr = GetHWnd() ? S_OK : E_FAIL;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
// 注册窗口类 // 禁用输入法
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) }; this->setKeyboardLayoutEnable(false);
UINT style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; // 重设客户区大小
if (wStyle.m_bNoClose) this->setWindowSize(width, height);
{ }
style |= CS_NOCLOSE; else
} {
wcex.style = style; UnregisterClass(L"E2DApp", HINST_THISCOMPONENT);
wcex.lpfnWndProc = EApp::WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = HINST_THISCOMPONENT;
wcex.hbrBackground = (HBRUSH)(GetStockObject(BLACK_BRUSH));
wcex.lpszMenuName = NULL;
wcex.hCursor = LoadCursor(NULL, IDI_APPLICATION);
wcex.lpszClassName = L"Easy2DApp";
if (wStyle.m_pIconID)
{
wcex.hIcon = (HICON)::LoadImage(GetModuleHandle(NULL), wStyle.m_pIconID, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
}
RegisterClassEx(&wcex);
// Because the CreateWindow function takes its size in pixels,
// obtain the system DPI and use it to scale the window size.
FLOAT dpiX, dpiY;
// The factory returns the current system DPI. This is also the value it will use
// to create its own windows.
GetFactory()->GetDesktopDpi(&dpiX, &dpiY);
width = static_cast<UINT>(ceil(width * dpiX / 96.f));
height = static_cast<UINT>(ceil(height * dpiY / 96.f));
// 获取屏幕分辨率
UINT screenWidth = static_cast<UINT>(GetSystemMetrics(SM_CXSCREEN));
UINT screenHeight = static_cast<UINT>(GetSystemMetrics(SM_CYSCREEN));
// 当输入的窗口大小比分辨率大时,给出警告
WARN_IF(screenWidth < width || screenHeight < height, "The window is larger than screen!");
width = min(width, screenWidth);
height = min(height, screenHeight);
// 创建窗口样式
DWORD dwStyle = WS_OVERLAPPED | WS_SYSMENU;
if (!wStyle.m_bNoMiniSize)
{
dwStyle |= WS_MINIMIZEBOX;
}
// 保存窗口是否置顶显示
m_bTopMost = wStyle.m_bTopMost;
// 保存窗口名称
m_sTitle = title;
// 创建窗口
GetHWnd() = CreateWindow(
L"Easy2DApp",
m_sTitle.c_str(),
dwStyle,
0,
0,
width,
height,
NULL,
NULL,
HINST_THISCOMPONENT,
this
);
hr = GetHWnd() ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
// 禁用输入法
this->setKeyboardLayoutEnable(false);
// 重设客户区大小
this->setWindowSize(width, height);
}
else
{
UnregisterClass(L"E2DApp", HINST_THISCOMPONENT);
}
} }
if (FAILED(hr)) if (FAILED(hr))
@ -186,13 +184,15 @@ bool e2d::EApp::isPaused()
return s_pInstance->m_bPaused || s_pInstance->m_bManualPaused; return s_pInstance->m_bPaused || s_pInstance->m_bManualPaused;
} }
void e2d::EApp::showConsole(bool show) void e2d::EApp::showConsole(bool show /* = true */)
{ {
// 查找已存在的控制台句柄
HWND hwnd = GetConsoleWindow();
static FILE * stdoutstream = nullptr; static FILE * stdoutstream = nullptr;
static FILE * stdinstream = nullptr; static FILE * stdinstream = nullptr;
static FILE * stderrstream = nullptr; static FILE * stderrstream = nullptr;
EApp::get()->m_bShowConsole = show;
// 查找已存在的控制台句柄
HWND hwnd = GetConsoleWindow();
// 关闭控制台 // 关闭控制台
if (show) if (show)
{ {
@ -238,6 +238,11 @@ void e2d::EApp::run()
ASSERT(GetHWnd() != nullptr, "Cannot find Game Window."); ASSERT(GetHWnd() != nullptr, "Cannot find Game Window.");
// 进入第一个场景 // 进入第一个场景
_enterNextScene(); _enterNextScene();
// 关闭控制台
if (!m_bShowConsole)
{
showConsole(false);
}
// 显示窗口 // 显示窗口
ShowWindow(GetHWnd(), SW_SHOWNORMAL); ShowWindow(GetHWnd(), SW_SHOWNORMAL);
UpdateWindow(GetHWnd()); UpdateWindow(GetHWnd());
@ -349,48 +354,42 @@ void e2d::EApp::_onControl()
EObjectManager::__flush(); // 刷新内存池 EObjectManager::__flush(); // 刷新内存池
ETimerManager::TimerProc(); // 定时器管理器执行程序 ETimerManager::TimerProc(); // 定时器管理器执行程序
EActionManager::ActionProc(); // 动作管理器执行程序 EActionManager::ActionProc(); // 动作管理器执行程序
EPhysicsManager::PhysicsProc(); // 物理引擎执行程序
} }
// This method discards device-specific
// resources if the Direct3D device dissapears during execution and
// recreates the resources the next time it's invoked.
void e2d::EApp::_onRender() void e2d::EApp::_onRender()
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
hr = _createDeviceResources(); // 开始绘图
GetRenderTarget()->BeginDraw();
if (SUCCEEDED(hr)) // 使用背景色清空屏幕
GetRenderTarget()->Clear(D2D1::ColorF(m_ClearColor));
// 绘制当前场景
if (m_pCurrentScene)
{ {
// 开始绘图 m_pCurrentScene->_onRender();
GetRenderTarget()->BeginDraw();
// 使用背景色清空屏幕
GetRenderTarget()->Clear(D2D1::ColorF(m_ClearColor));
// 绘制当前场景
if (m_pCurrentScene)
{
m_pCurrentScene->_onRender();
}
// 切换场景时,同时绘制两场景
if (m_bTransitional && m_pNextScene)
{
m_pNextScene->_onRender();
}
// 终止绘图
hr = GetRenderTarget()->EndDraw();
// 刷新界面
UpdateWindow(GetHWnd());
} }
// 切换场景时,同时绘制两场景
if (m_bTransitional && m_pNextScene)
{
m_pNextScene->_onRender();
}
// 终止绘图
hr = GetRenderTarget()->EndDraw();
// 刷新界面
UpdateWindow(GetHWnd());
if (hr == D2DERR_RECREATE_TARGET) if (hr == D2DERR_RECREATE_TARGET)
{ {
// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
// 并在下一次调用时重建资源
hr = S_OK; hr = S_OK;
_discardDeviceResources(); SafeReleaseInterface(&GetRenderTarget());
} }
if (FAILED(hr)) if (FAILED(hr))
{ {
// 渲染时产生了未知的错误,退出游戏
MessageBox(GetHWnd(), L"Game rendering failed!", L"Error", MB_OK); MessageBox(GetHWnd(), L"Game rendering failed!", L"Error", MB_OK);
this->quit(); this->quit();
} }
@ -468,22 +467,22 @@ void e2d::EApp::enterScene(EScene * scene, ETransition * transition, bool saveCu
} }
} }
void e2d::EApp::backScene() void e2d::EApp::backScene(ETransition * transition /* = nullptr */)
{ {
backScene(nullptr); // 栈为空时,调用返回场景函数失败
} WARN_IF(s_SceneStack.size() == 0, "Scene stack now is empty!");
if (s_SceneStack.size() == 0) return;
void e2d::EApp::backScene(ETransition * transition)
{
ASSERT(s_SceneStack.size(), "Scene stack now is empty!");
// 从栈顶取出场景指针,作为下一场景 // 从栈顶取出场景指针,作为下一场景
get()->m_pNextScene = s_SceneStack.top(); get()->m_pNextScene = s_SceneStack.top();
s_SceneStack.pop(); s_SceneStack.pop();
// 不保存当前场景
// 返回上一场景时,不保存当前场景
if (get()->m_pCurrentScene) if (get()->m_pCurrentScene)
{ {
get()->m_pCurrentScene->m_bWillSave = false; get()->m_pCurrentScene->m_bWillSave = false;
} }
// 设置切换场景动画 // 设置切换场景动画
if (transition) if (transition)
{ {
@ -496,6 +495,8 @@ void e2d::EApp::backScene(ETransition * transition)
} }
else else
{ {
// 把这个变量赋为 false场景将在下一帧画面
// 进行切换
get()->m_bTransitional = false; get()->m_bTransitional = false;
} }
} }
@ -506,7 +507,7 @@ void e2d::EApp::clearScene()
while (s_SceneStack.size()) while (s_SceneStack.size())
{ {
auto temp = s_SceneStack.top(); auto temp = s_SceneStack.top();
SafeReleaseAndClear(&temp); SafeRelease(&temp);
s_SceneStack.pop(); s_SceneStack.pop();
} }
} }
@ -518,14 +519,14 @@ e2d::EScene * e2d::EApp::getCurrentScene()
void e2d::EApp::setAppName(const EString &appname) void e2d::EApp::setAppName(const EString &appname)
{ {
s_pInstance->m_sAppName = appname; get()->m_sAppName = appname;
} }
e2d::EString e2d::EApp::getAppName() e2d::EString e2d::EApp::getAppName()
{ {
if (s_pInstance->m_sAppName.empty()) if (get()->m_sAppName.empty())
s_pInstance->m_sAppName = s_pInstance->m_sTitle; get()->m_sAppName = get()->m_sTitle;
return s_pInstance->m_sAppName; return get()->m_sAppName;
} }
void e2d::EApp::setBkColor(UINT32 color) void e2d::EApp::setBkColor(UINT32 color)
@ -576,12 +577,13 @@ void e2d::EApp::showWindow()
void e2d::EApp::quit() void e2d::EApp::quit()
{ {
// 这个变量将控制游戏是否结束
get()->m_bEnd = true; get()->m_bEnd = true;
} }
void e2d::EApp::end() void e2d::EApp::end()
{ {
get()->m_bEnd = true; EApp::quit();
} }
void e2d::EApp::_enterNextScene() void e2d::EApp::_enterNextScene()
@ -601,7 +603,7 @@ void e2d::EApp::_enterNextScene()
} }
else else
{ {
SafeReleaseAndClear(&m_pCurrentScene); SafeRelease(&m_pCurrentScene);
} }
} }
@ -612,59 +614,9 @@ void e2d::EApp::_enterNextScene()
m_pNextScene = nullptr; // 下一场景置空 m_pNextScene = nullptr; // 下一场景置空
} }
// Creates resources that are not bound to a particular device.
// Their lifetime effectively extends for the duration of the
// application.
HRESULT e2d::EApp::_createDeviceIndependentResources()
{
HRESULT hr = S_OK;
// Create a Direct2D factory.
hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &GetFactory());
if (FAILED(hr))
{
MessageBox(nullptr, L"Create Device Independent Resources Failed!", L"Error", MB_OK);
}
return hr;
}
// Creates resources that are bound to a particular
// Direct3D device. These resources need to be recreated
// if the Direct3D device dissapears, such as when the isVisiable
// changes, the window is remoted, etc.
HRESULT e2d::EApp::_createDeviceResources()
{
// 这个函数将自动创建设备相关资源
GetRenderTarget();
return S_OK;
}
// Discards device-dependent resources. These resources must be
// recreated when the Direct3D device is lost.
void e2d::EApp::_discardDeviceResources()
{
SafeReleaseInterface(&GetRenderTarget());
}
// If the application receives a WM_SIZE message, this method
// re2d::ESizes the render target appropriately.
void e2d::EApp::_onResize(UINT32 width, UINT32 height)
{
if (GetRenderTarget())
{
// Note: This method can fail, but it's okay to ignore the
// error here, because the error will be returned again
// the next time EndDraw is called.
GetRenderTarget()->Resize(D2D1::SizeU(width, height));
}
}
// Handles window messages.
LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ {
// 处理窗口消息
LRESULT result = 0; LRESULT result = 0;
if (message == WM_CREATE) if (message == WM_CREATE)
@ -738,7 +690,10 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam
{ {
UINT width = LOWORD(lParam); UINT width = LOWORD(lParam);
UINT height = HIWORD(lParam); UINT height = HIWORD(lParam);
pEApp->_onResize(width, height); // 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
// 目标适当。它可能会调用失败,但是这里可以忽略有可能的
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
GetRenderTarget()->Resize(D2D1::SizeU(width, height));
} }
result = 0; result = 0;
wasHandled = true; wasHandled = true;
@ -827,6 +782,7 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam
} }
} }
// 对当前消息没有特定的处理程序时,执行默认的窗口函数
if (!wasHandled) if (!wasHandled)
{ {
result = DefWindowProc(hWnd, message, wParam, lParam); result = DefWindowProc(hWnd, message, wParam, lParam);

View File

@ -4,7 +4,6 @@
e2d::EObject::EObject() e2d::EObject::EObject()
: m_nRefCount(0) : m_nRefCount(0)
, m_bManaged(false) , m_bManaged(false)
, m_bAutoRelease(false)
{ {
EObjectManager::add(this); // 将该对象放入释放池中 EObjectManager::add(this); // 将该对象放入释放池中
} }
@ -26,8 +25,3 @@ void e2d::EObject::release()
// 通知对象管理池刷新 // 通知对象管理池刷新
EObjectManager::notifyFlush(); EObjectManager::notifyFlush();
} }
void e2d::EObject::autoRelease()
{
m_bAutoRelease = true;
}

View File

@ -12,6 +12,7 @@ e2d::EScene::EScene()
, m_bGeometryVisiable(false) , m_bGeometryVisiable(false)
, m_pRoot(new ENode()) , m_pRoot(new ENode())
{ {
m_pRoot->retain();
m_pRoot->_onEnter(); m_pRoot->_onEnter();
m_pRoot->_setParentScene(this); m_pRoot->_setParentScene(this);
m_pRoot->_setSize(EApp::getWidth(), EApp::getHeight()); m_pRoot->_setSize(EApp::getWidth(), EApp::getHeight());
@ -20,7 +21,7 @@ e2d::EScene::EScene()
e2d::EScene::~EScene() e2d::EScene::~EScene()
{ {
SafeReleaseAndClear(&m_pRoot); SafeRelease(&m_pRoot);
} }
void e2d::EScene::onEnter() void e2d::EScene::onEnter()
@ -66,14 +67,14 @@ void e2d::EScene::add(ENode * child, int order /* = 0 */)
m_pRoot->addChild(child, order); m_pRoot->addChild(child, order);
} }
bool e2d::EScene::remove(ENode * child, bool release /* = false */) bool e2d::EScene::remove(ENode * child)
{ {
return m_pRoot->removeChild(child, release); return m_pRoot->removeChild(child);
} }
void e2d::EScene::remove(const EString &childName, bool release /* = false */) void e2d::EScene::remove(const EString &childName)
{ {
return m_pRoot->removeChild(childName, release); return m_pRoot->removeChild(childName);
} }
e2d::EVector<e2d::ENode*>& e2d::EScene::getChildren() e2d::EVector<e2d::ENode*>& e2d::EScene::getChildren()

View File

@ -217,7 +217,7 @@
<ClCompile Include="Geometry\EGeometry.cpp" /> <ClCompile Include="Geometry\EGeometry.cpp" />
<ClCompile Include="Geometry\EPhysicsMsg.cpp" /> <ClCompile Include="Geometry\EPhysicsMsg.cpp" />
<ClCompile Include="Geometry\ERectangle.cpp" /> <ClCompile Include="Geometry\ERectangle.cpp" />
<ClCompile Include="Listener\ECollisionListener.cpp" /> <ClCompile Include="Listener\EContactListener.cpp" />
<ClCompile Include="Listener\EKeyboardListener.cpp" /> <ClCompile Include="Listener\EKeyboardListener.cpp" />
<ClCompile Include="Listener\EKeyboardPressListener.cpp" /> <ClCompile Include="Listener\EKeyboardPressListener.cpp" />
<ClCompile Include="Listener\EListener.cpp" /> <ClCompile Include="Listener\EListener.cpp" />

View File

@ -192,9 +192,6 @@
<ClCompile Include="Geometry\EEllipse.cpp"> <ClCompile Include="Geometry\EEllipse.cpp">
<Filter>Geometry</Filter> <Filter>Geometry</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Listener\ECollisionListener.cpp">
<Filter>Listener</Filter>
</ClCompile>
<ClCompile Include="Common\EMouseMsg.cpp"> <ClCompile Include="Common\EMouseMsg.cpp">
<Filter>Common</Filter> <Filter>Common</Filter>
</ClCompile> </ClCompile>
@ -210,6 +207,9 @@
<ClCompile Include="Geometry\EPhysicsMsg.cpp"> <ClCompile Include="Geometry\EPhysicsMsg.cpp">
<Filter>Geometry</Filter> <Filter>Geometry</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Listener\EContactListener.cpp">
<Filter>Listener</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Win\winbase.h"> <ClInclude Include="Win\winbase.h">

View File

@ -1,15 +1,18 @@
#include "..\egeometry.h" #include "..\egeometry.h"
#include "..\Win\winbase.h" #include "..\emanagers.h"
#include "..\enodes.h" #include "..\enodes.h"
#include "..\Win\winbase.h"
e2d::EGeometry::EGeometry() e2d::EGeometry::EGeometry()
: m_bTransformed(false) : m_bTransformed(false)
, m_nCategoryBitmask(0)
,m_nContactBitmask(0)
, m_bIsVisiable(true)
, m_nColor(EColor::RED) , m_nColor(EColor::RED)
, m_fOpacity(1) , m_fOpacity(1)
, m_pParentNode(nullptr) , m_pParentNode(nullptr)
, m_pTransformedGeometry(nullptr) , m_pTransformedGeometry(nullptr)
{ {
this->autoRelease();
} }
e2d::EGeometry::~EGeometry() e2d::EGeometry::~EGeometry()
@ -17,11 +20,41 @@ e2d::EGeometry::~EGeometry()
SafeReleaseInterface(&m_pTransformedGeometry); SafeReleaseInterface(&m_pTransformedGeometry);
} }
bool e2d::EGeometry::isContactWith(EGeometry * geometry)
{
return ((this->m_nContactBitmask & geometry->m_nCategoryBitmask) != 0);
}
e2d::ENode * e2d::EGeometry::getParentNode() const e2d::ENode * e2d::EGeometry::getParentNode() const
{ {
return m_pParentNode; return m_pParentNode;
} }
UINT32 e2d::EGeometry::getCategoryBitmask() const
{
return m_nCategoryBitmask;
}
UINT32 e2d::EGeometry::getContactBitmask() const
{
return m_nContactBitmask;
}
void e2d::EGeometry::setCategoryBitmask(UINT32 mask)
{
m_nCategoryBitmask = mask;
}
void e2d::EGeometry::setContactBitmask(UINT32 mask)
{
m_nContactBitmask = mask;
}
void e2d::EGeometry::setVisiable(bool bVisiable)
{
m_bIsVisiable = bVisiable;
}
void e2d::EGeometry::setColor(UINT32 color) void e2d::EGeometry::setColor(UINT32 color)
{ {
m_nColor = color; m_nColor = color;
@ -29,7 +62,7 @@ void e2d::EGeometry::setColor(UINT32 color)
void e2d::EGeometry::setOpacity(float opacity) void e2d::EGeometry::setOpacity(float opacity)
{ {
m_fOpacity = opacity; m_fOpacity = min(max(opacity, 0), 1);
} }
void e2d::EGeometry::_onRender() void e2d::EGeometry::_onRender()
@ -71,14 +104,17 @@ void e2d::EGeometry::_transform()
{ {
if (m_pParentNode) if (m_pParentNode)
{ {
// 释放原形状
SafeReleaseInterface(&m_pTransformedGeometry); SafeReleaseInterface(&m_pTransformedGeometry);
// 根据父节点转换几何图形
GetFactory()->CreateTransformedGeometry( GetFactory()->CreateTransformedGeometry(
_getD2dGeometry(), _getD2dGeometry(),
m_pParentNode->m_Matri, m_pParentNode->m_Matri,
&m_pTransformedGeometry &m_pTransformedGeometry
); );
this->m_bTransformed = true; // 判断形状变换后的情况
EPhysicsManager::PhysicsGeometryProc(this);
} }
} }

View File

@ -1,29 +1,29 @@
#include "..\elisteners.h" #include "..\elisteners.h"
#include "..\egeometry.h" #include "..\egeometry.h"
e2d::ECollisionListener::ECollisionListener() e2d::EContactListener::EContactListener()
: EPhysicsListener() : EPhysicsListener()
{ {
} }
e2d::ECollisionListener::ECollisionListener(const EString & name) e2d::EContactListener::EContactListener(const EString & name)
: EPhysicsListener(name) : EPhysicsListener(name)
{ {
} }
e2d::ECollisionListener::ECollisionListener(const COLLISION_LISTENER_CALLBACK & callback) e2d::EContactListener::EContactListener(const COLLISION_LISTENER_CALLBACK & callback)
: EPhysicsListener() : EPhysicsListener()
{ {
this->m_Callback = callback; this->m_Callback = callback;
} }
e2d::ECollisionListener::ECollisionListener(const EString & name, const COLLISION_LISTENER_CALLBACK & callback) e2d::EContactListener::EContactListener(const EString & name, const COLLISION_LISTENER_CALLBACK & callback)
: EPhysicsListener(name) : EPhysicsListener(name)
{ {
this->m_Callback = callback; this->m_Callback = callback;
} }
void e2d::ECollisionListener::_callOn() void e2d::EContactListener::_callOn()
{ {
if (EPhysicsMsg::getMsg() == EPhysicsMsg::OVERLAP || if (EPhysicsMsg::getMsg() == EPhysicsMsg::OVERLAP ||
EPhysicsMsg::getMsg() == EPhysicsMsg::CONTAINS || EPhysicsMsg::getMsg() == EPhysicsMsg::CONTAINS ||

View File

@ -80,7 +80,7 @@ void e2d::EActionManager::_clearAllActionsBindedWith(ENode * pTargetNode)
auto a = s_vActions[i]; auto a = s_vActions[i];
if (a->getTarget() == pTargetNode) if (a->getTarget() == pTargetNode)
{ {
SafeReleaseAndClear(&a); SafeRelease(&a);
s_vActions.erase(s_vActions.begin() + i); s_vActions.erase(s_vActions.begin() + i);
} }
else else
@ -144,7 +144,7 @@ void e2d::EActionManager::ActionProc()
if (action->_isEnding()) if (action->_isEnding())
{ {
// 动作已经结束 // 动作已经结束
SafeReleaseAndClear(&action); SafeRelease(&action);
s_vActions.erase(s_vActions.begin() + i); s_vActions.erase(s_vActions.begin() + i);
} }
else else

View File

@ -24,7 +24,7 @@ void e2d::EMsgManager::MouseProc(UINT message, WPARAM wParam, LPARAM lParam)
if (EApp::isPaused() && !mlistener->m_bAlways) if (EApp::isPaused() && !mlistener->m_bAlways)
continue; continue;
if (mlistener->isRunning()) if (mlistener->m_bAlways || mlistener->isRunning())
{ {
if (mlistener->getParentNode() && if (mlistener->getParentNode() &&
mlistener->getParentNode()->getParentScene() == EApp::getCurrentScene()) mlistener->getParentNode()->getParentScene() == EApp::getCurrentScene())
@ -49,7 +49,7 @@ void e2d::EMsgManager::KeyboardProc(UINT message, WPARAM wParam, LPARAM lParam)
if (EApp::isPaused() && !klistener->m_bAlways) if (EApp::isPaused() && !klistener->m_bAlways)
continue; continue;
if (klistener->isRunning()) if (klistener->m_bAlways || klistener->isRunning())
{ {
if (klistener->getParentNode() && if (klistener->getParentNode() &&
klistener->getParentNode()->getParentScene() == EApp::getCurrentScene()) klistener->getParentNode()->getParentScene() == EApp::getCurrentScene())
@ -140,7 +140,7 @@ void e2d::EMsgManager::delMouseListeners(const EString & name)
{ {
if ((*mIter)->getName() == name) if ((*mIter)->getName() == name)
{ {
SafeReleaseAndClear(&(*mIter)); SafeRelease(&(*mIter));
mIter = s_vMouseListeners.erase(mIter); mIter = s_vMouseListeners.erase(mIter);
} }
else else
@ -182,7 +182,7 @@ void e2d::EMsgManager::delKeyboardListeners(const EString & name)
{ {
if ((*kIter)->getName() == name) if ((*kIter)->getName() == name)
{ {
SafeReleaseAndClear(&(*kIter)); SafeRelease(&(*kIter));
kIter = s_vKeyboardListeners.erase(kIter); kIter = s_vKeyboardListeners.erase(kIter);
} }
else else
@ -279,7 +279,7 @@ void e2d::EMsgManager::_clearAllMouseListenersBindedWith(ENode * pParentNode)
auto t = s_vMouseListeners[i]; auto t = s_vMouseListeners[i];
if (t->getParentNode() == pParentNode) if (t->getParentNode() == pParentNode)
{ {
SafeReleaseAndClear(&t); SafeRelease(&t);
s_vMouseListeners.erase(s_vMouseListeners.begin() + i); s_vMouseListeners.erase(s_vMouseListeners.begin() + i);
} }
else else
@ -296,7 +296,7 @@ void e2d::EMsgManager::_clearAllKeyboardListenersBindedWith(ENode * pParentNode)
auto t = s_vKeyboardListeners[i]; auto t = s_vKeyboardListeners[i];
if (t->getParentNode() == pParentNode) if (t->getParentNode() == pParentNode)
{ {
SafeReleaseAndClear(&t); SafeRelease(&t);
s_vKeyboardListeners.erase(s_vKeyboardListeners.begin() + i); s_vKeyboardListeners.erase(s_vKeyboardListeners.begin() + i);
} }
else else

View File

@ -23,9 +23,9 @@ void e2d::EObjectManager::__flush()
// 循环遍历容器中的所有对象 // 循环遍历容器中的所有对象
for (iter = s_vPool.begin(); iter != s_vPool.end();) for (iter = s_vPool.begin(); iter != s_vPool.end();)
{ {
if ((*iter)->m_bAutoRelease && (*iter)->m_nRefCount <= 0) if ((*iter)->m_nRefCount <= 0)
{ {
// 若对象的引用的计数 0, 释放该对象 // 若对象的引用的计数小于等于 0, 释放该对象
delete (*iter); delete (*iter);
// 从释放池中删除该对象 // 从释放池中删除该对象
iter = s_vPool.erase(iter); iter = s_vPool.erase(iter);

View File

@ -9,41 +9,26 @@ e2d::EVector<e2d::EPhysicsListener*> s_vListeners;
e2d::EVector<e2d::EGeometry*> s_vGeometries; e2d::EVector<e2d::EGeometry*> s_vGeometries;
void e2d::EPhysicsManager::PhysicsProc() void e2d::EPhysicsManager::PhysicsGeometryProc(EGeometry * pActiveGeometry)
{ {
if (s_vListeners.empty() || s_vGeometries.empty() || EApp::isPaused()) if (s_vListeners.empty() || s_vGeometries.empty() || EApp::isPaused())
return; return;
for (auto &geometry : s_vGeometries)
{
if (!geometry->getParentNode() ||
(geometry->getParentNode()->getParentScene() != EApp::getCurrentScene()))
continue;
// 只对进行了变化了对象进行判断
if (geometry->m_bTransformed)
{
// 判断变化后的图形情况
PhysicsGeometryProc(geometry);
// 取消变化标志
geometry->m_bTransformed = false;
}
}
}
void e2d::EPhysicsManager::PhysicsGeometryProc(EGeometry * pActiveGeometry)
{
// pActiveGeometry 为主动方 // pActiveGeometry 为主动方
EPhysicsMsg::s_pActiveGeometry = pActiveGeometry; EPhysicsMsg::s_pActiveGeometry = pActiveGeometry;
// 判断变化后的状态 // 判断变化后的状态
for (auto &pPassiveGeometry : s_vGeometries) for (auto &pPassiveGeometry : s_vGeometries)
{ {
// 不与其他场景的物体判断
if (!pPassiveGeometry->getParentNode() || if (!pPassiveGeometry->getParentNode() ||
(pPassiveGeometry->getParentNode()->getParentScene() != EApp::getCurrentScene())) (pPassiveGeometry->getParentNode()->getParentScene() != EApp::getCurrentScene()))
continue; continue;
if (pActiveGeometry != pPassiveGeometry) if (pActiveGeometry != pPassiveGeometry)
{ {
// 判断两物体是否会产生接触消息
if (!pActiveGeometry->isContactWith(pPassiveGeometry))
continue;
// pPassiveGeometry 为被动方 // pPassiveGeometry 为被动方
EPhysicsMsg::s_pPassiveGeometry = pPassiveGeometry; EPhysicsMsg::s_pPassiveGeometry = pPassiveGeometry;
// 获取两方的关系 // 获取两方的关系
@ -101,7 +86,7 @@ void e2d::EPhysicsManager::bindListener(EPhysicsListener * listener, ENode * pPa
} }
} }
void e2d::EPhysicsManager::addGeometry(EGeometry * geometry) void e2d::EPhysicsManager::_addGeometry(EGeometry * geometry)
{ {
if (geometry) if (geometry)
{ {
@ -110,7 +95,7 @@ void e2d::EPhysicsManager::addGeometry(EGeometry * geometry)
} }
} }
void e2d::EPhysicsManager::delGeometry(EGeometry * geometry) void e2d::EPhysicsManager::_delGeometry(EGeometry * geometry)
{ {
if (geometry) if (geometry)
{ {
@ -118,7 +103,7 @@ void e2d::EPhysicsManager::delGeometry(EGeometry * geometry)
{ {
if (s_vGeometries[i] == geometry) if (s_vGeometries[i] == geometry)
{ {
SafeReleaseAndClear(&geometry); SafeRelease(&geometry);
s_vGeometries.erase(s_vGeometries.begin() + i); s_vGeometries.erase(s_vGeometries.begin() + i);
return; return;
} }
@ -155,7 +140,7 @@ void e2d::EPhysicsManager::delListeners(const EString & name)
{ {
if ((*iter)->getName() == name) if ((*iter)->getName() == name)
{ {
SafeReleaseAndClear(&(*iter)); SafeRelease(&(*iter));
iter = s_vListeners.erase(iter); iter = s_vListeners.erase(iter);
} }
else else
@ -227,7 +212,7 @@ void e2d::EPhysicsManager::_clearAllListenersBindedWith(ENode * pParentNode)
auto listener = s_vListeners[i]; auto listener = s_vListeners[i];
if (listener->getParentNode() == pParentNode) if (listener->getParentNode() == pParentNode)
{ {
SafeReleaseAndClear(&listener); SafeRelease(&listener);
s_vListeners.erase(s_vListeners.begin() + i); s_vListeners.erase(s_vListeners.begin() + i);
} }
else else

View File

@ -81,7 +81,7 @@ void e2d::ETimerManager::delTimers(const EString & name)
{ {
if ((*mIter)->getName() == name) if ((*mIter)->getName() == name)
{ {
SafeReleaseAndClear(&(*mIter)); SafeRelease(&(*mIter));
mIter = s_vTimers.erase(mIter); mIter = s_vTimers.erase(mIter);
} }
else else
@ -138,7 +138,7 @@ void e2d::ETimerManager::_clearAllTimersBindedWith(ENode * pParentNode)
auto t = s_vTimers[i]; auto t = s_vTimers[i];
if (t->getParentNode() == pParentNode) if (t->getParentNode() == pParentNode)
{ {
SafeReleaseAndClear(&t); SafeRelease(&t);
s_vTimers.erase(s_vTimers.begin() + i); s_vTimers.erase(s_vTimers.begin() + i);
} }
else else

View File

@ -42,10 +42,10 @@ e2d::ENode::~ENode()
EMsgManager::_clearAllKeyboardListenersBindedWith(this); EMsgManager::_clearAllKeyboardListenersBindedWith(this);
EActionManager::_clearAllActionsBindedWith(this); EActionManager::_clearAllActionsBindedWith(this);
EPhysicsManager::_clearAllListenersBindedWith(this); EPhysicsManager::_clearAllListenersBindedWith(this);
EPhysicsManager::delGeometry(m_pGeometry); EPhysicsManager::_delGeometry(m_pGeometry);
for (auto child : m_vChildren) for (auto child : m_vChildren)
{ {
SafeReleaseAndClear(&child); SafeRelease(&child);
} }
} }
@ -112,7 +112,7 @@ void e2d::ENode::_onRender()
void e2d::ENode::_drawGeometry() void e2d::ENode::_drawGeometry()
{ {
// 绘制自身的几何形状 // 绘制自身的几何形状
if (m_pGeometry) if (m_pGeometry && m_pGeometry->m_bIsVisiable)
{ {
m_pGeometry->_onRender(); m_pGeometry->_onRender();
} }
@ -501,9 +501,9 @@ void e2d::ENode::setAnchor(float anchorX, float anchorY)
void e2d::ENode::setGeometry(EGeometry * geometry) void e2d::ENode::setGeometry(EGeometry * geometry)
{ {
// 删除旧的形状 // 删除旧的形状
EPhysicsManager::delGeometry(m_pGeometry); EPhysicsManager::_delGeometry(m_pGeometry);
// 添加新的形状 // 添加新的形状
EPhysicsManager::addGeometry(geometry); EPhysicsManager::_addGeometry(geometry);
if (geometry) if (geometry)
{ {
@ -589,15 +589,15 @@ e2d::ENode * e2d::ENode::getChild(const EString & name)
return nullptr; return nullptr;
} }
void e2d::ENode::removeFromParent(bool release /* = false */) void e2d::ENode::removeFromParent()
{ {
if (m_pParent) if (m_pParent)
{ {
m_pParent->removeChild(this, release); m_pParent->removeChild(this);
} }
} }
bool e2d::ENode::removeChild(ENode * child, bool release /* = true */) bool e2d::ENode::removeChild(ENode * child)
{ {
WARN_IF(child == nullptr, "ENode::removeChild NULL pointer exception."); WARN_IF(child == nullptr, "ENode::removeChild NULL pointer exception.");
@ -621,10 +621,6 @@ bool e2d::ENode::removeChild(ENode * child, bool release /* = true */)
} }
child->_onExit(); child->_onExit();
child->release(); child->release();
if (release)
{
child->autoRelease();
}
return true; return true;
} }
} }
@ -632,7 +628,7 @@ bool e2d::ENode::removeChild(ENode * child, bool release /* = true */)
return false; return false;
} }
void e2d::ENode::removeChild(const EString & childName, bool release /* = true */) void e2d::ENode::removeChild(const EString & childName)
{ {
WARN_IF(childName.empty(), "Invalid ENode name."); WARN_IF(childName.empty(), "Invalid ENode name.");
@ -659,26 +655,18 @@ void e2d::ENode::removeChild(const EString & childName, bool release /* = true *
} }
child->_onExit(); child->_onExit();
child->release(); child->release();
if (release)
{
child->autoRelease();
}
return; return;
} }
} }
} }
void e2d::ENode::clearAllChildren(bool release /* = true */) void e2d::ENode::clearAllChildren()
{ {
// 所有节点的引用计数减一 // 所有节点的引用计数减一
for (auto child : m_vChildren) for (auto child : m_vChildren)
{ {
child->_onExit(); child->_onExit();
child->release(); child->release();
if (release)
{
child->autoRelease();
}
} }
// 清空储存节点的容器 // 清空储存节点的容器
m_vChildren.clear(); m_vChildren.clear();

View File

@ -47,14 +47,14 @@ e2d::ESprite::ESprite(const EString & resourceName, const EString & resourceType
e2d::ESprite::~ESprite() e2d::ESprite::~ESprite()
{ {
SafeReleaseAndClear(&m_pTexture); SafeRelease(&m_pTexture);
} }
void e2d::ESprite::loadFrom(ETexture * texture) void e2d::ESprite::loadFrom(ETexture * texture)
{ {
if (texture) if (texture)
{ {
SafeReleaseAndClear(&m_pTexture); SafeRelease(&m_pTexture);
m_pTexture = texture; m_pTexture = texture;
m_pTexture->retain(); m_pTexture->retain();

View File

@ -37,7 +37,7 @@ e2d::EText::EText(const EString & text, EString fontFamily, float fontSize, UINT
e2d::EText::~EText() e2d::EText::~EText()
{ {
SafeReleaseAndClear(&m_pFont); SafeRelease(&m_pFont);
} }
e2d::EString e2d::EText::getText() const e2d::EString e2d::EText::getText() const
@ -70,7 +70,7 @@ void e2d::EText::setFont(EFont * font)
{ {
if (font) if (font)
{ {
SafeReleaseAndClear(&m_pFont); SafeRelease(&m_pFont);
m_pFont = font; m_pFont = font;
font->retain(); font->retain();

View File

@ -33,6 +33,21 @@ e2d::EString e2d::EFileUtils::getLocalAppDataPath()
return L""; return L"";
} }
e2d::EString e2d::EFileUtils::getTempPath()
{
// 获取临时文件目录
TCHAR path[_MAX_PATH];
::GetTempPath(_MAX_PATH, path);
// 创建临时文件目录
e2d::EString tempFilePath = path + e2d::EApp::getAppName();
if (_waccess(tempFilePath.c_str(), 0) == -1)
{
_wmkdir(tempFilePath.c_str());
}
return tempFilePath;
}
e2d::EString e2d::EFileUtils::getDefaultSavePath() e2d::EString e2d::EFileUtils::getDefaultSavePath()
{ {
EString path = EFileUtils::getLocalAppDataPath(); EString path = EFileUtils::getLocalAppDataPath();

View File

@ -1,10 +1,12 @@
#include "..\etools.h" #include "..\etools.h"
#include "..\Win\winbase.h" #include "..\Win\winbase.h"
#include <map>
#include <mmsystem.h> #include <mmsystem.h>
#include <Digitalv.h>
#pragma comment(lib , "winmm.lib") #pragma comment(lib , "winmm.lib")
#include <map> static size_t Hash(const e2d::EString & key);
#include <Digitalv.h> static bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName);
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -18,8 +20,8 @@ public:
~MciPlayer(); ~MciPlayer();
void close(); void close();
void open(const e2d::EString & pFileName, UINT uId); bool open(const e2d::EString & pFileName, UINT uId);
void open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, UINT uId); bool open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, UINT uId);
void play(bool bLoop = false); void play(bool bLoop = false);
void pause(); void pause();
void resume(); void resume();
@ -36,7 +38,7 @@ private:
UINT m_nSoundID; UINT m_nSoundID;
bool m_bPlaying; bool m_bPlaying;
bool m_bLoop; bool m_bLoop;
e2d::EString m_sTmpFileName; e2d::EString m_sTempFileName;
}; };
@ -53,78 +55,67 @@ MciPlayer::~MciPlayer()
close(); // 关闭播放器 close(); // 关闭播放器
} }
void MciPlayer::open(const e2d::EString & pFileName, UINT uId) bool MciPlayer::open(const e2d::EString & pFileName, UINT uId)
{ {
// 忽略不存在的文件 // 忽略不存在的文件
if (pFileName.empty()) return; if (pFileName.empty())
return false;
// 停止当前音乐 // 停止当前音乐
close(); close();
// 设置 MCI_OPEN_PARMS 参数 // 设置 MCI_OPEN_PARMS 参数
MCI_OPEN_PARMS mciOpen = { 0 }; MCI_OPEN_PARMS mciOpen = { 0 };
mciOpen.lpstrDeviceType = (LPCTSTR)-1;
mciOpen.lpstrElementName = pFileName.c_str(); mciOpen.lpstrElementName = pFileName.c_str();
// 打开这个文件 // 打开这个文件
MCIERROR mciError; MCIERROR mciError;
mciError = mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast<DWORD_PTR>(&mciOpen)); mciError = mciSendCommand(
// 出现错误时,忽略这次操作 0,
if (mciError) return; MCI_OPEN,
MCI_OPEN_ELEMENT | MCI_NOTIFY,
reinterpret_cast<DWORD_PTR>(&mciOpen)
);
// 保存设备等信息 if (mciError)
m_dev = mciOpen.wDeviceID;
m_nSoundID = uId;
m_bPlaying = false;
}
void MciPlayer::open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, UINT uId)
{
bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName);
// 忽略不存在的文件
if (pResouceName.empty() || pResouceType.empty()) return;
// 获取临时文件目录
TCHAR tmpFilePath[_MAX_PATH];
::GetTempPath(_MAX_PATH, tmpFilePath);
// 创建临时文件目录
e2d::EString tmpFileName = tmpFilePath + e2d::EApp::getAppName();
if (_waccess(tmpFileName.c_str(), 0) == -1)
{ {
_wmkdir(tmpFileName.c_str()); return false;
} }
else
// 产生临时文件的文件名
tmpFileName.append(L"\\");
tmpFileName.append(std::to_wstring(uId));
tmpFileName.append(L"." + musicExtension);
// 导出资源为临时文件
if (ExtractResource(tmpFileName.c_str(), pResouceType.c_str(), pResouceName.c_str()))
{ {
// 停止当前音乐
close();
// 设置 MCI_OPEN_PARMS 参数
MCI_OPEN_PARMS mciOpen = { 0 };
mciOpen.lpstrDeviceType = (LPCTSTR)-1;
mciOpen.lpstrElementName = tmpFileName.c_str();
// 打开这个文件
MCIERROR mciError;
mciError = mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast<DWORD_PTR>(&mciOpen));
// 出现错误时,忽略这次操作
if (mciError) return;
// 保存设备等信息 // 保存设备等信息
m_dev = mciOpen.wDeviceID; m_dev = mciOpen.wDeviceID;
m_nSoundID = uId; m_nSoundID = uId;
m_bPlaying = false; m_bPlaying = false;
m_sTmpFileName = tmpFileName; return true;
} }
} }
bool MciPlayer::open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, UINT uId)
{
// 忽略不存在的文件
if (pResouceName.empty() || pResouceType.empty() || musicExtension.empty()) return false;
// 获取临时文件目录
e2d::EString tempFileName = e2d::EFileUtils::getTempPath();
// 产生临时文件的文件名
tempFileName.append(L"\\");
tempFileName.append(std::to_wstring(uId));
tempFileName.append(L"." + musicExtension);
// 导出资源为临时文件
if (ExtractResource(tempFileName.c_str(), pResouceType.c_str(), pResouceName.c_str()))
{
if (open(tempFileName, uId))
{
m_sTempFileName = tempFileName;
return true;
}
}
return false;
}
void MciPlayer::play(bool bLoop) void MciPlayer::play(bool bLoop)
{ {
// 设备为空时,忽略这次操作 // 设备为空时,忽略这次操作
@ -135,8 +126,15 @@ void MciPlayer::play(bool bLoop)
// 设置播放参数 // 设置播放参数
MCI_PLAY_PARMS mciPlay = { 0 }; MCI_PLAY_PARMS mciPlay = { 0 };
MCIERROR s_mciError; MCIERROR s_mciError;
// 播放声音 // 播放声音
s_mciError = mciSendCommand(m_dev, MCI_PLAY, MCI_FROM | (bLoop ? MCI_DGV_PLAY_REPEAT : 0), reinterpret_cast<DWORD_PTR>(&mciPlay)); s_mciError = mciSendCommand(
m_dev,
MCI_PLAY,
MCI_FROM | MCI_NOTIFY | (bLoop ? MCI_DGV_PLAY_REPEAT : 0),
reinterpret_cast<DWORD_PTR>(&mciPlay)
);
// 未出错时,置 m_bPlaying 为 true // 未出错时,置 m_bPlaying 为 true
if (!s_mciError) if (!s_mciError)
{ {
@ -158,10 +156,10 @@ void MciPlayer::close()
_sendCommand(MCI_CLOSE); _sendCommand(MCI_CLOSE);
} }
// 删除临时文件 // 删除临时文件
if (!m_sTmpFileName.empty()) if (!m_sTempFileName.empty())
{ {
DeleteFile(m_sTmpFileName.c_str()); DeleteFile(m_sTempFileName.c_str());
m_sTmpFileName.clear(); m_sTempFileName.clear();
} }
// 恢复默认属性 // 恢复默认属性
m_dev = 0; m_dev = 0;
@ -197,10 +195,24 @@ void MciPlayer::rewind()
return; return;
} }
// 重置播放位置 // 重置播放位置
mciSendCommand(m_dev, MCI_SEEK, MCI_SEEK_TO_START, 0); mciSendCommand(
m_dev,
MCI_SEEK,
MCI_SEEK_TO_START | MCI_NOTIFY,
0
);
// 播放音乐 // 播放音乐
MCI_PLAY_PARMS mciPlay = { 0 }; MCI_PLAY_PARMS mciPlay = { 0 };
m_bPlaying = mciSendCommand(m_dev, MCI_PLAY, (m_bLoop ? MCI_DGV_PLAY_REPEAT : 0), reinterpret_cast<DWORD_PTR>(&mciPlay)) ? false : true; MCIERROR s_mciError;
// 播放声音
s_mciError = mciSendCommand(
m_dev,
MCI_PLAY,
MCI_NOTIFY | (m_bLoop ? MCI_DGV_PLAY_REPEAT : 0),
reinterpret_cast<DWORD_PTR>(&mciPlay)
);
m_bPlaying = s_mciError ? false : true;
} }
void MciPlayer::setVolume(float volume) void MciPlayer::setVolume(float volume)
@ -208,7 +220,12 @@ void MciPlayer::setVolume(float volume)
MCI_DGV_SETAUDIO_PARMS mciSetAudioPara = { 0 }; MCI_DGV_SETAUDIO_PARMS mciSetAudioPara = { 0 };
mciSetAudioPara.dwItem = MCI_DGV_SETAUDIO_VOLUME; mciSetAudioPara.dwItem = MCI_DGV_SETAUDIO_VOLUME;
mciSetAudioPara.dwValue = DWORD(1000 * min(max(volume, 0), 1)); mciSetAudioPara.dwValue = DWORD(1000 * min(max(volume, 0), 1));
mciSendCommand(m_dev, MCI_SETAUDIO, MCI_DGV_SETAUDIO_VALUE | MCI_DGV_SETAUDIO_ITEM, (DWORD_PTR)&mciSetAudioPara); mciSendCommand(
m_dev,
MCI_SETAUDIO,
MCI_NOTIFY | MCI_DGV_SETAUDIO_VALUE | MCI_DGV_SETAUDIO_ITEM,
(DWORD_PTR)&mciSetAudioPara
);
} }
bool MciPlayer::isPlaying() bool MciPlayer::isPlaying()
@ -243,8 +260,6 @@ void MciPlayer::_sendCommand(int nCommand, DWORD_PTR param1, DWORD_PTR parma2)
typedef std::map<unsigned int, MciPlayer *> MusicList; typedef std::map<unsigned int, MciPlayer *> MusicList;
typedef std::pair<unsigned int, MciPlayer *> Music; typedef std::pair<unsigned int, MciPlayer *> Music;
static size_t Hash(const e2d::EString & key);
static MusicList& getMciPlayerList() static MusicList& getMciPlayerList()
{ {

View File

@ -17,55 +17,71 @@ HWND &GetHWnd()
ID2D1Factory * &GetFactory() ID2D1Factory * &GetFactory()
{ {
return s_pDirect2dFactory; if (!s_pDirect2dFactory)
}
IWICImagingFactory * &GetImagingFactory()
{
if (!s_pIWICFactory)
{ {
CoCreateInstance( // 创建设备无关资源,它们的生命周期和程序的时长相同
CLSID_WICImagingFactory, HRESULT hr = S_OK;
NULL,
CLSCTX_INPROC_SERVER, // 创建一个 Direct2D 工厂
IID_IWICImagingFactory, hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &s_pDirect2dFactory);
reinterpret_cast<void **>(&s_pIWICFactory)
); ASSERT(SUCCEEDED(hr), "Create Device Independent Resources Failed!");
} }
return s_pIWICFactory; return s_pDirect2dFactory;
} }
ID2D1HwndRenderTarget * &GetRenderTarget() ID2D1HwndRenderTarget * &GetRenderTarget()
{ {
if (!s_pRenderTarget) if (!s_pRenderTarget)
{ {
// 创建设备相关资源。这些资源应在 Direct3D 设备消失时重建,
// 比如当 isVisiable 被修改,等等
RECT rc; RECT rc;
GetClientRect(s_HWnd, &rc); GetClientRect(GetHWnd(), &rc);
D2D1_SIZE_U size = D2D1::SizeU( D2D1_SIZE_U size = D2D1::SizeU(
rc.right - rc.left, rc.right - rc.left,
rc.bottom - rc.top rc.bottom - rc.top
); );
// Create a Direct2D render target. // 创建一个 Direct2D 渲染目标
HRESULT hr; HRESULT hr;
hr = GetFactory()->CreateHwndRenderTarget( hr = GetFactory()->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(), D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(s_HWnd, size), D2D1::HwndRenderTargetProperties(
GetHWnd(),
size),
&s_pRenderTarget &s_pRenderTarget
); );
ASSERT(SUCCEEDED(hr), "Create Render Target Failed!"); ASSERT(SUCCEEDED(hr), "Create Render Target Failed! Maybe you should initalize EApp first.");
} }
return s_pRenderTarget; return s_pRenderTarget;
} }
IWICImagingFactory * &GetImagingFactory()
{
if (!s_pIWICFactory)
{
// 创建 WIC 绘图工厂,用于统一处理各种格式的图片
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
reinterpret_cast<void**>(&s_pIWICFactory)
);
ASSERT(SUCCEEDED(hr), "Create WICImagingFactory Failed!");
}
return s_pIWICFactory;
}
IDWriteFactory * &GetDirectWriteFactory() IDWriteFactory * &GetDirectWriteFactory()
{ {
if (!s_pDWriteFactory) if (!s_pDWriteFactory)
{ {
HRESULT hr; // 创建 DirectWrite 工厂
hr = DWriteCreateFactory( HRESULT hr = DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED, DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory), __uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&s_pDWriteFactory) reinterpret_cast<IUnknown**>(&s_pDWriteFactory)

View File

@ -27,8 +27,7 @@ public:
bool init( bool init(
const EString &title, /* 窗口标题 */ const EString &title, /* 窗口标题 */
UINT32 width, /* 窗口宽度 */ UINT32 width, /* 窗口宽度 */
UINT32 height, /* 窗口高度 */ UINT32 height /* 窗口高度 */
bool showConsole = false/* 是否显示控制台 */
); );
// 初始化游戏界面 // 初始化游戏界面
@ -36,8 +35,7 @@ public:
const EString &title, /* 窗口标题 */ const EString &title, /* 窗口标题 */
UINT32 width, /* 窗口宽度 */ UINT32 width, /* 窗口宽度 */
UINT32 height, /* 窗口高度 */ UINT32 height, /* 窗口高度 */
EWindowStyle wStyle, /* 窗口样式 */ EWindowStyle wStyle /* 窗口样式 */
bool showConsole = false/* 是否显示控制台 */
); );
// 启动程序 // 启动程序
@ -61,7 +59,7 @@ public:
// 继续游戏 // 继续游戏
static void resume(); static void resume();
// 获取游戏是否暂停 // 游戏是否暂停
static bool isPaused(); static bool isPaused();
// 切换场景 // 切换场景
@ -77,12 +75,9 @@ public:
bool saveCurrentScene = true /* 是否保存当前场景 */ bool saveCurrentScene = true /* 是否保存当前场景 */
); );
// 返回上一场景
static void backScene();
// 返回上一场景 // 返回上一场景
static void backScene( static void backScene(
ETransition * transition /* 场景切换动画 */ ETransition * transition = nullptr /* 场景切换动画 */
); );
// 清空保存的所有场景 // 清空保存的所有场景
@ -96,7 +91,7 @@ public:
// 是否打开控制台 // 是否打开控制台
static void showConsole( static void showConsole(
bool show bool show = true
); );
// 终止程序 // 终止程序
@ -158,15 +153,6 @@ public:
); );
protected: protected:
// 创建设备无关资源
HRESULT _createDeviceIndependentResources();
// 创建设备相关资源
HRESULT _createDeviceResources();
// 释放设备相关资源
void _discardDeviceResources();
// 游戏主循环 // 游戏主循环
void _mainLoop(); void _mainLoop();
@ -179,12 +165,6 @@ protected:
// 进入下一场景 // 进入下一场景
void _enterNextScene(); void _enterNextScene();
// 重定 render target 大小
void _onResize(
UINT32 width,
UINT32 height
);
// 窗口程序 // 窗口程序
static LRESULT CALLBACK WndProc( static LRESULT CALLBACK WndProc(
HWND hWnd, HWND hWnd,
@ -199,6 +179,7 @@ protected:
bool m_bManualPaused; bool m_bManualPaused;
bool m_bTransitional; bool m_bTransitional;
bool m_bTopMost; bool m_bTopMost;
bool m_bShowConsole;
EString m_sTitle; EString m_sTitle;
EString m_sAppName; EString m_sAppName;
UINT32 m_ClearColor; UINT32 m_ClearColor;
@ -223,13 +204,9 @@ public:
// 引用计数减一 // 引用计数减一
void release(); void release();
// 让引擎自动释放这个对象
void autoRelease();
private: private:
int m_nRefCount; int m_nRefCount;
bool m_bManaged; bool m_bManaged;
bool m_bAutoRelease;
}; };
@ -266,14 +243,12 @@ public:
// 删除子节点 // 删除子节点
bool remove( bool remove(
ENode * child, ENode * child
bool release = false
); );
// 根据名称删除子节点 // 删除相同名称的子节点
void remove( void remove(
const EString &childName, const EString &childName
bool release = false
); );
// 获取所有子节点 // 获取所有子节点

View File

@ -49,9 +49,35 @@ public:
virtual ~EGeometry(); virtual ~EGeometry();
// 判断是否可以和另一几何图形产生接触消息
bool isContactWith(
EGeometry * geometry
);
// 获取父节点 // 获取父节点
ENode * getParentNode() const; ENode * getParentNode() const;
// 获取类别掩码
UINT32 getCategoryBitmask() const;
// 获取接触掩码
UINT32 getContactBitmask() const;
// 设置类别掩码
void setCategoryBitmask(
UINT32 mask
);
// 设置接触掩码
void setContactBitmask(
UINT32 mask
);
// 设置几何形状的可见性
void setVisiable(
bool bVisiable
);
// 设置绘制颜色 // 设置绘制颜色
void setColor( void setColor(
UINT32 color UINT32 color
@ -78,6 +104,9 @@ protected:
protected: protected:
bool m_bTransformed; bool m_bTransformed;
bool m_bIsVisiable;
UINT32 m_nCategoryBitmask;
UINT32 m_nContactBitmask;
UINT32 m_nColor; UINT32 m_nColor;
float m_fOpacity; float m_fOpacity;
ENode * m_pParentNode; ENode * m_pParentNode;

View File

@ -375,23 +375,23 @@ protected:
}; };
class ECollisionListener : class EContactListener :
public EPhysicsListener public EPhysicsListener
{ {
friend EMsgManager; friend EMsgManager;
public: public:
ECollisionListener(); EContactListener();
ECollisionListener( EContactListener(
const EString &name const EString &name
); );
ECollisionListener( EContactListener(
const COLLISION_LISTENER_CALLBACK &callback const COLLISION_LISTENER_CALLBACK &callback
); );
ECollisionListener( EContactListener(
const EString &name, const EString &name,
const COLLISION_LISTENER_CALLBACK &callback const COLLISION_LISTENER_CALLBACK &callback
); );

View File

@ -64,8 +64,5 @@
template<typename T> template<typename T>
inline void SafeDelete(T** p) { if (*p) { delete *p; *p = nullptr; } } inline void SafeDelete(T** p) { if (*p) { delete *p; *p = nullptr; } }
template<typename T>
inline void SafeReleaseAndClear(T** p) { if (*p) { (*p)->autoRelease(); (*p)->release(); *p = nullptr; } }
template<typename T> template<typename T>
inline void SafeRelease(T** p) { if (*p) { (*p)->release(); *p = nullptr; } } inline void SafeRelease(T** p) { if (*p) { (*p)->release(); *p = nullptr; } }

View File

@ -321,18 +321,9 @@ class EPhysicsManager
friend EApp; friend EApp;
friend EScene; friend EScene;
friend ENode; friend ENode;
friend EGeometry;
public: public:
// 添加形状
static void addGeometry(
EGeometry * geometry
);
// 删除已绑定的形状
static void delGeometry(
EGeometry * geometry
);
// 将监听器与场景绑定 // 将监听器与场景绑定
static void bindListener( static void bindListener(
EPhysicsListener * listener, EPhysicsListener * listener,
@ -390,14 +381,21 @@ private:
// 清空监听器管理器 // 清空监听器管理器
static void _clearManager(); static void _clearManager();
// 添加形状
static void _addGeometry(
EGeometry * geometry
);
// 删除已绑定的形状
static void _delGeometry(
EGeometry * geometry
);
// 清空绑定在节点上的所有监听器 // 清空绑定在节点上的所有监听器
static void _clearAllListenersBindedWith( static void _clearAllListenersBindedWith(
ENode * pParentNode ENode * pParentNode
); );
// 物理引擎执行程序
static void PhysicsProc();
// 几何图形判断程序 // 几何图形判断程序
static void PhysicsGeometryProc( static void PhysicsGeometryProc(
EGeometry * pActiveGeometry EGeometry * pActiveGeometry

View File

@ -244,26 +244,20 @@ public:
); );
// 从父节点移除 // 从父节点移除
virtual void removeFromParent( virtual void removeFromParent();
bool release = false
);
// 移除子节点 // 移除子节点
virtual bool removeChild( virtual bool removeChild(
ENode * child, ENode * child
bool release = true
); );
// 移除子节点 // 移除子节点
virtual void removeChild( virtual void removeChild(
const EString & childName, const EString & childName
bool release = true
); );
// 移除所有节点 // 移除所有节点
virtual void clearAllChildren( virtual void clearAllChildren();
bool release = true
);
// 执行动画 // 执行动画
virtual void runAction( virtual void runAction(

View File

@ -102,9 +102,12 @@ protected:
class EFileUtils class EFileUtils
{ {
public: public:
// 获取系统的 AppData\Local 路径 // 获取系统的 AppData Local 路径
static EString getLocalAppDataPath(); static EString getLocalAppDataPath();
// 获取临时文件目录
static EString getTempPath();
// 获取默认的保存路径 // 获取默认的保存路径
static EString getDefaultSavePath(); static EString getDefaultSavePath();

View File

@ -8,8 +8,6 @@ class ETransition :
public EObject public EObject
{ {
friend EApp; friend EApp;
public:
ETransition() { this->autoRelease(); }
protected: protected:
// 保存当前场景和下一场景的指针,和控制场景切换的变量 // 保存当前场景和下一场景的指针,和控制场景切换的变量