diff --git a/Easy2D/Action/EActionLoop.cpp b/Easy2D/Action/EActionLoop.cpp index a85db44f..eb2bfd11 100644 --- a/Easy2D/Action/EActionLoop.cpp +++ b/Easy2D/Action/EActionLoop.cpp @@ -8,7 +8,7 @@ e2d::EActionLoop::EActionLoop(EAction * action) : e2d::EActionLoop::~EActionLoop() { - SafeReleaseAndClear(&m_Action); + SafeRelease(&m_Action); } e2d::EActionLoop * e2d::EActionLoop::clone() const diff --git a/Easy2D/Action/EActionSequence.cpp b/Easy2D/Action/EActionSequence.cpp index 0dd3b266..1109efa5 100644 --- a/Easy2D/Action/EActionSequence.cpp +++ b/Easy2D/Action/EActionSequence.cpp @@ -25,7 +25,7 @@ e2d::EActionSequence::~EActionSequence() { for (auto action : m_vActions) { - SafeReleaseAndClear(&action); + SafeRelease(&action); } } diff --git a/Easy2D/Action/EActionTwo.cpp b/Easy2D/Action/EActionTwo.cpp index ec566137..e2f29af4 100644 --- a/Easy2D/Action/EActionTwo.cpp +++ b/Easy2D/Action/EActionTwo.cpp @@ -10,8 +10,8 @@ e2d::EActionTwo::EActionTwo(EAction * actionFirst, EAction * actionSecond) : e2d::EActionTwo::~EActionTwo() { - SafeReleaseAndClear(&m_pFirstAction); - SafeReleaseAndClear(&m_pSecondAction); + SafeRelease(&m_pFirstAction); + SafeRelease(&m_pSecondAction); } e2d::EActionTwo * e2d::EActionTwo::clone() const diff --git a/Easy2D/Action/EActionTwoAtSameTime.cpp b/Easy2D/Action/EActionTwoAtSameTime.cpp index 81e42ec1..c9a5ed08 100644 --- a/Easy2D/Action/EActionTwoAtSameTime.cpp +++ b/Easy2D/Action/EActionTwoAtSameTime.cpp @@ -10,8 +10,8 @@ e2d::EActionTwoAtSameTime::EActionTwoAtSameTime(EAction * actionFirst, EAction * e2d::EActionTwoAtSameTime::~EActionTwoAtSameTime() { - SafeReleaseAndClear(&m_pFirstAction); - SafeReleaseAndClear(&m_pSecondAction); + SafeRelease(&m_pFirstAction); + SafeRelease(&m_pSecondAction); } e2d::EActionTwoAtSameTime * e2d::EActionTwoAtSameTime::clone() const diff --git a/Easy2D/Action/EAnimation.cpp b/Easy2D/Action/EAnimation.cpp index 349d11fe..756726c7 100644 --- a/Easy2D/Action/EAnimation.cpp +++ b/Easy2D/Action/EAnimation.cpp @@ -19,7 +19,7 @@ e2d::EAnimation::~EAnimation() { for (auto frame : m_vFrames) { - SafeReleaseAndClear(&frame); + SafeRelease(&frame); } } diff --git a/Easy2D/Base/EApp.cpp b/Easy2D/Base/EApp.cpp index 3d0ea9d9..51b231eb 100644 --- a/Easy2D/Base/EApp.cpp +++ b/Easy2D/Base/EApp.cpp @@ -25,6 +25,7 @@ e2d::EApp::EApp() , m_bManualPaused(false) , m_bTransitional(false) , m_bTopMost(false) + , m_bShowConsole(false) , nAnimationInterval(17LL) , m_ClearColor(EColor::BLACK) , m_pCurrentScene(nullptr) @@ -33,7 +34,7 @@ e2d::EApp::EApp() ASSERT(s_pInstance == nullptr, "EApp instance already exists!"); s_pInstance = this; // 保存实例对象 - CoInitializeEx(NULL, COINIT_MULTITHREADED); + CoInitialize(NULL); } e2d::EApp::~EApp() @@ -54,104 +55,101 @@ e2d::EApp * e2d::EApp::get() 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; - // 显示或关闭控制台 - 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); + } - // 创建设备无关资源 - hr = _createDeviceIndependentResources(); + RegisterClassEx(&wcex); + + // 因为 CreateWindow 函数使用的是像素大小,获取系统的 DPI 以使它 + // 适应窗口缩放 + FLOAT dpiX, dpiY; + + // 工厂将返回当前的系统 DPI,这个值也将用来创建窗口 + GetFactory()->GetDesktopDpi(&dpiX, &dpiY); + + width = static_cast(ceil(width * dpiX / 96.f)); + height = static_cast(ceil(height * dpiY / 96.f)); + + // 获取屏幕分辨率 + UINT screenWidth = static_cast(GetSystemMetrics(SM_CXSCREEN)); + UINT screenHeight = static_cast(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)) { - // 注册窗口类 - WNDCLASSEX wcex = { sizeof(WNDCLASSEX) }; - UINT style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; - if (wStyle.m_bNoClose) - { - style |= CS_NOCLOSE; - } - wcex.style = style; - 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(ceil(width * dpiX / 96.f)); - height = static_cast(ceil(height * dpiY / 96.f)); - - // 获取屏幕分辨率 - UINT screenWidth = static_cast(GetSystemMetrics(SM_CXSCREEN)); - UINT screenHeight = static_cast(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); - } + // 禁用输入法 + this->setKeyboardLayoutEnable(false); + // 重设客户区大小 + this->setWindowSize(width, height); + } + else + { + UnregisterClass(L"E2DApp", HINST_THISCOMPONENT); } if (FAILED(hr)) @@ -186,13 +184,15 @@ bool e2d::EApp::isPaused() 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 * stdinstream = nullptr; static FILE * stderrstream = nullptr; + + EApp::get()->m_bShowConsole = show; + // 查找已存在的控制台句柄 + HWND hwnd = GetConsoleWindow(); // 关闭控制台 if (show) { @@ -238,6 +238,11 @@ void e2d::EApp::run() ASSERT(GetHWnd() != nullptr, "Cannot find Game Window."); // 进入第一个场景 _enterNextScene(); + // 关闭控制台 + if (!m_bShowConsole) + { + showConsole(false); + } // 显示窗口 ShowWindow(GetHWnd(), SW_SHOWNORMAL); UpdateWindow(GetHWnd()); @@ -349,48 +354,42 @@ void e2d::EApp::_onControl() EObjectManager::__flush(); // 刷新内存池 ETimerManager::TimerProc(); // 定时器管理器执行程序 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() { HRESULT hr = S_OK; - hr = _createDeviceResources(); - - if (SUCCEEDED(hr)) + // 开始绘图 + GetRenderTarget()->BeginDraw(); + // 使用背景色清空屏幕 + GetRenderTarget()->Clear(D2D1::ColorF(m_ClearColor)); + // 绘制当前场景 + if (m_pCurrentScene) { - // 开始绘图 - 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()); + m_pCurrentScene->_onRender(); } + // 切换场景时,同时绘制两场景 + if (m_bTransitional && m_pNextScene) + { + m_pNextScene->_onRender(); + } + // 终止绘图 + hr = GetRenderTarget()->EndDraw(); + // 刷新界面 + UpdateWindow(GetHWnd()); if (hr == D2DERR_RECREATE_TARGET) { + // 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源 + // 并在下一次调用时重建资源 hr = S_OK; - _discardDeviceResources(); + SafeReleaseInterface(&GetRenderTarget()); } if (FAILED(hr)) { + // 渲染时产生了未知的错误,退出游戏 MessageBox(GetHWnd(), L"Game rendering failed!", L"Error", MB_OK); 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(); s_SceneStack.pop(); - // 不保存当前场景 + + // 返回上一场景时,不保存当前场景 if (get()->m_pCurrentScene) { get()->m_pCurrentScene->m_bWillSave = false; } + // 设置切换场景动画 if (transition) { @@ -496,6 +495,8 @@ void e2d::EApp::backScene(ETransition * transition) } else { + // 把这个变量赋为 false,场景将在下一帧画面 + // 进行切换 get()->m_bTransitional = false; } } @@ -506,7 +507,7 @@ void e2d::EApp::clearScene() while (s_SceneStack.size()) { auto temp = s_SceneStack.top(); - SafeReleaseAndClear(&temp); + SafeRelease(&temp); s_SceneStack.pop(); } } @@ -518,14 +519,14 @@ e2d::EScene * e2d::EApp::getCurrentScene() void e2d::EApp::setAppName(const EString &appname) { - s_pInstance->m_sAppName = appname; + get()->m_sAppName = appname; } e2d::EString e2d::EApp::getAppName() { - if (s_pInstance->m_sAppName.empty()) - s_pInstance->m_sAppName = s_pInstance->m_sTitle; - return s_pInstance->m_sAppName; + if (get()->m_sAppName.empty()) + get()->m_sAppName = get()->m_sTitle; + return get()->m_sAppName; } void e2d::EApp::setBkColor(UINT32 color) @@ -576,12 +577,13 @@ void e2d::EApp::showWindow() void e2d::EApp::quit() { + // 这个变量将控制游戏是否结束 get()->m_bEnd = true; } void e2d::EApp::end() { - get()->m_bEnd = true; + EApp::quit(); } void e2d::EApp::_enterNextScene() @@ -601,7 +603,7 @@ void e2d::EApp::_enterNextScene() } else { - SafeReleaseAndClear(&m_pCurrentScene); + SafeRelease(&m_pCurrentScene); } } @@ -612,59 +614,9 @@ void e2d::EApp::_enterNextScene() 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 result = 0; 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 height = HIWORD(lParam); - pEApp->_onResize(width, height); + // 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染 + // 目标适当。它可能会调用失败,但是这里可以忽略有可能的 + // 错误,因为这个错误将在下一次调用 EndDraw 时产生 + GetRenderTarget()->Resize(D2D1::SizeU(width, height)); } result = 0; wasHandled = true; @@ -827,6 +782,7 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam } } + // 对当前消息没有特定的处理程序时,执行默认的窗口函数 if (!wasHandled) { result = DefWindowProc(hWnd, message, wParam, lParam); diff --git a/Easy2D/Base/EObject.cpp b/Easy2D/Base/EObject.cpp index cf0097f7..fbfd88e9 100644 --- a/Easy2D/Base/EObject.cpp +++ b/Easy2D/Base/EObject.cpp @@ -4,7 +4,6 @@ e2d::EObject::EObject() : m_nRefCount(0) , m_bManaged(false) - , m_bAutoRelease(false) { EObjectManager::add(this); // 将该对象放入释放池中 } @@ -26,8 +25,3 @@ void e2d::EObject::release() // 通知对象管理池刷新 EObjectManager::notifyFlush(); } - -void e2d::EObject::autoRelease() -{ - m_bAutoRelease = true; -} diff --git a/Easy2D/Base/EScene.cpp b/Easy2D/Base/EScene.cpp index 944dd717..42dd54ec 100644 --- a/Easy2D/Base/EScene.cpp +++ b/Easy2D/Base/EScene.cpp @@ -12,6 +12,7 @@ e2d::EScene::EScene() , m_bGeometryVisiable(false) , m_pRoot(new ENode()) { + m_pRoot->retain(); m_pRoot->_onEnter(); m_pRoot->_setParentScene(this); m_pRoot->_setSize(EApp::getWidth(), EApp::getHeight()); @@ -20,7 +21,7 @@ e2d::EScene::EScene() e2d::EScene::~EScene() { - SafeReleaseAndClear(&m_pRoot); + SafeRelease(&m_pRoot); } void e2d::EScene::onEnter() @@ -66,14 +67,14 @@ void e2d::EScene::add(ENode * child, int order /* = 0 */) 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::EScene::getChildren() diff --git a/Easy2D/Easy2D.vcxproj b/Easy2D/Easy2D.vcxproj index e0e75cb5..20b91013 100644 --- a/Easy2D/Easy2D.vcxproj +++ b/Easy2D/Easy2D.vcxproj @@ -217,7 +217,7 @@ - + diff --git a/Easy2D/Easy2D.vcxproj.filters b/Easy2D/Easy2D.vcxproj.filters index 8aecb84e..df69779c 100644 --- a/Easy2D/Easy2D.vcxproj.filters +++ b/Easy2D/Easy2D.vcxproj.filters @@ -192,9 +192,6 @@ Geometry - - Listener - Common @@ -210,6 +207,9 @@ Geometry + + Listener + diff --git a/Easy2D/Geometry/EGeometry.cpp b/Easy2D/Geometry/EGeometry.cpp index d1f60c36..0978ddba 100644 --- a/Easy2D/Geometry/EGeometry.cpp +++ b/Easy2D/Geometry/EGeometry.cpp @@ -1,15 +1,18 @@ #include "..\egeometry.h" -#include "..\Win\winbase.h" +#include "..\emanagers.h" #include "..\enodes.h" +#include "..\Win\winbase.h" e2d::EGeometry::EGeometry() : m_bTransformed(false) + , m_nCategoryBitmask(0) + ,m_nContactBitmask(0) + , m_bIsVisiable(true) , m_nColor(EColor::RED) , m_fOpacity(1) , m_pParentNode(nullptr) , m_pTransformedGeometry(nullptr) { - this->autoRelease(); } e2d::EGeometry::~EGeometry() @@ -17,11 +20,41 @@ e2d::EGeometry::~EGeometry() SafeReleaseInterface(&m_pTransformedGeometry); } +bool e2d::EGeometry::isContactWith(EGeometry * geometry) +{ + return ((this->m_nContactBitmask & geometry->m_nCategoryBitmask) != 0); +} + e2d::ENode * e2d::EGeometry::getParentNode() const { 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) { m_nColor = color; @@ -29,7 +62,7 @@ void e2d::EGeometry::setColor(UINT32 color) void e2d::EGeometry::setOpacity(float opacity) { - m_fOpacity = opacity; + m_fOpacity = min(max(opacity, 0), 1); } void e2d::EGeometry::_onRender() @@ -71,14 +104,17 @@ void e2d::EGeometry::_transform() { if (m_pParentNode) { + // 释放原形状 SafeReleaseInterface(&m_pTransformedGeometry); + // 根据父节点转换几何图形 GetFactory()->CreateTransformedGeometry( _getD2dGeometry(), m_pParentNode->m_Matri, &m_pTransformedGeometry ); - this->m_bTransformed = true; + // 判断形状变换后的情况 + EPhysicsManager::PhysicsGeometryProc(this); } } diff --git a/Easy2D/Listener/ECollisionListener.cpp b/Easy2D/Listener/EContactListener.cpp similarity index 59% rename from Easy2D/Listener/ECollisionListener.cpp rename to Easy2D/Listener/EContactListener.cpp index 86bc74df..7afec872 100644 --- a/Easy2D/Listener/ECollisionListener.cpp +++ b/Easy2D/Listener/EContactListener.cpp @@ -1,29 +1,29 @@ #include "..\elisteners.h" #include "..\egeometry.h" -e2d::ECollisionListener::ECollisionListener() +e2d::EContactListener::EContactListener() : EPhysicsListener() { } -e2d::ECollisionListener::ECollisionListener(const EString & name) +e2d::EContactListener::EContactListener(const EString & name) : EPhysicsListener(name) { } -e2d::ECollisionListener::ECollisionListener(const COLLISION_LISTENER_CALLBACK & callback) +e2d::EContactListener::EContactListener(const COLLISION_LISTENER_CALLBACK & callback) : EPhysicsListener() { 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) { this->m_Callback = callback; } -void e2d::ECollisionListener::_callOn() +void e2d::EContactListener::_callOn() { if (EPhysicsMsg::getMsg() == EPhysicsMsg::OVERLAP || EPhysicsMsg::getMsg() == EPhysicsMsg::CONTAINS || diff --git a/Easy2D/Manager/EActionManager.cpp b/Easy2D/Manager/EActionManager.cpp index 3a53a2c8..8e2e7cd7 100644 --- a/Easy2D/Manager/EActionManager.cpp +++ b/Easy2D/Manager/EActionManager.cpp @@ -80,7 +80,7 @@ void e2d::EActionManager::_clearAllActionsBindedWith(ENode * pTargetNode) auto a = s_vActions[i]; if (a->getTarget() == pTargetNode) { - SafeReleaseAndClear(&a); + SafeRelease(&a); s_vActions.erase(s_vActions.begin() + i); } else @@ -144,7 +144,7 @@ void e2d::EActionManager::ActionProc() if (action->_isEnding()) { // 动作已经结束 - SafeReleaseAndClear(&action); + SafeRelease(&action); s_vActions.erase(s_vActions.begin() + i); } else diff --git a/Easy2D/Manager/EMsgManager.cpp b/Easy2D/Manager/EMsgManager.cpp index 0ae48324..c9597ec1 100644 --- a/Easy2D/Manager/EMsgManager.cpp +++ b/Easy2D/Manager/EMsgManager.cpp @@ -24,7 +24,7 @@ void e2d::EMsgManager::MouseProc(UINT message, WPARAM wParam, LPARAM lParam) if (EApp::isPaused() && !mlistener->m_bAlways) continue; - if (mlistener->isRunning()) + if (mlistener->m_bAlways || mlistener->isRunning()) { if (mlistener->getParentNode() && 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) continue; - if (klistener->isRunning()) + if (klistener->m_bAlways || klistener->isRunning()) { if (klistener->getParentNode() && klistener->getParentNode()->getParentScene() == EApp::getCurrentScene()) @@ -140,7 +140,7 @@ void e2d::EMsgManager::delMouseListeners(const EString & name) { if ((*mIter)->getName() == name) { - SafeReleaseAndClear(&(*mIter)); + SafeRelease(&(*mIter)); mIter = s_vMouseListeners.erase(mIter); } else @@ -182,7 +182,7 @@ void e2d::EMsgManager::delKeyboardListeners(const EString & name) { if ((*kIter)->getName() == name) { - SafeReleaseAndClear(&(*kIter)); + SafeRelease(&(*kIter)); kIter = s_vKeyboardListeners.erase(kIter); } else @@ -279,7 +279,7 @@ void e2d::EMsgManager::_clearAllMouseListenersBindedWith(ENode * pParentNode) auto t = s_vMouseListeners[i]; if (t->getParentNode() == pParentNode) { - SafeReleaseAndClear(&t); + SafeRelease(&t); s_vMouseListeners.erase(s_vMouseListeners.begin() + i); } else @@ -296,7 +296,7 @@ void e2d::EMsgManager::_clearAllKeyboardListenersBindedWith(ENode * pParentNode) auto t = s_vKeyboardListeners[i]; if (t->getParentNode() == pParentNode) { - SafeReleaseAndClear(&t); + SafeRelease(&t); s_vKeyboardListeners.erase(s_vKeyboardListeners.begin() + i); } else diff --git a/Easy2D/Manager/EObjectManager.cpp b/Easy2D/Manager/EObjectManager.cpp index fbfdd767..7c6e3e15 100644 --- a/Easy2D/Manager/EObjectManager.cpp +++ b/Easy2D/Manager/EObjectManager.cpp @@ -23,9 +23,9 @@ void e2d::EObjectManager::__flush() // 循环遍历容器中的所有对象 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); // 从释放池中删除该对象 iter = s_vPool.erase(iter); diff --git a/Easy2D/Manager/EPhysicsManager.cpp b/Easy2D/Manager/EPhysicsManager.cpp index 98eb7c84..ab4449ae 100644 --- a/Easy2D/Manager/EPhysicsManager.cpp +++ b/Easy2D/Manager/EPhysicsManager.cpp @@ -9,41 +9,26 @@ e2d::EVector s_vListeners; e2d::EVector s_vGeometries; -void e2d::EPhysicsManager::PhysicsProc() +void e2d::EPhysicsManager::PhysicsGeometryProc(EGeometry * pActiveGeometry) { if (s_vListeners.empty() || s_vGeometries.empty() || EApp::isPaused()) 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 为主动方 EPhysicsMsg::s_pActiveGeometry = pActiveGeometry; // 判断变化后的状态 for (auto &pPassiveGeometry : s_vGeometries) { + // 不与其他场景的物体判断 if (!pPassiveGeometry->getParentNode() || (pPassiveGeometry->getParentNode()->getParentScene() != EApp::getCurrentScene())) continue; if (pActiveGeometry != pPassiveGeometry) { + // 判断两物体是否会产生接触消息 + if (!pActiveGeometry->isContactWith(pPassiveGeometry)) + continue; // 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) { @@ -110,7 +95,7 @@ void e2d::EPhysicsManager::addGeometry(EGeometry * geometry) } } -void e2d::EPhysicsManager::delGeometry(EGeometry * geometry) +void e2d::EPhysicsManager::_delGeometry(EGeometry * geometry) { if (geometry) { @@ -118,7 +103,7 @@ void e2d::EPhysicsManager::delGeometry(EGeometry * geometry) { if (s_vGeometries[i] == geometry) { - SafeReleaseAndClear(&geometry); + SafeRelease(&geometry); s_vGeometries.erase(s_vGeometries.begin() + i); return; } @@ -155,7 +140,7 @@ void e2d::EPhysicsManager::delListeners(const EString & name) { if ((*iter)->getName() == name) { - SafeReleaseAndClear(&(*iter)); + SafeRelease(&(*iter)); iter = s_vListeners.erase(iter); } else @@ -227,7 +212,7 @@ void e2d::EPhysicsManager::_clearAllListenersBindedWith(ENode * pParentNode) auto listener = s_vListeners[i]; if (listener->getParentNode() == pParentNode) { - SafeReleaseAndClear(&listener); + SafeRelease(&listener); s_vListeners.erase(s_vListeners.begin() + i); } else diff --git a/Easy2D/Manager/ETimerManager.cpp b/Easy2D/Manager/ETimerManager.cpp index 2318ef73..1ee7cc67 100644 --- a/Easy2D/Manager/ETimerManager.cpp +++ b/Easy2D/Manager/ETimerManager.cpp @@ -81,7 +81,7 @@ void e2d::ETimerManager::delTimers(const EString & name) { if ((*mIter)->getName() == name) { - SafeReleaseAndClear(&(*mIter)); + SafeRelease(&(*mIter)); mIter = s_vTimers.erase(mIter); } else @@ -138,7 +138,7 @@ void e2d::ETimerManager::_clearAllTimersBindedWith(ENode * pParentNode) auto t = s_vTimers[i]; if (t->getParentNode() == pParentNode) { - SafeReleaseAndClear(&t); + SafeRelease(&t); s_vTimers.erase(s_vTimers.begin() + i); } else diff --git a/Easy2D/Node/ENode.cpp b/Easy2D/Node/ENode.cpp index 0d5ee9f3..cf64bfb3 100644 --- a/Easy2D/Node/ENode.cpp +++ b/Easy2D/Node/ENode.cpp @@ -42,10 +42,10 @@ e2d::ENode::~ENode() EMsgManager::_clearAllKeyboardListenersBindedWith(this); EActionManager::_clearAllActionsBindedWith(this); EPhysicsManager::_clearAllListenersBindedWith(this); - EPhysicsManager::delGeometry(m_pGeometry); + EPhysicsManager::_delGeometry(m_pGeometry); for (auto child : m_vChildren) { - SafeReleaseAndClear(&child); + SafeRelease(&child); } } @@ -112,7 +112,7 @@ void e2d::ENode::_onRender() void e2d::ENode::_drawGeometry() { // 绘制自身的几何形状 - if (m_pGeometry) + if (m_pGeometry && m_pGeometry->m_bIsVisiable) { m_pGeometry->_onRender(); } @@ -501,9 +501,9 @@ void e2d::ENode::setAnchor(float anchorX, float anchorY) void e2d::ENode::setGeometry(EGeometry * geometry) { // 删除旧的形状 - EPhysicsManager::delGeometry(m_pGeometry); + EPhysicsManager::_delGeometry(m_pGeometry); // 添加新的形状 - EPhysicsManager::addGeometry(geometry); + EPhysicsManager::_addGeometry(geometry); if (geometry) { @@ -589,15 +589,15 @@ e2d::ENode * e2d::ENode::getChild(const EString & name) return nullptr; } -void e2d::ENode::removeFromParent(bool release /* = false */) +void e2d::ENode::removeFromParent() { 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."); @@ -621,10 +621,6 @@ bool e2d::ENode::removeChild(ENode * child, bool release /* = true */) } child->_onExit(); child->release(); - if (release) - { - child->autoRelease(); - } return true; } } @@ -632,7 +628,7 @@ bool e2d::ENode::removeChild(ENode * child, bool release /* = true */) 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."); @@ -659,26 +655,18 @@ void e2d::ENode::removeChild(const EString & childName, bool release /* = true * } child->_onExit(); child->release(); - if (release) - { - child->autoRelease(); - } return; } } } -void e2d::ENode::clearAllChildren(bool release /* = true */) +void e2d::ENode::clearAllChildren() { // 所有节点的引用计数减一 for (auto child : m_vChildren) { child->_onExit(); child->release(); - if (release) - { - child->autoRelease(); - } } // 清空储存节点的容器 m_vChildren.clear(); diff --git a/Easy2D/Node/ESprite.cpp b/Easy2D/Node/ESprite.cpp index 9c637e4a..09c31d21 100644 --- a/Easy2D/Node/ESprite.cpp +++ b/Easy2D/Node/ESprite.cpp @@ -47,14 +47,14 @@ e2d::ESprite::ESprite(const EString & resourceName, const EString & resourceType e2d::ESprite::~ESprite() { - SafeReleaseAndClear(&m_pTexture); + SafeRelease(&m_pTexture); } void e2d::ESprite::loadFrom(ETexture * texture) { if (texture) { - SafeReleaseAndClear(&m_pTexture); + SafeRelease(&m_pTexture); m_pTexture = texture; m_pTexture->retain(); diff --git a/Easy2D/Node/EText.cpp b/Easy2D/Node/EText.cpp index dfedb8cf..8361fe53 100644 --- a/Easy2D/Node/EText.cpp +++ b/Easy2D/Node/EText.cpp @@ -37,7 +37,7 @@ e2d::EText::EText(const EString & text, EString fontFamily, float fontSize, UINT e2d::EText::~EText() { - SafeReleaseAndClear(&m_pFont); + SafeRelease(&m_pFont); } e2d::EString e2d::EText::getText() const @@ -70,7 +70,7 @@ void e2d::EText::setFont(EFont * font) { if (font) { - SafeReleaseAndClear(&m_pFont); + SafeRelease(&m_pFont); m_pFont = font; font->retain(); diff --git a/Easy2D/Tool/EFileUtils.cpp b/Easy2D/Tool/EFileUtils.cpp index 6ef76160..660eb761 100644 --- a/Easy2D/Tool/EFileUtils.cpp +++ b/Easy2D/Tool/EFileUtils.cpp @@ -33,6 +33,21 @@ e2d::EString e2d::EFileUtils::getLocalAppDataPath() 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() { EString path = EFileUtils::getLocalAppDataPath(); diff --git a/Easy2D/Tool/EMusicUtils.cpp b/Easy2D/Tool/EMusicUtils.cpp index a8b85517..947f63b2 100644 --- a/Easy2D/Tool/EMusicUtils.cpp +++ b/Easy2D/Tool/EMusicUtils.cpp @@ -1,10 +1,12 @@ #include "..\etools.h" #include "..\Win\winbase.h" +#include #include +#include #pragma comment(lib , "winmm.lib") -#include -#include +static size_t Hash(const e2d::EString & key); +static bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName); //////////////////////////////////////////////////////////////////// @@ -18,8 +20,8 @@ public: ~MciPlayer(); void close(); - void 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 & pFileName, UINT uId); + bool open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, UINT uId); void play(bool bLoop = false); void pause(); void resume(); @@ -36,7 +38,7 @@ private: UINT m_nSoundID; bool m_bPlaying; bool m_bLoop; - e2d::EString m_sTmpFileName; + e2d::EString m_sTempFileName; }; @@ -53,78 +55,67 @@ MciPlayer::~MciPlayer() 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(); // 设置 MCI_OPEN_PARMS 参数 MCI_OPEN_PARMS mciOpen = { 0 }; - mciOpen.lpstrDeviceType = (LPCTSTR)-1; mciOpen.lpstrElementName = pFileName.c_str(); // 打开这个文件 MCIERROR mciError; - mciError = mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast(&mciOpen)); - // 出现错误时,忽略这次操作 - if (mciError) return; + mciError = mciSendCommand( + 0, + MCI_OPEN, + MCI_OPEN_ELEMENT | MCI_NOTIFY, + reinterpret_cast(&mciOpen) + ); - // 保存设备等信息 - 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) + if (mciError) { - _wmkdir(tmpFileName.c_str()); + return false; } - - // 产生临时文件的文件名 - tmpFileName.append(L"\\"); - tmpFileName.append(std::to_wstring(uId)); - tmpFileName.append(L"." + musicExtension); - - // 导出资源为临时文件 - if (ExtractResource(tmpFileName.c_str(), pResouceType.c_str(), pResouceName.c_str())) + else { - // 停止当前音乐 - 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(&mciOpen)); - // 出现错误时,忽略这次操作 - if (mciError) return; - // 保存设备等信息 m_dev = mciOpen.wDeviceID; m_nSoundID = uId; 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) { // 设备为空时,忽略这次操作 @@ -135,8 +126,15 @@ void MciPlayer::play(bool bLoop) // 设置播放参数 MCI_PLAY_PARMS mciPlay = { 0 }; MCIERROR s_mciError; + // 播放声音 - s_mciError = mciSendCommand(m_dev, MCI_PLAY, MCI_FROM | (bLoop ? MCI_DGV_PLAY_REPEAT : 0), reinterpret_cast(&mciPlay)); + s_mciError = mciSendCommand( + m_dev, + MCI_PLAY, + MCI_FROM | MCI_NOTIFY | (bLoop ? MCI_DGV_PLAY_REPEAT : 0), + reinterpret_cast(&mciPlay) + ); + // 未出错时,置 m_bPlaying 为 true if (!s_mciError) { @@ -158,10 +156,10 @@ void MciPlayer::close() _sendCommand(MCI_CLOSE); } // 删除临时文件 - if (!m_sTmpFileName.empty()) + if (!m_sTempFileName.empty()) { - DeleteFile(m_sTmpFileName.c_str()); - m_sTmpFileName.clear(); + DeleteFile(m_sTempFileName.c_str()); + m_sTempFileName.clear(); } // 恢复默认属性 m_dev = 0; @@ -197,10 +195,24 @@ void MciPlayer::rewind() 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 }; - m_bPlaying = mciSendCommand(m_dev, MCI_PLAY, (m_bLoop ? MCI_DGV_PLAY_REPEAT : 0), reinterpret_cast(&mciPlay)) ? false : true; + MCIERROR s_mciError; + + // 播放声音 + s_mciError = mciSendCommand( + m_dev, + MCI_PLAY, + MCI_NOTIFY | (m_bLoop ? MCI_DGV_PLAY_REPEAT : 0), + reinterpret_cast(&mciPlay) + ); + m_bPlaying = s_mciError ? false : true; } void MciPlayer::setVolume(float volume) @@ -208,7 +220,12 @@ void MciPlayer::setVolume(float volume) MCI_DGV_SETAUDIO_PARMS mciSetAudioPara = { 0 }; mciSetAudioPara.dwItem = MCI_DGV_SETAUDIO_VOLUME; 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() @@ -243,8 +260,6 @@ void MciPlayer::_sendCommand(int nCommand, DWORD_PTR param1, DWORD_PTR parma2) typedef std::map MusicList; typedef std::pair Music; -static size_t Hash(const e2d::EString & key); - static MusicList& getMciPlayerList() { diff --git a/Easy2D/Win/winbase.cpp b/Easy2D/Win/winbase.cpp index c54a2ce8..2ac0449b 100644 --- a/Easy2D/Win/winbase.cpp +++ b/Easy2D/Win/winbase.cpp @@ -17,55 +17,71 @@ HWND &GetHWnd() ID2D1Factory * &GetFactory() { - return s_pDirect2dFactory; -} - -IWICImagingFactory * &GetImagingFactory() -{ - if (!s_pIWICFactory) + if (!s_pDirect2dFactory) { - CoCreateInstance( - CLSID_WICImagingFactory, - NULL, - CLSCTX_INPROC_SERVER, - IID_IWICImagingFactory, - reinterpret_cast(&s_pIWICFactory) - ); + // 创建设备无关资源,它们的生命周期和程序的时长相同 + HRESULT hr = S_OK; + + // 创建一个 Direct2D 工厂 + hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &s_pDirect2dFactory); + + ASSERT(SUCCEEDED(hr), "Create Device Independent Resources Failed!"); } - return s_pIWICFactory; + return s_pDirect2dFactory; } ID2D1HwndRenderTarget * &GetRenderTarget() { if (!s_pRenderTarget) { + // 创建设备相关资源。这些资源应在 Direct3D 设备消失时重建, + // 比如当 isVisiable 被修改,等等 RECT rc; - GetClientRect(s_HWnd, &rc); + GetClientRect(GetHWnd(), &rc); D2D1_SIZE_U size = D2D1::SizeU( rc.right - rc.left, rc.bottom - rc.top ); - // Create a Direct2D render target. + // 创建一个 Direct2D 渲染目标 HRESULT hr; hr = GetFactory()->CreateHwndRenderTarget( D2D1::RenderTargetProperties(), - D2D1::HwndRenderTargetProperties(s_HWnd, size), + D2D1::HwndRenderTargetProperties( + GetHWnd(), + size), &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; } +IWICImagingFactory * &GetImagingFactory() +{ + if (!s_pIWICFactory) + { + // 创建 WIC 绘图工厂,用于统一处理各种格式的图片 + HRESULT hr = CoCreateInstance( + CLSID_WICImagingFactory, + NULL, + CLSCTX_INPROC_SERVER, + IID_IWICImagingFactory, + reinterpret_cast(&s_pIWICFactory) + ); + ASSERT(SUCCEEDED(hr), "Create WICImagingFactory Failed!"); + } + return s_pIWICFactory; +} + IDWriteFactory * &GetDirectWriteFactory() { if (!s_pDWriteFactory) { - HRESULT hr; - hr = DWriteCreateFactory( + // 创建 DirectWrite 工厂 + HRESULT hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast(&s_pDWriteFactory) diff --git a/Easy2D/ebase.h b/Easy2D/ebase.h index 01c5a0ab..8a8d1a13 100644 --- a/Easy2D/ebase.h +++ b/Easy2D/ebase.h @@ -27,8 +27,7 @@ public: bool init( const EString &title, /* 窗口标题 */ UINT32 width, /* 窗口宽度 */ - UINT32 height, /* 窗口高度 */ - bool showConsole = false/* 是否显示控制台 */ + UINT32 height /* 窗口高度 */ ); // 初始化游戏界面 @@ -36,8 +35,7 @@ public: const EString &title, /* 窗口标题 */ UINT32 width, /* 窗口宽度 */ UINT32 height, /* 窗口高度 */ - EWindowStyle wStyle, /* 窗口样式 */ - bool showConsole = false/* 是否显示控制台 */ + EWindowStyle wStyle /* 窗口样式 */ ); // 启动程序 @@ -61,7 +59,7 @@ public: // 继续游戏 static void resume(); - // 获取游戏是否暂停 + // 游戏是否暂停 static bool isPaused(); // 切换场景 @@ -77,12 +75,9 @@ public: bool saveCurrentScene = true /* 是否保存当前场景 */ ); - // 返回上一场景 - static void backScene(); - // 返回上一场景 static void backScene( - ETransition * transition /* 场景切换动画 */ + ETransition * transition = nullptr /* 场景切换动画 */ ); // 清空保存的所有场景 @@ -96,7 +91,7 @@ public: // 是否打开控制台 static void showConsole( - bool show + bool show = true ); // 终止程序 @@ -158,15 +153,6 @@ public: ); protected: - // 创建设备无关资源 - HRESULT _createDeviceIndependentResources(); - - // 创建设备相关资源 - HRESULT _createDeviceResources(); - - // 释放设备相关资源 - void _discardDeviceResources(); - // 游戏主循环 void _mainLoop(); @@ -179,12 +165,6 @@ protected: // 进入下一场景 void _enterNextScene(); - // 重定 render target 大小 - void _onResize( - UINT32 width, - UINT32 height - ); - // 窗口程序 static LRESULT CALLBACK WndProc( HWND hWnd, @@ -199,6 +179,7 @@ protected: bool m_bManualPaused; bool m_bTransitional; bool m_bTopMost; + bool m_bShowConsole; EString m_sTitle; EString m_sAppName; UINT32 m_ClearColor; @@ -223,13 +204,9 @@ public: // 引用计数减一 void release(); - // 让引擎自动释放这个对象 - void autoRelease(); - private: int m_nRefCount; bool m_bManaged; - bool m_bAutoRelease; }; @@ -266,14 +243,12 @@ public: // 删除子节点 bool remove( - ENode * child, - bool release = false + ENode * child ); - // 根据名称删除子节点 + // 删除相同名称的子节点 void remove( - const EString &childName, - bool release = false + const EString &childName ); // 获取所有子节点 diff --git a/Easy2D/egeometry.h b/Easy2D/egeometry.h index 5c85240c..fd081321 100644 --- a/Easy2D/egeometry.h +++ b/Easy2D/egeometry.h @@ -49,9 +49,35 @@ public: virtual ~EGeometry(); + // 判断是否可以和另一几何图形产生接触消息 + bool isContactWith( + EGeometry * geometry + ); + // 获取父节点 ENode * getParentNode() const; + // 获取类别掩码 + UINT32 getCategoryBitmask() const; + + // 获取接触掩码 + UINT32 getContactBitmask() const; + + // 设置类别掩码 + void setCategoryBitmask( + UINT32 mask + ); + + // 设置接触掩码 + void setContactBitmask( + UINT32 mask + ); + + // 设置几何形状的可见性 + void setVisiable( + bool bVisiable + ); + // 设置绘制颜色 void setColor( UINT32 color @@ -78,6 +104,9 @@ protected: protected: bool m_bTransformed; + bool m_bIsVisiable; + UINT32 m_nCategoryBitmask; + UINT32 m_nContactBitmask; UINT32 m_nColor; float m_fOpacity; ENode * m_pParentNode; diff --git a/Easy2D/elisteners.h b/Easy2D/elisteners.h index e2e118c2..b55fc70b 100644 --- a/Easy2D/elisteners.h +++ b/Easy2D/elisteners.h @@ -375,23 +375,23 @@ protected: }; -class ECollisionListener : +class EContactListener : public EPhysicsListener { friend EMsgManager; public: - ECollisionListener(); + EContactListener(); - ECollisionListener( + EContactListener( const EString &name ); - ECollisionListener( + EContactListener( const COLLISION_LISTENER_CALLBACK &callback ); - ECollisionListener( + EContactListener( const EString &name, const COLLISION_LISTENER_CALLBACK &callback ); diff --git a/Easy2D/emacros.h b/Easy2D/emacros.h index 0c6a54ef..9d5a5075 100644 --- a/Easy2D/emacros.h +++ b/Easy2D/emacros.h @@ -64,8 +64,5 @@ template inline void SafeDelete(T** p) { if (*p) { delete *p; *p = nullptr; } } -template -inline void SafeReleaseAndClear(T** p) { if (*p) { (*p)->autoRelease(); (*p)->release(); *p = nullptr; } } - template inline void SafeRelease(T** p) { if (*p) { (*p)->release(); *p = nullptr; } } \ No newline at end of file diff --git a/Easy2D/emanagers.h b/Easy2D/emanagers.h index ece88ea3..5d2462cf 100644 --- a/Easy2D/emanagers.h +++ b/Easy2D/emanagers.h @@ -321,18 +321,9 @@ class EPhysicsManager friend EApp; friend EScene; friend ENode; + friend EGeometry; public: - // 添加形状 - static void addGeometry( - EGeometry * geometry - ); - - // 删除已绑定的形状 - static void delGeometry( - EGeometry * geometry - ); - // 将监听器与场景绑定 static void bindListener( EPhysicsListener * listener, @@ -390,14 +381,21 @@ private: // 清空监听器管理器 static void _clearManager(); + // 添加形状 + static void _addGeometry( + EGeometry * geometry + ); + + // 删除已绑定的形状 + static void _delGeometry( + EGeometry * geometry + ); + // 清空绑定在节点上的所有监听器 static void _clearAllListenersBindedWith( ENode * pParentNode ); - // 物理引擎执行程序 - static void PhysicsProc(); - // 几何图形判断程序 static void PhysicsGeometryProc( EGeometry * pActiveGeometry diff --git a/Easy2D/enodes.h b/Easy2D/enodes.h index 7deb5a6d..b6f993c0 100644 --- a/Easy2D/enodes.h +++ b/Easy2D/enodes.h @@ -244,26 +244,20 @@ public: ); // 从父节点移除 - virtual void removeFromParent( - bool release = false - ); + virtual void removeFromParent(); // 移除子节点 virtual bool removeChild( - ENode * child, - bool release = true + ENode * child ); // 移除子节点 virtual void removeChild( - const EString & childName, - bool release = true + const EString & childName ); // 移除所有节点 - virtual void clearAllChildren( - bool release = true - ); + virtual void clearAllChildren(); // 执行动画 virtual void runAction( diff --git a/Easy2D/etools.h b/Easy2D/etools.h index f7a4fb55..64b5e082 100644 --- a/Easy2D/etools.h +++ b/Easy2D/etools.h @@ -102,9 +102,12 @@ protected: class EFileUtils { public: - // 获取系统的 AppData\Local 路径 + // 获取系统的 AppData Local 路径 static EString getLocalAppDataPath(); + // 获取临时文件目录 + static EString getTempPath(); + // 获取默认的保存路径 static EString getDefaultSavePath(); diff --git a/Easy2D/etransitions.h b/Easy2D/etransitions.h index 97c3e1bb..c05ae7b3 100644 --- a/Easy2D/etransitions.h +++ b/Easy2D/etransitions.h @@ -8,8 +8,6 @@ class ETransition : public EObject { friend EApp; -public: - ETransition() { this->autoRelease(); } protected: // 保存当前场景和下一场景的指针,和控制场景切换的变量