diff --git a/Demo/main.cpp b/Demo/main.cpp index a1ee6002..99d1e400 100644 --- a/Demo/main.cpp +++ b/Demo/main.cpp @@ -9,8 +9,7 @@ int WINAPI WinMain( ) { EApp app; - auto listenerCallback = [](EPoint p) {}; - auto s = new EListenerMouseClick(listenerCallback); + if (app.init(L"Easy2D Demo", 640, 480)) { float w = EApp::getWidth(); @@ -40,15 +39,14 @@ int WINAPI WinMain( animation->addFrame(new ESpriteFrame(L"atlas.png", 5, 982, 34, 24)); animation->addFrame(new ESpriteFrame(L"atlas.png", 61, 982, 34, 24)); animation->addFrame(new ESpriteFrame(L"atlas.png", 117, 982, 34, 24)); + animation->addFrame(new ESpriteFrame(L"atlas.png", 61, 982, 34, 24)); bird->runAction(new EActionLoop(animation)); bird->setPivot(0.5f, 0.5f); bird->setPos(EApp::getWidth() / 2, EApp::getHeight() / 2); scene2->add(bird); auto btnStart = new ESprite(L"atlas.png", 702, 234, 116, 70); - btnStart->setPivot(0.5f, 0.5f); auto btnStartSelected = new ESprite(L"atlas.png", 702, 234, 116, 70); - btnStartSelected->setPivot(0.5f, 0.5f); btnStartSelected->setPosY(5); auto button = new EButton(btnStart, btnStartSelected, [=] { if (EApp::isPaused()) @@ -61,9 +59,17 @@ int WINAPI WinMain( } //EApp::enterScene(scene, new ETransitionScaleEmerge(1, ETransitionScaleEmerge::BACK)); }); + button->setPivot(0.5f, 0.5f); button->setPos(EApp::getWidth() / 2, EApp::getHeight() / 2 + 100); scene2->add(button); + scene2->runAction(new EActionSequence(5, + new EActionCallback([]() { EMusicUtils::playMusic(L"music.wav", -1); }), + new EActionDelay(3), + new EActionCallback([]() { EMusicUtils::pauseMusic(L"music.wav"); }), + new EActionDelay(3), + new EActionCallback([]() { EMusicUtils::resumeMusic(L"music.wav"); }))); + app.enterScene(scene2, new ETransitionFade(0, 1)); app.run(); } diff --git a/Demo/music.wav b/Demo/music.wav new file mode 100644 index 00000000..9b991a4b Binary files /dev/null and b/Demo/music.wav differ diff --git a/Demo/short.wav b/Demo/short.wav new file mode 100644 index 00000000..76da7877 Binary files /dev/null and b/Demo/short.wav differ diff --git a/Easy2D/Action/EAction.cpp b/Easy2D/Action/EAction.cpp index 0d1b0829..8bbf106e 100644 --- a/Easy2D/Action/EAction.cpp +++ b/Easy2D/Action/EAction.cpp @@ -85,7 +85,7 @@ void e2d::EAction::_init() m_tLast = GetNow(); } -void e2d::EAction::_callOn() +void e2d::EAction::_update() { if (!m_bInit) { diff --git a/Easy2D/Action/EActionCallback.cpp b/Easy2D/Action/EActionCallback.cpp index 0b7aafbb..910c1f49 100644 --- a/Easy2D/Action/EActionCallback.cpp +++ b/Easy2D/Action/EActionCallback.cpp @@ -15,7 +15,7 @@ void e2d::EActionCallback::_init() // 执行回调函数的动作不需要初始化 } -void e2d::EActionCallback::_callOn() +void e2d::EActionCallback::_update() { m_Callback(); this->stop(); diff --git a/Easy2D/Action/EActionDelay.cpp b/Easy2D/Action/EActionDelay.cpp index 7047ede3..856db795 100644 --- a/Easy2D/Action/EActionDelay.cpp +++ b/Easy2D/Action/EActionDelay.cpp @@ -16,9 +16,9 @@ void e2d::EActionDelay::_init() EAction::_init(); } -void e2d::EActionDelay::_callOn() +void e2d::EActionDelay::_update() { - EAction::_callOn(); + EAction::_update(); // 判断时间间隔是否足够 if (GetInterval(m_tLast) > m_nAnimationInterval) { diff --git a/Easy2D/Action/EActionLoop.cpp b/Easy2D/Action/EActionLoop.cpp index 18ca592d..63f0a3e2 100644 --- a/Easy2D/Action/EActionLoop.cpp +++ b/Easy2D/Action/EActionLoop.cpp @@ -25,9 +25,9 @@ void e2d::EActionLoop::_init() m_pAction->_init(); } -void e2d::EActionLoop::_callOn() +void e2d::EActionLoop::_update() { - EAction::_callOn(); + EAction::_update(); if (m_nTimes == m_nTotalTimes) { @@ -35,7 +35,7 @@ void e2d::EActionLoop::_callOn() return; } - m_pAction->_callOn(); + m_pAction->_update(); if (m_pAction->_isEnding()) { diff --git a/Easy2D/Action/EActionMoveBy.cpp b/Easy2D/Action/EActionMoveBy.cpp index da3ca261..1c4dfc27 100644 --- a/Easy2D/Action/EActionMoveBy.cpp +++ b/Easy2D/Action/EActionMoveBy.cpp @@ -16,9 +16,9 @@ void e2d::EActionMoveBy::_init() } } -void e2d::EActionMoveBy::_callOn() +void e2d::EActionMoveBy::_update() { - EAction::_callOn(); + EAction::_update(); if (m_pTarget == nullptr) { diff --git a/Easy2D/Action/EActionOpacityBy.cpp b/Easy2D/Action/EActionOpacityBy.cpp index 7833e425..32128251 100644 --- a/Easy2D/Action/EActionOpacityBy.cpp +++ b/Easy2D/Action/EActionOpacityBy.cpp @@ -16,9 +16,9 @@ void e2d::EActionOpacityBy::_init() } } -void e2d::EActionOpacityBy::_callOn() +void e2d::EActionOpacityBy::_update() { - EAction::_callOn(); + EAction::_update(); if (m_pTarget == nullptr) { diff --git a/Easy2D/Action/EActionRotateBy.cpp b/Easy2D/Action/EActionRotateBy.cpp index 732d5306..b294a82f 100644 --- a/Easy2D/Action/EActionRotateBy.cpp +++ b/Easy2D/Action/EActionRotateBy.cpp @@ -16,9 +16,9 @@ void e2d::EActionRotateBy::_init() } } -void e2d::EActionRotateBy::_callOn() +void e2d::EActionRotateBy::_update() { - EAction::_callOn(); + EAction::_update(); if (m_pTarget == nullptr) { diff --git a/Easy2D/Action/EActionScaleBy.cpp b/Easy2D/Action/EActionScaleBy.cpp index 8e3f8d17..4d2194d4 100644 --- a/Easy2D/Action/EActionScaleBy.cpp +++ b/Easy2D/Action/EActionScaleBy.cpp @@ -25,9 +25,9 @@ void e2d::EActionScaleBy::_init() } } -void e2d::EActionScaleBy::_callOn() +void e2d::EActionScaleBy::_update() { - EAction::_callOn(); + EAction::_update(); if (m_pTarget == nullptr) { diff --git a/Easy2D/Action/EActionSequence.cpp b/Easy2D/Action/EActionSequence.cpp index a21b84f2..7ad50209 100644 --- a/Easy2D/Action/EActionSequence.cpp +++ b/Easy2D/Action/EActionSequence.cpp @@ -42,12 +42,12 @@ void e2d::EActionSequence::_init() m_vActions[0]->_init(); } -void e2d::EActionSequence::_callOn() +void e2d::EActionSequence::_update() { - EAction::_callOn(); + EAction::_update(); auto &action = m_vActions[m_nActionIndex]; - action->_callOn(); + action->_update(); if (action->_isEnding()) { diff --git a/Easy2D/Action/EActionTwo.cpp b/Easy2D/Action/EActionTwo.cpp index 9ad503d9..72b5c4a6 100644 --- a/Easy2D/Action/EActionTwo.cpp +++ b/Easy2D/Action/EActionTwo.cpp @@ -40,13 +40,13 @@ void e2d::EActionTwo::_init() m_pFirstAction->_init(); } -void e2d::EActionTwo::_callOn() +void e2d::EActionTwo::_update() { - EAction::_callOn(); + EAction::_update(); if (!m_pFirstAction->_isEnding()) { - m_pFirstAction->_callOn(); + m_pFirstAction->_update(); if (m_pFirstAction->_isEnding()) { // 返回 true 表示第一个动作已经结束 @@ -55,7 +55,7 @@ void e2d::EActionTwo::_callOn() } else if (!m_pSecondAction->_isEnding()) { - m_pSecondAction->_callOn(); + m_pSecondAction->_update(); } else { diff --git a/Easy2D/Action/EActionTwoAtSameTime.cpp b/Easy2D/Action/EActionTwoAtSameTime.cpp index db40987a..0b8d3642 100644 --- a/Easy2D/Action/EActionTwoAtSameTime.cpp +++ b/Easy2D/Action/EActionTwoAtSameTime.cpp @@ -41,17 +41,17 @@ void e2d::EActionTwoAtSameTime::_init() m_pSecondAction->_init(); } -void e2d::EActionTwoAtSameTime::_callOn() +void e2d::EActionTwoAtSameTime::_update() { - EAction::_callOn(); + EAction::_update(); if (!m_pFirstAction->_isEnding()) { - m_pFirstAction->_callOn(); + m_pFirstAction->_update(); } if (!m_pSecondAction->_isEnding()) { - m_pSecondAction->_callOn(); + m_pSecondAction->_update(); } // 两个动作都结束时,动作结束 diff --git a/Easy2D/Action/EAnimation.cpp b/Easy2D/Action/EAnimation.cpp index c325a21a..f8cc4e66 100644 --- a/Easy2D/Action/EAnimation.cpp +++ b/Easy2D/Action/EAnimation.cpp @@ -28,9 +28,9 @@ void e2d::EAnimation::_init() EAction::_init(); } -void e2d::EAnimation::_callOn() +void e2d::EAnimation::_update() { - EAction::_callOn(); + EAction::_update(); if (m_pTarget == nullptr) { diff --git a/Easy2D/Base/EApp.cpp b/Easy2D/Base/EApp.cpp index 19ed3c2e..8f1856b1 100644 --- a/Easy2D/Base/EApp.cpp +++ b/Easy2D/Base/EApp.cpp @@ -3,6 +3,7 @@ #include "..\emanagers.h" #include "..\enodes.h" #include "..\etransitions.h" +#include "..\etools.h" #include #include #include @@ -129,10 +130,7 @@ bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, EWindowS L"Easy2DApp", m_sTitle.c_str(), dwStyle, - 0, - 0, - width, - height, + 0, 0, width, height, NULL, NULL, HINST_THISCOMPONENT, @@ -150,7 +148,7 @@ bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, EWindowS } else { - UnregisterClass(L"E2DApp", HINST_THISCOMPONENT); + UnregisterClass(L"Easy2DApp", HINST_THISCOMPONENT); } if (FAILED(hr)) @@ -172,11 +170,7 @@ void e2d::EApp::resume() { EApp::get()->m_bPaused = false; EApp::get()->m_bManualPaused = false; - // 刷新当前时间 - GetNow() = steady_clock::now(); - // 重置动画和定时器 - EActionManager::_resetAllActions(); - ETimerManager::_resetAllTimers(); + EApp::_updateTime(); } } @@ -261,7 +255,7 @@ void e2d::EApp::run() while (!m_bEnd) { // 处理窗口消息 - while (PeekMessage(&msg, GetHWnd(), 0, 0, PM_REMOVE)) + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); @@ -314,9 +308,9 @@ void e2d::EApp::_mainLoop() // 记录当前时间 tLast += microseconds(m_nAnimationInterval); // 游戏控制流程 - _onControl(); + _update(); // 刷新游戏画面 - _onRender(); + _render(); } else { @@ -330,7 +324,7 @@ void e2d::EApp::_mainLoop() } } -void e2d::EApp::_onControl() +void e2d::EApp::_update() { if (isPaused()) { @@ -363,7 +357,7 @@ void e2d::EApp::_onControl() EActionManager::ActionProc(); // 动作管理器执行程序 } -void e2d::EApp::_onRender() +void e2d::EApp::_render() { HRESULT hr = S_OK; @@ -374,12 +368,12 @@ void e2d::EApp::_onRender() // 绘制当前场景 if (m_pCurrentScene) { - m_pCurrentScene->_onRender(); + m_pCurrentScene->_render(); } // 切换场景时,同时绘制两场景 if (m_bTransitional && m_pNextScene) { - m_pNextScene->_onRender(); + m_pNextScene->_render(); } // 终止绘图 hr = GetRenderTarget()->EndDraw(); @@ -626,14 +620,25 @@ void e2d::EApp::_enterNextScene() m_pNextScene = nullptr; // 下一场景置空 } +void e2d::EApp::_updateTime() +{ + // 刷新当前时间 + GetNow() = steady_clock::now(); + // 重置动画和定时器 + EActionManager::_resetAllActions(); + ETimerManager::_resetAllTimers(); +} + LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - // 处理窗口消息 - LRESULT result = 0; - e2d::EApp *pEApp = EApp::get(); - - if (pEApp) + if (s_pInstance == nullptr) { + return DefWindowProc(hWnd, message, wParam, lParam); + } + else + { + LRESULT result = 0; + switch (message) { // 处理鼠标消息 @@ -650,7 +655,7 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam case WM_MOUSEWHEEL: { // 执行场景切换时屏蔽按键和鼠标消息 - if (!pEApp->m_bTransitional && !pEApp->m_pNextScene) + if (!s_pInstance->m_bTransitional && !s_pInstance->m_pNextScene) { EMsgManager::MouseProc(message, wParam, lParam); } @@ -663,7 +668,7 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam case WM_KEYUP: { // 执行场景切换时屏蔽按键和鼠标消息 - if (!pEApp->m_bTransitional && !pEApp->m_pNextScene) + if (!s_pInstance->m_bTransitional && !s_pInstance->m_pNextScene) { EMsgManager::KeyboardProc(message, wParam, lParam); } @@ -695,7 +700,7 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam // 重绘窗口 case WM_PAINT: { - pEApp->_onRender(); + s_pInstance->_render(); ValidateRect(hWnd, NULL); } result = 0; @@ -706,25 +711,28 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam { if (LOWORD(wParam) == WA_INACTIVE) { - if (pEApp->getCurrentScene() && - pEApp->getCurrentScene()->onInactive() && - pEApp->onInactive()) + if (s_pInstance->getCurrentScene() && + s_pInstance->getCurrentScene()->onInactive() && + s_pInstance->onInactive()) { - pEApp->m_bPaused = true; + s_pInstance->m_bPaused = true; + // 暂停音乐 + EMusicUtils::pauseAllMusics(); } } - else if (pEApp->m_bPaused) + else if (s_pInstance->m_bPaused) { - if (pEApp->getCurrentScene() && - pEApp->getCurrentScene()->onActivate() && - pEApp->onActivate()) + if (s_pInstance->getCurrentScene() && + s_pInstance->getCurrentScene()->onActivate() && + s_pInstance->onActivate()) { - pEApp->m_bPaused = false; - // 刷新当前时间 - GetNow() = steady_clock::now(); - // 重置动画和定时器 - EActionManager::_resetAllActions(); - ETimerManager::_resetAllTimers(); + s_pInstance->m_bPaused = false; + if (!s_pInstance->m_bManualPaused) + { + EApp::_updateTime(); + // 继续播放音乐 + EMusicUtils::resumeAllMusics(); + } } } } @@ -734,17 +742,17 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam // 窗口关闭消息 case WM_CLOSE: { - if (!pEApp->getCurrentScene()) + if (!s_pInstance->getCurrentScene()) { - if (pEApp->onCloseWindow()) + if (s_pInstance->onCloseWindow()) { DestroyWindow(hWnd); } } else { - if (pEApp->getCurrentScene()->onCloseWindow() && - pEApp->onCloseWindow()) + if (s_pInstance->getCurrentScene()->onCloseWindow() && + s_pInstance->onCloseWindow()) { DestroyWindow(hWnd); } @@ -757,7 +765,7 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam case WM_DESTROY: { // 退出程序 - pEApp->quit(); + s_pInstance->quit(); // 发送退出消息 PostQuitMessage(0); } @@ -767,7 +775,7 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam default: result = DefWindowProc(hWnd, message, wParam, lParam); } - } - return result; + return result; + } } diff --git a/Easy2D/Base/EScene.cpp b/Easy2D/Base/EScene.cpp index 58664f9d..7e1d9eea 100644 --- a/Easy2D/Base/EScene.cpp +++ b/Easy2D/Base/EScene.cpp @@ -47,10 +47,10 @@ bool e2d::EScene::onCloseWindow() return true; } -void e2d::EScene::_onRender() +void e2d::EScene::_render() { // 访问根节点 - m_pRoot->_callOn(); + m_pRoot->_update(); // 恢复矩阵转换 GetRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); diff --git a/Easy2D/Easy2D.vcxproj b/Easy2D/Easy2D.vcxproj index b5c27dde..0c917008 100644 --- a/Easy2D/Easy2D.vcxproj +++ b/Easy2D/Easy2D.vcxproj @@ -250,6 +250,7 @@ + @@ -265,6 +266,7 @@ + diff --git a/Easy2D/Easy2D.vcxproj.filters b/Easy2D/Easy2D.vcxproj.filters index b5590415..3a8e48df 100644 --- a/Easy2D/Easy2D.vcxproj.filters +++ b/Easy2D/Easy2D.vcxproj.filters @@ -216,6 +216,9 @@ Common + + Win + @@ -233,5 +236,8 @@ + + Win + \ No newline at end of file diff --git a/Easy2D/Geometry/EGeometry.cpp b/Easy2D/Geometry/EGeometry.cpp index 7b994cdc..236062c6 100644 --- a/Easy2D/Geometry/EGeometry.cpp +++ b/Easy2D/Geometry/EGeometry.cpp @@ -59,7 +59,7 @@ void e2d::EGeometry::setOpacity(float opacity) m_fOpacity = min(max(opacity, 0), 1); } -void e2d::EGeometry::_onRender() +void e2d::EGeometry::_render() { if (m_pTransformedGeometry) { diff --git a/Easy2D/Manager/EActionManager.cpp b/Easy2D/Manager/EActionManager.cpp index 24423e56..e171a3df 100644 --- a/Easy2D/Manager/EActionManager.cpp +++ b/Easy2D/Manager/EActionManager.cpp @@ -150,7 +150,7 @@ void e2d::EActionManager::ActionProc() else { // 执行动作 - action->_callOn(); + action->_update(); } } } diff --git a/Easy2D/Node/ENode.cpp b/Easy2D/Node/ENode.cpp index 3dd91ba3..40d24c54 100644 --- a/Easy2D/Node/ENode.cpp +++ b/Easy2D/Node/ENode.cpp @@ -62,7 +62,7 @@ void e2d::ENode::onExit() { } -void e2d::ENode::_callOn() +void e2d::ENode::_update() { if (!m_bVisiable) { @@ -86,7 +86,7 @@ void e2d::ENode::_callOn() // 访问 Order 小于零的节点 if (child->getOrder() < 0) { - child->_callOn(); + child->_update(); } else { @@ -96,21 +96,21 @@ void e2d::ENode::_callOn() GetRenderTarget()->SetTransform(m_MatriFinal); // 渲染自身 - this->_onRender(); + this->_render(); // 访问剩余节点 for (; i < size; i++) - m_vChildren[i]->_callOn(); + m_vChildren[i]->_update(); } else { GetRenderTarget()->SetTransform(m_MatriFinal); // 渲染自身 - this->_onRender(); + this->_render(); } } -void e2d::ENode::_onRender() +void e2d::ENode::_render() { } @@ -119,7 +119,7 @@ void e2d::ENode::_drawGeometry() // 绘制自身的几何形状 if (m_pGeometry && m_pGeometry->m_bIsVisiable) { - m_pGeometry->_onRender(); + m_pGeometry->_render(); } // 绘制所有子节点的几何形状 diff --git a/Easy2D/Node/ESprite.cpp b/Easy2D/Node/ESprite.cpp index ee2be277..58111bdd 100644 --- a/Easy2D/Node/ESprite.cpp +++ b/Easy2D/Node/ESprite.cpp @@ -97,7 +97,7 @@ void e2d::ESprite::clip(float x, float y, float width, float height) ENode::_setHeight(min(max(height, 0), m_pTexture->getSourceHeight() - m_fSourceClipY)); } -void e2d::ESprite::_onRender() +void e2d::ESprite::_render() { if (m_pTexture && m_pTexture->_getBitmap()) { diff --git a/Easy2D/Node/EText.cpp b/Easy2D/Node/EText.cpp index 8361fe53..b13f567b 100644 --- a/Easy2D/Node/EText.cpp +++ b/Easy2D/Node/EText.cpp @@ -90,7 +90,7 @@ void e2d::EText::setWordWrappingWidth(float wordWrapWidth) _initTextLayout(); } -void e2d::EText::_onRender() +void e2d::EText::_render() { GetSolidColorBrush()->SetColor(D2D1::ColorF(m_pFont->m_Color, m_fDisplayOpacity)); GetRenderTarget()->DrawTextW( diff --git a/Easy2D/Tool/EMusicUtils - 鍓湰.cpp b/Easy2D/Tool/EMusicUtils - 鍓湰.cpp deleted file mode 100644 index c831de24..00000000 --- a/Easy2D/Tool/EMusicUtils - 鍓湰.cpp +++ /dev/null @@ -1,525 +0,0 @@ -#include "..\etools.h" -#include "..\Win\winbase.h" -#include -#include -#include -#pragma comment(lib , "winmm.lib") - -static size_t Hash(const e2d::EString & key); -static bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName); - - -//////////////////////////////////////////////////////////////////// -// MciPlayer -//////////////////////////////////////////////////////////////////// - -class MciPlayer -{ -public: - MciPlayer(); - ~MciPlayer(); - - void close(); - bool open(const e2d::EString & pFileName, size_t uId); - bool open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, size_t uId); - void play(bool bLoop = false); - void pause(); - void resume(); - void stop(); - void rewind(); - void setVolume(float volume); - bool isPlaying(); - size_t getSoundID(); - -private: - void _sendCommand(int nCommand, DWORD_PTR param1 = 0, DWORD_PTR parma2 = 0); - - MCIDEVICEID m_dev; - size_t m_nSoundID; - bool m_bPlaying; - bool m_bLoop; - e2d::EString m_sTempFileName; -}; - - -MciPlayer::MciPlayer() : - m_dev(0L), - m_nSoundID(0), - m_bPlaying(false), - m_bLoop(false) -{ -} - -MciPlayer::~MciPlayer() -{ - close(); // 关闭播放器 -} - -bool MciPlayer::open(const e2d::EString & pFileName, size_t uId) -{ - // 忽略不存在的文件 - if (pFileName.empty()) - return false; - - // 停止当前音乐 - close(); - - // 设置 MCI_OPEN_PARMS 参数 - MCI_OPEN_PARMS mciOpen = { 0 }; - mciOpen.lpstrElementName = pFileName.c_str(); - - // 打开这个文件 - MCIERROR mciError; - mciError = mciSendCommand( - 0, - MCI_OPEN, - MCI_OPEN_ELEMENT | MCI_NOTIFY, - reinterpret_cast(&mciOpen) - ); - - if (mciError) - { - return false; - } - else - { - // 保存设备等信息 - m_dev = mciOpen.wDeviceID; - m_nSoundID = uId; - m_bPlaying = false; - return true; - } -} - -bool MciPlayer::open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, size_t 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) -{ - // 设备为空时,忽略这次操作 - if (!m_dev) - { - return; - } - // 设置播放参数 - MCI_PLAY_PARMS mciPlay = { 0 }; - MCIERROR s_mciError; - - // 播放声音 - 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) - { - m_bPlaying = true; - m_bLoop = bLoop; - } -} - -void MciPlayer::close() -{ - // 停止音乐 - if (m_bPlaying) - { - stop(); - } - // 关闭设备 - if (m_dev) - { - _sendCommand(MCI_CLOSE); - } - // 删除临时文件 - if (!m_sTempFileName.empty()) - { - DeleteFile(m_sTempFileName.c_str()); - m_sTempFileName.clear(); - } - // 恢复默认属性 - m_dev = 0; - m_bPlaying = false; -} - -void MciPlayer::pause() -{ - // 暂停音乐 - _sendCommand(MCI_PAUSE); - m_bPlaying = false; -} - -void MciPlayer::resume() -{ - // 继续播放音乐 - _sendCommand(MCI_RESUME); - m_bPlaying = true; -} - -void MciPlayer::stop() -{ - // 停止音乐 - _sendCommand(MCI_STOP); - m_bPlaying = false; -} - -void MciPlayer::rewind() -{ - // 设备为空时,忽略这次操作 - if (!m_dev) - { - return; - } - // 重置播放位置 - mciSendCommand( - m_dev, - MCI_SEEK, - MCI_SEEK_TO_START | MCI_NOTIFY, - 0 - ); - // 播放音乐 - MCI_PLAY_PARMS mciPlay = { 0 }; - 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) -{ - 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_NOTIFY | MCI_DGV_SETAUDIO_VALUE | MCI_DGV_SETAUDIO_ITEM, - (DWORD_PTR)&mciSetAudioPara - ); -} - -bool MciPlayer::isPlaying() -{ - return m_bPlaying; -} - -size_t MciPlayer::getSoundID() -{ - return m_nSoundID; -} - -void MciPlayer::_sendCommand(int nCommand, DWORD_PTR param1, DWORD_PTR parma2) -{ - // 空设备时忽略这次操作 - if (!m_dev) - { - return; - } - // 向当前设备发送操作 - mciSendCommand(m_dev, nCommand, param1, parma2); -} - - - - -//////////////////////////////////////////////////////////////////// -// e2d::EMusicUtils -//////////////////////////////////////////////////////////////////// - - -typedef std::map MusicList; -typedef std::pair Music; - - -static MusicList& getMciPlayerList() -{ - static MusicList s_List; - return s_List; -} - -static MciPlayer& getBgMciPlayer() -{ - static MciPlayer s_Music; - return s_Music; -} - -void e2d::EMusicUtils::end() -{ - // 停止背景音乐 - getBgMciPlayer().close(); - // 停止其他所有音乐 - for (auto& iter : getMciPlayerList()) - { - SafeDelete(&iter.second); - } - // 清空音乐列表 - getMciPlayerList().clear(); - return; -} - -void e2d::EMusicUtils::setVolume(float volume) -{ - // 设置背景音乐音量 - getBgMciPlayer().setVolume(volume); - // 设置其他音乐音量 - for (auto& iter : getMciPlayerList()) - { - iter.second->setVolume(volume); - } -} - -void e2d::EMusicUtils::setVolume(const EString & musicFilePath, float volume) -{ - size_t nRet = ::Hash(musicFilePath); - - MusicList::iterator p = getMciPlayerList().find(nRet); - if (p != getMciPlayerList().end()) - { - p->second->setVolume(volume); - } -} - -void e2d::EMusicUtils::playBackgroundMusic(const EString & musicFilePath, bool bLoop) -{ - if (musicFilePath.empty()) - { - return; - } - - getBgMciPlayer().open(musicFilePath, ::Hash(musicFilePath)); - getBgMciPlayer().play(bLoop); -} - -void e2d::EMusicUtils::playBackgroundMusic(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension, bool loop) -{ - if (musicResourceName.empty() || musicResourceType.empty()) - { - return; - } - - getBgMciPlayer().open(musicResourceName, musicResourceType, musicExtension, ::Hash(musicResourceName)); - getBgMciPlayer().play(loop); -} - -void e2d::EMusicUtils::stopBackgroundMusic(bool bReleaseData) -{ - if (bReleaseData) - { - getBgMciPlayer().close(); - } - else - { - getBgMciPlayer().stop(); - } -} - -void e2d::EMusicUtils::pauseBackgroundMusic() -{ - getBgMciPlayer().pause(); -} - -void e2d::EMusicUtils::resumeBackgroundMusic() -{ - getBgMciPlayer().resume(); -} - -void e2d::EMusicUtils::rewindBackgroundMusic() -{ - getBgMciPlayer().rewind(); -} - -bool e2d::EMusicUtils::isBackgroundMusicPlaying() -{ - return getBgMciPlayer().isPlaying(); -} - -void e2d::EMusicUtils::setBackgroundMusicVolume(float volume) -{ - getBgMciPlayer().setVolume(volume); -} - -void e2d::EMusicUtils::playMusic(const EString & musicFilePath, bool bLoop) -{ - size_t nRet = ::Hash(musicFilePath); - - preloadMusic(musicFilePath); - - MusicList::iterator p = getMciPlayerList().find(nRet); - if (p != getMciPlayerList().end()) - { - p->second->play(bLoop); - } -} - -void e2d::EMusicUtils::playMusic(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension, bool loop) -{ - size_t nRet = ::Hash(musicResourceName); - - preloadMusic(musicResourceName, musicResourceType, musicExtension); - - MusicList::iterator p = getMciPlayerList().find(nRet); - if (p != getMciPlayerList().end()) - { - p->second->play(loop); - } -} - -void e2d::EMusicUtils::_stopMusic(size_t nSoundId) -{ - MusicList::iterator p = getMciPlayerList().find(nSoundId); - if (p != getMciPlayerList().end()) - { - p->second->stop(); - } -} - -void e2d::EMusicUtils::preloadMusic(const EString & musicFilePath) -{ - if (musicFilePath.empty()) return; - - size_t nRet = ::Hash(musicFilePath); - - if (getMciPlayerList().end() != getMciPlayerList().find(nRet)) return; - - getMciPlayerList().insert(Music(nRet, new MciPlayer())); - MciPlayer * pPlayer = getMciPlayerList()[nRet]; - pPlayer->open(musicFilePath, nRet); - - if (nRet == pPlayer->getSoundID()) return; - - delete pPlayer; - getMciPlayerList().erase(nRet); - nRet = 0; -} - -void e2d::EMusicUtils::preloadMusic(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension) -{ - if (musicResourceName.empty() || musicResourceType.empty()) return; - - size_t nRet = ::Hash(musicResourceName); - - if (getMciPlayerList().end() != getMciPlayerList().find(nRet)) return; - - getMciPlayerList().insert(Music(nRet, new MciPlayer())); - MciPlayer * pPlayer = getMciPlayerList()[nRet]; - pPlayer->open(musicResourceName, musicResourceType, musicExtension, nRet); - - if (nRet == pPlayer->getSoundID()) return; - - delete pPlayer; - getMciPlayerList().erase(nRet); - nRet = 0; -} - -void e2d::EMusicUtils::_pauseMusic(size_t nSoundId) -{ - MusicList::iterator p = getMciPlayerList().find(nSoundId); - if (p != getMciPlayerList().end()) - { - p->second->pause(); - } -} - -void e2d::EMusicUtils::pauseAllMusics() -{ - for (auto& iter : getMciPlayerList()) - { - iter.second->pause(); - } -} - -void e2d::EMusicUtils::_resumeMusic(size_t nSoundId) -{ - MusicList::iterator p = getMciPlayerList().find(nSoundId); - if (p != getMciPlayerList().end()) - { - p->second->resume(); - } -} - -void e2d::EMusicUtils::resumeAllMusics() -{ - for (auto& iter : getMciPlayerList()) - { - iter.second->resume(); - } -} - -void e2d::EMusicUtils::stopAllMusics() -{ - for (auto& iter : getMciPlayerList()) - { - iter.second->stop(); - } -} - -void e2d::EMusicUtils::unloadMusic(const EString & musicFilePath) -{ - size_t nID = ::Hash(musicFilePath); - - MusicList::iterator p = getMciPlayerList().find(nID); - if (p != getMciPlayerList().end()) - { - SafeDelete(&p->second); - getMciPlayerList().erase(nID); - } -} - - - - -size_t Hash(const e2d::EString & key) -{ - static std::hash h; - return h(key); -} - -bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName) -{ - // 创建文件 - HANDLE hFile = ::CreateFile(strDstFile, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return false; - - // 查找资源文件中、加载资源到内存、得到资源大小 - HRSRC hRes = ::FindResource(NULL, strResName, strResType); - HGLOBAL hMem = ::LoadResource(NULL, hRes); - DWORD dwSize = ::SizeofResource(NULL, hRes); - - // 写入文件 - DWORD dwWrite = 0; // 返回写入字节 - ::WriteFile(hFile, hMem, dwSize, &dwWrite, NULL); - ::CloseHandle(hFile); - - return true; -} \ No newline at end of file diff --git a/Easy2D/Tool/EMusicUtils.cpp b/Easy2D/Tool/EMusicUtils.cpp index a0ce0d55..889063d2 100644 --- a/Easy2D/Tool/EMusicUtils.cpp +++ b/Easy2D/Tool/EMusicUtils.cpp @@ -1,470 +1,134 @@ #include "..\etools.h" -#include "..\Win\winbase.h" -#include #include -#include -#pragma comment(lib , "winmm.lib") +#include "..\Win\MciPlayer.h" +#include -static size_t Hash(const e2d::EString & key); -static bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName); +typedef std::pair Music; +typedef std::map MusicList; - -//////////////////////////////////////////////////////////////////// -// MciPlayer -//////////////////////////////////////////////////////////////////// - -class MciPlayer -{ -public: - MciPlayer(); - ~MciPlayer(); - - void close(); - bool open(const e2d::EString & pFileName, size_t uId); - bool open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, size_t uId); - void play(bool bLoop = false); - void pause(); - void resume(); - void stop(); - void rewind(); - void setVolume(float volume); - bool isPlaying(); - size_t getSoundID(); - -private: - void _sendCommand(int nCommand, DWORD_PTR param1 = 0, DWORD_PTR parma2 = 0); - - MCIDEVICEID m_dev; - size_t m_nSoundID; - bool m_bPlaying; - bool m_bLoop; - e2d::EString m_sTempFileName; -}; - - -MciPlayer::MciPlayer() : - m_dev(0L), - m_nSoundID(0), - m_bPlaying(false), - m_bLoop(false) +static UINT Hash(const e2d::EString & key) { + static std::hash h; + return h(key); } -MciPlayer::~MciPlayer() -{ - close(); // 关闭播放器 -} - -bool MciPlayer::open(const e2d::EString & pFileName, size_t uId) -{ - // 忽略不存在的文件 - if (pFileName.empty()) - return false; - - // 停止当前音乐 - close(); - - // 设置 MCI_OPEN_PARMS 参数 - MCI_OPEN_PARMS mciOpen = { 0 }; - mciOpen.lpstrElementName = pFileName.c_str(); - - // 打开这个文件 - MCIERROR mciError; - mciError = mciSendCommand( - 0, - MCI_OPEN, - MCI_OPEN_ELEMENT | MCI_NOTIFY, - reinterpret_cast(&mciOpen) - ); - - if (mciError) - { - return false; - } - else - { - // 保存设备等信息 - m_dev = mciOpen.wDeviceID; - m_nSoundID = uId; - m_bPlaying = false; - return true; - } -} - -bool MciPlayer::open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, size_t 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) -{ - // 设备为空时,忽略这次操作 - if (!m_dev) - { - return; - } - // 设置播放参数 - MCI_PLAY_PARMS mciPlay = { 0 }; - MCIERROR s_mciError; - - // 播放声音 - 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) - { - m_bPlaying = true; - m_bLoop = bLoop; - } -} - -void MciPlayer::close() -{ - // 停止音乐 - if (m_bPlaying) - { - stop(); - } - // 关闭设备 - if (m_dev) - { - _sendCommand(MCI_CLOSE); - } - // 删除临时文件 - if (!m_sTempFileName.empty()) - { - DeleteFile(m_sTempFileName.c_str()); - m_sTempFileName.clear(); - } - // 恢复默认属性 - m_dev = 0; - m_bPlaying = false; -} - -void MciPlayer::pause() -{ - // 暂停音乐 - _sendCommand(MCI_PAUSE); - m_bPlaying = false; -} - -void MciPlayer::resume() -{ - // 继续播放音乐 - _sendCommand(MCI_RESUME); - m_bPlaying = true; -} - -void MciPlayer::stop() -{ - // 停止音乐 - _sendCommand(MCI_STOP); - m_bPlaying = false; -} - -void MciPlayer::rewind() -{ - // 设备为空时,忽略这次操作 - if (!m_dev) - { - return; - } - // 重置播放位置 - mciSendCommand( - m_dev, - MCI_SEEK, - MCI_SEEK_TO_START | MCI_NOTIFY, - 0 - ); - // 播放音乐 - MCI_PLAY_PARMS mciPlay = { 0 }; - 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) -{ - 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_NOTIFY | MCI_DGV_SETAUDIO_VALUE | MCI_DGV_SETAUDIO_ITEM, - (DWORD_PTR)&mciSetAudioPara - ); -} - -bool MciPlayer::isPlaying() -{ - return m_bPlaying; -} - -size_t MciPlayer::getSoundID() -{ - return m_nSoundID; -} - -void MciPlayer::_sendCommand(int nCommand, DWORD_PTR param1, DWORD_PTR parma2) -{ - // 空设备时忽略这次操作 - if (!m_dev) - { - return; - } - // 向当前设备发送操作 - mciSendCommand(m_dev, nCommand, param1, parma2); -} - - - - -//////////////////////////////////////////////////////////////////// -// e2d::EMusicUtils -//////////////////////////////////////////////////////////////////// - - -typedef std::map MusicList; -typedef std::pair Music; - - static MusicList& getMciPlayerList() { static MusicList s_List; return s_List; } -static MciPlayer& getBgMciPlayer() -{ - static MciPlayer s_Music; - return s_Music; -} -void e2d::EMusicUtils::end() +UINT e2d::EMusicUtils::playMusic(const EString & musicFilePath, int repeatTimes) { - // 停止背景音乐 - getBgMciPlayer().close(); - // 停止其他所有音乐 - for (auto& iter : getMciPlayerList()) + UINT nRet = preloadMusic(musicFilePath); + + if (nRet) { - SafeDelete(&iter.second); + getMciPlayerList()[nRet]->play(repeatTimes); } - // 清空音乐列表 - getMciPlayerList().clear(); - return; + return nRet; } -void e2d::EMusicUtils::setVolume(float volume) +UINT e2d::EMusicUtils::playMusic(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension, int repeatTimes) { - // 设置背景音乐音量 - getBgMciPlayer().setVolume(volume); - // 设置其他音乐音量 - for (auto& iter : getMciPlayerList()) + UINT nRet = preloadMusic(musicResourceName, musicResourceType, musicExtension); + + if (nRet) { - iter.second->setVolume(volume); + getMciPlayerList()[nRet]->play(repeatTimes); } + return nRet; } -void e2d::EMusicUtils::setVolume(const EString & musicFilePath, float volume) +UINT e2d::EMusicUtils::preloadMusic(const EString & musicFilePath) { - size_t nRet = ::Hash(musicFilePath); + if (musicFilePath.empty()) + return 0; - MusicList::iterator p = getMciPlayerList().find(nRet); - if (p != getMciPlayerList().end()) - { - p->second->setVolume(volume); - } -} + UINT nRet = ::Hash(musicFilePath); -void e2d::EMusicUtils::playBackgroundMusic(const EString & musicFilePath, bool bLoop) -{ - if (musicFilePath.empty()) - { - return; - } - - getBgMciPlayer().open(musicFilePath, ::Hash(musicFilePath)); - getBgMciPlayer().play(bLoop); -} - -void e2d::EMusicUtils::playBackgroundMusic(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension, bool loop) -{ - if (musicResourceName.empty() || musicResourceType.empty()) - { - return; - } - - getBgMciPlayer().open(musicResourceName, musicResourceType, musicExtension, ::Hash(musicResourceName)); - getBgMciPlayer().play(loop); -} - -void e2d::EMusicUtils::stopBackgroundMusic(bool bReleaseData) -{ - if (bReleaseData) - { - getBgMciPlayer().close(); - } - else - { - getBgMciPlayer().stop(); - } -} - -void e2d::EMusicUtils::pauseBackgroundMusic() -{ - getBgMciPlayer().pause(); -} - -void e2d::EMusicUtils::resumeBackgroundMusic() -{ - getBgMciPlayer().resume(); -} - -void e2d::EMusicUtils::rewindBackgroundMusic() -{ - getBgMciPlayer().rewind(); -} - -bool e2d::EMusicUtils::isBackgroundMusicPlaying() -{ - return getBgMciPlayer().isPlaying(); -} - -void e2d::EMusicUtils::setBackgroundMusicVolume(float volume) -{ - getBgMciPlayer().setVolume(volume); -} - -void e2d::EMusicUtils::playMusic(const EString & musicFilePath, bool bLoop) -{ - MCI_OPEN_PARMS mciOpen = { 0 }; - mciOpen.lpstrElementName = musicFilePath.c_str(); - - // 打开这个文件 - MCIERROR mciError; - mciError = mciSendCommand( - 0, - MCI_OPEN, - MCI_OPEN_ELEMENT | MCI_NOTIFY, - reinterpret_cast(&mciOpen) - ); - - if (!mciError) - { - // 设置播放参数 - MCI_PLAY_PARMS mciPlay = { 0 }; - MCIERROR s_mciError; - - // 播放声音 - s_mciError = mciSendCommand( - mciOpen.wDeviceID, - MCI_PLAY, - MCI_FROM | MCI_NOTIFY | (bLoop ? MCI_DGV_PLAY_REPEAT : 0), - reinterpret_cast(&mciPlay) - ); - } -} - -void e2d::EMusicUtils::playMusic(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension, bool loop) -{ - size_t nRet = ::Hash(musicResourceName); - - preloadMusic(musicResourceName, musicResourceType, musicExtension); - - MusicList::iterator p = getMciPlayerList().find(nRet); - if (p != getMciPlayerList().end()) - { - p->second->play(loop); - } -} - -void e2d::EMusicUtils::_stopMusic(size_t nSoundId) -{ - MusicList::iterator p = getMciPlayerList().find(nSoundId); - if (p != getMciPlayerList().end()) - { - p->second->stop(); - } -} - -void e2d::EMusicUtils::preloadMusic(const EString & musicFilePath) -{ - if (musicFilePath.empty()) return; - - size_t nRet = ::Hash(musicFilePath); - - if (getMciPlayerList().end() != getMciPlayerList().find(nRet)) return; + if (getMciPlayerList().end() != getMciPlayerList().find(nRet)) + return nRet; getMciPlayerList().insert(Music(nRet, new MciPlayer())); MciPlayer * pPlayer = getMciPlayerList()[nRet]; pPlayer->open(musicFilePath, nRet); - if (nRet == pPlayer->getSoundID()) return; + if (nRet == pPlayer->getMusicID()) return nRet; delete pPlayer; getMciPlayerList().erase(nRet); - nRet = 0; + return 0; } -void e2d::EMusicUtils::preloadMusic(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension) +UINT e2d::EMusicUtils::preloadMusic(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension) { - if (musicResourceName.empty() || musicResourceType.empty()) return; + if (musicResourceName.empty() || musicResourceType.empty()) + return 0; - size_t nRet = ::Hash(musicResourceName); + UINT nRet = ::Hash(musicResourceName); - if (getMciPlayerList().end() != getMciPlayerList().find(nRet)) return; + if (getMciPlayerList().end() != getMciPlayerList().find(nRet)) + return nRet; getMciPlayerList().insert(Music(nRet, new MciPlayer())); MciPlayer * pPlayer = getMciPlayerList()[nRet]; pPlayer->open(musicResourceName, musicResourceType, musicExtension, nRet); - if (nRet == pPlayer->getSoundID()) return; + if (nRet == pPlayer->getMusicID()) return nRet; delete pPlayer; getMciPlayerList().erase(nRet); - nRet = 0; + return 0; } -void e2d::EMusicUtils::_pauseMusic(size_t nSoundId) +bool e2d::EMusicUtils::resumeMusic(UINT musicId) { - MusicList::iterator p = getMciPlayerList().find(nSoundId); + MusicList::iterator p = getMciPlayerList().find(musicId); + if (p != getMciPlayerList().end()) + { + p->second->resume(); + return true; + } + return false; +} + +bool e2d::EMusicUtils::resumeMusic(const EString & musicName) +{ + return resumeMusic(Hash(musicName));; +} + +bool e2d::EMusicUtils::pauseMusic(UINT musicId) +{ + MusicList::iterator p = getMciPlayerList().find(musicId); if (p != getMciPlayerList().end()) { p->second->pause(); + return true; } + return false; +} + +bool e2d::EMusicUtils::pauseMusic(const EString & musicName) +{ + return pauseMusic(Hash(musicName)); +} + +bool e2d::EMusicUtils::stopMusic(UINT musicId) +{ + MusicList::iterator p = getMciPlayerList().find(musicId); + if (p != getMciPlayerList().end()) + { + p->second->stop(); + return true; + } + return false; +} + +bool e2d::EMusicUtils::stopMusic(const EString & musicName) +{ + return stopMusic(Hash(musicName));; } void e2d::EMusicUtils::pauseAllMusics() @@ -475,15 +139,6 @@ void e2d::EMusicUtils::pauseAllMusics() } } -void e2d::EMusicUtils::_resumeMusic(size_t nSoundId) -{ - MusicList::iterator p = getMciPlayerList().find(nSoundId); - if (p != getMciPlayerList().end()) - { - p->second->resume(); - } -} - void e2d::EMusicUtils::resumeAllMusics() { for (auto& iter : getMciPlayerList()) @@ -499,44 +154,3 @@ void e2d::EMusicUtils::stopAllMusics() iter.second->stop(); } } - -void e2d::EMusicUtils::unloadMusic(const EString & musicFilePath) -{ - size_t nID = ::Hash(musicFilePath); - - MusicList::iterator p = getMciPlayerList().find(nID); - if (p != getMciPlayerList().end()) - { - SafeDelete(&p->second); - getMciPlayerList().erase(nID); - } -} - - - - -size_t Hash(const e2d::EString & key) -{ - static std::hash h; - return h(key); -} - -bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName) -{ - // 创建文件 - HANDLE hFile = ::CreateFile(strDstFile, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return false; - - // 查找资源文件中、加载资源到内存、得到资源大小 - HRSRC hRes = ::FindResource(NULL, strResName, strResType); - HGLOBAL hMem = ::LoadResource(NULL, hRes); - DWORD dwSize = ::SizeofResource(NULL, hRes); - - // 写入文件 - DWORD dwWrite = 0; // 返回写入字节 - ::WriteFile(hFile, hMem, dwSize, &dwWrite, NULL); - ::CloseHandle(hFile); - - return true; -} \ No newline at end of file diff --git a/Easy2D/Win/MciPlayer.cpp b/Easy2D/Win/MciPlayer.cpp new file mode 100644 index 00000000..41c4c67e --- /dev/null +++ b/Easy2D/Win/MciPlayer.cpp @@ -0,0 +1,269 @@ +#include "..\etools.h" +#include +#include "winbase.h" +#include "MciPlayer.h" +#pragma comment(lib , "winmm.lib") + +#define WIN_CLASS_NAME L"MciPlayerCallbackWnd" + +static HINSTANCE s_hInstance = nullptr; + +LRESULT WINAPI _MciPlayerProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); +static bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName); + + +MciPlayer::MciPlayer() + : m_wnd(NULL) + , m_dev(0L) + , m_nMusicID(0) + , m_bPlaying(false) + , m_nRepeatTimes(0) +{ + if (!s_hInstance) + { + s_hInstance = HINST_THISCOMPONENT; + + WNDCLASS wc; + wc.style = 0; + wc.lpfnWndProc = _MciPlayerProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = s_hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = WIN_CLASS_NAME; + + if (!RegisterClass(&wc) && 1410 != GetLastError()) + { + return; + } + } + + m_wnd = CreateWindowEx( + WS_EX_APPWINDOW, + WIN_CLASS_NAME, + NULL, + WS_POPUPWINDOW, + 0, 0, 0, 0, + NULL, + NULL, + s_hInstance, + NULL); + + if (m_wnd) + { + SetWindowLongPtr(m_wnd, GWLP_USERDATA, (LONG_PTR)this); + } +} + +MciPlayer::~MciPlayer() +{ + close(); + DestroyWindow(m_wnd); +} + +bool MciPlayer::open(const e2d::EString & pFileName, UINT uId) +{ + if (pFileName.empty()) + return false; + + close(); + + MCI_OPEN_PARMS mciOpen = { 0 }; + mciOpen.lpstrDeviceType = (LPCTSTR)MCI_ALL_DEVICE_ID; + mciOpen.lpstrElementName = pFileName.c_str(); + + MCIERROR mciError; + mciError = mciSendCommand( + 0, + MCI_OPEN, + MCI_OPEN_ELEMENT, + reinterpret_cast(&mciOpen) + ); + + if (mciError == 0) + { + m_dev = mciOpen.wDeviceID; + m_nMusicID = uId; + m_bPlaying = false; + return true; + } + return false; +} + +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())) + { + return open(tempFileName, uId); + } + return false; +} + +void MciPlayer::play(int repeatTimes) +{ + if (!m_dev) + { + return; + } + + MCI_PLAY_PARMS mciPlay = { 0 }; + mciPlay.dwCallback = reinterpret_cast(m_wnd); + + // 播放声音 + MCIERROR mciError = mciSendCommand( + m_dev, + MCI_PLAY, + MCI_FROM | MCI_NOTIFY, + reinterpret_cast(&mciPlay) + ); + + if (!mciError) + { + m_bPlaying = true; + m_nRepeatTimes = repeatTimes; + } +} + +void MciPlayer::close() +{ + if (m_bPlaying) + { + stop(); + } + + if (m_dev) + { + _sendCommand(MCI_CLOSE); + } + + m_dev = 0; + m_bPlaying = false; +} + +void MciPlayer::pause() +{ + _sendCommand(MCI_PAUSE); + m_bPlaying = false; +} + +void MciPlayer::resume() +{ + _sendCommand(MCI_RESUME); + m_bPlaying = true; +} + +void MciPlayer::stop() +{ + _sendCommand(MCI_STOP); + m_bPlaying = false; +} + +void MciPlayer::rewind() +{ + if (!m_dev) + { + return; + } + + mciSendCommand(m_dev, MCI_SEEK, MCI_SEEK_TO_START, 0); + + MCI_PLAY_PARMS mciPlay = { 0 }; + mciPlay.dwCallback = reinterpret_cast(m_wnd); + + MCIERROR mciError = mciSendCommand( + m_dev, + MCI_PLAY, + MCI_NOTIFY, + reinterpret_cast(&mciPlay) + ); + m_bPlaying = mciError ? false : true; +} + +bool MciPlayer::isPlaying() +{ + return m_bPlaying; +} + +UINT MciPlayer::getMusicID() +{ + return m_nMusicID; +} + +void MciPlayer::_sendCommand(int nCommand, DWORD_PTR param1, DWORD_PTR parma2) +{ + // 空设备时忽略这次操作 + if (!m_dev) + { + return; + } + // 向当前设备发送操作 + mciSendCommand(m_dev, nCommand, param1, parma2); +} + + + + +bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName) +{ + // 创建文件 + HANDLE hFile = ::CreateFile(strDstFile, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return false; + + // 查找资源文件中、加载资源到内存、得到资源大小 + HRSRC hRes = ::FindResource(NULL, strResName, strResType); + HGLOBAL hMem = ::LoadResource(NULL, hRes); + DWORD dwSize = ::SizeofResource(NULL, hRes); + + // 写入文件 + DWORD dwWrite = 0; // 返回写入字节 + ::WriteFile(hFile, hMem, dwSize, &dwWrite, NULL); + ::CloseHandle(hFile); + + return true; +} + +LRESULT WINAPI _MciPlayerProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + MciPlayer * pPlayer = NULL; + + if (Msg == MM_MCINOTIFY + && wParam == MCI_NOTIFY_SUCCESSFUL + && (pPlayer = (MciPlayer *)GetWindowLongPtr(hWnd, GWLP_USERDATA))) + { + if (pPlayer->m_nRepeatTimes > 0) + { + pPlayer->m_nRepeatTimes--; + } + + if (pPlayer->m_nRepeatTimes) + { + mciSendCommand(lParam, MCI_SEEK, MCI_SEEK_TO_START, 0); + + MCI_PLAY_PARMS mciPlay = { 0 }; + mciPlay.dwCallback = reinterpret_cast(hWnd); + mciSendCommand(lParam, MCI_PLAY, MCI_NOTIFY, reinterpret_cast(&mciPlay)); + } + else + { + pPlayer->m_bPlaying = false; + return 0; + } + } + return DefWindowProc(hWnd, Msg, wParam, lParam); +} \ No newline at end of file diff --git a/Easy2D/Win/MciPlayer.h b/Easy2D/Win/MciPlayer.h new file mode 100644 index 00000000..9b8c45ff --- /dev/null +++ b/Easy2D/Win/MciPlayer.h @@ -0,0 +1,29 @@ +#pragma once + +class MciPlayer +{ +public: + MciPlayer(); + ~MciPlayer(); + + void close(); + 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(int repeatTimes); + void pause(); + void resume(); + void stop(); + void rewind(); + bool isPlaying(); + UINT getMusicID(); + +private: + friend LRESULT WINAPI _MciPlayerProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); + void _sendCommand(int nCommand, DWORD_PTR param1 = 0, DWORD_PTR parma2 = 0); + + MCIDEVICEID m_dev; + HWND m_wnd; + UINT m_nMusicID; + bool m_bPlaying; + int m_nRepeatTimes; +}; diff --git a/Easy2D/eactions.h b/Easy2D/eactions.h index c45b2ebe..490dafba 100644 --- a/Easy2D/eactions.h +++ b/Easy2D/eactions.h @@ -65,7 +65,7 @@ protected: virtual void _init(); // 执行动作 - virtual void _callOn(); + virtual void _update(); // 获取动作结束状态 virtual bool _isEnding(); @@ -137,7 +137,7 @@ protected: virtual void _init() override; // 执行动画 - virtual void _callOn() override; + virtual void _update() override; // 重置动画 virtual void _reset() override; @@ -201,7 +201,7 @@ protected: virtual void _init() override; // 执行动画 - virtual void _callOn() override; + virtual void _update() override; // 重置动画 virtual void _reset() override; @@ -268,7 +268,7 @@ protected: virtual void _init() override; // 执行动画 - virtual void _callOn() override; + virtual void _update() override; // 重置动画 virtual void _reset() override; @@ -347,7 +347,7 @@ protected: virtual void _init() override; // 执行动画 - virtual void _callOn() override; + virtual void _update() override; // 重置动画 virtual void _reset() override; @@ -408,7 +408,7 @@ protected: virtual void _init() override; // 执行动作 - virtual void _callOn() override; + virtual void _update() override; // 重置动作 virtual void _reset() override; @@ -456,7 +456,7 @@ protected: virtual void _init() override; // 执行动作 - virtual void _callOn() override; + virtual void _update() override; // 重置动作 virtual void _reset() override; @@ -487,7 +487,7 @@ protected: virtual void _init() override; // 执行动作 - virtual void _callOn() override; + virtual void _update() override; // 重置动作 virtual void _reset() override; @@ -519,7 +519,7 @@ protected: virtual void _init() override; // 执行动作 - virtual void _callOn() override; + virtual void _update() override; // 重置动作 virtual void _reset() override; @@ -553,7 +553,7 @@ protected: virtual void _init() override; // 执行动作 - virtual void _callOn() override; + virtual void _update() override; // 重置动作 virtual void _reset() override; @@ -598,7 +598,7 @@ protected: virtual void _init() override; // 执行动作 - virtual void _callOn() override; + virtual void _update() override; // 重置动作 virtual void _reset() override; @@ -626,7 +626,7 @@ protected: virtual void _init() override; // 执行动作 - virtual void _callOn() override; + virtual void _update() override; // 重置动作 virtual void _reset() override; diff --git a/Easy2D/ebase.h b/Easy2D/ebase.h index 0138f484..e9dd996b 100644 --- a/Easy2D/ebase.h +++ b/Easy2D/ebase.h @@ -160,14 +160,17 @@ protected: void _mainLoop(); // 游戏控制流程 - void _onControl(); + void _update(); // 渲染游戏画面 - void _onRender(); + void _render(); // 进入下一场景 void _enterNextScene(); + // 刷新游戏时间 + static void _updateTime(); + // 窗口程序 static LRESULT CALLBACK WndProc( HWND hWnd, @@ -262,7 +265,7 @@ public: protected: // 渲染场景画面 - void _onRender(); + void _render(); protected: bool m_bSortNeeded; diff --git a/Easy2D/egeometry.h b/Easy2D/egeometry.h index 633407be..1b1934f6 100644 --- a/Easy2D/egeometry.h +++ b/Easy2D/egeometry.h @@ -64,7 +64,7 @@ protected: virtual void _transform(); // 渲染几何图形 - virtual void _onRender(); + virtual void _render(); virtual ID2D1Geometry * _getD2dGeometry() const = 0; diff --git a/Easy2D/enodes.h b/Easy2D/enodes.h index 515c0361..b592f841 100644 --- a/Easy2D/enodes.h +++ b/Easy2D/enodes.h @@ -313,11 +313,11 @@ public: ); protected: - // 访问节点 - virtual void _callOn(); + // 更新节点 + virtual void _update(); // 渲染节点 - virtual void _onRender(); + virtual void _render(); // 渲染几何图形 virtual void _drawGeometry(); @@ -489,7 +489,7 @@ public: protected: // 渲染精灵 - virtual void _onRender() override; + virtual void _render() override; protected: float m_fSourceClipX; @@ -562,7 +562,7 @@ public: protected: // 渲染文字 - virtual void _onRender() override; + virtual void _render() override; // 创建文字布局 void _initTextLayout(); diff --git a/Easy2D/etools.h b/Easy2D/etools.h index 966b6a4a..da2bf206 100644 --- a/Easy2D/etools.h +++ b/Easy2D/etools.h @@ -212,79 +212,62 @@ public: class EMusicUtils { public: - // 播放背景音乐 - static void playBackgroundMusic( - const EString & musicFilePath, - bool loop = true + // 播放音乐 + static UINT playMusic( + const EString & musicFilePath, /* 音乐文件路径 */ + int repeatTimes = 1 ); - // 播放背景音乐 - static void playBackgroundMusic( + // 播放音乐 + static UINT playMusic( const EString & musicResourceName, /* 资源名称 */ const EString & musicResourceType, /* 资源类别 */ const EString & musicExtension, /* 指定资源的扩展名 */ - bool loop = true + int repeatTimes = 1 ); - // 停止背景音乐 - static void stopBackgroundMusic( - bool release = false + // 暂停音乐 + static bool pauseMusic( + UINT musicId ); - // 暂停背景音乐 - static void pauseBackgroundMusic(); - - // 继续播放背景音乐 - static void resumeBackgroundMusic(); - - // 从头播放背景音乐 - static void rewindBackgroundMusic(); - - // 背景音乐是否正在播放 - static bool isBackgroundMusicPlaying(); - - // 设置背景音乐音量,范围 [0 ~ 1.0] - static void setBackgroundMusicVolume( - float volume + // 暂停音乐 + static bool pauseMusic( + const EString& musicName ); - // 播放音效 - static void playMusic( - const EString & musicFilePath, - bool loop = false + // 继续播放音乐 + static bool resumeMusic( + UINT musicId ); - // 播放音效 - static void playMusic( - const EString & musicResourceName, /* 资源名称 */ - const EString & musicResourceType, /* 资源类别 */ - const EString & musicExtension, /* 指定资源的扩展名 */ - bool loop = false + // 继续播放音乐 + static bool resumeMusic( + const EString& musicName ); - // 预加载音效 - static void preloadMusic( + // 停止音乐 + static bool stopMusic( + UINT musicId + ); + + // 停止音乐 + static bool stopMusic( + const EString& musicName + ); + + // 预加载音乐 + static UINT preloadMusic( const EString & musicFilePath ); - // 预加载音效 - static void preloadMusic( + // 预加载音乐 + static UINT preloadMusic( const EString & musicResourceName, /* 资源名称 */ const EString & musicResourceType, /* 资源类别 */ const EString & musicExtension /* 指定资源的扩展名 */ ); - // 卸载音效 - static void unloadMusic( - const EString & musicFilePath - ); - - // 设置特定音乐的音量,范围 [0 ~ 1.0] - static void setVolume( - const EString & musicFilePath, - float volume - ); - // 暂停所有音乐 static void pauseAllMusics(); @@ -293,30 +276,6 @@ public: // 停止所有音乐 static void stopAllMusics(); - - // 停止所有音乐,并释放内存 - static void end(); - - // 设置总音量,范围 [0 ~ 1.0] - static void setVolume( - float volume - ); - -protected: - // 暂停音效 - static void _pauseMusic( - size_t nSoundId - ); - - // 继续播放音效 - static void _resumeMusic( - size_t nSoundId - ); - - // 停止音效 - static void _stopMusic( - size_t nSoundId - ); }; } \ No newline at end of file