重做了EMusicUtils类,简易了使用方法

This commit is contained in:
Nomango 2017-12-08 15:37:52 +08:00
parent a9ddbf7384
commit c28b9653c5
33 changed files with 544 additions and 1173 deletions

View File

@ -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();
}

BIN
Demo/music.wav Normal file

Binary file not shown.

BIN
Demo/short.wav Normal file

Binary file not shown.

View File

@ -85,7 +85,7 @@ void e2d::EAction::_init()
m_tLast = GetNow();
}
void e2d::EAction::_callOn()
void e2d::EAction::_update()
{
if (!m_bInit)
{

View File

@ -15,7 +15,7 @@ void e2d::EActionCallback::_init()
// 执行回调函数的动作不需要初始化
}
void e2d::EActionCallback::_callOn()
void e2d::EActionCallback::_update()
{
m_Callback();
this->stop();

View File

@ -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)
{

View File

@ -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())
{

View File

@ -16,9 +16,9 @@ void e2d::EActionMoveBy::_init()
}
}
void e2d::EActionMoveBy::_callOn()
void e2d::EActionMoveBy::_update()
{
EAction::_callOn();
EAction::_update();
if (m_pTarget == nullptr)
{

View File

@ -16,9 +16,9 @@ void e2d::EActionOpacityBy::_init()
}
}
void e2d::EActionOpacityBy::_callOn()
void e2d::EActionOpacityBy::_update()
{
EAction::_callOn();
EAction::_update();
if (m_pTarget == nullptr)
{

View File

@ -16,9 +16,9 @@ void e2d::EActionRotateBy::_init()
}
}
void e2d::EActionRotateBy::_callOn()
void e2d::EActionRotateBy::_update()
{
EAction::_callOn();
EAction::_update();
if (m_pTarget == nullptr)
{

View File

@ -25,9 +25,9 @@ void e2d::EActionScaleBy::_init()
}
}
void e2d::EActionScaleBy::_callOn()
void e2d::EActionScaleBy::_update()
{
EAction::_callOn();
EAction::_update();
if (m_pTarget == nullptr)
{

View File

@ -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())
{

View File

@ -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
{

View File

@ -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();
}
// 两个动作都结束时,动作结束

View File

@ -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)
{

View File

@ -3,6 +3,7 @@
#include "..\emanagers.h"
#include "..\enodes.h"
#include "..\etransitions.h"
#include "..\etools.h"
#include <stack>
#include <thread>
#include <imm.h>
@ -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;
}
}

View File

@ -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());

View File

@ -250,6 +250,7 @@
<ClCompile Include="Transition\ETransitionMove.cpp" />
<ClCompile Include="Transition\ETransitionScale.cpp" />
<ClCompile Include="Transition\ETransitionScaleEmerge.cpp" />
<ClCompile Include="Win\MciPlayer.cpp" />
<ClCompile Include="Win\winbase.cpp" />
</ItemGroup>
<ItemGroup>
@ -265,6 +266,7 @@
<ClInclude Include="etools.h" />
<ClInclude Include="etransitions.h" />
<ClInclude Include="etypedef.h" />
<ClInclude Include="Win\MciPlayer.h" />
<ClInclude Include="Win\winbase.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -216,6 +216,9 @@
<ClCompile Include="Common\ESpriteFrame.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Win\MciPlayer.cpp">
<Filter>Win</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Win\winbase.h">
@ -233,5 +236,8 @@
<ClInclude Include="elisteners.h" />
<ClInclude Include="emanagers.h" />
<ClInclude Include="etypedef.h" />
<ClInclude Include="Win\MciPlayer.h">
<Filter>Win</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -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)
{

View File

@ -150,7 +150,7 @@ void e2d::EActionManager::ActionProc()
else
{
// 执行动作
action->_callOn();
action->_update();
}
}
}

View File

@ -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();
}
// 绘制所有子节点的几何形状

View File

@ -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())
{

View File

@ -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(

View File

@ -1,525 +0,0 @@
#include "..\etools.h"
#include "..\Win\winbase.h"
#include <map>
#include <mmsystem.h>
#include <Digitalv.h>
#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<DWORD_PTR>(&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<DWORD_PTR>(&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<DWORD_PTR>(&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<size_t, MciPlayer *> MusicList;
typedef std::pair<size_t, MciPlayer *> 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<e2d::EString> 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;
}

View File

@ -1,470 +1,134 @@
#include "..\etools.h"
#include "..\Win\winbase.h"
#include <map>
#include <mmsystem.h>
#include <Digitalv.h>
#pragma comment(lib , "winmm.lib")
#include "..\Win\MciPlayer.h"
#include <map>
static size_t Hash(const e2d::EString & key);
static bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName);
typedef std::pair<UINT, MciPlayer *> Music;
typedef std::map<UINT, MciPlayer *> 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<e2d::EString> 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<DWORD_PTR>(&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<DWORD_PTR>(&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<DWORD_PTR>(&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<size_t, MciPlayer *> MusicList;
typedef std::pair<size_t, MciPlayer *> 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<DWORD_PTR>(&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<DWORD_PTR>(&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<e2d::EString> 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;
}

269
Easy2D/Win/MciPlayer.cpp Normal file
View File

@ -0,0 +1,269 @@
#include "..\etools.h"
#include <mmsystem.h>
#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<DWORD_PTR>(&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<DWORD_PTR>(m_wnd);
// 播放声音
MCIERROR mciError = mciSendCommand(
m_dev,
MCI_PLAY,
MCI_FROM | MCI_NOTIFY,
reinterpret_cast<DWORD_PTR>(&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<DWORD_PTR>(m_wnd);
MCIERROR mciError = mciSendCommand(
m_dev,
MCI_PLAY,
MCI_NOTIFY,
reinterpret_cast<DWORD_PTR>(&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<DWORD_PTR>(hWnd);
mciSendCommand(lParam, MCI_PLAY, MCI_NOTIFY, reinterpret_cast<DWORD_PTR>(&mciPlay));
}
else
{
pPlayer->m_bPlaying = false;
return 0;
}
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}

29
Easy2D/Win/MciPlayer.h Normal file
View File

@ -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;
};

View File

@ -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;

View File

@ -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;

View File

@ -64,7 +64,7 @@ protected:
virtual void _transform();
// 斡횡섯부暠近
virtual void _onRender();
virtual void _render();
virtual ID2D1Geometry * _getD2dGeometry() const = 0;

View File

@ -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();

View File

@ -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();
// <20>零교쒼稜있稜좆렀鍋 [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
);
// <20>零景땍稜있돨稜좆렀鍋 [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();
// <20>零悧稜좆렀鍋 [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
);
};
}