修复了组合动画在某些情况下时间重置出错的BUG

This commit is contained in:
Nomango 2017-12-04 10:03:14 +08:00
parent 80d4880f19
commit 2fca388cb2
55 changed files with 603 additions and 6241 deletions

View File

@ -97,6 +97,10 @@ void e2d::EAction::_reset()
{
m_bInit = false;
m_bEnding = false;
// 记录当前时间
m_tLast = GetNow();
}
void e2d::EAction::_resetTime()
{
m_tLast = GetNow();
}

View File

@ -53,3 +53,8 @@ void e2d::EActionLoop::_reset()
m_pAction->_reset();
m_nTimes = 0;
}
void e2d::EActionLoop::_resetTime()
{
m_pAction->_resetTime();
}

View File

@ -73,6 +73,14 @@ void e2d::EActionSequence::_reset()
m_nActionIndex = 0;
}
void e2d::EActionSequence::_resetTime()
{
for (auto action : m_vActions)
{
action->_resetTime();
}
}
void e2d::EActionSequence::addAction(EAction * action)
{
if (action)

View File

@ -70,3 +70,9 @@ void e2d::EActionTwo::_reset()
m_pFirstAction->_reset();
m_pSecondAction->_reset();
}
void e2d::EActionTwo::_resetTime()
{
m_pFirstAction->_resetTime();
m_pSecondAction->_resetTime();
}

View File

@ -69,3 +69,9 @@ void e2d::EActionTwoAtSameTime::_reset()
m_pFirstAction->_reset();
m_pSecondAction->_reset();
}
void e2d::EActionTwoAtSameTime::_resetTime()
{
m_pFirstAction->_resetTime();
m_pSecondAction->_resetTime();
}

View File

@ -332,6 +332,11 @@ void e2d::EApp::_mainLoop()
void e2d::EApp::_onControl()
{
if (isPaused())
{
return;
}
// 正在切换场景时,执行场景切换动画
if (m_bTransitional)
{
@ -708,13 +713,13 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam
pEApp->m_bPaused = true;
}
}
else
else if (pEApp->m_bPaused)
{
if (pEApp->getCurrentScene() &&
pEApp->getCurrentScene()->onActivate() &&
pEApp->onActivate())
{
EApp::get()->m_bPaused = false;
pEApp->m_bPaused = false;
// 刷新当前时间
GetNow() = steady_clock::now();
// 重置动画和定时器

View File

@ -101,7 +101,7 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>None</DebugInformationFormat>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>

View File

@ -124,13 +124,13 @@ void e2d::EActionManager::_resetAllActions()
{
for (const auto & action : s_vActions)
{
action->m_tLast = GetNow();
action->_resetTime();
}
}
void e2d::EActionManager::ActionProc()
{
if (EApp::isPaused() || s_vActions.empty())
if (s_vActions.empty())
return;
// 循环遍历所有正在运行的动作

View File

@ -8,7 +8,7 @@ static e2d::EVector<e2d::ETimer*> s_vTimers;
void e2d::ETimerManager::TimerProc()
{
if (s_vTimers.empty() || EApp::isPaused())
if (s_vTimers.empty())
return;
for (size_t i = 0; i < s_vTimers.size(); i++)

View File

@ -1,6 +1,5 @@
#include "..\etools.h"
#include "..\Win\winbase.h"
#include <sstream>
#include <algorithm>
#include <commdlg.h>

View File

@ -0,0 +1,525 @@
#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

@ -370,14 +370,31 @@ void e2d::EMusicUtils::setBackgroundMusicVolume(float volume)
void e2d::EMusicUtils::playMusic(const EString & musicFilePath, bool bLoop)
{
size_t nRet = ::Hash(musicFilePath);
MCI_OPEN_PARMS mciOpen = { 0 };
mciOpen.lpstrElementName = musicFilePath.c_str();
preloadMusic(musicFilePath);
// 打开这个文件
MCIERROR mciError;
mciError = mciSendCommand(
0,
MCI_OPEN,
MCI_OPEN_ELEMENT | MCI_NOTIFY,
reinterpret_cast<DWORD_PTR>(&mciOpen)
);
MusicList::iterator p = getMciPlayerList().find(nRet);
if (p != getMciPlayerList().end())
if (!mciError)
{
p->second->play(bLoop);
// 设置播放参数
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)
);
}
}

View File

@ -73,6 +73,9 @@ protected:
// 重置动作
virtual void _reset();
// 重置动画时间
virtual void _resetTime();
protected:
bool m_bRunning;
bool m_bEnding;
@ -410,6 +413,9 @@ protected:
// 重置动作
virtual void _reset() override;
// 重置动画时间
virtual void _resetTime() override;
protected:
EAction * m_pFirstAction;
EAction * m_pSecondAction;
@ -455,6 +461,9 @@ protected:
// 重置动作
virtual void _reset() override;
// 重置动画时间
virtual void _resetTime() override;
protected:
UINT m_nActionIndex;
std::vector<EAction*> m_vActions;
@ -515,6 +524,9 @@ protected:
// 重置动作
virtual void _reset() override;
// 重置动画时间
virtual void _resetTime() override;
protected:
EAction * m_pFirstAction;
EAction * m_pSecondAction;
@ -546,6 +558,9 @@ protected:
// 重置动作
virtual void _reset() override;
// 重置动画时间
virtual void _resetTime() override;
protected:
EAction * m_pAction;
int m_nTimes;

View File

@ -1,85 +0,0 @@
#include "..\easy2d.h"
#include <assert.h>
Action::Action() :
m_bRunning(true),
m_bWaiting(false),
m_bEnding(false),
m_bInit(false),
m_pTargetSprite(nullptr),
m_pParentScene(nullptr)
{
// 默认动作 15ms 运行一次
setInterval(15);
}
Action::~Action()
{
}
bool Action::isRunning()
{
return m_bRunning && !m_bWaiting;
}
bool Action::isEnding()
{
return m_bEnding;
}
void Action::start()
{
m_bRunning = true;
}
void Action::resume()
{
m_bRunning = true;
}
void Action::pause()
{
m_bRunning = false;
}
void Action::stop()
{
m_bEnding = true;
}
void Action::wait()
{
m_bWaiting = true;
}
void Action::notify()
{
m_bWaiting = false;
}
void Action::setInterval(LONGLONG milliSeconds)
{
// 设置动作的时间间隔
m_nAnimationInterval = milliSeconds;
}
Action * Action::reverse() const
{
assert(0);
return nullptr;
}
Sprite * Action::getTarget()
{
return m_pTargetSprite;
}
void Action::_init()
{
m_bInit = true;
}
void Action::_reset()
{
m_bInit = false;
m_bEnding = false;
}

View File

@ -1,31 +0,0 @@
#include "..\easy2d.h"
ActionCallback::ActionCallback(const std::function<void()>& callback) :
m_Callback(callback)
{
}
ActionCallback::~ActionCallback()
{
}
ActionCallback * ActionCallback::copy() const
{
return new ActionCallback(m_Callback);
}
void ActionCallback::_init()
{
Action::_init();
}
void ActionCallback::_exec(std::chrono::steady_clock::time_point nNow)
{
m_Callback();
this->stop();
}
void ActionCallback::_reset()
{
Action::_reset();
}

View File

@ -1,39 +0,0 @@
#include "..\easy2d.h"
#include "..\Win\winbase.h"
ActionDelay::ActionDelay(float duration)
{
setInterval(LONGLONG(duration * 1000));
}
ActionDelay::~ActionDelay()
{
}
ActionDelay * ActionDelay::copy() const
{
return new ActionDelay(m_nAnimationInterval / 1000.0f);
}
void ActionDelay::_init()
{
Action::_init();
// 记录当前时间
m_nLast = steady_clock::now();
}
void ActionDelay::_exec(steady_clock::time_point nNow)
{
// 判断时间间隔是否足够
if (duration_cast<milliseconds>(nNow - m_nLast).count() > m_nAnimationInterval)
{
this->stop();
}
}
void ActionDelay::_reset()
{
Action::_reset();
// 记录当前时间
m_nLast = steady_clock::now();
}

View File

@ -1,83 +0,0 @@
#include "..\easy2d.h"
#include "..\Win\winbase.h"
ActionFrames::ActionFrames() :
m_nFrameIndex(0)
{
// 帧动画默认 .5s 刷新一次
setInterval(500);
}
ActionFrames::ActionFrames(LONGLONG frameDelay) :
m_nFrameIndex(0)
{
setInterval(frameDelay);
}
ActionFrames::~ActionFrames()
{
for (auto frame : m_vFrames)
{
frame->autoRelease();
frame->release();
}
}
void ActionFrames::_init()
{
Action::_init();
// 记录当前时间
m_nLast = steady_clock::now();
}
void ActionFrames::_exec(steady_clock::time_point nNow)
{
// 判断时间间隔是否足够
while (duration_cast<milliseconds>(nNow - m_nLast).count() > m_nAnimationInterval)
{
// 重新记录时间
m_nLast += milliseconds(m_nAnimationInterval);
m_pTargetSprite->setImage(m_vFrames[m_nFrameIndex]);
m_nFrameIndex++;
// 判断动作是否结束
if (m_nFrameIndex == m_vFrames.size())
{
this->stop();
break;
}
}
}
void ActionFrames::_reset()
{
Action::_reset();
m_nFrameIndex = 0;
// 记录当前时间
m_nLast = steady_clock::now();
}
void ActionFrames::addFrame(Image * frame)
{
if (frame)
{
m_vFrames.push_back(frame);
frame->retain();
}
}
ActionFrames * ActionFrames::copy() const
{
auto a = new ActionFrames(this->m_nAnimationInterval);
for (auto f : m_vFrames)
{
a->addFrame(f);
}
return a;
}
ActionFrames * ActionFrames::reverse() const
{
auto a = this->copy();
a->m_vFrames.reserve(m_vFrames.size());
return a;
}

View File

@ -1,51 +0,0 @@
#include "..\easy2d.h"
#include "..\Win\winbase.h"
ActionMoveBy::ActionMoveBy(float duration, CVector vec) :
Animation(duration)
{
m_MoveVector = vec;
}
ActionMoveBy::~ActionMoveBy()
{
}
void ActionMoveBy::_init()
{
Animation::_init();
m_BeginPos = m_pTargetSprite->getPos();
}
void ActionMoveBy::_exec(steady_clock::time_point nNow)
{
while (Animation::_isDelayEnough(nNow))
{
// 计算移动位置
float scale = float(m_nDuration) / m_nTotalDuration;
// 移动 Sprite
m_pTargetSprite->setPos(int(m_BeginPos.x + m_MoveVector.x * scale),
int(m_BeginPos.y + m_MoveVector.y * scale));
// 判断动作是否结束
if (_isEnd())
{
this->stop();
break;
}
}
}
void ActionMoveBy::_reset()
{
Animation::_reset();
}
ActionMoveBy * ActionMoveBy::copy() const
{
return new ActionMoveBy(m_nAnimationInterval / 1000.0f, m_MoveVector);
}
ActionMoveBy * ActionMoveBy::reverse() const
{
return new ActionMoveBy(m_nTotalDuration / 1000.0f, CVector(-m_MoveVector.x, -m_MoveVector.y));
}

View File

@ -1,27 +0,0 @@
#include "..\easy2d.h"
ActionMoveTo::ActionMoveTo(float duration, CPoint pos) :
ActionMoveBy(duration, CVector())
{
m_EndPos = pos;
}
ActionMoveTo::~ActionMoveTo()
{
}
ActionMoveTo * ActionMoveTo::copy() const
{
return new ActionMoveTo(m_nAnimationInterval / 1000.0f, m_EndPos);
}
void ActionMoveTo::_init()
{
ActionMoveBy::_init();
m_MoveVector = m_EndPos - m_BeginPos;
}
void ActionMoveTo::_reset()
{
ActionMoveBy::_reset();
}

View File

@ -1,39 +0,0 @@
#include "..\easy2d.h"
ActionNeverStop::ActionNeverStop(Action * action) :
m_Action(action)
{
m_Action->retain();
}
ActionNeverStop::~ActionNeverStop()
{
SafeRelease(m_Action);
}
ActionNeverStop * ActionNeverStop::copy() const
{
return new ActionNeverStop(m_Action->copy());
}
void ActionNeverStop::_init()
{
Action::_init();
m_Action->m_pTargetSprite = m_pTargetSprite;
m_Action->_init();
}
void ActionNeverStop::_exec(std::chrono::steady_clock::time_point nNow)
{
m_Action->_exec(nNow);
if (m_Action->isEnding())
{
m_Action->_reset();
}
}
void ActionNeverStop::_reset()
{
Action::_reset();
}

View File

@ -1,50 +0,0 @@
#include "..\easy2d.h"
#include "..\Win\winbase.h"
ActionOpacityBy::ActionOpacityBy(float duration, float opacity) :
Animation(duration)
{
m_nVariation = opacity;
}
ActionOpacityBy::~ActionOpacityBy()
{
}
void ActionOpacityBy::_init()
{
Animation::_init();
m_nBeginVal = m_pTargetSprite->getOpacity();
}
void ActionOpacityBy::_exec(steady_clock::time_point nNow)
{
while (Animation::_isDelayEnough(nNow))
{
// 计算移动位置
float scale = float(m_nDuration) / m_nTotalDuration;
// 移动 Sprite
m_pTargetSprite->setOpacity(m_nBeginVal + m_nVariation * scale);
// 判断动作是否结束
if (_isEnd())
{
this->stop();
break;
}
}
}
void ActionOpacityBy::_reset()
{
Animation::_reset();
}
ActionOpacityBy * ActionOpacityBy::copy() const
{
return new ActionOpacityBy(m_nAnimationInterval / 1000.0f, m_nVariation);
}
ActionOpacityBy * ActionOpacityBy::reverse() const
{
return new ActionOpacityBy(m_nTotalDuration / 1000.0f, -m_nVariation);
}

View File

@ -1,27 +0,0 @@
#include "..\easy2d.h"
ActionOpacityTo::ActionOpacityTo(float duration, float opacity) :
ActionOpacityBy(duration, 0)
{
m_nEndVal = opacity;
}
ActionOpacityTo::~ActionOpacityTo()
{
}
ActionOpacityTo * ActionOpacityTo::copy() const
{
return new ActionOpacityTo(m_nAnimationInterval / 1000.0f, m_nEndVal);
}
void ActionOpacityTo::_init()
{
ActionOpacityBy::_init();
m_nVariation = m_nEndVal - m_nBeginVal;
}
void ActionOpacityTo::_reset()
{
ActionOpacityBy::_reset();
}

View File

@ -1,52 +0,0 @@
#include "..\easy2d.h"
#include "..\Win\winbase.h"
ActionScaleBy::ActionScaleBy(float duration, float scaleX, float scaleY) :
Animation(duration)
{
m_nVariationX = scaleX;
m_nVariationY = scaleY;
}
ActionScaleBy::~ActionScaleBy()
{
}
void ActionScaleBy::_init()
{
Animation::_init();
m_nBeginScaleX = m_pTargetSprite->getScaleX();
m_nBeginScaleY = m_pTargetSprite->getScaleY();
}
void ActionScaleBy::_exec(steady_clock::time_point nNow)
{
while (Animation::_isDelayEnough(nNow))
{
// 计算移动位置
float scale = float(m_nDuration) / m_nTotalDuration;
// 移动 Sprite
m_pTargetSprite->setScale(m_nBeginScaleX + m_nVariationX * scale, m_nBeginScaleX + m_nVariationX * scale);
// 判断动作是否结束
if (_isEnd())
{
this->stop();
break;
}
}
}
void ActionScaleBy::_reset()
{
Animation::_reset();
}
ActionScaleBy * ActionScaleBy::copy() const
{
return new ActionScaleBy(m_nAnimationInterval / 1000.0f, m_nVariationX, m_nVariationY);
}
ActionScaleBy * ActionScaleBy::reverse() const
{
return new ActionScaleBy(m_nTotalDuration / 1000.0f, -m_nVariationX, -m_nVariationY);
}

View File

@ -1,29 +0,0 @@
#include "..\easy2d.h"
ActionScaleTo::ActionScaleTo(float duration, float scaleX, float scaleY) :
ActionScaleBy(duration, 0, 0)
{
m_nEndScaleX = scaleX;
m_nEndScaleY = scaleY;
}
ActionScaleTo::~ActionScaleTo()
{
}
ActionScaleTo * ActionScaleTo::copy() const
{
return new ActionScaleTo(m_nAnimationInterval / 1000.0f, m_nEndScaleX, m_nEndScaleY);
}
void ActionScaleTo::_init()
{
ActionScaleBy::_init();
m_nVariationX = m_nEndScaleX - m_nBeginScaleX;
m_nVariationY = m_nEndScaleY - m_nBeginScaleY;
}
void ActionScaleTo::_reset()
{
ActionScaleBy::_reset();
}

View File

@ -1,105 +0,0 @@
#include "..\easy2d.h"
#include <stdarg.h>
ActionSequence::ActionSequence() :
m_nActionIndex(0)
{
}
ActionSequence::ActionSequence(int number, Action * action1, ...) :
m_nActionIndex(0)
{
va_list params;
va_start(params, number);
while (number > 0)
{
this->addAction(va_arg(params, Action*));
number--;
}
va_end(params);
}
ActionSequence::~ActionSequence()
{
for (auto action : m_vActions)
{
SafeRelease(action);
}
}
void ActionSequence::_init()
{
Action::_init();
// 将所有动作与目标绑定
for (auto action : m_vActions)
{
action->m_pTargetSprite = m_pTargetSprite;
}
// 初始化第一个动作
m_vActions[0]->_init();
}
void ActionSequence::_exec(std::chrono::steady_clock::time_point nNow)
{
m_vActions[m_nActionIndex]->_exec(nNow);
if (m_vActions[m_nActionIndex]->isEnding())
{
m_nActionIndex++;
if (m_nActionIndex == m_vActions.size())
{
this->stop();
}
else
{
m_vActions[m_nActionIndex]->_init();
}
}
}
void ActionSequence::_reset()
{
Action::_reset();
for (auto action : m_vActions)
{
action->_reset();
}
m_nActionIndex = 0;
}
void ActionSequence::addAction(Action * action)
{
m_vActions.push_back(action);
action->retain();
}
ActionSequence * ActionSequence::copy() const
{
auto a = new ActionSequence();
for (auto action : m_vActions)
{
a->addAction(action->copy());
}
return a;
}
ActionSequence * ActionSequence::reverse(bool actionReverse) const
{
auto a = new ActionSequence();
for (auto action : a->m_vActions)
{
if (actionReverse)
{
a->addAction(action->reverse());
}
else
{
a->addAction(action->copy());
}
}
// 将动作顺序逆序排列
a->m_vActions.reserve(m_vActions.size());
return a;
}

View File

@ -1,70 +0,0 @@
#include "..\easy2d.h"
ActionTwo::ActionTwo(Action * actionFirst, Action * actionSecond) :
m_FirstAction(actionFirst),
m_SecondAction(actionSecond)
{
m_FirstAction->retain();
m_SecondAction->retain();
}
ActionTwo::~ActionTwo()
{
SafeRelease(m_FirstAction);
SafeRelease(m_SecondAction);
}
ActionTwo * ActionTwo::copy() const
{
return new ActionTwo(m_FirstAction->copy(), m_SecondAction->copy());
}
ActionTwo * ActionTwo::reverse(bool actionReverse) const
{
if (actionReverse)
{
return new ActionTwo(m_SecondAction->reverse(), m_FirstAction->reverse());
}
else
{
return new ActionTwo(m_SecondAction->copy(), m_FirstAction->copy());
}
}
void ActionTwo::_init()
{
Action::_init();
m_FirstAction->m_pTargetSprite = m_pTargetSprite;
m_SecondAction->m_pTargetSprite = m_pTargetSprite;
m_FirstAction->_init();
}
void ActionTwo::_exec(std::chrono::steady_clock::time_point nNow)
{
if (!m_FirstAction->isEnding())
{
m_FirstAction->_exec(nNow);
if (m_FirstAction->isEnding())
{
// 返回 true 表示第一个动作已经结束
m_SecondAction->_init();
}
}
else if (!m_SecondAction->isEnding())
{
m_SecondAction->_exec(nNow);
}
else
{
this->stop();
}
}
void ActionTwo::_reset()
{
Action::_reset();
m_FirstAction->_reset();
m_SecondAction->_reset();
}

View File

@ -1,45 +0,0 @@
#include "..\easy2d.h"
#include "..\Win\winbase.h"
Animation::Animation(float duration)
{
m_nDuration = 0;
m_nTotalDuration = UINT(duration * 1000);
}
Animation::~Animation()
{
}
bool Animation::_isEnd() const
{
return m_nDuration >= m_nTotalDuration;
}
void Animation::_init()
{
Action::_init();
// 记录当前时间
m_nLast = steady_clock::now();
}
bool Animation::_isDelayEnough(steady_clock::time_point nNow)
{
// 判断时间间隔是否足够
if (duration_cast<milliseconds>(nNow - m_nLast).count() > m_nAnimationInterval)
{
// 重新记录时间
m_nLast += milliseconds(m_nAnimationInterval);
m_nDuration += m_nAnimationInterval;
return true;
}
return false;
}
void Animation::_reset()
{
Action::_reset();
m_nDuration = 0;
// 记录当前时间
m_nLast = steady_clock::now();
}

View File

@ -1,314 +0,0 @@
#include "..\easy2d.h"
#include "..\EasyX\easyx.h"
#include <conio.h>
// 按键监听回调函数的容器
static std::vector<KeyMsg*> s_vListeners;
// 虚拟键值的定义
const VK_KEY KeyMsg::A = 'A';
const VK_KEY KeyMsg::B = 'B';
const VK_KEY KeyMsg::C = 'C';
const VK_KEY KeyMsg::D = 'D';
const VK_KEY KeyMsg::E = 'E';
const VK_KEY KeyMsg::F = 'F';
const VK_KEY KeyMsg::G = 'G';
const VK_KEY KeyMsg::H = 'H';
const VK_KEY KeyMsg::I = 'I';
const VK_KEY KeyMsg::J = 'J';
const VK_KEY KeyMsg::K = 'K';
const VK_KEY KeyMsg::L = 'L';
const VK_KEY KeyMsg::M = 'M';
const VK_KEY KeyMsg::N = 'N';
const VK_KEY KeyMsg::O = 'O';
const VK_KEY KeyMsg::P = 'P';
const VK_KEY KeyMsg::Q = 'Q';
const VK_KEY KeyMsg::R = 'R';
const VK_KEY KeyMsg::S = 'S';
const VK_KEY KeyMsg::T = 'T';
const VK_KEY KeyMsg::U = 'U';
const VK_KEY KeyMsg::V = 'V';
const VK_KEY KeyMsg::W = 'W';
const VK_KEY KeyMsg::X = 'X';
const VK_KEY KeyMsg::Y = 'Y';
const VK_KEY KeyMsg::Z = 'Z';
const VK_KEY KeyMsg::NUM_0 = '0';
const VK_KEY KeyMsg::NUM_1 = '1';
const VK_KEY KeyMsg::NUM_2 = '2';
const VK_KEY KeyMsg::NUM_3 = '3';
const VK_KEY KeyMsg::NUM_4 = '4';
const VK_KEY KeyMsg::NUM_5 = '5';
const VK_KEY KeyMsg::NUM_6 = '6';
const VK_KEY KeyMsg::NUM_7 = '7';
const VK_KEY KeyMsg::NUM_8 = '8';
const VK_KEY KeyMsg::NUM_9 = '9';
const VK_KEY KeyMsg::NUMPAD_0 = VK_NUMPAD0;
const VK_KEY KeyMsg::NUMPAD_1 = VK_NUMPAD1;
const VK_KEY KeyMsg::NUMPAD_2 = VK_NUMPAD2;
const VK_KEY KeyMsg::NUMPAD_3 = VK_NUMPAD3;
const VK_KEY KeyMsg::NUMPAD_4 = VK_NUMPAD4;
const VK_KEY KeyMsg::NUMPAD_5 = VK_NUMPAD5;
const VK_KEY KeyMsg::NUMPAD_6 = VK_NUMPAD6;
const VK_KEY KeyMsg::NUMPAD_7 = VK_NUMPAD7;
const VK_KEY KeyMsg::NUMPAD_8 = VK_NUMPAD8;
const VK_KEY KeyMsg::NUMPAD_9 = VK_NUMPAD9;
const VK_KEY KeyMsg::Enter = VK_RETURN;
const VK_KEY KeyMsg::Space = VK_SPACE;
const VK_KEY KeyMsg::Ctrl = VK_CONTROL;
const VK_KEY KeyMsg::LCtrl = VK_LCONTROL;
const VK_KEY KeyMsg::RCtrl = VK_RCONTROL;
const VK_KEY KeyMsg::Shift = VK_SHIFT;
const VK_KEY KeyMsg::LShift = VK_LSHIFT;
const VK_KEY KeyMsg::RShift = VK_RSHIFT;
const VK_KEY KeyMsg::Up = VK_UP;
const VK_KEY KeyMsg::Down = VK_DOWN;
const VK_KEY KeyMsg::Left = VK_LEFT;
const VK_KEY KeyMsg::Right = VK_RIGHT;
const VK_KEY KeyMsg::Esc = VK_ESCAPE;
const VK_KEY KeyMsg::F1 = VK_F1;
const VK_KEY KeyMsg::F2 = VK_F2;
const VK_KEY KeyMsg::F3 = VK_F3;
const VK_KEY KeyMsg::F4 = VK_F4;
const VK_KEY KeyMsg::F5 = VK_F5;
const VK_KEY KeyMsg::F6 = VK_F6;
const VK_KEY KeyMsg::F7 = VK_F7;
const VK_KEY KeyMsg::F8 = VK_F8;
const VK_KEY KeyMsg::F9 = VK_F9;
const VK_KEY KeyMsg::F10 = VK_F10;
const VK_KEY KeyMsg::F11 = VK_F11;
const VK_KEY KeyMsg::F12 = VK_F12;
static VK_KEY convert(int ascii);
KeyMsg::KeyMsg(TString name, const KEY_CALLBACK & callback) :
m_sName(name),
m_callback(callback),
m_pParentScene(nullptr),
m_bRunning(true),
m_bWaiting(false)
{
}
KeyMsg::~KeyMsg()
{
}
void KeyMsg::onKbHit(VK_KEY key)
{
m_callback(key);
}
void KeyMsg::start()
{
m_bRunning = true;
}
void KeyMsg::stop()
{
m_bRunning = false;
}
void KeyMsg::wait()
{
m_bWaiting = true;
}
void KeyMsg::notify()
{
m_bWaiting = false;
}
void KeyMsg::__exec()
{
if (_kbhit()) // 检测有无按键消息
{
VK_KEY key = convert(_getch()); // 获取键盘消息
for (auto l : s_vListeners) // 分发该消息
{
if (!l->m_bWaiting && l->m_bRunning)
{
l->onKbHit(key); // 执行按键回调函数
}
}
}
}
void KeyMsg::addListener(TString name, const KEY_CALLBACK & callback)
{
// 创建新的监听对象
auto listener = new KeyMsg(name, callback);
// 绑定在场景上
listener->m_pParentScene = EApp::getLoadingScene();
// 添加新的按键回调函数
s_vListeners.push_back(listener);
}
void KeyMsg::startListener(TString name)
{
// 查找名称相同的监听器
for (auto l : s_vListeners)
{
if (l->m_sName == name && l->m_pParentScene == EApp::getCurrentScene())
{
l->start();
}
}
}
void KeyMsg::stopListener(TString name)
{
// 查找名称相同的监听器
for (auto l : s_vListeners)
{
if (l->m_sName == name && l->m_pParentScene == EApp::getCurrentScene())
{
l->stop();
}
}
}
void KeyMsg::delListener(TString name)
{
// 创建迭代器
std::vector<KeyMsg*>::iterator iter;
// 循环遍历所有监听器
for (iter = s_vListeners.begin(); iter != s_vListeners.end();)
{
// 查找相同名称的监听器
if ((*iter)->m_sName == name && (*iter)->m_pParentScene == EApp::getCurrentScene())
{
// 删除该定时器
delete (*iter);
iter = s_vListeners.erase(iter);
}
else
{
iter++;
}
}
}
void KeyMsg::notifyAllSceneListeners(EScene * scene)
{
for (auto l : s_vListeners)
{
if (l->m_pParentScene == scene)
{
l->notify();
}
}
}
void KeyMsg::waitAllSceneListeners(EScene * scene)
{
for (auto l : s_vListeners)
{
if (l->m_pParentScene == scene)
{
l->wait();
}
}
}
void KeyMsg::clearAllSceneListeners(EScene * scene)
{
// 创建迭代器
std::vector<KeyMsg*>::iterator iter;
// 循环遍历所有监听器
for (iter = s_vListeners.begin(); iter != s_vListeners.end();)
{
// 查找相同名称的监听器
if ((*iter)->m_pParentScene == scene)
{
// 删除该定时器
delete (*iter);
iter = s_vListeners.erase(iter);
}
else
{
iter++;
}
}
}
void KeyMsg::clearAllListeners()
{
// 删除所有监听器
for (auto l : s_vListeners)
{
delete l;
}
// 清空容器
s_vListeners.clear();
}
bool KeyMsg::isKeyDown(VK_KEY key)
{
// 获取 key 的按下情况
return (GetAsyncKeyState(key) & 0x8000);
}
VK_KEY convert(int ascii)
{
// 字母键
if (ascii >= 'a' && ascii <= 'z')
{
return VK_KEY(ascii - ('a' - 'A'));
}
else if (ascii >= 'A' && ascii <= 'Z')
{
return VK_KEY(ascii);
}
// 数字键
else if (ascii >= '0' && ascii <= '9')
{
return VK_KEY(ascii);
}
// 回车、空格、Esc键
else if (ascii == 0x0D || ascii == 0x20 || ascii == 0x1B)
{
return VK_KEY(ascii);
}
// 功能键
else if (ascii == 0 || ascii == 0xE0)
{
switch (_getch())
{
case 72:
return KeyMsg::Up;
case 75:
return KeyMsg::Left;
case 77:
return KeyMsg::Right;
case 80:
return KeyMsg::Down;
case 59:
return KeyMsg::F1;
case 60:
return KeyMsg::F2;
case 61:
return KeyMsg::F3;
case 62:
return KeyMsg::F4;
case 63:
return KeyMsg::F5;
case 64:
return KeyMsg::F6;
case 65:
return KeyMsg::F7;
case 66:
return KeyMsg::F8;
case 67:
return KeyMsg::F9;
case 133:
return KeyMsg::F10;
case 134:
return KeyMsg::F11;
default:
return 0;
}
}
return 0;
}

View File

@ -1,223 +0,0 @@
#include "..\easy2d.h"
#include "..\EasyX\easyx.h"
// 鼠标监听回调函数的容器
static std::vector<MouseMsg*> s_vListeners;
// 鼠标消息
static MOUSEMSG s_mouseMsg;
void MouseMsg::__exec()
{
// 获取鼠标消息
while (MouseHit())
{
// 获取鼠标消息
s_mouseMsg = GetMouseMsg();
// 执行场景程序
EApp::get()->getCurrentScene()->_exec();
// 执行鼠标监听回调函数
for (auto l : s_vListeners) // 循环遍历所有的鼠标监听
{
if (!l->m_bWaiting && l->m_bRunning)
{
l->onMouseMsg(); // 执行回调函数
}
}
}
}
MouseMsg::MouseMsg() :
m_callback([]() {}),
m_pParentScene(nullptr),
m_bRunning(true),
m_bWaiting(false)
{
}
MouseMsg::MouseMsg(TString name, const MOUSE_CALLBACK & callback) :
m_sName(name),
m_callback(callback),
m_pParentScene(nullptr),
m_bRunning(true),
m_bWaiting(false)
{
}
MouseMsg::~MouseMsg()
{
}
void MouseMsg::onMouseMsg()
{
m_callback();
}
void MouseMsg::addListener(TString name, const MOUSE_CALLBACK & callback)
{
// 创建新的监听对象
auto listener = new MouseMsg(name, callback);
// 绑定在场景上
listener->m_pParentScene = EApp::getLoadingScene();
// 添加新的按键回调函数
s_vListeners.push_back(listener);
}
void MouseMsg::startListener(TString name)
{
// 查找名称相同的监听器
for (auto l : s_vListeners)
{
if (l->m_sName == name && l->m_pParentScene == EApp::getCurrentScene())
{
l->start();
}
}
}
void MouseMsg::stopListener(TString name)
{
// 查找名称相同的监听器
for (auto l : s_vListeners)
{
if (l->m_sName == name && l->m_pParentScene == EApp::getCurrentScene())
{
l->stop();
}
}
}
void MouseMsg::delListener(TString name)
{
// 创建迭代器
std::vector<MouseMsg*>::iterator iter;
// 循环遍历所有监听器
for (iter = s_vListeners.begin(); iter != s_vListeners.end();)
{
// 查找相同名称的监听器
if ((*iter)->m_sName == name && (*iter)->m_pParentScene == EApp::getCurrentScene())
{
// 删除该定时器
delete (*iter);
iter = s_vListeners.erase(iter);
}
else
{
iter++;
}
}
}
void MouseMsg::start()
{
m_bRunning = true;
}
void MouseMsg::stop()
{
m_bRunning = false;
}
void MouseMsg::wait()
{
m_bWaiting = true;
}
void MouseMsg::notify()
{
m_bWaiting = false;
}
void MouseMsg::clearAllListeners()
{
// 删除所有监听器
for (auto l : s_vListeners)
{
delete l;
}
// 清空容器
s_vListeners.clear();
}
void MouseMsg::notifyAllSceneListeners(EScene * scene)
{
for (auto l : s_vListeners)
{
if (l->m_pParentScene == scene)
{
l->notify();
}
}
}
void MouseMsg::waitAllSceneListeners(EScene * scene)
{
for (auto l : s_vListeners)
{
if (l->m_pParentScene == scene)
{
l->wait();
}
}
}
void MouseMsg::clearAllSceneListeners(EScene * scene)
{
// 创建迭代器
std::vector<MouseMsg*>::iterator iter;
// 循环遍历所有监听器
for (iter = s_vListeners.begin(); iter != s_vListeners.end();)
{
// 查找相同名称的监听器
if ((*iter)->m_pParentScene == scene)
{
// 删除该定时器
delete (*iter);
iter = s_vListeners.erase(iter);
}
else
{
iter++;
}
}
}
bool MouseMsg::isLButtonDown()
{
return s_mouseMsg.mkLButton;
}
bool MouseMsg::isRButtonDown()
{
return s_mouseMsg.mkRButton;
}
bool MouseMsg::isMButtonDown()
{
return s_mouseMsg.mkMButton;
}
int MouseMsg::getX()
{
return s_mouseMsg.x;
}
int MouseMsg::getY()
{
return s_mouseMsg.y;
}
CPoint MouseMsg::getPos()
{
return CPoint(s_mouseMsg.x, s_mouseMsg.y);
}
int MouseMsg::getWheel()
{
return s_mouseMsg.wheel;
}
MouseMsg::MESSAGE MouseMsg::getMsg()
{
return MESSAGE(s_mouseMsg.uMsg);
}

View File

@ -1,190 +0,0 @@
#include "..\easy2d.h"
#include "..\EasyX\easyx.h"
BatchNode::BatchNode()
{
}
BatchNode::~BatchNode()
{
clearAllChildren();
}
bool BatchNode::_exec(bool active)
{
// 批量节点是否显示
if (!m_bDisplay)
{
return false;
}
// 逆序遍历所有子节点
for (int i = int(m_vChildren.size() - 1); i >= 0; i--)
{
if (m_vChildren[i]->_exec(active))
{
active = false;
}
}
// 若子节点取得了画面焦点,则该节点也取得了焦点
return !active;
}
void BatchNode::_onDraw()
{
// 节点是否显示
if (!m_bDisplay)
{
return;
}
for (auto child : m_vChildren)
{
// 绘制子节点
child->_onDraw();
}
}
void BatchNode::add(Node * child, int z_Order)
{
if (child == nullptr) return;
// 设置节点的父场景
child->setParentScene(this->getParentScene());
// 设置节点在批量节点中的 z 轴顺序
child->setZOrder(z_Order);
// 对象的引用计数加一
child->retain();
// 修改子节点位置
child->move(getPos());
// 按 z 轴顺序插入节点
size_t size = m_vChildren.size();
for (unsigned i = 0; i <= size; i++)
{
if (i != size)
{
if (z_Order < m_vChildren.at(i)->getZOrder())
{
m_vChildren.insert(m_vChildren.begin() + i, child);
break;
}
}
else
{
m_vChildren.push_back(child);
break;
}
}
}
bool BatchNode::del(Node * child)
{
if (child == nullptr) return false;
// 寻找是否有相同节点
std::vector<Node*>::iterator iter;
for (iter = m_vChildren.begin(); iter != m_vChildren.end(); iter++)
{
// 找到相同节点
if ((*iter) == child)
{
// 对象的引用计数减一
(*iter)->release();
// 去掉该节点
m_vChildren.erase(iter);
return true;
}
}
return false;
}
int BatchNode::getCount()
{
return (int)m_vChildren.size();
}
std::vector<Node*>& BatchNode::getChildren()
{
return m_vChildren;
}
void BatchNode::clearAllChildren()
{
// 所有节点的引用计数减一
for (auto child : m_vChildren)
{
child->autoRelease();
child->release();
}
// 清空储存节点的容器
m_vChildren.clear();
}
void BatchNode::setX(int x)
{
// 计算相对移动位置
int var = x - getX();
// 移动所有子节点的位置
for (auto child : m_vChildren)
{
child->move(var, 0);
}
Node::setX(x);
}
void BatchNode::setY(int y)
{
// 计算相对移动位置
int var = y - getY();
// 移动所有子节点的位置
for (auto child : m_vChildren)
{
child->move(0, var);
}
Node::setY(y);
}
void BatchNode::setPos(int x, int y)
{
// 计算相对移动位置
CPoint var(x - getX(), y - getY());
// 移动所有子节点的位置
for (auto child : m_vChildren)
{
child->move(var);
}
Node::setPos(x, y);
}
void BatchNode::setPos(CPoint p)
{
// 计算相对移动位置
CPoint var(p - getPos());
// 移动所有子节点的位置
for (auto child : m_vChildren)
{
child->move(var);
}
Node::setPos(p);
}
void BatchNode::move(int x, int y)
{
// 移动所有子节点的位置
for (auto child : m_vChildren)
{
child->move(x, y);
}
Node::move(x, y);
}
void BatchNode::move(CVector v)
{
// 移动所有子节点的位置
for (auto child : m_vChildren)
{
child->move(v);
}
Node::move(v);
}

View File

@ -1,260 +0,0 @@
#include "..\easy2d.h"
BatchSprite::BatchSprite()
{
}
BatchSprite::~BatchSprite()
{
}
void BatchSprite::addSprite(Sprite * sprite, int z_Order)
{
if (sprite == nullptr) return;
// 设置节点的父场景
sprite->setParentScene(this->getParentScene());
// 设置节点在批量节点中的 z 轴顺序
sprite->setZOrder(z_Order);
// 对象的引用计数加一
sprite->retain();
// 按 z 轴顺序插入节点
size_t size = m_vSprites.size();
for (unsigned i = 0; i <= size; i++)
{
if (i != size)
{
if (z_Order < m_vSprites.at(i)->getZOrder())
{
m_vSprites.insert(m_vSprites.begin() + i, sprite);
break;
}
}
else
{
m_vSprites.push_back(sprite);
break;
}
}
}
bool BatchSprite::delSprite(Sprite * sprite)
{
if (sprite == nullptr) return false;
// 寻找是否有相同节点
std::vector<Sprite*>::iterator iter;
for (iter = m_vSprites.begin(); iter != m_vSprites.end(); iter++)
{
// 找到相同节点
if ((*iter) == sprite)
{
// 对象的引用计数减一
(*iter)->release();
// 去掉该节点
m_vSprites.erase(iter);
return true;
}
}
return false;
}
int BatchSprite::getCount()
{
return (int)m_vSprites.size();
}
std::vector<Sprite*>& BatchSprite::getChildren()
{
return m_vSprites;
}
void BatchSprite::clearAllSprites()
{
// 所有节点的引用计数减一
for (auto s : m_vSprites)
{
s->release();
}
// 清空储存节点的容器
m_vSprites.clear();
}
bool BatchSprite::_exec(bool active)
{
// 批量节点是否显示
if (!m_bDisplay)
{
return false;
}
// 逆序遍历所有子节点
for (int i = int(m_vSprites.size() - 1); i >= 0; i--)
{
if (m_vSprites[i]->_exec(active))
{
active = false;
}
}
// 若子节点取得了画面焦点,则该节点也取得了焦点
return !active;
}
void BatchSprite::_onDraw()
{
// 节点是否显示
if (!m_bDisplay)
{
return;
}
// 在相对位置绘制子节点
for (auto sprite : m_vSprites)
{
// 将子节点移动到相对位置
sprite->move(getX(), getY());
// 绘制子节点
sprite->_onDraw();
// 将子节点移回原位
sprite->move(-getX(), -getY());
}
}
Sprite * BatchSprite::isCollisionWith(Sprite * sprite)
{
for (int i = int(m_vSprites.size() - 1); i >= 0; i--)
{
if (m_vSprites[i]->isCollisionWith(sprite))
{
return m_vSprites[i];
}
}
return nullptr;
}
Sprite * BatchSprite::isPointIn(CPoint point)
{
for (int i = int(m_vSprites.size() - 1); i >= 0; i--)
{
if (m_vSprites[i]->isPointIn(point))
{
return m_vSprites[i];
}
}
return nullptr;
}
void BatchSprite::addAction(Action * action)
{
Sprite::addAction(action);
}
float BatchSprite::getScaleX() const
{
return m_fScaleX;
}
float BatchSprite::getScaleY() const
{
return m_fScaleY;
}
float BatchSprite::getOpacity() const
{
return m_nAlpha / 255.0f;
}
void BatchSprite::setScale(float scaleX, float scaleY)
{
m_fScaleX = scaleX;
m_fScaleY = scaleY;
for (auto s : m_vSprites)
{
s->setScale(scaleX, scaleY);
}
}
void BatchSprite::setOpacity(float opacity)
{
m_nAlpha = BYTE(min(max(opacity, 0), 1) * 255);
for (auto s : m_vSprites)
{
s->setOpacity(opacity);
}
}
void BatchSprite::setImage(Image * image)
{
for (auto s : m_vSprites)
{
s->setImage(image);
}
}
void BatchSprite::setX(int x)
{
// 计算相对移动位置
int var = x - getX();
// 移动所有子节点的位置
for (auto s : m_vSprites)
{
s->move(var, 0);
}
RectNode::setX(x);
}
void BatchSprite::setY(int y)
{
// 计算相对移动位置
int var = y - getY();
// 移动所有子节点的位置
for (auto s : m_vSprites)
{
s->move(0, var);
}
RectNode::setY(y);
}
void BatchSprite::setPos(int x, int y)
{
// 计算相对移动位置
CPoint var(x - getX(), y - getY());
// 移动所有子节点的位置
for (auto s : m_vSprites)
{
s->move(var);
}
RectNode::setPos(x, y);
}
void BatchSprite::setPos(CPoint p)
{
// 计算相对移动位置
CPoint var(p - getPos());
// 移动所有子节点的位置
for (auto s : m_vSprites)
{
s->move(var);
}
RectNode::setPos(p);
}
void BatchSprite::move(int x, int y)
{
// 移动所有子节点的位置
for (auto s : m_vSprites)
{
s->move(x, y);
}
RectNode::move(x, y);
}
void BatchSprite::move(CVector v)
{
// 移动所有子节点的位置
for (auto s : m_vSprites)
{
s->move(v);
}
RectNode::move(v);
}

View File

@ -1,80 +0,0 @@
#include "..\..\easy2d.h"
#include "..\..\EasyX\easyx.h"
Button::Button() :
m_bEnable(true)
{
}
Button::~Button()
{
}
bool Button::_exec(bool active)
{
// 按钮是否启用
if (!m_bEnable)
{
return false;
}
return MouseNode::_exec(active);
}
void Button::_onDraw()
{
// 按钮是否启用
if (!m_bEnable)
{
// 未启用时,绘制 Disable 状态
_onDisable();
return;
}
MouseNode::_onDraw();
}
bool Button::isEnable()
{
return m_bEnable;
}
void Button::setEnable(bool enable)
{
m_bEnable = enable;
}
void Button::setX(int x)
{
MouseNode::setX(x);
_resetPosition();
}
void Button::setY(int y)
{
MouseNode::setY(y);
_resetPosition();
}
void Button::setPos(int x, int y)
{
MouseNode::setPos(x, y);
_resetPosition();
}
void Button::setPos(CPoint p)
{
MouseNode::setPos(p);
_resetPosition();
}
void Button::move(int x, int y)
{
MouseNode::move(x, y);
_resetPosition();
}
void Button::move(CVector v)
{
MouseNode::move(v);
_resetPosition();
}

View File

@ -1,172 +0,0 @@
#include "..\..\easy2d.h"
ImageButton::ImageButton() :
m_pNormalImage(nullptr),
m_pMouseInImage(nullptr),
m_pSelectedImage(nullptr),
m_pUnableImage(nullptr)
{
}
ImageButton::ImageButton(LPCTSTR image) :
ImageButton()
{
setNormal(new Image(image)); // 设置按钮在正常状态时的图片
}
ImageButton::ImageButton(Image * image) :
ImageButton()
{
setNormal(image); // 设置按钮在正常状态时的图片
}
ImageButton::~ImageButton()
{
// 所有图片的引用计数减一
SafeRelease(m_pNormalImage);
SafeRelease(m_pMouseInImage);
SafeRelease(m_pSelectedImage);
SafeRelease(m_pUnableImage);
}
void ImageButton::_setStatus(Status status)
{
if (m_eStatus != status)
{
if (status == MOUSEIN)
{
if (m_pMouseInImage) setRect(m_pMouseInImage->getRect());
}
else if (status == SELECTED)
{
if (m_pSelectedImage) setRect(m_pSelectedImage->getRect());
}
else
{
setRect(m_pNormalImage->getRect());
}
}
MouseNode::_setStatus(status);
}
void ImageButton::_onNormal()
{
if (m_pNormalImage)
{
m_pNormalImage->_onDraw();
}
}
void ImageButton::_onMouseIn()
{
if (m_pMouseInImage)
{
m_pMouseInImage->_onDraw();
}
else
{
_onNormal();
}
}
void ImageButton::_onSelected()
{
if (m_pSelectedImage)
{
m_pSelectedImage->_onDraw();
}
else
{
_onNormal();
}
}
void ImageButton::_onDisable()
{
if (m_pUnableImage)
{
m_pUnableImage->_onDraw();
}
else
{
_onNormal();
}
}
void ImageButton::setNormal(Image * image)
{
if (image)
{
// 原图片引用计数减一
SafeRelease(m_pNormalImage);
// 修改图片
m_pNormalImage = image;
// 现图片引用计数加一
m_pNormalImage->retain();
// 根据图片宽高设定按钮大小
setSize(m_pNormalImage->getSize());
// 重新计算图片位置
_resetPosition();
}
}
void ImageButton::setMouseIn(Image * image)
{
if (image)
{
SafeRelease(m_pMouseInImage);
m_pMouseInImage = image;
m_pMouseInImage->retain();
_resetPosition();
}
}
void ImageButton::setSelected(Image * image)
{
if (image)
{
SafeRelease(m_pSelectedImage);
m_pSelectedImage = image;
m_pSelectedImage->retain();
_resetPosition();
}
}
void ImageButton::setUnable(Image * image)
{
if (image)
{
SafeRelease(m_pUnableImage);
m_pUnableImage = image;
m_pUnableImage->retain();
_resetPosition();
}
}
void ImageButton::_resetPosition()
{
if (m_pNormalImage)
{
// 根据按钮位置和图片宽高设置图片位置居中显示
m_pNormalImage->setPos(getX(), getY());
}
if (m_pMouseInImage)
{
m_pMouseInImage->setPos(
getX() + (getWidth() - m_pMouseInImage->getWidth()) / 2,
getY() + (getHeight() - m_pMouseInImage->getHeight()) / 2);
}
if (m_pSelectedImage)
{
m_pSelectedImage->setPos(
getX() + (getWidth() - m_pSelectedImage->getWidth()) / 2,
getY() + (getHeight() - m_pSelectedImage->getHeight()) / 2);
}
if (m_pUnableImage)
{
m_pUnableImage->setPos(
getX() + (getWidth() - m_pUnableImage->getWidth()) / 2,
getY() + (getHeight() - m_pUnableImage->getHeight()) / 2);
}
}

View File

@ -1,172 +0,0 @@
#include "..\..\easy2d.h"
TextButton::TextButton() :
m_pNormalText(nullptr),
m_pMouseInText(nullptr),
m_pSelectedText(nullptr),
m_pUnableText(nullptr)
{
}
TextButton::TextButton(TString text) :
TextButton()
{
setNormal(new Text(text)); // 设置按钮在正常状态时的文字
}
TextButton::TextButton(Text * text) :
TextButton()
{
setNormal(text); // 设置按钮在正常状态时的文字
}
TextButton::~TextButton()
{
// 所有文本的引用计数减一
SafeRelease(m_pNormalText);
SafeRelease(m_pMouseInText);
SafeRelease(m_pSelectedText);
SafeRelease(m_pUnableText);
}
void TextButton::_setStatus(Status status)
{
if (m_eStatus != status)
{
if (status == MOUSEIN)
{
if (m_pMouseInText) setRect(m_pMouseInText->getRect());
}
else if (status == SELECTED)
{
if (m_pSelectedText) setRect(m_pSelectedText->getRect());
}
else
{
setRect(m_pNormalText->getRect());
}
}
MouseNode::_setStatus(status);
}
void TextButton::_onNormal()
{
if (m_pNormalText)
{
m_pNormalText->_onDraw();
}
}
void TextButton::_onMouseIn()
{
if (m_pMouseInText)
{
m_pMouseInText->_onDraw();
}
else
{
_onNormal();
}
}
void TextButton::_onSelected()
{
if (m_pSelectedText)
{
m_pSelectedText->_onDraw();
}
else
{
_onNormal();
}
}
void TextButton::_onDisable()
{
if (m_pUnableText)
{
m_pUnableText->_onDraw();
}
else
{
_onNormal();
}
}
void TextButton::setNormal(Text * text)
{
if (text)
{
// 原文本引用计数减一
SafeRelease(m_pNormalText);
// 修改文本
m_pNormalText = text;
// 现文本引用计数加一
m_pNormalText->retain();
// 根据文字宽高设定按钮大小
setSize(m_pNormalText->getSize());
// 重新计算文本位置
_resetPosition();
}
}
void TextButton::setMouseIn(Text * text)
{
if (text)
{
SafeRelease(m_pMouseInText);
m_pMouseInText = text;
m_pMouseInText->retain();
_resetPosition();
}
}
void TextButton::setSelected(Text * text)
{
if (text)
{
SafeRelease(m_pSelectedText);
m_pSelectedText = text;
m_pSelectedText->retain();
_resetPosition();
}
}
void TextButton::setUnable(Text * text)
{
if (text)
{
SafeRelease(m_pUnableText);
m_pUnableText = text;
m_pUnableText->retain();
_resetPosition();
}
}
void TextButton::_resetPosition()
{
if (m_pNormalText)
{
// 根据按钮位置和文字宽高设置文字位置居中显示
m_pNormalText->setPos(getX() , getY());
}
if (m_pMouseInText)
{
m_pMouseInText->setPos(
getX() + (getWidth() - m_pMouseInText->getWidth()) / 2,
getY() + (getHeight() - m_pMouseInText->getHeight()) / 2);
}
if (m_pSelectedText)
{
m_pSelectedText->setPos(
getX() + (getWidth() - m_pSelectedText->getWidth()) / 2,
getY() + (getHeight() - m_pSelectedText->getHeight()) / 2);
}
if (m_pUnableText)
{
m_pUnableText->setPos(
getX() + (getWidth() - m_pUnableText->getWidth()) / 2,
getY() + (getHeight() - m_pUnableText->getHeight()) / 2);
}
}

View File

@ -1,199 +0,0 @@
#include "..\enodes.h"
#include "..\Win\winbase.h"
e2d::ENode::ENode()
: m_nZOrder(0)
, m_bVisiable(true)
{
}
e2d::ENode::ENode(EPoint p)
: ENode()
{
setPos(p);
}
e2d::ENode::ENode(int x, int y)
: ENode()
{
setPos(x, y);
}
e2d::ENode::~ENode()
{
}
bool e2d::ENode::_exec(bool active)
{
return false;
}
void e2d::ENode::_onDraw()
{
D2D1_RECT_F rectangle = D2D1::RectF(
m_Rect.left,
m_Rect.top,
m_Rect.right,
m_Rect.bottom
);
ID2D1SolidColorBrush* m_pLightSlateGrayBrush;
GetRenderTarget()->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::LightSlateGray),
&m_pLightSlateGrayBrush
);
GetRenderTarget()->FillRectangle(&rectangle, m_pLightSlateGrayBrush);
}
int e2d::ENode::getX() const
{
if (m_pParent)
{
return m_pParent->getX() + m_Rect.TopLeft().x;
}
return m_Rect.TopLeft().x;
}
int e2d::ENode::getY() const
{
if (m_pParent)
{
return m_pParent->getY() + m_Rect.TopLeft().y;
}
return m_Rect.TopLeft().y;
}
CPoint e2d::ENode::getPos() const
{
if (m_pParent)
{
return m_pParent->getPos() + m_Rect.TopLeft();
}
return m_Rect.TopLeft();
}
UINT32 e2d::ENode::getWidth() const
{
return UINT32(m_Rect.Size().cx);
}
UINT32 e2d::ENode::getHeight() const
{
return UINT32(m_Rect.Size().cy);
}
e2d::ESize e2d::ENode::getSize() const
{
return e2d::ESize(m_Rect.Size());
}
e2d::ERect e2d::ENode::getRect() const
{
return e2d::ERect(m_Rect);
}
void e2d::ENode::setX(int x)
{
m_Rect.TopLeft().x = x;
}
void e2d::ENode::setY(int y)
{
m_Rect.TopLeft().y = y;
}
void e2d::ENode::setPos(int x, int y)
{
m_Rect.TopLeft().SetPoint(x, y);
}
void e2d::ENode::setPos(EPoint p)
{
m_Rect.TopLeft() = p;
}
void e2d::ENode::move(int x, int y)
{
m_Rect.OffsetRect(x, y);
}
void e2d::ENode::move(EVector v)
{
m_Rect.OffsetRect(v);
}
void e2d::ENode::setWidth(UINT32 width)
{
m_Rect.BottomRight().x = m_Rect.TopLeft().x + width;
}
void e2d::ENode::setHeight(UINT32 height)
{
m_Rect.BottomRight().y = m_Rect.TopLeft().y + height;
}
void e2d::ENode::setSize(UINT32 width, UINT32 height)
{
setWidth(width);
setHeight(height);
}
void e2d::ENode::setSize(e2d::ESize size)
{
setSize(size.cx, size.cy);
}
void e2d::ENode::setRect(int x1, int y1, int x2, int y2)
{
m_Rect.SetRect(x1, y1, x2, y2);
}
void e2d::ENode::setRect(EPoint leftTop, EPoint rightBottom)
{
m_Rect.TopLeft() = leftTop;
m_Rect.BottomRight() = rightBottom;
}
void e2d::ENode::setRect(e2d::ERect rect)
{
m_Rect = rect;
}
int e2d::ENode::getZOrder() const
{
return m_nZOrder;
}
void e2d::ENode::setZOrder(int z)
{
m_nZOrder = z;
}
void e2d::ENode::setParent(e2d::ENode * parent)
{
m_pParent = parent;
}
e2d::ENode *& e2d::ENode::getParent()
{
return m_pParent;
}
e2d::EScene * &e2d::ENode::getParentScene()
{
return m_pParentScene;
}
void e2d::ENode::setParentScene(e2d::EScene * scene)
{
m_pParentScene = scene;
}
void e2d::ENode::setVisiable(bool value)
{
m_bVisiable = value;
}
bool e2d::ENode::isVisiable() const
{
return m_bVisiable;
}

View File

@ -1,251 +0,0 @@
#include "..\easy2d.h"
#include "..\EasyX\easyx.h"
#include <map>
using namespace std;
// 图片缓存
static map<TString, CImage*> s_mCImages;
// 从图片缓存中读取图片
static CImage* GetCImage(TString name, bool fromRes = false);
// 对 PNG 图像进行像素转换
static void CrossImage(CImage &img);
Image::Image() :
m_pCImage(nullptr),
m_nAlpha(255),
m_fScaleX(1),
m_fScaleY(1)
{
}
Image::Image(LPCTSTR ImageFile) :
Image()
{
setImage(ImageFile); // 设置图片资源
}
Image::Image(LPCTSTR ImageFile, int x, int y, int width, int height) :
Image()
{
setImage(ImageFile, x, y, width, height); // 设置图片资源和裁剪大小
}
Image::~Image()
{
}
void Image::_onDraw()
{
// display 属性为 false或未设置图片资源时不绘制该图片
if (!m_bDisplay || !m_pCImage)
{
return;
}
// 绘制图片
if (m_pCImage->GetBPP() == 32)
{
m_pCImage->AlphaBlend(GetImageHDC(), m_Rect, m_SrcRect, m_nAlpha, AC_SRC_OVER);
}
else
{
m_pCImage->Draw(GetImageHDC(), m_Rect, m_SrcRect);
}
}
float Image::getScaleX() const
{
return m_fScaleX;
}
float Image::getScaleY() const
{
return m_fScaleY;
}
float Image::getOpacity() const
{
return m_nAlpha / 255.0f;
}
bool Image::setImage(LPCTSTR ImageFile)
{
m_pCImage = GetCImage(ImageFile);
if (m_pCImage)
{
reset();
return true;
}
return false;
}
bool Image::setImage(LPCTSTR ImageFile, int x, int y, int width, int height)
{
if (!setImage(ImageFile))
{
return false;
}
// 裁剪图片大小
crop(x, y, width, height);
return true;
}
bool Image::setImageFromRes(LPCTSTR pResName)
{
m_pCImage = GetCImage(pResName, true);
if (m_pCImage)
{
reset();
return true;
}
return false;
}
bool Image::setImageFromRes(LPCTSTR pResName, int x, int y, int width, int height)
{
if (!setImageFromRes(pResName))
{
return false;
}
// 裁剪图片大小
crop(x, y, width, height);
return true;
}
void Image::crop(int x, int y, int width, int height)
{
width = min(max(width, 0), m_pCImage->GetWidth() - x);
height = min(max(height, 0), m_pCImage->GetHeight() - y);
// 设置源矩形的位置和大小(用于裁剪)
m_SrcRect.SetRect(x, y, x + width, y + height);
// 设置目标矩形(即绘制到窗口的位置和大小)
setSize(int(width * m_fScaleX), int(height * m_fScaleY));
}
void Image::stretch(int width, int height)
{
// 设置目标矩形的位置和大小(即绘制到窗口的位置和大小,用于拉伸图片)
setSize(max(width, 0), max(height, 0));
// 重置比例缩放属性
m_fScaleX = 1;
m_fScaleY = 1;
}
void Image::setScale(float scaleX, float scaleY)
{
m_fScaleX = max(scaleX, 0);
m_fScaleY = max(scaleY, 0);
setSize(int(m_SrcRect.Width() * scaleX), int(m_SrcRect.Height() * scaleY));
}
void Image::setOpacity(float value)
{
if (m_pCImage->GetBPP() == 32)
{
m_nAlpha = BYTE(min(max(value, 0), 1) * 255);
}
}
void Image::setTransparentColor(COLORREF value)
{
// 设置透明色
m_pCImage->SetTransparentColor(value);
}
void Image::reset()
{
// 设置目标矩形(即绘制到窗口的位置和大小)
setSize(m_pCImage->GetWidth(), m_pCImage->GetHeight());
// 设置源矩形(即截取图片的大小)
m_SrcRect.SetRect(0, 0, m_pCImage->GetWidth(), m_pCImage->GetHeight());
// 重置缩放属性
m_fScaleX = 1;
m_fScaleY = 1;
// 重置透明度
m_nAlpha = 255;
}
bool Image::preload(LPCTSTR fileName, bool fromRes)
{
// 判断图片是否已经加载
if (s_mCImages.find(fileName) != s_mCImages.end())
{
return true;
}
// 加载图片
CImage* cImage = nullptr;
if (fromRes)
{
cImage = new CImage();
// 从资源加载图片(不支持 PNG
cImage->LoadFromResource(GetModuleHandle(NULL), fileName);
}
else
{
//判断图片路径是否存在
if (!PathFileExists(fileName))
{
return false;
}
cImage = new CImage();
cImage->Load(fileName);
}
// 加载失败
if (!cImage || cImage->IsNull())
{
return false;
}
// 确认该图像包含 Alpha 通道
if (cImage->GetBPP() == 32)
{
// 透明图片处理
CrossImage(*cImage);
}
s_mCImages.insert(map<TString, CImage*>::value_type(fileName, cImage));
return true;
}
void Image::saveScreenshot()
{
TString savePath;
// 获取保存位置
if (FileUtils::getSaveFilePath(savePath, _T("截图保存到"), _T("jpg")))
{
// 保存窗口截图
IMAGE image;
getimage(&image, 0, 0, EApp::getWidth(), EApp::getHeight());
saveimage(savePath.c_str(), &image);
}
}
// 对 PNG 图像进行像素转换
void CrossImage(CImage &img)
{
// 进行像素转换
for (int i = 0; i < img.GetWidth(); i++)
{
for (int j = 0; j < img.GetHeight(); j++)
{
UCHAR *cr = (UCHAR*)img.GetPixelAddress(i, j);
cr[0] = cr[0] * cr[3] / 255;
cr[1] = cr[1] * cr[3] / 255;
cr[2] = cr[2] * cr[3] / 255;
}
}
}
CImage* GetCImage(TString name, bool fromRes)
{
if (Image::preload(name.c_str()))
{
return s_mCImages.at(name);
}
else
{
return nullptr;
}
}

View File

@ -1,27 +0,0 @@
#include "..\easy2d.h"
Layer::Layer() :
m_bBlock(true)
{
}
Layer::~Layer()
{
}
int Layer::getBlock() const
{
return m_bBlock;
}
void Layer::setBlock(bool block)
{
m_bBlock = block;
}
bool Layer::_exec(bool active)
{
// 若图层阻塞消息,则永远取得画面焦点
return BatchNode::_exec(active) || m_bBlock;
}

View File

@ -1,174 +0,0 @@
#include "..\easy2d.h"
MouseNode::MouseNode() :
m_bBlock(true),
m_bTarget(false),
m_ClickCallback([]() {}),
m_OnMouseInCallback([]() {}),
m_OnMouseOutCallback([]() {}),
m_OnSelectCallback([]() {}),
m_OnUnselectCallback([]() {})
{
}
MouseNode::~MouseNode()
{
}
bool MouseNode::_exec(bool active)
{
// 若 display 属性为 false退出函数
if (!m_bDisplay)
{
return false;
}
// 若画面已取得焦点,重置按钮属性并退出
if (!active)
{
reset();
return false;
}
// 判断节点当前的状态
// 若节点未取得焦点,则重新判断节点状态
if (!m_bTarget)
{
// 若鼠标位置在节点所在的矩形区域中
if (_isMouseIn())
{
// 状态设为 MOUSEIN
_setStatus(MOUSEIN);
// 若此时按下鼠标左键
if (MouseMsg::getMsg() == MouseMsg::LBUTTON_DOWN)
{
m_bTarget = true; // 取得焦点标记
_setStatus(SELECTED); // 状态设为 SELECTED
}
// 若节点阻塞鼠标消息,则取得画面焦点
if (m_bBlock) return true;
}
else
{
reset(); // 恢复默认状态
}
}
else
{
// 节点取得焦点时鼠标左键抬起
if (MouseMsg::getMsg() == MouseMsg::LBUTTON_UP)
{
// 若左键抬起时鼠标仍在节点内
if (_isMouseIn())
{
m_ClickCallback(); // 执行回调函数
}
reset(); // 恢复默认状态
}
// 若节点阻塞鼠标消息,则取得画面焦点
if (m_bBlock) return true;
}
return false;
}
void MouseNode::_onDraw()
{
// 节点是否显示
if (!m_bDisplay)
{
return;
}
// 节点是否被选中
if (m_eStatus == SELECTED)
{
_onSelected();
}
else
{
// 鼠标是否在节点上
if (m_eStatus == MOUSEIN)
{
_onMouseIn();
}
else
{
_onNormal();
}
}
}
bool MouseNode::_isMouseIn()
{
return isPointIn(MouseMsg::getPos());
}
void MouseNode::_setStatus(Status status)
{
if (m_eStatus != status)
{
// 退出某个状态的回调函数
if (m_eStatus == MOUSEIN)
{
m_OnMouseOutCallback();
}
else if (m_eStatus == SELECTED)
{
m_OnUnselectCallback();
}
// 进入某个状态的回调函数
if (status == MOUSEIN)
{
m_OnMouseInCallback();
}
else if (status == SELECTED)
{
m_OnSelectCallback();
}
m_eStatus = status;
}
}
bool MouseNode::isMouseIn()
{
return m_eStatus == MOUSEIN || m_eStatus == SELECTED;
}
bool MouseNode::isSelected()
{
return m_eStatus == SELECTED;
}
void MouseNode::setClickedCallback(const CLICK_CALLBACK & callback)
{
m_ClickCallback = callback;
}
void MouseNode::setMouseInCallback(const CLICK_CALLBACK & callback)
{
m_OnMouseInCallback = callback;
}
void MouseNode::setMouseOutCallback(const CLICK_CALLBACK & callback)
{
m_OnMouseOutCallback = callback;
}
void MouseNode::setSelectCallback(const CLICK_CALLBACK & callback)
{
m_OnSelectCallback = callback;
}
void MouseNode::setUnselectCallback(const CLICK_CALLBACK & callback)
{
m_OnUnselectCallback = callback;
}
void MouseNode::reset()
{
m_bTarget = false; // 失去焦点标记
_setStatus(NORMAL); // 恢复默认状态
}
void MouseNode::setBlock(bool block)
{
m_bBlock = block;
}

View File

@ -1,139 +0,0 @@
#include "..\easy2d.h"
RectNode::RectNode() :
m_Rect(0, 0, 0, 0)
{
}
RectNode::~RectNode()
{
}
bool RectNode::isCollisionWith(RectNode * rectNode) const
{
static CRect rt;
return IntersectRect(&rt, &m_Rect, &rectNode->m_Rect);
}
bool RectNode::isPointIn(CPoint p) const
{
return m_Rect.PtInRect(p);
}
void RectNode::setWindowCenterX()
{
setX((EApp::getWidth() - getWidth()) / 2);
}
void RectNode::setWindowCenterY()
{
setY((EApp::getHeight() - getHeight()) / 2);
}
void RectNode::setWindowCenter()
{
setWindowCenterX();
setWindowCenterY();
}
int RectNode::getX() const
{
return m_Rect.left;
}
int RectNode::getY() const
{
return m_Rect.top;
}
CPoint RectNode::getPos() const
{
return m_Rect.TopLeft();
}
int RectNode::getWidth() const
{
return m_Rect.Width(); // 矩形宽度
}
int RectNode::getHeight() const
{
return m_Rect.Height(); // 矩形高度
}
CSize RectNode::getSize() const
{
return m_Rect.Size();
}
CRect RectNode::getRect() const
{
return m_Rect;
}
void RectNode::setX(int x)
{
m_Rect.MoveToX(x);
}
void RectNode::setY(int y)
{
m_Rect.MoveToY(y);
}
void RectNode::setPos(int x, int y)
{
m_Rect.MoveToXY(x, y); // 修改矩形位置
}
void RectNode::setPos(CPoint p)
{
m_Rect.MoveToXY(p); // 修改矩形位置
}
void RectNode::move(int x, int y)
{
m_Rect.OffsetRect(x, y); // 移动矩形
}
void RectNode::move(CVector v)
{
m_Rect.OffsetRect(v); // 移动矩形
}
void RectNode::setWidth(int width)
{
m_Rect.right = max(m_Rect.left + width, 0);
}
void RectNode::setHeight(int height)
{
m_Rect.bottom = max(m_Rect.top + height, 0);
}
void RectNode::setSize(int width, int height)
{
setWidth(width);
setHeight(height);
}
void RectNode::setSize(CSize size)
{
setSize(size.cx, size.cy);
}
void RectNode::setRect(int x1, int y1, int x2, int y2)
{
m_Rect.SetRect(x1, y1, x2, y2);
}
void RectNode::setRect(CPoint leftTop, CPoint rightBottom)
{
m_Rect.SetRect(leftTop, rightBottom);
}
void RectNode::setRect(CRect rect)
{
m_Rect.CopyRect(&rect);
}

View File

@ -1,43 +0,0 @@
#include "..\..\easy2d.h"
#include "..\..\EasyX\easyx.h"
Circle::Circle() :
m_nRadius(0)
{
}
Circle::Circle(int x, int y, int radius) :
m_nRadius(radius)
{
setPos(x, y);
}
Circle::~Circle()
{
}
void Circle::solidShape()
{
solidcircle(getX(), getY(), m_nRadius);
}
void Circle::fillShape()
{
fillcircle(getX(), getY(), m_nRadius);
}
void Circle::roundShape()
{
circle(getX(), getY(), m_nRadius);
}
int Circle::getRadius() const
{
return m_nRadius;
}
void Circle::setRadius(int r)
{
m_nRadius = r;
}

View File

@ -1,58 +0,0 @@
#include "..\..\easy2d.h"
#include "..\..\EasyX\easyx.h"
Rect::Rect()
{
}
Rect::Rect(int x, int y, int width, int height) :
m_Size(width, height)
{
setPos(x, y);
}
Rect::~Rect()
{
}
void Rect::solidShape()
{
solidrectangle(getX(), getY(), getX() + m_Size.cx, getY() + m_Size.cy);
}
void Rect::fillShape()
{
fillrectangle(getX(), getY(), getX() + m_Size.cx, getY() + m_Size.cy);
}
void Rect::roundShape()
{
rectangle(getX(), getY(), getX() + m_Size.cx, getY() + m_Size.cy);
}
int Rect::getWidth() const
{
return m_Size.cx;
}
int Rect::getHeight() const
{
return m_Size.cy;
}
void Rect::setWidth(int width)
{
m_Size.cx = width;
}
void Rect::setHeight(int height)
{
m_Size.cy = height;
}
void Rect::setSize(int width, int height)
{
m_Size.cx = width;
m_Size.cy = height;
}

View File

@ -1,64 +0,0 @@
#include "..\..\easy2d.h"
#include "..\..\EasyX\easyx.h"
Shape::Shape() :
lineColor(Color::black),
fillColor(Color::white),
m_eStyle(SOLID)
{
}
Shape::~Shape()
{
}
void Shape::_onDraw()
{
// 形状是否显示
if (!m_bDisplay)
{
return;
}
// 设置线条和填充颜色
setlinecolor(lineColor);
setfillcolor(fillColor);
// 根据形状的样式进行不同的绘制
if (m_eStyle == Shape::STYLE::ROUND)
{
roundShape();
}
else if (m_eStyle == Shape::STYLE::SOLID)
{
solidShape();
}
else if (m_eStyle == Shape::STYLE::FILL)
{
fillShape();
}
}
inline COLORREF Shape::getFillColor() const
{
return fillColor;
}
inline COLORREF Shape::getLineColor() const
{
return lineColor;
}
void Shape::setFillColor(COLORREF color)
{
fillColor = color;
}
void Shape::setLineColor(COLORREF color)
{
lineColor = color;
}
void Shape::setStyle(STYLE style)
{
m_eStyle = style;
}

View File

@ -1,147 +0,0 @@
#include "..\easy2d.h"
#include "..\EasyX\easyx.h"
Sprite::Sprite() :
m_nAlpha(255),
m_fScaleX(1),
m_fScaleY(1),
m_pImage(nullptr)
{
}
Sprite::Sprite(Image * image) :
Sprite()
{
setImage(image);
}
Sprite::Sprite(LPCTSTR imageFileName) :
Sprite()
{
setImage(new Image(imageFileName));
}
Sprite::~Sprite()
{
SafeRelease(m_pImage);
}
bool Sprite::_exec(bool active)
{
return false;
}
void Sprite::_onDraw()
{
// display 属性为 false或未设置图片资源时不绘制该图片
if (!m_bDisplay || !m_pImage || !m_pImage->m_pCImage)
{
return;
}
// 绘制图片
if (m_pImage->m_pCImage->GetBPP() == 32)
{
m_pImage->m_pCImage->AlphaBlend(GetImageHDC(), getRect(), m_pImage->m_SrcRect, m_nAlpha, AC_SRC_OVER);
}
else
{
m_pImage->m_pCImage->Draw(GetImageHDC(), getRect(), m_pImage->m_SrcRect);
}
}
void Sprite::setImage(Image * image)
{
SafeRelease(m_pImage);
m_pImage = image;
setSize(int(m_pImage->getWidth() * m_fScaleX), int(m_pImage->getHeight() * m_fScaleY));
m_pImage->retain();
}
bool Sprite::isCollisionWith(Sprite * sprite)
{
static CRect rt;
return IntersectRect(&rt, &getRect(), &sprite->getRect());
}
void Sprite::addAction(Action * action)
{
if (action)
{
// 将动作与 Sprite 绑定
action->m_pTargetSprite = this;
// 将动作加入动作管理器,管理器会处理这个动作
ActionManager::addAction(action);
}
}
void Sprite::runAction(Action * action)
{
addAction(action);
}
void Sprite::resumeAction(Action * action)
{
if (action->getTarget() == this)
{
ActionManager::resumeAction(action);
}
}
void Sprite::pauseAction(Action * action)
{
if (action->getTarget() == this)
{
ActionManager::pauseAction(action);
}
}
void Sprite::stopAction(Action * action)
{
if (action->getTarget() == this)
{
ActionManager::stopAction(action);
}
}
void Sprite::pauseAllActions()
{
ActionManager::pauseSpriteAllActions(this);
}
void Sprite::resumeAllActions()
{
ActionManager::resumeSpriteAllActions(this);
}
void Sprite::stopAllActions()
{
ActionManager::stopSpriteAllActions(this);
}
float Sprite::getScaleX() const
{
return m_fScaleX;
}
float Sprite::getScaleY() const
{
return m_fScaleY;
}
float Sprite::getOpacity() const
{
return m_nAlpha / 255.0f;
}
void Sprite::setScale(float scaleX, float scaleY)
{
m_fScaleX = max(scaleX, 0);
m_fScaleY = max(scaleY, 0);
setSize(int(m_pImage->getWidth() * scaleX), int(m_pImage->getHeight() * scaleY));
}
void Sprite::setOpacity(float opacity)
{
m_nAlpha = BYTE(min(max(opacity, 0), 1) * 255);
}

View File

@ -1,91 +0,0 @@
#include "..\easy2d.h"
#include "..\EasyX\easyx.h"
Text::Text() :
m_sText(_T("")),
m_color(Color::white),
m_pFontStyle(FontStyle::getDefault())
{
m_pFontStyle->retain(); // 字体引用计数加一
}
Text::Text(TString text, COLORREF color, FontStyle * font) :
m_color(color),
m_pFontStyle(font)
{
setText(text);
m_pFontStyle->retain(); // 字体引用计数加一
}
Text::Text(int x, int y, TString text, COLORREF color, FontStyle * font) :
m_color(color),
m_pFontStyle(font)
{
setText(text);
setPos(x, y);
m_pFontStyle->retain(); // 字体引用计数加一
}
Text::~Text()
{
SafeRelease(m_pFontStyle); // 字体引用计数减一
}
void Text::_onDraw()
{
// 若 display 属性为 false不绘制这个文本
if (!m_bDisplay)
{
return;
}
// 设置字体
settextstyle(&m_pFontStyle->m_font);
// 设置文本颜色
settextcolor(m_color);
// 输出文字
outtextxy(getX(), getY(), m_sText.c_str());
}
COLORREF Text::getColor() const
{
return m_color;
}
TString Text::getText() const
{
return m_sText;
}
FontStyle * Text::getFontStyle()
{
return m_pFontStyle;
}
bool Text::isEmpty() const
{
return m_sText.empty(); // 文本是否为空
}
void Text::setText(TString text)
{
m_sText = text;
// 先设置字体,然后获取该文本在该字体下的宽度和高度
settextstyle(&m_pFontStyle->m_font);
setSize(textwidth(getText().c_str()), textheight(getText().c_str()));
}
void Text::setColor(COLORREF color)
{
m_color = color;
}
void Text::setFontStyle(FontStyle * style)
{
SafeRelease(m_pFontStyle); // 原字体引用计数减一
m_pFontStyle = style; // 修改字体
m_pFontStyle->retain(); // 现字体引用计数加一
// 先设置字体,然后获取该文本在该字体下的宽度和高度
settextstyle(&m_pFontStyle->m_font);
setSize(textwidth(getText().c_str()), textheight(getText().c_str()));
}

View File

@ -1,56 +0,0 @@
#include "..\easy2d.h"
#include "..\EasyX\easyx.h"
// 常用颜色值的定义
const COLORREF Color::black = BLACK;
const COLORREF Color::blue = BLUE;
const COLORREF Color::green = GREEN;
const COLORREF Color::cyan = CYAN;
const COLORREF Color::red = RED;
const COLORREF Color::magenta = MAGENTA;
const COLORREF Color::brown = BROWN;
const COLORREF Color::lightgray = LIGHTGRAY;
const COLORREF Color::darkgray = DARKGRAY;
const COLORREF Color::lightblue = LIGHTBLUE;
const COLORREF Color::lightgreen = LIGHTGREEN;
const COLORREF Color::lightcyan = LIGHTCYAN;
const COLORREF Color::lightred = LIGHTRED;
const COLORREF Color::lightmagenta = LIGHTMAGENTA;
const COLORREF Color::yellow = YELLOW;
const COLORREF Color::white = WHITE;
COLORREF Color::getFromRGB(BYTE r, BYTE g, BYTE b)
{
return RGB(r, g, b); // 从 (r, g, b) 三色值转化为颜色
}
COLORREF Color::getFromHSL(float H, float S, float L)
{
return HSLtoRGB(H, S, L);
}
COLORREF Color::getFromHSV(float H, float S, float V)
{
return HSVtoRGB(H, S, V);
}
BYTE Color::getRValue(COLORREF color)
{
return GetRValue(color); // 返回颜色中的红色值
}
BYTE Color::getGValue(COLORREF color)
{
return GetGValue(color); // 返回颜色中的绿色值
}
BYTE Color::getBValue(COLORREF color)
{
return GetBValue(color); // 返回颜色中的蓝色值
}
COLORREF Color::getGray(COLORREF color)
{
return RGBtoGRAY(color); // 获取颜色中的灰度值
}

View File

@ -1 +0,0 @@
/* FillStyle 是 EasyX 中的类,目前尚未考虑实现 */

View File

@ -1,103 +0,0 @@
#include "..\easy2d.h"
// ³£ÓÃ×ÖÌå´ÖϸֵµÄ¶¨Òå
const LONG FontWeight::dontcare = 0;
const LONG FontWeight::thin = 100;
const LONG FontWeight::extraLight = 200;
const LONG FontWeight::light = 300;
const LONG FontWeight::normal = 400;
const LONG FontWeight::regular = 400;
const LONG FontWeight::medium = 500;
const LONG FontWeight::demiBlod = 600;
const LONG FontWeight::blod = 700;
const LONG FontWeight::extraBold = 800;
const LONG FontWeight::black = 900;
const LONG FontWeight::heavy = 900;
FontStyle::FontStyle()
{
setFontFamily(_T(""));
m_font.lfWeight = 18;
m_font.lfHeight = 0;
m_font.lfWidth = 0;
m_font.lfItalic = 0;
m_font.lfUnderline = 0;
m_font.lfStrikeOut = 0;
m_font.lfEscapement = 0;
m_font.lfOrientation = 0;
setQuality(true);
}
FontStyle::FontStyle(LPCTSTR fontfamily, LONG height, LONG weight, LONG width, bool italic, bool underline, bool strikeout, LONG escapement, LONG orientation, bool quality)
{
setFontFamily(fontfamily);
m_font.lfWeight = weight;
m_font.lfHeight = height;
m_font.lfWidth = width;
m_font.lfItalic = italic;
m_font.lfUnderline = underline;
m_font.lfStrikeOut = strikeout;
m_font.lfEscapement = escapement;
m_font.lfOrientation = orientation;
setQuality(quality);
}
FontStyle::~FontStyle()
{
}
FontStyle * FontStyle::getDefault()
{
return new FontStyle(_T(""), 18, FontWeight::normal);
}
void FontStyle::setHeight(LONG value)
{
m_font.lfHeight = value;
}
void FontStyle::setWidth(LONG value)
{
m_font.lfWidth = value;
}
void FontStyle::setFontFamily(LPCTSTR value)
{
_tcscpy_s(m_font.lfFaceName, 32, value);
}
void FontStyle::setEscapement(LONG value)
{
m_font.lfEscapement = value;
}
void FontStyle::setOrientation(LONG value)
{
m_font.lfOrientation = value;
}
void FontStyle::setQuality(bool value)
{
m_font.lfQuality = value ? ANTIALIASED_QUALITY : DEFAULT_QUALITY;
}
void FontStyle::setWeight(LONG value)
{
m_font.lfWeight = value;
}
void FontStyle::setItalic(bool value)
{
m_font.lfItalic = value;
}
void FontStyle::setUnderline(bool value)
{
m_font.lfUnderline = value;
}
void FontStyle::setStrikeOut(bool value)
{
m_font.lfStrikeOut = value;
}

View File

@ -1 +0,0 @@
/* LineStyle 是 EasyX 中的类,目前尚未考虑实现 */

View File

@ -1,200 +0,0 @@
#include "..\easy2d.h"
#include "..\Win\winbase.h"
#include <assert.h>
static std::vector<Action*> s_vActions;
void ActionManager::__exec()
{
// 临时指针
static Action * action;
// 循环遍历所有正在运行的动作
for (size_t i = 0; i < s_vActions.size(); i++)
{
action = s_vActions[i];
// 获取动作运行状态
if (action->isRunning())
{
if (action->isEnding())
{
// 动作已经结束
action->autoRelease();
action->release();
s_vActions.erase(s_vActions.begin() + i);
}
else
{
// 初始化动作
if (!action->m_bInit)
{
action->_init();
}
// 执行动作
action->_exec(GetNow());
}
}
}
}
void ActionManager::addAction(Action * action)
{
if (action)
{
#ifdef _DEBUG
for (auto a : s_vActions)
{
assert(a != action);
}
#endif
action->m_pParentScene = EApp::getLoadingScene();
s_vActions.push_back(action);
}
}
void ActionManager::notifyAllSceneActions(EScene * scene)
{
for (auto action : s_vActions)
{
if (action->m_pParentScene == scene)
{
action->notify();
}
}
}
void ActionManager::waitAllSceneActions(EScene * scene)
{
for (auto action : s_vActions)
{
if (action->m_pParentScene == scene)
{
action->wait();
}
}
}
void ActionManager::stopAllSceneActions(EScene * scene)
{
for (auto action : s_vActions)
{
if (action->m_pParentScene == scene)
{
action->stop();
}
}
}
void ActionManager::startAction(Action * action)
{
resumeAction(action);
}
void ActionManager::resumeAction(Action * action)
{
for (auto act : s_vActions)
{
if (act == action)
{
act->resume();
}
}
}
void ActionManager::pauseAction(Action * action)
{
for (auto act : s_vActions)
{
if (act == action)
{
act->pause();
}
}
}
void ActionManager::stopAction(Action * action)
{
for (auto act : s_vActions)
{
if (act == action)
{
act->stop();
}
}
}
void ActionManager::startSpriteAllActions(Sprite * sprite)
{
resumeSpriteAllActions(sprite);
}
void ActionManager::resumeSpriteAllActions(Sprite * sprite)
{
for (auto action : s_vActions)
{
if (action->m_pTargetSprite == sprite)
{
action->resume();
}
}
}
void ActionManager::pauseSpriteAllActions(Sprite * sprite)
{
for (auto action : s_vActions)
{
if (action->m_pTargetSprite == sprite)
{
action->pause();
}
}
}
void ActionManager::stopSpriteAllActions(Sprite * sprite)
{
for (auto action : s_vActions)
{
if (action->m_pTargetSprite == sprite)
{
action->stop();
}
}
}
void ActionManager::startAllActions()
{
resumeAllActions();
}
void ActionManager::resumeAllActions()
{
for (auto action : s_vActions)
{
action->resume();
}
}
void ActionManager::pauseAllActions()
{
for (auto action : s_vActions)
{
action->pause();
}
}
void ActionManager::stopAllActions()
{
for (auto action : s_vActions)
{
action->stop();
}
}
void ActionManager::clearAllActions()
{
for (auto action : s_vActions)
{
action->autoRelease();
action->release();
}
s_vActions.clear();
}

View File

@ -1,51 +0,0 @@
#include "..\etools.h"
#include <vector>
// EObjectManager 释放池的实现机制:
/// EObject 类中的引用计数m_nRefCount保证了指针的使用安全
/// 它记录了对象被使用的次数,当计数为 0 时EObjectManager 会自动释放这个对象
/// 所有的 EObject 对象都应在被使用时(例如 Text 添加到了场景中)
/// 调用 retain 函数保证该对象不被删除,并在不再使用时调用 release 函数
/// 让其自动释放
// 释放池容器
static std::vector<e2d::EObject*> s_vPool;
void e2d::EObjectManager::__flush()
{
// 创建迭代器
static std::vector<e2d::EObject*>::iterator iter;
// 循环遍历容器中的所有对象
for (iter = s_vPool.begin(); iter != s_vPool.end();)
{
if ((*iter)->m_bAutoRelease && (*iter)->m_nRefCount == 0)
{
// 若对象的引用的计数为 0, 释放该对象
delete (*iter);
// 从释放池中删除该对象
iter = s_vPool.erase(iter);
}
else
{
iter++; // 移动迭代器
}
}
}
void e2d::EObjectManager::add(e2d::EObject * nptr)
{
if (!nptr->m_bManaged)
{
nptr->m_bManaged = true;
s_vPool.push_back(nptr); // 将一个对象放入释放池中
}
}
void e2d::EObjectManager::clearAllObjects()
{
for (auto o : s_vPool)
{
delete o;
}
s_vPool.clear();
}

View File

@ -1,168 +0,0 @@
#include "..\easy2d.h"
#include "..\EasyX\easyx.h"
#include <Shlobj.h>
#pragma comment(lib, "shell32.lib")
#include <sstream>
#include <algorithm>
#ifndef UNICODE
#include <io.h>
#include <direct.h>
#endif
TString FileUtils::getLocalAppDataPath()
{
TCHAR m_lpszDefaultDir[MAX_PATH] = { 0 };
TCHAR szDocument[MAX_PATH] = { 0 };
// 获取 AppData\Local 文件夹的 ID
LPITEMIDLIST pidl = NULL;
SHGetSpecialFolderLocation(NULL, CSIDL_LOCAL_APPDATA, &pidl);
if (pidl && SHGetPathFromIDList(pidl, szDocument))
{
// 获取文件夹路径
GetShortPathName(szDocument, m_lpszDefaultDir, _MAX_PATH);
}
return m_lpszDefaultDir;
}
TString FileUtils::getDefaultSavePath()
{
TCHAR m_lpszDefaultDir[MAX_PATH] = { 0 };
TCHAR szDocument[MAX_PATH] = { 0 };
// 获取 AppData\Local 文件夹的 ID
LPITEMIDLIST pidl = NULL;
SHGetSpecialFolderLocation(NULL, CSIDL_LOCAL_APPDATA, &pidl);
if (pidl && SHGetPathFromIDList(pidl, szDocument))
{
// 获取文件夹路径
GetShortPathName(szDocument, m_lpszDefaultDir, _MAX_PATH);
}
TString path = m_lpszDefaultDir;
path.append(_T("\\"));
path.append(EApp::getAppName());
#ifdef UNICODE
if (_waccess(path.c_str(), 0) == -1)
{
_wmkdir(path.c_str());
}
#else
if (_access(path.c_str(), 0) == -1)
{
_mkdir(path.c_str());
}
#endif
path.append(_T("\\DefaultData.ini"));
return path;
}
void FileUtils::saveInt(LPCTSTR key, int value)
{
#ifdef UNICODE
std::wstringstream ss;
#else
std::stringstream ss;
#endif
ss << value;
::WritePrivateProfileString(_T("Default"), key, ss.str().c_str(), getDefaultSavePath().c_str());
}
void FileUtils::saveDouble(LPCTSTR key, double value)
{
#ifdef UNICODE
std::wstringstream ss;
#else
std::stringstream ss;
#endif
ss << value;
::WritePrivateProfileString(_T("Default"), key, ss.str().c_str(), getDefaultSavePath().c_str());
}
void FileUtils::saveString(LPCTSTR key, TString value)
{
::WritePrivateProfileString(_T("Default"), key, value.c_str(), getDefaultSavePath().c_str());
}
int FileUtils::getInt(LPCTSTR key, int default)
{
return ::GetPrivateProfileInt(_T("Default"), key, default, getDefaultSavePath().c_str());
}
#include <iostream>
using namespace std;
double FileUtils::getDouble(LPCTSTR key, double default)
{
// 将 default 参数转化为字符串
#ifdef UNICODE
std::wstringstream ss;
#else
std::stringstream ss;
#endif
ss << default;
// 读取数据
TCHAR temp[128] = { 0 };
::GetPrivateProfileString(_T("Default"), key, ss.str().c_str(), temp, 128, getDefaultSavePath().c_str());
// 转换为字符串流
ss.str(_T(""));
ss << temp;
// 将字符串转化为 double
#ifdef UNICODE
double d = _wtof(ss.str().c_str());
#else
double d = atof(ss.str().c_str());
#endif
return d;
}
TString FileUtils::geTString(LPCTSTR key, TString default)
{
TCHAR temp[128] = { 0 };
::GetPrivateProfileString(_T("Default"), key, default.c_str(), temp, 128, getDefaultSavePath().c_str());
return TString(temp);
}
TString FileUtils::getFileExtension(const TString & filePath)
{
TString fileExtension;
// 找到文件名中的最后一个 '.' 的位置
size_t pos = filePath.find_last_of('.');
// 判断 pos 是否是个有效位置
if (pos != TString::npos)
{
// 截取扩展名
fileExtension = filePath.substr(pos, filePath.length());
// 转换为小写字母
std::transform(fileExtension.begin(), fileExtension.end(), fileExtension.begin(), ::tolower);
}
return fileExtension;
}
bool FileUtils::getSaveFilePath(TString& path, LPCTSTR title, LPCTSTR defExt)
{
// 弹出保存对话框
OPENFILENAME ofn = { 0 };
TCHAR strFilename[MAX_PATH] = { 0 }; // 用于接收文件名
ofn.lStructSize = sizeof(OPENFILENAME); // 结构体大小
ofn.hwndOwner = GetHWnd(); // 拥有着窗口句柄NULL 表示对话框是非模态的
ofn.lpstrFilter = _T("所有文件\0*.*\0\0"); // 设置过滤
ofn.nFilterIndex = 1; // 过滤器索引
ofn.lpstrFile = strFilename; // 接收返回的文件路径和文件名
ofn.nMaxFile = sizeof(strFilename); // 缓冲区长度
ofn.lpstrInitialDir = NULL; // 初始目录为默认
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;// 目录必须存在,覆盖文件前发出警告
ofn.lpstrTitle = title; // 使用系统默认标题留空即可
ofn.lpstrDefExt = defExt; // 默认追加的扩展名
if (GetSaveFileName(&ofn))
{
path = strFilename;
return true;
}
return false;
}

View File

@ -1,9 +0,0 @@
#include "..\easy2d.h"
std::default_random_engine &Math::getEngine()
{
static std::random_device device;
static std::default_random_engine engine(device());
return engine;
}

View File

@ -1,417 +0,0 @@
#include "..\easy2d.h"
#include <mmsystem.h>
#pragma comment(lib , "winmm.lib")
#include <Digitalv.h>
#include <map>
////////////////////////////////////////////////////////////////////
// MciPlayer
////////////////////////////////////////////////////////////////////
class MciPlayer
{
public:
MciPlayer();
~MciPlayer();
void close();
void open(TString pFileName, UINT uId);
void play(bool bLoop = false);
void pause();
void resume();
void stop();
void rewind();
void setVolume(float volume);
bool isPlaying();
UINT getSoundID();
private:
void _sendCommand(int nCommand, DWORD_PTR param1 = 0, DWORD_PTR parma2 = 0);
MCIDEVICEID m_dev;
UINT m_nSoundID;
bool m_bPlaying;
bool m_bLoop;
TString m_sExt;
};
MciPlayer::MciPlayer() :
m_dev(0L),
m_nSoundID(0),
m_bPlaying(false),
m_bLoop(false),
m_sExt(_T(""))
{
}
MciPlayer::~MciPlayer()
{
close(); // 关闭播放器
}
void MciPlayer::open(TString pFileName, UINT uId)
{
// 忽略不存在的文件
if (pFileName.empty() || !PathFileExists(pFileName.c_str())) return;
// 获取文件后缀名
m_sExt = FileUtils::getFileExtension(pFileName);
// 停止当前音乐
close();
// 设置 MCI_OPEN_PARMS 参数
MCI_OPEN_PARMS mciOpen = { 0 };
mciOpen.lpstrDeviceType = (LPCTSTR)-1; // device ID for "all devices"
mciOpen.lpstrElementName = pFileName.c_str();
// 打开这个文件
MCIERROR mciError;
mciError = mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast<DWORD_PTR>(&mciOpen));
// 出现错误时,忽略这次操作
if (mciError) return;
// 保存设备等信息
m_dev = mciOpen.wDeviceID;
m_nSoundID = uId;
m_bPlaying = 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 | (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);
}
// 恢复默认属性
m_dev = 0;
m_bPlaying = false;
}
void MciPlayer::pause()
{
// 暂停音乐
_sendCommand(MCI_PAUSE);
m_bPlaying = false;
}
void MciPlayer::resume()
{
// 继续音乐
if (m_sExt == _T(".mid"))
{
// midi 不支持 MCI_RESUME 参数,应使用 MCI_FROM 设置播放起始位置
// 获取 MCI 状态
MCI_STATUS_PARMS mciStatusParms;
mciStatusParms.dwItem = MCI_STATUS_POSITION;
_sendCommand(MCI_STATUS, MCI_STATUS_ITEM, reinterpret_cast<DWORD_PTR>(&mciStatusParms));
// 设置播放起始位置,并开始播放
MCI_PLAY_PARMS mciPlayParms;
mciPlayParms.dwFrom = (DWORD)mciStatusParms.dwReturn;
_sendCommand(MCI_PLAY, MCI_FROM, reinterpret_cast<DWORD_PTR>(&mciPlayParms));
}
else
{
// 继续播放音乐
_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 };
m_bPlaying = mciSendCommand(m_dev, MCI_PLAY, (m_bLoop ? MCI_DGV_PLAY_REPEAT : 0), reinterpret_cast<DWORD_PTR>(&mciPlay)) ? false : true;
}
void MciPlayer::setVolume(float volume)
{
volume = min(max(volume, 0), 1);
MCI_DGV_SETAUDIO_PARMS mciSetAudioPara = { 0 };
mciSetAudioPara.dwItem = MCI_DGV_SETAUDIO_VOLUME;
mciSetAudioPara.dwValue = DWORD(1000 * volume);
mciSendCommand(m_dev, MCI_SETAUDIO, MCI_DGV_SETAUDIO_VALUE | MCI_DGV_SETAUDIO_ITEM, (DWORD_PTR)&mciSetAudioPara);
}
bool MciPlayer::isPlaying()
{
return m_bPlaying;
}
UINT 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);
}
////////////////////////////////////////////////////////////////////
// MusicUtils
////////////////////////////////////////////////////////////////////
typedef std::map<unsigned int, MciPlayer *> MusicList;
typedef std::pair<unsigned int, MciPlayer *> Music;
static unsigned int _Hash(TString key);
static MusicList& getMciPlayerList()
{
static MusicList s_List;
return s_List;
}
static MciPlayer& getBgMciPlayer()
{
static MciPlayer s_Music;
return s_Music;
}
void MusicUtils::end()
{
// 停止背景音乐
getBgMciPlayer().close();
// 停止其他所有音乐
for (auto& iter : getMciPlayerList())
{
SafeDelete(iter.second);
}
// 清空音乐列表
getMciPlayerList().clear();
return;
}
void MusicUtils::setVolume(float volume)
{
// 设置背景音乐音量
getBgMciPlayer().setVolume(volume);
// 设置其他音乐音量
for (auto& iter : getMciPlayerList())
{
iter.second->setVolume(volume);
}
}
void MusicUtils::setVolume(TString pszFilePath, float volume)
{
unsigned int nRet = ::_Hash(pszFilePath);
MusicList::iterator p = getMciPlayerList().find(nRet);
if (p != getMciPlayerList().end())
{
p->second->setVolume(volume);
}
}
void MusicUtils::playBackgroundMusic(TString pszFilePath, bool bLoop)
{
if (pszFilePath.empty())
{
return;
}
getBgMciPlayer().open(pszFilePath, ::_Hash(pszFilePath));
getBgMciPlayer().play(bLoop);
}
void MusicUtils::stopBackgroundMusic(bool bReleaseData)
{
if (bReleaseData)
{
getBgMciPlayer().close();
}
else
{
getBgMciPlayer().stop();
}
}
void MusicUtils::pauseBackgroundMusic()
{
getBgMciPlayer().pause();
}
void MusicUtils::resumeBackgroundMusic()
{
getBgMciPlayer().resume();
}
void MusicUtils::rewindBackgroundMusic()
{
getBgMciPlayer().rewind();
}
bool MusicUtils::isBackgroundMusicPlaying()
{
return getBgMciPlayer().isPlaying();
}
void MusicUtils::setBackgroundMusicVolume(float volume)
{
getBgMciPlayer().setVolume(volume);
}
unsigned int MusicUtils::playMusic(TString pszFilePath, bool bLoop)
{
unsigned int nRet = ::_Hash(pszFilePath);
preloadMusic(pszFilePath);
MusicList::iterator p = getMciPlayerList().find(nRet);
if (p != getMciPlayerList().end())
{
p->second->play(bLoop);
}
return nRet;
}
void MusicUtils::stopMusic(unsigned int nSoundId)
{
MusicList::iterator p = getMciPlayerList().find(nSoundId);
if (p != getMciPlayerList().end())
{
p->second->stop();
}
}
void MusicUtils::preloadMusic(TString pszFilePath)
{
if (pszFilePath.empty()) return;
int nRet = ::_Hash(pszFilePath);
if (getMciPlayerList().end() != getMciPlayerList().find(nRet)) return;
getMciPlayerList().insert(Music(nRet, new MciPlayer()));
MciPlayer * pPlayer = getMciPlayerList()[nRet];
pPlayer->open(pszFilePath, nRet);
if (nRet == pPlayer->getSoundID()) return;
delete pPlayer;
getMciPlayerList().erase(nRet);
nRet = 0;
}
void MusicUtils::pauseMusic(unsigned int nSoundId)
{
MusicList::iterator p = getMciPlayerList().find(nSoundId);
if (p != getMciPlayerList().end())
{
p->second->pause();
}
}
void MusicUtils::pauseAllMusics()
{
for (auto& iter : getMciPlayerList())
{
iter.second->pause();
}
}
void MusicUtils::resumeMusic(unsigned int nSoundId)
{
MusicList::iterator p = getMciPlayerList().find(nSoundId);
if (p != getMciPlayerList().end())
{
p->second->resume();
}
}
void MusicUtils::resumeAllMusics()
{
for (auto& iter : getMciPlayerList())
{
iter.second->resume();
}
}
void MusicUtils::stopAllMusics()
{
for (auto& iter : getMciPlayerList())
{
iter.second->stop();
}
}
void MusicUtils::unloadMusic(LPCTSTR pszFilePath)
{
unsigned int nID = ::_Hash(pszFilePath);
MusicList::iterator p = getMciPlayerList().find(nID);
if (p != getMciPlayerList().end())
{
SafeDelete(p->second);
getMciPlayerList().erase(nID);
}
}
unsigned int _Hash(TString key)
{
unsigned int len = unsigned(key.size());
unsigned int hash = 0;
for (unsigned i = 0; i < len; i++)
{
hash *= 16777619;
hash ^= (unsigned int)(unsigned char)toupper(key[i]);
}
return (hash);
}

View File

@ -1,223 +0,0 @@
#include "..\easy2d.h"
#include "..\Win\winbase.h"
// 储存所有定时器的容器
static std::vector<Timer*> s_vTimers;
Timer::Timer(TString name, LONGLONG milliSeconds, const TIMER_CALLBACK & callback) :
m_sName(name),
m_bRunning(false),
m_bWaiting(false),
m_callback(callback),
m_pParentScene(nullptr)
{
setInterval(milliSeconds); // 设置定时器的时间间隔
}
Timer::~Timer()
{
}
void Timer::start()
{
// 标志该定时器正在运行
m_bRunning = true;
// 记录当前时间
m_nLast = steady_clock::now();
}
void Timer::stop()
{
m_bRunning = false; // 标志该定时器已停止
}
void Timer::wait()
{
m_bWaiting = true;
}
void Timer::notify()
{
m_bWaiting = false;
}
bool Timer::isRunning()
{
return m_bRunning && !m_bWaiting; // 获取该定时器的运行状态
}
void Timer::setInterval(LONGLONG milliSeconds)
{
// 设置定时器的时间间隔
m_nAnimationInterval = milliSeconds;
}
void Timer::setCallback(const TIMER_CALLBACK & callback)
{
m_callback = callback; // 保存回调函数
}
void Timer::setName(TString name)
{
m_sName = name; // 修改定时器名称
}
LONGLONG Timer::getInterval() const
{
return m_nAnimationInterval;// 获取定时器的时间间隔
}
TString Timer::getName() const
{
return m_sName; // 获取定时器的名称
}
void Timer::__exec()
{
// 定时器容器为空
if (!s_vTimers.size())
{
return;
}
// 循环遍历所有的定时器
for (auto timer : s_vTimers)
{
// 若定时器未运行,跳过这个定时器
if (!timer->isRunning())
{
continue;
}
// 判断时间间隔是否足够
while (duration_cast<milliseconds>(GetNow() - timer->m_nLast).count() > timer->m_nAnimationInterval)
{
// 重新记录时间
timer->m_nLast += milliseconds(timer->m_nAnimationInterval);
// 运行回调函数
timer->m_callback();
}
}
}
void Timer::addTimer(Timer * timer)
{
// 启动定时器
timer->start();
// 绑定在场景上
timer->m_pParentScene = EApp::getLoadingScene();
// 将该定时器放入容器
s_vTimers.push_back(timer);
}
void Timer::addTimer(TString name, const TIMER_CALLBACK & callback)
{
addTimer(name, 20, callback);
}
void Timer::addTimer(TString name, LONGLONG milliSeconds, const TIMER_CALLBACK & callback)
{
// 创建定时器
auto timer = new Timer(name, milliSeconds, callback);
// 添加定时器
addTimer(timer);
}
void Timer::startTimer(TString name)
{
// 查找名称相同的定时器
for (auto timer : s_vTimers)
{
if (timer->m_sName == name && timer->m_pParentScene == EApp::getCurrentScene())
{
// 启动定时器
timer->start();
}
}
}
void Timer::stopTimer(TString name)
{
// 查找名称相同的定时器
for (auto timer : s_vTimers)
{
if (timer->m_sName == name && timer->m_pParentScene == EApp::getCurrentScene())
{
// 停止定时器
timer->stop();
}
}
}
void Timer::delTimer(TString name)
{
// 创建迭代器
std::vector<Timer*>::iterator iter;
// 循环遍历所有定时器
for (iter = s_vTimers.begin(); iter != s_vTimers.end();)
{
// 查找相同名称的定时器
if ((*iter)->m_sName == name && (*iter)->m_pParentScene == EApp::getCurrentScene())
{
// 删除该定时器
delete (*iter);
iter = s_vTimers.erase(iter);
}
else
{
iter++;
}
}
}
void Timer::clearAllTimers()
{
// 删除所有定时器
for (auto t : s_vTimers)
{
delete t;
}
// 清空容器
s_vTimers.clear();
}
void Timer::notifyAllSceneTimers(EScene * scene)
{
for (auto t : s_vTimers)
{
if (t->m_pParentScene == scene)
{
t->notify();
}
}
}
void Timer::waitAllSceneTimers(EScene * scene)
{
for (auto t : s_vTimers)
{
if (t->m_pParentScene == scene)
{
t->wait();
}
}
}
void Timer::clearAllSceneTimers(EScene * scene)
{
// 创建迭代器
std::vector<Timer*>::iterator iter;
// 循环遍历所有定时器
for (iter = s_vTimers.begin(); iter != s_vTimers.end();)
{
// 查找相同名称的定时器
if ((*iter)->m_pParentScene == scene)
{
// 删除该定时器
delete (*iter);
iter = s_vTimers.erase(iter);
}
else
{
iter++;
}
}
}

File diff suppressed because it is too large Load Diff