diff --git a/Easy2D/Action/Action.cpp b/Easy2D/Action/Action.cpp new file mode 100644 index 00000000..d2c008d3 --- /dev/null +++ b/Easy2D/Action/Action.cpp @@ -0,0 +1,56 @@ +#include "..\easy2d.h" +#include + +Action::Action() : + m_bRunning(true), + m_bStop(false), + m_pParent(nullptr) +{ + // 默认动作 15ms 运行一次 + setInterval(15); +} + +Action::~Action() +{ +} + +bool Action::isRunning() +{ + return m_bRunning; +} + +void Action::start() +{ + m_bRunning = true; +} + +void Action::resume() +{ + m_bRunning = true; +} + +void Action::pause() +{ + m_bRunning = false; +} + +void Action::stop() +{ + m_bStop = true; +} + +void Action::setInterval(UINT ms) +{ + // 设置动作的时间间隔 + LARGE_INTEGER nFreq; + QueryPerformanceFrequency(&nFreq); + m_nAnimationInterval.QuadPart = (LONGLONG)(ms / 1000.0 * nFreq.QuadPart); + // 保存时间间隔的时长 + this->m_nMilliSeconds = ms; +} + +Action * Action::reverse() const +{ + assert(0); + return nullptr; +} diff --git a/Easy2D/Action/ActionCallback.cpp b/Easy2D/Action/ActionCallback.cpp new file mode 100644 index 00000000..d3bb6c0e --- /dev/null +++ b/Easy2D/Action/ActionCallback.cpp @@ -0,0 +1,32 @@ +#include "..\easy2d.h" + +ActionCallback::ActionCallback(const std::function& callback) : + m_Callback(callback) +{ +} + +ActionCallback::~ActionCallback() +{ +} + +ActionCallback * ActionCallback::copy() +{ + return new ActionCallback(m_Callback); +} + +void ActionCallback::_init() +{ +} + +bool ActionCallback::_exec(LARGE_INTEGER nNow) +{ + if (!m_bStop) + { + m_Callback(); + } + return true; +} + +void ActionCallback::_reset() +{ +} diff --git a/Easy2D/Action/ActionDelay.cpp b/Easy2D/Action/ActionDelay.cpp new file mode 100644 index 00000000..6c546eb8 --- /dev/null +++ b/Easy2D/Action/ActionDelay.cpp @@ -0,0 +1,40 @@ +#include "..\easy2d.h" + +ActionDelay::ActionDelay(float duration) +{ + setInterval(UINT(duration * 1000)); +} + +ActionDelay::~ActionDelay() +{ +} + +ActionDelay * easy2d::ActionDelay::copy() +{ + return new ActionDelay(*this); +} + +void ActionDelay::_init() +{ + // 记录当前时间 + QueryPerformanceCounter(&m_nLast); +} + +bool ActionDelay::_exec(LARGE_INTEGER nNow) +{ + if (m_bStop) return true; + if (!m_bRunning) return false; + + // 判断时间间隔是否足够 + if (nNow.QuadPart - m_nLast.QuadPart > m_nAnimationInterval.QuadPart) + { + return true; + } + return false; +} + +void ActionDelay::_reset() +{ + // 重新记录当前时间 + QueryPerformanceCounter(&m_nLast); +} diff --git a/Easy2D/Action/ActionFrames.cpp b/Easy2D/Action/ActionFrames.cpp new file mode 100644 index 00000000..225189ea --- /dev/null +++ b/Easy2D/Action/ActionFrames.cpp @@ -0,0 +1,74 @@ +#include "..\easy2d.h" + +ActionFrames::ActionFrames() : + m_nFrameIndex(0) +{ + // 帧动画默认 .5s 刷新一次 + setInterval(500); +} + +ActionFrames::~ActionFrames() +{ + for (auto frame : m_vFrames) + { + frame->release(); + } +} + +void ActionFrames::_init() +{ + // 记录当前时间 + QueryPerformanceCounter(&m_nLast); +} + +bool ActionFrames::_exec(LARGE_INTEGER nNow) +{ + if (m_bStop) return true; + if (!m_bRunning) return false; + + // 判断时间间隔是否足够 + while (nNow.QuadPart - m_nLast.QuadPart > m_nAnimationInterval.QuadPart) + { + // 用求余的方法重新记录时间 + m_nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart % m_nAnimationInterval.QuadPart); + m_pParent->setImage(m_vFrames[m_nFrameIndex]); + m_nFrameIndex++; + if (m_nFrameIndex == m_vFrames.size()) + { + return true; + } + } + return false; +} + +void ActionFrames::_reset() +{ + m_nFrameIndex = 0; +} + +void ActionFrames::addFrame(Image * frame) +{ + if (frame) + { + m_vFrames.push_back(frame); + frame->retain(); + } +} + +ActionFrames * ActionFrames::copy() +{ + auto a = new ActionFrames(); + for (auto f : m_vFrames) + { + a->addFrame(f); + } + return a; +} + +ActionFrames * ActionFrames::reverse() const +{ + auto a = new ActionFrames(); + a->m_vFrames = this->m_vFrames; + a->m_vFrames.reserve(m_vFrames.size()); + return a; +} diff --git a/Easy2D/Action/ActionMoveBy.cpp b/Easy2D/Action/ActionMoveBy.cpp new file mode 100644 index 00000000..7859ca47 --- /dev/null +++ b/Easy2D/Action/ActionMoveBy.cpp @@ -0,0 +1,55 @@ +#include "..\easy2d.h" + +ActionMoveBy::ActionMoveBy(float duration, CVector vec) : + Animation(duration) +{ + m_MoveVector = vec; +} + +ActionMoveBy::~ActionMoveBy() +{ +} + +void ActionMoveBy::_init() +{ + Animation::_init(); + m_BeginPos = m_pParent->getPos(); +} + +bool ActionMoveBy::_exec(LARGE_INTEGER nNow) +{ + if (m_bStop) return true; + if (!m_bRunning) return false; + + while (Animation::_exec(nNow)) + { + // 计算移动位置 + float scale = float(m_nDuration) / m_nTotalDuration; + // 移动 Sprite + m_pParent->setPos(int(m_BeginPos.x + m_MoveVector.x * scale), + int(m_BeginPos.y + m_MoveVector.y * scale)); + // 判断动作是否结束 + if (m_nDuration >= m_nTotalDuration) + { + return true; + } + } + return false; +} + +void ActionMoveBy::_reset() +{ + Animation::_reset(); +} + +ActionMoveBy * ActionMoveBy::copy() +{ + auto a = new ActionMoveBy(*this); + a->_reset(); + return a; +} + +ActionMoveBy * ActionMoveBy::reverse() const +{ + return new ActionMoveBy(m_nTotalDuration / 1000.0f, CVector(-m_MoveVector.x, -m_MoveVector.y)); +} \ No newline at end of file diff --git a/Easy2D/Action/ActionMoveTo.cpp b/Easy2D/Action/ActionMoveTo.cpp new file mode 100644 index 00000000..cc9830fe --- /dev/null +++ b/Easy2D/Action/ActionMoveTo.cpp @@ -0,0 +1,29 @@ +#include "..\easy2d.h" + +ActionMoveTo::ActionMoveTo(float duration, CPoint pos) : + ActionMoveBy(duration, CVector()) +{ + m_EndPos = pos; +} + +ActionMoveTo::~ActionMoveTo() +{ +} + +ActionMoveTo * ActionMoveTo::copy() +{ + auto a = new ActionMoveTo(*this); + a->_reset(); + return a; +} + +void ActionMoveTo::_init() +{ + ActionMoveBy::_init(); + m_MoveVector = m_EndPos - m_BeginPos; +} + +void ActionMoveTo::_reset() +{ + ActionMoveBy::_reset(); +} diff --git a/Easy2D/Action/ActionNeverStop.cpp b/Easy2D/Action/ActionNeverStop.cpp new file mode 100644 index 00000000..ffa82eeb --- /dev/null +++ b/Easy2D/Action/ActionNeverStop.cpp @@ -0,0 +1,41 @@ +#include "..\easy2d.h" + +ActionNeverStop::ActionNeverStop(Action * action) : + m_Action(action) +{ + m_Action->retain(); +} + +ActionNeverStop::~ActionNeverStop() +{ + SAFE_RELEASE(m_Action); +} + +ActionNeverStop * ActionNeverStop::copy() +{ + return new ActionNeverStop(m_Action->copy()); +} + +void ActionNeverStop::_init() +{ + m_Action->m_pParent = m_pParent; + m_Action->_init(); +} + +bool ActionNeverStop::_exec(LARGE_INTEGER nNow) +{ + if (m_bStop) return true; + if (!m_bRunning) return false; + + if (m_Action->_exec(nNow)) + { + m_Action->_reset(); + } + // 永不结束 + return false; +} + +void ActionNeverStop::_reset() +{ + m_Action->_reset(); +} diff --git a/Easy2D/Action/ActionOpacityBy.cpp b/Easy2D/Action/ActionOpacityBy.cpp new file mode 100644 index 00000000..f1838340 --- /dev/null +++ b/Easy2D/Action/ActionOpacityBy.cpp @@ -0,0 +1,54 @@ +#include "..\easy2d.h" + +ActionOpacityBy::ActionOpacityBy(float duration, float opacity) : + Animation(duration) +{ + m_nVariation = opacity; +} + +ActionOpacityBy::~ActionOpacityBy() +{ +} + +void ActionOpacityBy::_init() +{ + Animation::_init(); + m_nBeginVal = m_pParent->getOpacity(); +} + +bool ActionOpacityBy::_exec(LARGE_INTEGER nNow) +{ + if (m_bStop) return true; + if (!m_bRunning) return false; + + while (Animation::_exec(nNow)) + { + // 计算移动位置 + float scale = float(m_nDuration) / m_nTotalDuration; + // 移动 Sprite + m_pParent->setOpacity(m_nBeginVal + m_nVariation * scale); + // 判断动作是否结束 + if (m_nDuration >= m_nTotalDuration) + { + return true; + } + } + return false; +} + +void ActionOpacityBy::_reset() +{ + Animation::_reset(); +} + +ActionOpacityBy * ActionOpacityBy::copy() +{ + auto a = new ActionOpacityBy(*this); + a->_reset(); + return a; +} + +ActionOpacityBy * ActionOpacityBy::reverse() const +{ + return new ActionOpacityBy(m_nTotalDuration / 1000.0f, -m_nVariation); +} \ No newline at end of file diff --git a/Easy2D/Action/ActionOpacityTo.cpp b/Easy2D/Action/ActionOpacityTo.cpp new file mode 100644 index 00000000..87feb328 --- /dev/null +++ b/Easy2D/Action/ActionOpacityTo.cpp @@ -0,0 +1,29 @@ +#include "..\easy2d.h" + +ActionOpacityTo::ActionOpacityTo(float duration, float opacity) : + ActionOpacityBy(duration, 0) +{ + m_nEndVal = opacity; +} + +ActionOpacityTo::~ActionOpacityTo() +{ +} + +ActionOpacityTo * ActionOpacityTo::copy() +{ + auto a = new ActionOpacityTo(*this); + a->_reset(); + return a; +} + +void ActionOpacityTo::_init() +{ + ActionOpacityBy::_init(); + m_nVariation = m_nEndVal - m_nBeginVal; +} + +void ActionOpacityTo::_reset() +{ + ActionOpacityBy::_reset(); +} diff --git a/Easy2D/Action/ActionScaleBy.cpp b/Easy2D/Action/ActionScaleBy.cpp new file mode 100644 index 00000000..0ef21217 --- /dev/null +++ b/Easy2D/Action/ActionScaleBy.cpp @@ -0,0 +1,56 @@ +#include "..\easy2d.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_pParent->getScaleX(); + m_nBeginScaleY = m_pParent->getScaleY(); +} + +bool ActionScaleBy::_exec(LARGE_INTEGER nNow) +{ + if (m_bStop) return true; + if (!m_bRunning) return false; + + while (Animation::_exec(nNow)) + { + // 计算移动位置 + float scale = float(m_nDuration) / m_nTotalDuration; + // 移动 Sprite + m_pParent->setScale(m_nBeginScaleX + m_nVariationX * scale, m_nBeginScaleX + m_nVariationX * scale); + // 判断动作是否结束 + if (m_nDuration >= m_nTotalDuration) + { + return true; + } + } + return false; +} + +void ActionScaleBy::_reset() +{ + Animation::_reset(); +} + +ActionScaleBy * ActionScaleBy::copy() +{ + auto a = new ActionScaleBy(*this); + a->_reset(); + return a; +} + +ActionScaleBy * ActionScaleBy::reverse() const +{ + return new ActionScaleBy(m_nTotalDuration / 1000.0f, -m_nVariationX, -m_nVariationY); +} \ No newline at end of file diff --git a/Easy2D/Action/ActionScaleTo.cpp b/Easy2D/Action/ActionScaleTo.cpp new file mode 100644 index 00000000..b4324e37 --- /dev/null +++ b/Easy2D/Action/ActionScaleTo.cpp @@ -0,0 +1,31 @@ +#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() +{ + auto a = new ActionScaleTo(*this); + a->_reset(); + return a; +} + +void ActionScaleTo::_init() +{ + ActionScaleBy::_init(); + m_nVariationX = m_nEndScaleX - m_nBeginScaleX; + m_nVariationY = m_nEndScaleY - m_nBeginScaleY; +} + +void ActionScaleTo::_reset() +{ + ActionScaleBy::_reset(); +} diff --git a/Easy2D/Action/ActionSequence.cpp b/Easy2D/Action/ActionSequence.cpp new file mode 100644 index 00000000..a0fc8773 --- /dev/null +++ b/Easy2D/Action/ActionSequence.cpp @@ -0,0 +1,89 @@ +#include "..\easy2d.h" +#include + +ActionSequence::ActionSequence(int number, Action * action1, ...) : + m_nActionIndex(0) +{ + va_list params; + va_start(params, number); + + while (number > 0) + { + Action* arg = va_arg(params, Action*); + arg->retain(); + m_vActions.push_back(arg); + number--; + } + + va_end(params); +} + +ActionSequence::~ActionSequence() +{ + for (auto action : m_vActions) + { + SAFE_RELEASE(action); + } +} + +void ActionSequence::_init() +{ + for (auto action : m_vActions) + { + action->m_pParent = m_pParent; + } + m_vActions[0]->_init(); +} + +bool ActionSequence::_exec(LARGE_INTEGER nNow) +{ + if (m_bStop) return true; + if (!m_bRunning) return false; + + if (m_vActions[m_nActionIndex]->_exec(nNow)) + { + m_nActionIndex++; + if (m_nActionIndex == m_vActions.size()) + { + return true; + } + else + { + m_vActions[m_nActionIndex]->_init(); + } + } + return false; +} + +void ActionSequence::_reset() +{ + for (auto action : m_vActions) + { + action->_reset(); + } + m_nActionIndex = 0; +} + +ActionSequence * ActionSequence::copy() +{ + auto a = new ActionSequence(*this); + a->_reset(); + return a; +} + +ActionSequence * ActionSequence::reverse() const +{ + // 复制一个相同的动作 + auto a = new ActionSequence(*this); + a->_reset(); + a->m_bRunning = true; + a->m_bStop = false; + // 将动作顺序逆序排列 + a->m_vActions.reserve(m_vActions.size()); + // 将所有动作逆向运行 + for (auto action : a->m_vActions) + { + action->reverse(); + } + return a; +} \ No newline at end of file diff --git a/Easy2D/Action/ActionTwo.cpp b/Easy2D/Action/ActionTwo.cpp new file mode 100644 index 00000000..82b45c6a --- /dev/null +++ b/Easy2D/Action/ActionTwo.cpp @@ -0,0 +1,73 @@ +#include "..\easy2d.h" + +ActionTwo::ActionTwo(Action * actionFirst, Action * actionSecond) : + m_FirstAction(actionFirst), + m_SecondAction(actionSecond) +{ + if (m_FirstAction) m_FirstAction->retain(); + if (m_SecondAction) m_SecondAction->retain(); +} + +ActionTwo::~ActionTwo() +{ + SAFE_RELEASE(m_FirstAction); + SAFE_RELEASE(m_SecondAction); +} + +ActionTwo * ActionTwo::copy() +{ + auto a = new ActionTwo(*this); + a->_reset(); + return a; +} + +ActionTwo * ActionTwo::reverse() const +{ + return new ActionTwo(m_SecondAction->copy(), m_FirstAction->copy()); +} + +void ActionTwo::_init() +{ + m_FirstAction->m_pParent = m_pParent; + m_FirstAction->_init(); + + m_SecondAction->m_pParent = m_pParent; +} + +bool ActionTwo::_exec(LARGE_INTEGER nNow) +{ + if (m_bStop) return true; + if (!m_bRunning) return false; + + if (m_FirstAction) + { + if (m_FirstAction->_exec(nNow)) + { + // 返回 true 表示第一个动作已经结束,删除这个 + // 动作,并初始化第二个动作 + SAFE_RELEASE(m_FirstAction); + m_FirstAction = nullptr; + m_SecondAction->_init(); + } + } + else if (m_SecondAction) + { + if (m_SecondAction->_exec(nNow)) + { + SAFE_RELEASE(m_SecondAction); + m_SecondAction = nullptr; + return true; + } + } + else + { + return true; + } + return false; +} + +void ActionTwo::_reset() +{ + if (m_FirstAction) m_FirstAction->_reset(); + if (m_SecondAction) m_SecondAction->_reset(); +} diff --git a/Easy2D/Action/Animation.cpp b/Easy2D/Action/Animation.cpp new file mode 100644 index 00000000..c5901a1c --- /dev/null +++ b/Easy2D/Action/Animation.cpp @@ -0,0 +1,37 @@ +#include "..\easy2d.h" + +Animation::Animation(float duration) +{ + m_nDuration = 0; + m_nTotalDuration = UINT(duration * 1000); +} + +Animation::~Animation() +{ +} + +void Animation::_init() +{ + // 记录当前时间 + QueryPerformanceCounter(&m_nLast); +} + +bool Animation::_exec(LARGE_INTEGER nNow) +{ + // 判断时间间隔是否足够 + if (nNow.QuadPart - m_nLast.QuadPart > m_nAnimationInterval.QuadPart) + { + // 用求余的方法重新记录时间 + m_nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart % m_nAnimationInterval.QuadPart); + m_nDuration += m_nMilliSeconds; + return true; + } + return false; +} + +void Animation::_reset() +{ + m_nDuration = 0; + // 重新记录当前时间 + QueryPerformanceCounter(&m_nLast); +} diff --git a/Easy2D/App.cpp b/Easy2D/Base/App.cpp similarity index 74% rename from Easy2D/App.cpp rename to Easy2D/Base/App.cpp index 811fea1f..e025d384 100644 --- a/Easy2D/App.cpp +++ b/Easy2D/Base/App.cpp @@ -1,5 +1,5 @@ -#include "easy2d.h" -#include "EasyX\easyx.h" +#include "..\easy2d.h" +#include "..\EasyX\easyx.h" #include #include #include @@ -7,9 +7,6 @@ #include #pragma comment(lib, "winmm.lib") -// Easy2D 版本号 -#define E2D_VERSION _T("1.0.4") - // App 的唯一实例 static App * s_pInstance = nullptr; // 坐标原点的物理坐标 @@ -17,11 +14,9 @@ static int originX = 0; static int originY = 0; App::App() : - m_currentScene(nullptr), - m_nextScene(nullptr), + m_CurrentScene(nullptr), + m_NextScene(nullptr), m_bRunning(false), - m_nWidth(0), - m_nHeight(0), m_nWindowMode(0) { assert(!s_pInstance); // 不能同时存在两个 App 实例 @@ -119,7 +114,7 @@ int App::run() void App::_initGraph() { // 创建绘图环境 - initgraph(m_nWidth, m_nHeight, m_nWindowMode); + initgraph(m_Size.cx, m_Size.cy, m_nWindowMode); // 隐藏当前窗口(防止在加载阶段显示黑窗口) ShowWindow(GetHWnd(), SW_HIDE); // 获取屏幕分辨率 @@ -157,47 +152,53 @@ void App::_initGraph() void App::_mainLoop() { // 下一场景指针不为空时,切换场景 - if (m_nextScene) + if (m_NextScene) { // 执行当前场景的 onExit 函数 - if (m_currentScene) + if (m_CurrentScene) { - m_currentScene->onExit(); + m_CurrentScene->onExit(); } // 进入下一场景 _enterNextScene(); // 执行当前场景的 onEnter 函数 - m_currentScene->onEnter(); + m_CurrentScene->onEnter(); } // 断言当前场景非空 - assert(m_currentScene); + assert(m_CurrentScene); cleardevice(); // 清空画面 - m_currentScene->_onDraw(); // 绘制当前场景 + m_CurrentScene->_onDraw(); // 绘制当前场景 FlushBatchDraw(); // 刷新画面 // 其他执行程序 MouseMsg::__exec(); // 鼠标检测 KeyMsg::__exec(); // 键盘按键检测 Timer::__exec(); // 定时器执行程序 + ActionManager::__exec(); // 动作管理器执行程序 FreePool::__flush(); // 刷新内存池 } void App::createWindow(int width, int height, int mode) { // 保存窗口信息 - m_nWidth = width; - m_nHeight = height; + m_Size.cx = width; + m_Size.cy = height; m_nWindowMode = mode; // 创建窗口 _initGraph(); } +void App::createWindow(CSize size, int mode) +{ + createWindow(size.cx, size.cy, mode); +} + void App::createWindow(tstring title, int width, int height, int mode) { // 保存窗口信息 - m_nWidth = width; - m_nHeight = height; + m_Size.cx = width; + m_Size.cy = height; m_nWindowMode = mode; m_sTitle = title; m_sAppName = title; @@ -205,10 +206,15 @@ void App::createWindow(tstring title, int width, int height, int mode) _initGraph(); } +void App::createWindow(tstring title, CSize size, int mode) +{ + createWindow(title, size.cx, size.cy, mode); +} + void App::setWindowSize(int width, int height) { // 游戏正在运行时才允许修改窗口大小 - assert(m_bRunning); + assert(s_pInstance->m_bRunning); // 获取屏幕分辨率 int screenWidth = GetSystemMetrics(SM_CXSCREEN); @@ -235,17 +241,22 @@ void App::setWindowSize(int width, int height) reset(); } +void App::setWindowSize(CSize size) +{ + setWindowSize(size.cx, size.cy); +} + void App::setWindowTitle(tstring title) { // 设置窗口标题 SetWindowText(GetHWnd(), title.c_str()); // 保存当前标题,用于修改窗口大小时恢复标题 - m_sTitle = title; + s_pInstance->m_sTitle = title; } tstring App::getWindowTitle() { - return m_sTitle; + return s_pInstance->m_sTitle; } void App::close() @@ -256,38 +267,38 @@ void App::close() void App::enterScene(Scene * scene, bool save) { // 保存下一场景的指针 - m_nextScene = scene; + s_pInstance->m_NextScene = scene; // 切换场景时,是否保存当前场景 - m_bSaveScene = save; + s_pInstance->m_bSaveScene = save; } void App::backScene() { // 从栈顶取出场景指针,作为下一场景 - m_nextScene = m_sceneStack.top(); + s_pInstance->m_NextScene = s_pInstance->m_SceneStack.top(); // 不保存当前场景 - m_bSaveScene = false; + s_pInstance->m_bSaveScene = false; } void App::clearScene() { // 清空场景栈 - while (m_sceneStack.size()) + while (s_pInstance->m_SceneStack.size()) { - auto temp = m_sceneStack.top(); + auto temp = s_pInstance->m_SceneStack.top(); SAFE_DELETE(temp); - m_sceneStack.pop(); + s_pInstance->m_SceneStack.pop(); } } void App::setAppName(tstring appname) { - m_sAppName = appname; + s_pInstance->m_sAppName = appname; } -tstring App::getAppName() const +tstring App::getAppName() { - return m_sAppName; + return s_pInstance->m_sAppName; } void App::setBkColor(COLORREF color) @@ -298,32 +309,32 @@ void App::setBkColor(COLORREF color) void App::_enterNextScene() { // 若下一场景处于栈顶,说明正在返回上一场景 - if (m_sceneStack.size() && m_nextScene == m_sceneStack.top()) + if (m_SceneStack.size() && m_NextScene == m_SceneStack.top()) { - m_sceneStack.pop(); // 删除栈顶场景 + m_SceneStack.pop(); // 删除栈顶场景 } if (m_bSaveScene) { - m_sceneStack.push(m_currentScene); // 若要保存当前场景,把它的指针放到栈顶 + m_SceneStack.push(m_CurrentScene); // 若要保存当前场景,把它的指针放到栈顶 } else { - SAFE_DELETE(m_currentScene); // 否则删除当前场景 + SAFE_DELETE(m_CurrentScene); // 否则删除当前场景 } - m_currentScene = m_nextScene; // 切换场景 - m_nextScene = nullptr; // 下一场景置空 + m_CurrentScene = m_NextScene; // 切换场景 + m_NextScene = nullptr; // 下一场景置空 } void App::quit() { - m_bRunning = false; + s_pInstance->m_bRunning = false; } void App::end() { - m_bRunning = false; + s_pInstance->m_bRunning = false; } void App::reset() @@ -337,12 +348,7 @@ void App::reset() Scene * App::getCurrentScene() { // 获取当前场景的指针 - return m_currentScene; -} - -LPCTSTR App::getVersion() -{ - return E2D_VERSION; + return s_pInstance->m_CurrentScene; } void App::setFPS(DWORD fps) @@ -350,30 +356,30 @@ void App::setFPS(DWORD fps) // 设置画面帧率,以毫秒为单位 LARGE_INTEGER nFreq; QueryPerformanceFrequency(&nFreq); - m_nAnimationInterval.QuadPart = (LONGLONG)(1.0 / fps * nFreq.QuadPart); + s_pInstance->m_nAnimationInterval.QuadPart = (LONGLONG)(1.0 / fps * nFreq.QuadPart); } -int App::getWidth() const +int App::getWidth() { - return m_nWidth; + return s_pInstance->m_Size.cx; } -int App::getHeight() const +int App::getHeight() { - return m_nHeight; + return s_pInstance->m_Size.cy; } void App::free() { // 释放场景内存 - SAFE_DELETE(m_currentScene); - SAFE_DELETE(m_nextScene); + SAFE_DELETE(m_CurrentScene); + SAFE_DELETE(m_NextScene); // 清空场景栈 - while (m_sceneStack.size()) + while (m_SceneStack.size()) { - auto temp = m_sceneStack.top(); + auto temp = m_SceneStack.top(); SAFE_DELETE(temp); - m_sceneStack.pop(); + m_SceneStack.pop(); } // 删除所有定时器 Timer::clearAllTimers(); diff --git a/Easy2D/FreePool.cpp b/Easy2D/Base/FreePool.cpp similarity index 88% rename from Easy2D/FreePool.cpp rename to Easy2D/Base/FreePool.cpp index 0a95e706..f2ab7fd0 100644 --- a/Easy2D/FreePool.cpp +++ b/Easy2D/Base/FreePool.cpp @@ -1,4 +1,5 @@ -#include "easy2d.h" +#include "..\easy2d.h" +#include // FreePool 释放池的实现机制: /// Object 类中的引用计数(m_nRef)保证了指针的使用安全 @@ -34,9 +35,12 @@ void FreePool::__flush() void FreePool::__add(Object * nptr) { +#ifdef _DEBUG for (auto o : pool) { - if (o == nptr) return; // 不得有重复的指针存在 + assert(o != nptr); // 不得有重复的指针存在 } +#endif + pool.push_back(nptr); // 将一个对象放入释放池中 } diff --git a/Easy2D/Scene.cpp b/Easy2D/Base/Scene.cpp similarity index 96% rename from Easy2D/Scene.cpp rename to Easy2D/Base/Scene.cpp index dca60aa6..ebf36cf2 100644 --- a/Easy2D/Scene.cpp +++ b/Easy2D/Base/Scene.cpp @@ -1,4 +1,4 @@ -#include "easy2d.h" +#include "..\easy2d.h" #include Scene::Scene() @@ -77,8 +77,7 @@ void Scene::add(Node * child, int zOrder) bool Scene::del(Node * child) { - // 断言节点非空 - assert(child); + if (child == nullptr) return false; // 寻找是否有相同节点 std::vector::iterator iter; diff --git a/Easy2D/Easy2D.vcxproj b/Easy2D/Easy2D.vcxproj index 240d2245..c61d5ab2 100644 --- a/Easy2D/Easy2D.vcxproj +++ b/Easy2D/Easy2D.vcxproj @@ -335,35 +335,57 @@ - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Easy2D/Easy2D.vcxproj.filters b/Easy2D/Easy2D.vcxproj.filters index 7d904b78..2ae69405 100644 --- a/Easy2D/Easy2D.vcxproj.filters +++ b/Easy2D/Easy2D.vcxproj.filters @@ -19,26 +19,26 @@ {682a1a3c-39d8-4ac9-ba03-fa90c089c9ab} - + {d6778635-8947-4f9b-9388-dd088642b5b2} - - {e5ec6183-113b-4140-8285-18b18ea37d15} - - + {065a3244-7169-4a45-bc9f-f2a80d8a9759} {72dbabab-8278-4ee4-917f-bfffb474a51b} - + {bdcd902b-b53d-4537-9632-76ea14c141a0} + + {e1501580-8f69-4ad6-a9f1-76d825572c3d} + + + {261633d3-3814-40c7-bd6d-201ede6c6ade} + - - 婧愭枃浠 - 婧愭枃浠禱Style @@ -54,44 +54,35 @@ 婧愭枃浠禱Style - - 婧愭枃浠禱Node + + 婧愭枃浠禱Object - - 婧愭枃浠禱Node + + 婧愭枃浠禱Object - - 婧愭枃浠禱Node + + 婧愭枃浠禱Object - - 婧愭枃浠禱Node + + 婧愭枃浠禱Object - - 婧愭枃浠禱Node\Sprite + + 婧愭枃浠禱Object\Shape - - 婧愭枃浠禱Node\Sprite + + 婧愭枃浠禱Object\Shape - - 婧愭枃浠禱Node\Shape + + 婧愭枃浠禱Object\Shape - - 婧愭枃浠禱Node\Shape - - - 婧愭枃浠禱Node\Shape - - - 婧愭枃浠禱Node + + 婧愭枃浠禱Object 婧愭枃浠禱Style - - 婧愭枃浠 - - - 婧愭枃浠 + + 婧愭枃浠禱Object 婧愭枃浠禱Style @@ -102,23 +93,101 @@ 婧愭枃浠禱Msg - - 婧愭枃浠 + + 婧愭枃浠禱Object\Button - - 婧愭枃浠禱Node\Button + + 婧愭枃浠禱Object\Button - - 婧愭枃浠禱Node\Button + + 婧愭枃浠禱Object\Button - - 婧愭枃浠禱Node\Button + + 婧愭枃浠禱Object - - 婧愭枃浠禱Node + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Base + + + 婧愭枃浠禱Base + + + 婧愭枃浠禱Base + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Object + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Tool + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Action + + + 婧愭枃浠禱Object + + + 婧愭枃浠禱Object + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + 澶存枃浠 diff --git a/Easy2D/Msg/MouseMsg.cpp b/Easy2D/Msg/MouseMsg.cpp index 0e8a33c8..d016fdfa 100644 --- a/Easy2D/Msg/MouseMsg.cpp +++ b/Easy2D/Msg/MouseMsg.cpp @@ -1,5 +1,6 @@ #include "..\easy2d.h" #include "..\EasyX\easyx.h" +#include "..\e2dmsg.h" // 鼠标监听回调函数的容器 static std::vector s_vMouseMsg; @@ -107,6 +108,11 @@ 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; diff --git a/Easy2D/Node/Button/Button.cpp b/Easy2D/Node/Button/Button.cpp deleted file mode 100644 index 112d3c74..00000000 --- a/Easy2D/Node/Button/Button.cpp +++ /dev/null @@ -1,44 +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; -} diff --git a/Easy2D/Node/Sprite/Sprite.cpp b/Easy2D/Node/Sprite/Sprite.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/Easy2D/Node/Sprite/SpriteFrame.cpp b/Easy2D/Node/Sprite/SpriteFrame.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/Easy2D/Node/BatchNode.cpp b/Easy2D/Object/BatchNode.cpp similarity index 85% rename from Easy2D/Node/BatchNode.cpp rename to Easy2D/Object/BatchNode.cpp index 10d2a6ac..2bdbe0d3 100644 --- a/Easy2D/Node/BatchNode.cpp +++ b/Easy2D/Object/BatchNode.cpp @@ -1,6 +1,5 @@ #include "..\easy2d.h" #include "..\EasyX\easyx.h" -#include BatchNode::BatchNode() { @@ -22,7 +21,6 @@ bool BatchNode::_exec(bool active) // 逆序遍历所有子节点 for (int i = int(m_vChildren.size() - 1); i >= 0; i--) { - assert(m_vChildren[i]); if (m_vChildren[i]->_exec(active)) { active = false; @@ -41,19 +39,18 @@ void BatchNode::_onDraw() } // 在相对位置绘制子节点 - App::setOrigin(App::getOriginX() + m_nX, App::getOriginY() + m_nY); + App::setOrigin(App::getOriginX() + getX(), App::getOriginY() + getY()); for (auto child : m_vChildren) { - assert(child); child->_onDraw(); } - App::setOrigin(App::getOriginX() - m_nX, App::getOriginY() - m_nY); + App::setOrigin(App::getOriginX() - getX(), App::getOriginY() - getY()); } void BatchNode::add(Node * child, int z_Order) { - // 断言添加的节点非空 - assert(child); + if (child == nullptr) return; + // 设置节点的父场景 child->setParentScene(this->getParentScene()); // 设置节点在批量节点中的 z 轴顺序 @@ -83,8 +80,7 @@ void BatchNode::add(Node * child, int z_Order) bool BatchNode::del(Node * child) { - // 断言节点非空 - assert(child); + if (child == nullptr) return false; // 寻找是否有相同节点 std::vector::iterator iter; diff --git a/Easy2D/Object/BatchSprite.cpp b/Easy2D/Object/BatchSprite.cpp new file mode 100644 index 00000000..3e11d844 --- /dev/null +++ b/Easy2D/Object/BatchSprite.cpp @@ -0,0 +1,174 @@ +#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::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; +} + +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; + } + + // 在相对位置绘制子节点 + App::setOrigin(App::getOriginX() + getX(), App::getOriginY() + getY()); + for (auto sprite : m_vSprites) + { + sprite->_onDraw(); + } + App::setOrigin(App::getOriginX() - getX(), App::getOriginY() - 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; +} + +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); + } +} diff --git a/Easy2D/Object/Button/Button.cpp b/Easy2D/Object/Button/Button.cpp new file mode 100644 index 00000000..21ac9c1b --- /dev/null +++ b/Easy2D/Object/Button/Button.cpp @@ -0,0 +1,81 @@ +#include "..\..\easy2d.h" +#include "..\..\EasyX\easyx.h" +#include "..\..\e2dobj.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(); +} diff --git a/Easy2D/Node/Button/ImageButton.cpp b/Easy2D/Object/Button/ImageButton.cpp similarity index 67% rename from Easy2D/Node/Button/ImageButton.cpp rename to Easy2D/Object/Button/ImageButton.cpp index 566b6d06..3572e2da 100644 --- a/Easy2D/Node/Button/ImageButton.cpp +++ b/Easy2D/Object/Button/ImageButton.cpp @@ -1,4 +1,4 @@ -#include "..\..\Easy2d.h" +#include "..\..\easy2d.h" ImageButton::ImageButton() : @@ -7,8 +7,6 @@ ImageButton::ImageButton() : m_pSelectedImage(nullptr), m_pUnableImage(nullptr) { - m_nWidth = 0; - m_nHeight = 0; } ImageButton::ImageButton(LPCTSTR image) : @@ -32,6 +30,26 @@ ImageButton::~ImageButton() SAFE_RELEASE(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) @@ -86,8 +104,10 @@ void ImageButton::setNormal(Image * image) m_pNormalImage = image; // 现图片引用计数加一 m_pNormalImage->retain(); + // 根据图片宽高设定按钮大小 + setSize(m_pNormalImage->getSize()); // 重新计算图片位置 - resetImagePosition(); + _resetPosition(); } } @@ -98,7 +118,7 @@ void ImageButton::setMouseIn(Image * image) SAFE_RELEASE(m_pMouseInImage); m_pMouseInImage = image; m_pMouseInImage->retain(); - resetImagePosition(); + _resetPosition(); } } @@ -109,7 +129,7 @@ void ImageButton::setSelected(Image * image) SAFE_RELEASE(m_pSelectedImage); m_pSelectedImage = image; m_pSelectedImage->retain(); - resetImagePosition(); + _resetPosition(); } } @@ -120,54 +140,33 @@ void ImageButton::setUnable(Image * image) SAFE_RELEASE(m_pUnableImage); m_pUnableImage = image; m_pUnableImage->retain(); - resetImagePosition(); + _resetPosition(); } } -void ImageButton::setX(int x) -{ - Node::setX(x); - resetImagePosition(); -} - -void ImageButton::setY(int y) -{ - Node::setY(y); - resetImagePosition(); -} - -void ImageButton::setPos(int x, int y) -{ - Node::setPos(x, y); - resetImagePosition(); -} - -void ImageButton::resetImagePosition() +void ImageButton::_resetPosition() { if (m_pNormalImage) { - // 根据图片宽高设定按钮大小 - m_nWidth = m_pNormalImage->getWidth(); - m_nHeight = m_pNormalImage->getHeight(); // 根据按钮位置和图片宽高设置图片位置居中显示 - m_pNormalImage->setPos(m_nX, m_nY); + m_pNormalImage->setPos(getX(), getY()); } if (m_pMouseInImage) { m_pMouseInImage->setPos( - m_nX + (m_nWidth - m_pMouseInImage->getWidth()) / 2, - m_nY + (m_nHeight - m_pMouseInImage->getHeight()) / 2); + getX() + (getWidth() - m_pMouseInImage->getWidth()) / 2, + getY() + (getHeight() - m_pMouseInImage->getHeight()) / 2); } if (m_pSelectedImage) { m_pSelectedImage->setPos( - m_nX + (m_nWidth - m_pSelectedImage->getWidth()) / 2, - m_nY + (m_nHeight - m_pSelectedImage->getHeight()) / 2); + getX() + (getWidth() - m_pSelectedImage->getWidth()) / 2, + getY() + (getHeight() - m_pSelectedImage->getHeight()) / 2); } if (m_pUnableImage) { m_pUnableImage->setPos( - m_nX + (m_nWidth - m_pUnableImage->getWidth()) / 2, - m_nY + (m_nHeight - m_pUnableImage->getHeight()) / 2); + getX() + (getWidth() - m_pUnableImage->getWidth()) / 2, + getY() + (getHeight() - m_pUnableImage->getHeight()) / 2); } } diff --git a/Easy2D/Node/Button/TextButton.cpp b/Easy2D/Object/Button/TextButton.cpp similarity index 67% rename from Easy2D/Node/Button/TextButton.cpp rename to Easy2D/Object/Button/TextButton.cpp index dc474bc3..b5e10acd 100644 --- a/Easy2D/Node/Button/TextButton.cpp +++ b/Easy2D/Object/Button/TextButton.cpp @@ -1,4 +1,4 @@ -#include "..\..\Easy2d.h" +#include "..\..\easy2d.h" TextButton::TextButton() : @@ -7,8 +7,6 @@ TextButton::TextButton() : m_pSelectedText(nullptr), m_pUnableText(nullptr) { - m_nWidth = 0; - m_nHeight = 0; } TextButton::TextButton(tstring text) : @@ -32,6 +30,26 @@ TextButton::~TextButton() SAFE_RELEASE(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) @@ -86,8 +104,10 @@ void TextButton::setNormal(Text * text) m_pNormalText = text; // 现文本引用计数加一 m_pNormalText->retain(); + // 根据文字宽高设定按钮大小 + setSize(m_pNormalText->getSize()); // 重新计算文本位置 - resetTextPosition(); + _resetPosition(); } } @@ -98,7 +118,7 @@ void TextButton::setMouseIn(Text * text) SAFE_RELEASE(m_pMouseInText); m_pMouseInText = text; m_pMouseInText->retain(); - resetTextPosition(); + _resetPosition(); } } @@ -109,7 +129,7 @@ void TextButton::setSelected(Text * text) SAFE_RELEASE(m_pSelectedText); m_pSelectedText = text; m_pSelectedText->retain(); - resetTextPosition(); + _resetPosition(); } } @@ -120,54 +140,33 @@ void TextButton::setUnable(Text * text) SAFE_RELEASE(m_pUnableText); m_pUnableText = text; m_pUnableText->retain(); - resetTextPosition(); + _resetPosition(); } } -void TextButton::setX(int x) -{ - Node::setX(x); - resetTextPosition(); -} - -void TextButton::setY(int y) -{ - Node::setY(y); - resetTextPosition(); -} - -void TextButton::setPos(int x, int y) -{ - Node::setPos(x, y); - resetTextPosition(); -} - -void TextButton::resetTextPosition() +void TextButton::_resetPosition() { if (m_pNormalText) { - // 根据文字宽高设定按钮大小 - m_nWidth = m_pNormalText->getWidth(); - m_nHeight = m_pNormalText->getHeight(); // 根据按钮位置和文字宽高设置文字位置居中显示 - m_pNormalText->setPos(m_nX , m_nY); + m_pNormalText->setPos(getX() , getY()); } if (m_pMouseInText) { m_pMouseInText->setPos( - m_nX + (m_nWidth - m_pMouseInText->getWidth()) / 2, - m_nY + (m_nHeight - m_pMouseInText->getHeight()) / 2); + getX() + (getWidth() - m_pMouseInText->getWidth()) / 2, + getY() + (getHeight() - m_pMouseInText->getHeight()) / 2); } if (m_pSelectedText) { m_pSelectedText->setPos( - m_nX + (m_nWidth - m_pSelectedText->getWidth()) / 2, - m_nY + (m_nHeight - m_pSelectedText->getHeight()) / 2); + getX() + (getWidth() - m_pSelectedText->getWidth()) / 2, + getY() + (getHeight() - m_pSelectedText->getHeight()) / 2); } if (m_pUnableText) { m_pUnableText->setPos( - m_nX + (m_nWidth - m_pUnableText->getWidth()) / 2, - m_nY + (m_nHeight - m_pUnableText->getHeight()) / 2); + getX() + (getWidth() - m_pUnableText->getWidth()) / 2, + getY() + (getHeight() - m_pUnableText->getHeight()) / 2); } } diff --git a/Easy2D/Node/Image.cpp b/Easy2D/Object/Image.cpp similarity index 64% rename from Easy2D/Node/Image.cpp rename to Easy2D/Object/Image.cpp index 3b96aad9..615f67a2 100644 --- a/Easy2D/Node/Image.cpp +++ b/Easy2D/Object/Image.cpp @@ -1,25 +1,24 @@ -#include "..\Easy2d.h" +#include "..\easy2d.h" #include "..\EasyX\easyx.h" // 对 PNG 图像进行像素转换 static void CrossImage(CImage &img); Image::Image() : + m_nAlpha(255), m_fScaleX(1), m_fScaleY(1) { } Image::Image(LPCTSTR ImageFile) : - m_fScaleX(1), - m_fScaleY(1) + Image() { setImage(ImageFile); // 设置图片资源 } Image::Image(LPCTSTR ImageFile, int x, int y, int width, int height) : - m_fScaleX(1), - m_fScaleY(1) + Image() { setImage(ImageFile, x, y, width, height); // 设置图片资源和裁剪大小 } @@ -36,17 +35,14 @@ void Image::_onDraw() return; } // 绘制图片 - m_Image.Draw(GetImageHDC(), m_rDest, m_rSrc); -} - -int Image::getWidth() const -{ - return m_rDest.Width(); // 目标矩形的宽度 -} - -int Image::getHeight() const -{ - return m_rDest.Height(); // 目标矩形的高度 + if (m_Image.GetBPP() == 32) + { + m_Image.AlphaBlend(GetImageHDC(), m_Rect, m_SrcRect, m_nAlpha, AC_SRC_OVER); + } + else + { + m_Image.Draw(GetImageHDC(), m_Rect, m_SrcRect); + } } float Image::getScaleX() const @@ -59,6 +55,11 @@ float Image::getScaleY() const return m_fScaleY; } +float Image::getOpacity() const +{ + return m_nAlpha / 255.0f; +} + bool Image::setImage(LPCTSTR ImageFile) { //判断图片路径是否存在 @@ -78,20 +79,13 @@ bool Image::setImage(LPCTSTR ImageFile) { return false; } - // 获取扩展名,对 PNG 图片进行特殊处理 - if (_T(".png") == FileUtils::getFileExtension(ImageFile)) + // 确认该图像包含 Alpha 通道 + if (m_Image.GetBPP() == 32) { - // 像素转换 + // 透明图片处理 CrossImage(m_Image); - // Alpha 通道 - m_Image.AlphaBlend(GetImageHDC(), 15, 30); } - // 设置目标矩形(即绘制到窗口的位置和大小) - m_rDest.SetRect(m_nX, m_nY, m_nX + m_Image.GetWidth(), m_nY + m_Image.GetHeight()); - m_rSrc.SetRect(0, 0, m_Image.GetWidth(), m_Image.GetHeight()); - // 重置缩放属性 - m_fScaleX = 1; - m_fScaleY = 1; + reset(); return true; } @@ -117,12 +111,7 @@ bool Image::setImageFromRes(LPCTSTR pResName) { return false; } - // 设置目标矩形(即绘制到窗口的位置和大小) - m_rDest.SetRect(m_nX, m_nY, m_nX + m_Image.GetWidth(), m_nY + m_Image.GetHeight()); - m_rSrc.SetRect(0, 0, m_Image.GetWidth(), m_Image.GetHeight()); - // 重置缩放属性 - m_fScaleX = 1; - m_fScaleY = 1; + reset(); return true; } @@ -144,60 +133,33 @@ void Image::crop(int x, int y, int width, int height) width = min(max(width, 0), m_Image.GetWidth()); height = min(max(height, 0), m_Image.GetHeight()); // 设置源矩形的位置和大小(用于裁剪) - m_rSrc.SetRect(x, y, x + width, y + height); + m_SrcRect.SetRect(x, y, x + width, y + height); // 设置目标矩形(即绘制到窗口的位置和大小) - m_rDest.SetRect(m_nX, m_nY, m_nX + int(width * m_fScaleX), m_nY + int(height * m_fScaleY)); + setSize(int(width * m_fScaleX), int(height * m_fScaleY)); } void Image::stretch(int width, int height) { - width = max(width, 0); - height = max(height, 0); // 设置目标矩形的位置和大小(即绘制到窗口的位置和大小,用于拉伸图片) - m_rDest.SetRect(m_nX, m_nY, m_nX + width, m_nY + height); + setSize(max(width, 0), max(height, 0)); // 重置比例缩放属性 m_fScaleX = 1; m_fScaleY = 1; } -void Image::scale(float scaleX, float scaleY) +void Image::setScale(float scaleX, float scaleY) { m_fScaleX = max(scaleX, 0); m_fScaleY = max(scaleY, 0); - m_rDest.SetRect( - m_nX, m_nY, - m_nX + int(m_rSrc.Width() * scaleX), - m_nY + int(m_rSrc.Height() * scaleY)); + setSize(int(m_SrcRect.Width() * scaleX), int(m_SrcRect.Height() * scaleY)); } -void Image::setPos(int x, int y) +void Image::setOpacity(float value) { - // 移动目标矩形 - m_rDest.MoveToXY(x, y); - m_nX = x; - m_nY = y; -} - -void Image::move(int x, int y) -{ - // 移动目标矩形 - m_rDest.OffsetRect(x, y); - m_nX += x; - m_nY += y; -} - -void Image::setX(int x) -{ - // 移动目标矩形 - m_rDest.MoveToX(x); - m_nX = x; -} - -void Image::setY(int y) -{ - // 移动目标矩形 - m_rDest.MoveToY(y); - m_nY = y; + if (m_Image.GetBPP() == 32) + { + m_nAlpha = BYTE(min(max(value, 0), 1) * 255); + } } void Image::setTransparentColor(COLORREF value) @@ -206,6 +168,19 @@ void Image::setTransparentColor(COLORREF value) m_Image.SetTransparentColor(value); } +void Image::reset() +{ + // 设置目标矩形(即绘制到窗口的位置和大小) + setSize(m_Image.GetWidth(), m_Image.GetHeight()); + // 设置源矩形(即截取图片的大小) + m_SrcRect.SetRect(0, 0, m_Image.GetWidth(), m_Image.GetHeight()); + // 重置缩放属性 + m_fScaleX = 1; + m_fScaleY = 1; + // 重置透明度 + m_nAlpha = 255; +} + void Image::saveScreenshot() { tstring savePath; @@ -223,6 +198,7 @@ void Image::saveScreenshot() // 对 PNG 图像进行像素转换 void CrossImage(CImage &img) { + // 进行像素转换 for (int i = 0; i < img.GetWidth(); i++) { for (int j = 0; j < img.GetHeight(); j++) diff --git a/Easy2D/Node/Layer.cpp b/Easy2D/Object/Layer.cpp similarity index 100% rename from Easy2D/Node/Layer.cpp rename to Easy2D/Object/Layer.cpp diff --git a/Easy2D/Node/MouseNode.cpp b/Easy2D/Object/MouseNode.cpp similarity index 93% rename from Easy2D/Node/MouseNode.cpp rename to Easy2D/Object/MouseNode.cpp index 0187ecdf..6838b140 100644 --- a/Easy2D/Node/MouseNode.cpp +++ b/Easy2D/Object/MouseNode.cpp @@ -1,4 +1,5 @@ #include "..\easy2d.h" +#include "..\e2dobj.h" MouseNode::MouseNode() : @@ -34,7 +35,7 @@ bool MouseNode::_exec(bool active) if (!m_bTarget) { // 若鼠标位置在节点所在的矩形区域中 - if (_judge()) + if (_isMouseIn()) { // 状态设为 MOUSEIN _setStatus(MOUSEIN); @@ -58,7 +59,7 @@ bool MouseNode::_exec(bool active) if (MouseMsg::isOnLButtonUp()) { // 若左键抬起时鼠标仍在节点内 - if (_judge()) + if (_isMouseIn()) { m_ClickCallback(); // 执行回调函数 } @@ -96,10 +97,9 @@ void MouseNode::_onDraw() } } -bool MouseNode::_judge() +bool MouseNode::_isMouseIn() { - return (MouseMsg::getX() >= m_nX && MouseMsg::getX() <= m_nX + m_nWidth) && - (MouseMsg::getY() >= m_nY && MouseMsg::getY() <= m_nY + m_nHeight); + return isPointIn(MouseMsg::getPos()); } void MouseNode::_setStatus(Status status) diff --git a/Easy2D/Node/Node.cpp b/Easy2D/Object/Node.cpp similarity index 62% rename from Easy2D/Node/Node.cpp rename to Easy2D/Object/Node.cpp index 3f8ea475..51ff9e75 100644 --- a/Easy2D/Node/Node.cpp +++ b/Easy2D/Object/Node.cpp @@ -1,18 +1,19 @@ -#include "..\Easy2d.h" +#include "..\easy2d.h" Node::Node() : m_nZOrder(0), - m_bDisplay(true), - m_nX(0), - m_nY(0) + m_bDisplay(true) +{ +} + +Node::Node(CPoint p) : + m_Pos(p) { } Node::Node(int x, int y) : m_nZOrder(0), - m_bDisplay(true), - m_nX(x), - m_nY(y) + m_bDisplay(true) { } @@ -29,36 +30,49 @@ void Node::_onDraw() { } -const int Node::getX() const +int Node::getX() const { - return m_nX; + return m_Pos.x; } -const int Node::getY() const +int Node::getY() const { - return m_nY; + return m_Pos.y; +} + +CPoint Node::getPos() const +{ + return m_Pos; } void Node::setX(int x) { - m_nX = x; + m_Pos.x = x; } void Node::setY(int y) { - m_nY = y; + m_Pos.y = y; } void Node::setPos(int x, int y) { - m_nX = x; - m_nY = y; + m_Pos.SetPoint(x, y); +} + +void Node::setPos(CPoint p) +{ + m_Pos = p; } void Node::move(int x, int y) { - m_nX += x; - m_nY += y; + m_Pos.Offset(x, y); +} + +void Node::move(CVector v) +{ + m_Pos.Offset(v); } int Node::getZOrder() const diff --git a/Easy2D/Object.cpp b/Easy2D/Object/Object.cpp similarity index 100% rename from Easy2D/Object.cpp rename to Easy2D/Object/Object.cpp diff --git a/Easy2D/Object/RectNode.cpp b/Easy2D/Object/RectNode.cpp new file mode 100644 index 00000000..a4c6465d --- /dev/null +++ b/Easy2D/Object/RectNode.cpp @@ -0,0 +1,138 @@ +#include "..\easy2d.h" + +RectNode::RectNode() : + m_Rect(0, 0, 0, 0) +{ + +} + +RectNode::~RectNode() +{ +} + +bool RectNode::isCollisionWith(RectNode * rectNode) const +{ + return IntersectRect(NULL, &m_Rect, &rectNode->m_Rect); +} + +bool RectNode::isPointIn(CPoint p) const +{ + return m_Rect.PtInRect(p); +} + +void RectNode::setWindowCenterX() +{ + setX((App::getWidth() - getWidth()) / 2); +} + +void RectNode::setWindowCenterY() +{ + setY((App::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); +} diff --git a/Easy2D/Node/Shape/Circle.cpp b/Easy2D/Object/Shape/Circle.cpp similarity index 74% rename from Easy2D/Node/Shape/Circle.cpp rename to Easy2D/Object/Shape/Circle.cpp index 0e5af186..a8e1c3e6 100644 --- a/Easy2D/Node/Shape/Circle.cpp +++ b/Easy2D/Object/Shape/Circle.cpp @@ -8,9 +8,9 @@ Circle::Circle() : } Circle::Circle(int x, int y, int radius) : - Node(x, y), m_nRadius(radius) { + setPos(x, y); } Circle::~Circle() @@ -19,17 +19,17 @@ Circle::~Circle() void Circle::solidShape() { - solidcircle(m_nX, m_nY, m_nRadius); + solidcircle(getX(), getY(), m_nRadius); } void Circle::fillShape() { - fillcircle(m_nX, m_nY, m_nRadius); + fillcircle(getX(), getY(), m_nRadius); } void Circle::roundShape() { - circle(m_nX, m_nY, m_nRadius); + circle(getX(), getY(), m_nRadius); } int Circle::getRadius() const diff --git a/Easy2D/Node/Shape/Rectangle.cpp b/Easy2D/Object/Shape/Rectangle.cpp similarity index 50% rename from Easy2D/Node/Shape/Rectangle.cpp rename to Easy2D/Object/Shape/Rectangle.cpp index 4c7517a4..854163d2 100644 --- a/Easy2D/Node/Shape/Rectangle.cpp +++ b/Easy2D/Object/Shape/Rectangle.cpp @@ -2,17 +2,14 @@ #include "..\..\EasyX\easyx.h" -Rect::Rect() : - m_nWidth(0), - m_nHeight(0) +Rect::Rect() { } Rect::Rect(int x, int y, int width, int height) : - Node(x, y), - m_nWidth(width), - m_nHeight(height) + m_Size(width, height) { + setPos(x, y); } Rect::~Rect() @@ -21,41 +18,41 @@ Rect::~Rect() void Rect::solidShape() { - solidrectangle(m_nX, m_nY, m_nX + m_nWidth, m_nY + m_nHeight); + solidrectangle(getX(), getY(), getX() + m_Size.cx, getY() + m_Size.cy); } void Rect::fillShape() { - fillrectangle(m_nX, m_nY, m_nX + m_nWidth, m_nY + m_nHeight); + fillrectangle(getX(), getY(), getX() + m_Size.cx, getY() + m_Size.cy); } void Rect::roundShape() { - rectangle(m_nX, m_nY, m_nX + m_nWidth, m_nY + m_nHeight); + rectangle(getX(), getY(), getX() + m_Size.cx, getY() + m_Size.cy); } int Rect::getWidth() const { - return m_nWidth; + return m_Size.cx; } int Rect::getHeight() const { - return m_nHeight; + return m_Size.cy; } void Rect::setWidth(int width) { - m_nWidth = width; + m_Size.cx = width; } void Rect::setHeight(int height) { - m_nHeight = height; + m_Size.cy = height; } void Rect::setSize(int width, int height) { - m_nWidth = width; - m_nHeight = height; + m_Size.cx = width; + m_Size.cy = height; } \ No newline at end of file diff --git a/Easy2D/Node/Shape/Shape.cpp b/Easy2D/Object/Shape/Shape.cpp similarity index 97% rename from Easy2D/Node/Shape/Shape.cpp rename to Easy2D/Object/Shape/Shape.cpp index 6a1c66ec..f0747499 100644 --- a/Easy2D/Node/Shape/Shape.cpp +++ b/Easy2D/Object/Shape/Shape.cpp @@ -1,4 +1,4 @@ -#include "..\..\Easy2d.h" +#include "..\..\easy2d.h" #include "..\..\EasyX\easyx.h" Shape::Shape() : diff --git a/Easy2D/Object/Sprite.cpp b/Easy2D/Object/Sprite.cpp new file mode 100644 index 00000000..711824db --- /dev/null +++ b/Easy2D/Object/Sprite.cpp @@ -0,0 +1,117 @@ +#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() +{ + SAFE_RELEASE(m_pImage); +} + +bool Sprite::_exec(bool active) +{ + return false; +} + +void Sprite::_onDraw() +{ + // display 属性为 false,或未设置图片资源时,不绘制该图片 + if (!m_bDisplay || m_pImage->m_Image.IsNull()) + { + return; + } + // 绘制图片 + if (m_pImage->m_Image.GetBPP() == 32) + { + m_pImage->m_Image.AlphaBlend(GetImageHDC(), getRect(), m_pImage->m_SrcRect, m_nAlpha, AC_SRC_OVER); + } + else + { + m_pImage->m_Image.Draw(GetImageHDC(), getRect(), m_pImage->m_SrcRect); + } +} + +void Sprite::setImage(Image * image) +{ + SAFE_RELEASE(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) +{ + return IntersectRect(NULL, &getRect(), &sprite->getRect()); +} + +void Sprite::addAction(Action * action) +{ + if (action) + { + // 将动作与 Sprite 绑定 + action->m_pParent = this; + // 将动作加入动作管理器,管理器会处理这个动作 + ActionManager::addAction(action); + } +} + +void Sprite::pauseAllAction() +{ + ActionManager::pauseSpriteAllActions(this); +} + +void Sprite::resumeAllAction() +{ + ActionManager::resumeSpriteAllActions(this); +} + +void Sprite::stopAllAction() +{ + 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); +} diff --git a/Easy2D/Node/Text.cpp b/Easy2D/Object/Text.cpp similarity index 79% rename from Easy2D/Node/Text.cpp rename to Easy2D/Object/Text.cpp index cbef6dbd..3b9e7f5a 100644 --- a/Easy2D/Node/Text.cpp +++ b/Easy2D/Object/Text.cpp @@ -1,4 +1,4 @@ -#include "..\Easy2d.h" +#include "..\easy2d.h" #include "..\EasyX\easyx.h" @@ -11,19 +11,19 @@ Text::Text() : } Text::Text(tstring text, COLORREF color, FontStyle * font) : - m_sText(text), m_color(color), m_pFontStyle(font) { + setText(text); m_pFontStyle->retain(); // 字体引用计数加一 } Text::Text(int x, int y, tstring text, COLORREF color, FontStyle * font) : - Node(x, y), - m_sText(text), m_color(color), m_pFontStyle(font) { + setText(text); + setPos(x, y); m_pFontStyle->retain(); // 字体引用计数加一 } @@ -44,7 +44,7 @@ void Text::_onDraw() // 设置文本颜色 settextcolor(m_color); // 输出文字 - outtextxy(m_nX, m_nY, m_sText.c_str()); + outtextxy(getX(), getY(), m_sText.c_str()); } COLORREF Text::getColor() const @@ -62,20 +62,6 @@ FontStyle * Text::getFontStyle() return m_pFontStyle; } -int Text::getWidth() -{ - // 先设置字体,然后获取该文本在该字体下的宽度 - settextstyle(&m_pFontStyle->m_font); - return textwidth(getText().c_str()); -} - -int Text::getHeight() -{ - // 先设置字体,然后获取该文本在该字体下的高度 - settextstyle(&m_pFontStyle->m_font); - return textheight(getText().c_str()); -} - bool Text::isEmpty() const { return m_sText.empty(); // 文本是否为空 @@ -84,6 +70,9 @@ bool Text::isEmpty() const 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) @@ -96,4 +85,7 @@ void Text::setFontStyle(FontStyle * style) SAFE_RELEASE(m_pFontStyle); // 原字体引用计数减一 m_pFontStyle = style; // 修改字体 m_pFontStyle->retain(); // 现字体引用计数加一 + // 先设置字体,然后获取该文本在该字体下的宽度和高度 + settextstyle(&m_pFontStyle->m_font); + setSize(textwidth(getText().c_str()), textheight(getText().c_str())); } diff --git a/Easy2D/Style/Color.cpp b/Easy2D/Style/Color.cpp index 5daa3584..c14aa401 100644 --- a/Easy2D/Style/Color.cpp +++ b/Easy2D/Style/Color.cpp @@ -1,4 +1,4 @@ -#include "..\Easy2d.h" +#include "..\easy2d.h" #include "..\EasyX\easyx.h" // 常用颜色值的定义 diff --git a/Easy2D/Style/FontStyle.cpp b/Easy2D/Style/FontStyle.cpp index 40617cca..2c5c69ba 100644 --- a/Easy2D/Style/FontStyle.cpp +++ b/Easy2D/Style/FontStyle.cpp @@ -1,4 +1,4 @@ -#include "..\Easy2d.h" +#include "..\easy2d.h" // 常用字体粗细值的定义 const LONG FontWeight::dontcare = 0; diff --git a/Easy2D/Tool/ActionManager.cpp b/Easy2D/Tool/ActionManager.cpp new file mode 100644 index 00000000..bbcd1440 --- /dev/null +++ b/Easy2D/Tool/ActionManager.cpp @@ -0,0 +1,140 @@ +#include "..\easy2d.h" + +static std::vector s_vActions; + +void ActionManager::__exec() +{ + // 获取当前时间 + static LARGE_INTEGER nNow; + QueryPerformanceCounter(&nNow); + // 循环遍历所有正在运行的动作 + std::vector::iterator iter; + for (iter = s_vActions.begin(); iter != s_vActions.end();) + { + if ((*iter)->isRunning() && (*iter)->_exec(nNow)) + { + // _exec 返回 true 时说明动作已经结束 + (*iter)->release(); + iter = s_vActions.erase(iter); + } + else + { + iter++; + } + } +} + +void ActionManager::addAction(Action * action) +{ + if (action) + { + action->_init(); + s_vActions.push_back(action); + action->retain(); + } +} + +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_pParent == sprite) + { + action->resume(); + } + } +} + +void ActionManager::pauseSpriteAllActions(Sprite * sprite) +{ + for (auto action : s_vActions) + { + if (action->m_pParent == sprite) + { + action->pause(); + } + } +} + +void ActionManager::stopSpriteAllActions(Sprite * sprite) +{ + for (auto action : s_vActions) + { + if (action->m_pParent == 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(); + } +} diff --git a/Easy2D/Tool/FileUtils.cpp b/Easy2D/Tool/FileUtils.cpp index 811fb46d..32dd5d0b 100644 --- a/Easy2D/Tool/FileUtils.cpp +++ b/Easy2D/Tool/FileUtils.cpp @@ -1,9 +1,9 @@ -#include "..\Easy2d.h" +#include "..\easy2d.h" #include "..\EasyX\easyx.h" -#include -#include #include #pragma comment(lib, "shell32.lib") +#include +#include #ifndef UNICODE #include diff --git a/Easy2D/Tool/MusicUtils.cpp b/Easy2D/Tool/MusicUtils.cpp index 8b215cf1..42666f67 100644 --- a/Easy2D/Tool/MusicUtils.cpp +++ b/Easy2D/Tool/MusicUtils.cpp @@ -1,7 +1,8 @@ -#include "..\Easy2d.h" -#include +#include "..\easy2d.h" #include #pragma comment(lib , "winmm.lib") + +#include #include //////////////////////////////////////////////////////////////////// diff --git a/Easy2D/Tool/Timer.cpp b/Easy2D/Tool/Timer.cpp index 172a3652..a8141c56 100644 --- a/Easy2D/Tool/Timer.cpp +++ b/Easy2D/Tool/Timer.cpp @@ -1,4 +1,4 @@ -#include "..\Easy2d.h" +#include "..\easy2d.h" // 储存所有定时器的容器 static std::vector s_nTimers; diff --git a/Easy2D/e2daction.h b/Easy2D/e2daction.h new file mode 100644 index 00000000..1fe66f48 --- /dev/null +++ b/Easy2D/e2daction.h @@ -0,0 +1,313 @@ +#pragma once +#include + +namespace easy2d +{ + class Action : + public Object + { + friend class Sprite; + friend class ActionManager; + friend class ActionTwo; + friend class ActionNeverStop; + friend class ActionSequence; + public: + Action(); + virtual ~Action(); + + bool isRunning(); + void start(); + void resume(); + void pause(); + void stop(); + void setInterval(UINT ms); + virtual Action * copy() = 0; + virtual Action * reverse() const; + + protected: + bool m_bRunning; + bool m_bStop; + Sprite * m_pParent; + UINT m_nMilliSeconds; + LARGE_INTEGER m_nLast; + LARGE_INTEGER m_nAnimationInterval; + + protected: + virtual void _init() = 0; + virtual bool _exec(LARGE_INTEGER nNow) = 0; + virtual void _reset() = 0; + }; + + + class Animation : + public Action + { + public: + Animation(float duration); + virtual ~Animation(); + + protected: + UINT m_nDuration; + UINT m_nTotalDuration; + + protected: + virtual void _init() override; + virtual bool _exec(LARGE_INTEGER nNow) override; + virtual void _reset() override; + }; + + + class ActionMoveBy : + public Animation + { + public: + ActionMoveBy(float duration, CVector vec); + virtual ~ActionMoveBy(); + + virtual ActionMoveBy * copy() override; + virtual ActionMoveBy * reverse() const override; + + protected: + CPoint m_BeginPos; + CVector m_MoveVector; + + protected: + virtual void _init() override; + virtual bool _exec(LARGE_INTEGER nNow) override; + virtual void _reset() override; + }; + + + class ActionMoveTo : + public ActionMoveBy + { + public: + ActionMoveTo(float duration, CPoint pos); + virtual ~ActionMoveTo(); + + virtual ActionMoveTo * copy() override; + + protected: + CPoint m_EndPos; + + protected: + virtual void _init() override; + virtual void _reset() override; + }; + + + class ActionScaleBy : + public Animation + { + public: + ActionScaleBy(float duration, float scaleX, float scaleY); + virtual ~ActionScaleBy(); + + virtual ActionScaleBy * copy() override; + virtual ActionScaleBy * reverse() const override; + + protected: + float m_nBeginScaleX; + float m_nBeginScaleY; + float m_nVariationX; + float m_nVariationY; + + protected: + virtual void _init() override; + virtual bool _exec(LARGE_INTEGER nNow) override; + virtual void _reset() override; + }; + + + class ActionScaleTo : + public ActionScaleBy + { + public: + ActionScaleTo(float duration, float scaleX, float scaleY); + virtual ~ActionScaleTo(); + + virtual ActionScaleTo * copy() override; + + protected: + float m_nEndScaleX; + float m_nEndScaleY; + + protected: + virtual void _init() override; + virtual void _reset() override; + }; + + + class ActionOpacityBy : + public Animation + { + public: + ActionOpacityBy(float duration, float opacity); + virtual ~ActionOpacityBy(); + + virtual ActionOpacityBy * copy() override; + virtual ActionOpacityBy * reverse() const override; + + protected: + float m_nBeginVal; + float m_nVariation; + + protected: + virtual void _init() override; + virtual bool _exec(LARGE_INTEGER nNow) override; + virtual void _reset() override; + }; + + + class ActionOpacityTo : + public ActionOpacityBy + { + public: + ActionOpacityTo(float duration, float opacity); + virtual ~ActionOpacityTo(); + + virtual ActionOpacityTo * copy() override; + + protected: + float m_nEndVal; + + protected: + virtual void _init() override; + virtual void _reset() override; + }; + + + class ActionFadeIn : + public ActionOpacityTo + { + public: + ActionFadeIn(float duration) : ActionOpacityTo(duration, 1) {} + }; + + + class ActionFadeOut : + public ActionOpacityTo + { + public: + ActionFadeOut(float duration) : ActionOpacityTo(duration, 0) {} + }; + + + class ActionTwo : + public Action + { + public: + ActionTwo(Action * actionFirst, Action * actionSecond); + virtual ~ActionTwo(); + + virtual ActionTwo * copy() override; + virtual ActionTwo * reverse() const override; + + protected: + Action * m_FirstAction; + Action * m_SecondAction; + + protected: + virtual void _init() override; + virtual bool _exec(LARGE_INTEGER nNow) override; + virtual void _reset() override; + }; + + + class ActionSequence : + public Action + { + public: + ActionSequence(int number, Action * action1, ...); + virtual ~ActionSequence(); + + virtual ActionSequence * copy() override; + virtual ActionSequence * reverse() const override; + + protected: + UINT m_nActionIndex; + std::vector m_vActions; + + protected: + virtual void _init() override; + virtual bool _exec(LARGE_INTEGER nNow) override; + virtual void _reset() override; + }; + + + class ActionDelay : + public Action + { + public: + ActionDelay(float duration); + virtual ~ActionDelay(); + + virtual ActionDelay * copy() override; + + protected: + virtual void _init() override; + virtual bool _exec(LARGE_INTEGER nNow) override; + virtual void _reset() override; + }; + + + class ActionNeverStop : + public Action + { + public: + ActionNeverStop(Action * action); + virtual ~ActionNeverStop(); + + virtual ActionNeverStop * copy() override; + + protected: + Action * m_Action; + + protected: + virtual void _init() override; + virtual bool _exec(LARGE_INTEGER nNow) override; + virtual void _reset() override; + }; + + + class ActionFrames : + public Action + { + public: + ActionFrames(); + ~ActionFrames(); + + void addFrame(Image * frame); + virtual ActionFrames * copy() override; + virtual ActionFrames * reverse() const override; + + protected: + UINT m_nFrameIndex; + std::vector m_vFrames; + + protected: + virtual void _init() override; + virtual bool _exec(LARGE_INTEGER nNow) override; + virtual void _reset() override; + }; + + + class ActionCallback : + public Action + { + public: + ActionCallback(const std::function& callback); + ~ActionCallback(); + + virtual ActionCallback * copy() override; + + protected: + std::function m_Callback; + + protected: + virtual void _init() override; + virtual bool _exec(LARGE_INTEGER nNow) override; + virtual void _reset() override; + }; + +} // End of easy2d namespace \ No newline at end of file diff --git a/Easy2D/e2dbase.h b/Easy2D/e2dbase.h new file mode 100644 index 00000000..383a9ff4 --- /dev/null +++ b/Easy2D/e2dbase.h @@ -0,0 +1,184 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +// String macros + +#ifdef UNICODE +#define tstring std::wstring +#else +#define tstring std::string +#endif + + +// Safe macros + +#define SAFE_DELETE(p) { delete (p); (p) = nullptr; } +#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p) = nullptr; } } +#define SAFE_RELEASE(p) { if (p) p->release(); } + + +// Type Declare + +typedef CPoint CVector; +typedef unsigned int VK_KEY; +typedef std::function CLICK_CALLBACK; +typedef std::function TIMER_CALLBACK; +typedef std::function KEY_CALLBACK; +typedef std::function MOUSE_CALLBACK; + + +// Classes Declare + +namespace easy2d +{ + class Scene; + class Node; + + class App + { + public: + App(); + ~App(); + + // 窗口可选模式 + enum MODE { SHOW_CONSOLE = 1, NO_CLOSE = 2, NO_MINI_MIZE = 4 }; + + // 定义绘图窗口 + void createWindow(int width, int height, int mode = 0); + // 定义绘图窗口 + void createWindow(CSize size, int mode = 0); + // 定义绘图窗口 + void createWindow(tstring title, int width, int height, int mode = 0); + // 定义绘图窗口 + void createWindow(tstring title, CSize size, int mode = 0); + // 启动程序 + int run(); + // 释放所有内存资源 + void free(); + // 销毁该对象 + void destory(); + + // 获取程序实例 + static App * get(); + // 设置坐标原点 + static void setOrigin(int originX, int originY); + // 获取坐标原点的物理横坐标 + static int getOriginX(); + // 获取坐标原点的物理纵坐标 + static int getOriginY(); + // 终止程序 + static void quit(); + // 终止程序 + static void end(); + // 修改窗口大小 + static void setWindowSize(int width, int height); + // 修改窗口大小 + static void setWindowSize(CSize size); + // 关闭窗口 + static void close(); + // 设置窗口标题 + static void setWindowTitle(tstring title); + // 获取窗口标题 + static tstring getWindowTitle(); + // 获取窗口宽度 + static int getWidth(); + // 获取窗口高度 + static int getHeight(); + // 切换场景 + static void enterScene(Scene *scene, bool save = true); + // 返回上一场景 + static void backScene(); + // 清空之前保存的所有场景 + static void clearScene(); + // 设置 AppName + static void setAppName(tstring appname); + // 获取 AppName + static tstring getAppName(); + // 修改窗口背景色 + static void setBkColor(COLORREF color); + // 设置帧率 + static void setFPS(DWORD fps); + // 重置绘图样式为默认值 + static void reset(); + // 获取当前场景 + static Scene * getCurrentScene(); + + protected: + tstring m_sTitle; + tstring m_sAppName; + Scene* m_CurrentScene; + Scene* m_NextScene; + std::stack m_SceneStack; + LARGE_INTEGER m_nAnimationInterval; + CSize m_Size; + int m_nWindowMode; + bool m_bRunning; + bool m_bSaveScene; + + protected: + void _initGraph(); + void _mainLoop(); + void _enterNextScene(); + }; + + class FreePool + { + friend class App; + friend class Object; + + private: + // 刷新内存池 + static void __flush(); + // 将一个节点放入释放池 + static void __add(Object * nptr); + }; + + class Scene + { + friend class App; + friend class MouseMsg; + + public: + Scene(); + ~Scene(); + + // 重写这个函数,它将在进入这个场景时自动执行 + virtual void onEnter(); + // 重写这个函数,它将在离开这个场景时自动执行 + virtual void onExit(); + // 添加子成员到场景 + void add(Node * child, int zOrder = 0); + // 删除子成员 + bool del(Node * child); + // 清空所有子成员 + void clearAllChildren(); + + protected: + std::vector m_vChildren; + + protected: + void _exec(); + void _onDraw(); + }; + + class Object + { + friend class FreePool; + + public: + Object(); + virtual ~Object(); + + void retain(); + void release(); + + protected: + int m_nRef; + }; + +} // End of easy2d namespace \ No newline at end of file diff --git a/Easy2D/e2dmsg.h b/Easy2D/e2dmsg.h new file mode 100644 index 00000000..e2494c3d --- /dev/null +++ b/Easy2D/e2dmsg.h @@ -0,0 +1,112 @@ +#pragma once +#include + +namespace easy2d +{ + class MouseMsg + { + friend class App; + + public: + MouseMsg(); + MouseMsg(tstring name, const MOUSE_CALLBACK& callback); + ~MouseMsg(); + + // 添加键盘监听 + static void addListener(tstring name, const MOUSE_CALLBACK& callback); + // 删除键盘监听 + static bool delListener(tstring name); + // 删除所有键盘监听 + static void clearAllListeners(); + // 左键是否按下 + static bool isLButtonDown(); + // 右键是否按下 + static bool isRButtonDown(); + // 中键是否按下 + static bool isMButtonDown(); + // 获取鼠标X坐标 + static int getX(); + // 获取鼠标Y坐标 + static int getY(); + // 获取鼠标坐标 + static CPoint getPos(); + // 获取鼠标滚轮值 + static int getWheel(); + // 鼠标移动消息 + static bool isOnMouseMoved(); + // 左键双击消息 + static bool isOnLButtonDBClicked(); + // 右键按下消息 + static bool isOnLButtonDown(); + // 左键弹起消息 + static bool isOnLButtonUp(); + // 右键双击消息 + static bool isOnRButtonDBClicked(); + // 右键按下消息 + static bool isOnRButtonDown(); + // 右键弹起消息 + static bool isOnRButtonUp(); + // 中键双击消息 + static bool isOnMButtonDBClicked(); + // 中键按下消息 + static bool isOnMButtonDown(); + // 中键弹起消息 + static bool isOnMButtonUp(); + // 鼠标滚轮拨动消息 + static bool isOnWheel(); + // 清空鼠标消息 + static void resetMouseMsg(); + + private: + static void __exec(); + + protected: + tstring m_sName; + MOUSE_CALLBACK m_callback; + + protected: + // 执行回调函数 + void onMouseMsg(); + }; + + + class KeyMsg + { + friend class App; + + public: + KeyMsg(tstring name, const KEY_CALLBACK& callback); + ~KeyMsg(); + + // 执行回调函数 + void onKbHit(VK_KEY key); + + // 添加键盘监听 + static void addListener(tstring name, const KEY_CALLBACK& callback); + // 删除键盘监听 + static bool delListener(tstring name); + // 删除所有键盘监听 + static void clearAllListeners(); + // 判断键是否被按下,按下返回true + static bool isKeyDown(VK_KEY key); + + public: + // 字母键值 + static const VK_KEY A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z; + // 数字键值 + static const VK_KEY NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9, NUM_0; + // 小数字键盘值 + static const VK_KEY NUMPAD_1, NUMPAD_2, NUMPAD_3, NUMPAD_4, NUMPAD_5, NUMPAD_6, NUMPAD_7, NUMPAD_8, NUMPAD_9, NUMPAD_0; + // 控制键值 + static const VK_KEY Enter, Space, Up, Down, Left, Right, Esc, Shift, LShift, RShift, Ctrl, LCtrl, RCtrl; + // F 键值 + static const VK_KEY F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12; + + private: + static void __exec(); + + protected: + tstring m_sName; + KEY_CALLBACK m_callback; + }; +} // End of easy2d namespace \ No newline at end of file diff --git a/Easy2D/e2dobj.h b/Easy2D/e2dobj.h new file mode 100644 index 00000000..93e915a0 --- /dev/null +++ b/Easy2D/e2dobj.h @@ -0,0 +1,589 @@ +#pragma once +#include +#include + +namespace easy2d +{ + class FontStyle; + class Color; + class Action; + + class Node : + public Object + { + friend class Scene; + friend class BatchNode; + + public: + Node(); + Node(CPoint p); + Node(int x, int y); + virtual ~Node(); + + // 获取节点横坐标 + virtual int getX() const; + // 获取节点纵坐标 + virtual int getY() const; + // 获取节点坐标 + virtual CPoint getPos() const; + // 设置节点横坐标 + virtual void setX(int x); + // 设置节点纵坐标 + virtual void setY(int y); + // 设置节点横纵坐标 + virtual void setPos(int x, int y); + // 设置节点横纵坐标 + virtual void setPos(CPoint p); + // 移动节点 + virtual void move(int x, int y); + // 设置节点横纵坐标 + virtual void move(CVector v); + // 节点是否显示 + virtual bool display() const; + // 设置节点是否显示 + virtual void setDisplay(bool value); + // 获取节点绘图顺序 + virtual int getZOrder() const; + // 设置节点绘图顺序(0为最先绘制,显示在最底层) + virtual void setZOrder(int z); + // 获取节点所在场景 + Scene * getParentScene(); + + protected: + int m_nZOrder; + bool m_bDisplay; + Scene* m_pScene; + CPoint m_Pos; + + protected: + virtual bool _exec(bool active); + virtual void _onDraw() = 0; + void setParentScene(Scene * scene); + }; + + + class BatchNode : + public Node + { + public: + BatchNode(); + virtual ~BatchNode(); + + // 添加子节点 + void add(Node *child, int z_Order = 0); + // 删除子节点 + bool del(Node * child); + // 清空所有子节点 + void clearAllChildren(); + + protected: + std::vector m_vChildren; + + protected: + virtual bool _exec(bool active) override; + virtual void _onDraw() override; + }; + + + class Layer : + public BatchNode + { + public: + Layer(); + virtual ~Layer(); + + // 图层是否阻塞消息 + int getBlock() const; + // 设置图层是否阻塞消息 + void setBlock(bool block); + + protected: + bool m_bBlock; + + protected: + virtual bool _exec(bool active) override; + }; + + + class RectNode : + public Node + { + public: + RectNode(); + ~RectNode(); + + virtual bool isCollisionWith(RectNode * rectNode) const; + virtual bool isPointIn(CPoint p) const; + + virtual void setWindowCenterX(); + virtual void setWindowCenterY(); + virtual void setWindowCenter(); + + virtual int getX() const override; + virtual int getY() const override; + virtual CPoint getPos() const override; + virtual int getWidth() const; + virtual int getHeight() const; + virtual CSize getSize() const; + virtual CRect getRect() const; + + virtual void setX(int x) override; + virtual void setY(int y) override; + virtual void setPos(int x, int y) override; + virtual void setPos(CPoint p) override; + virtual void move(int x, int y) override; + virtual void move(CVector v) override; + virtual void setWidth(int width); + virtual void setHeight(int height); + virtual void setSize(int width, int height); + virtual void setSize(CSize size); + virtual void setRect(int x1, int y1, int x2, int y2); + virtual void setRect(CPoint leftTop, CPoint rightBottom); + virtual void setRect(CRect rect); + + protected: + CRect m_Rect; + }; + + + class Text : + public RectNode + { + friend class TextButton; + + public: + Text(); + // 根据字符串、颜色和字体创建文字 + Text(tstring text, COLORREF color = Color::white, FontStyle * font = FontStyle::getDefault()); + // 根据横纵坐标、字符串、颜色和字体创建文字 + Text(int x, int y, tstring text, COLORREF color = Color::white, FontStyle * font = FontStyle::getDefault()); + virtual ~Text(); + + // 获取当前颜色 + COLORREF getColor() const; + // 获取当前文字 + tstring getText() const; + // 获取当前字体 + FontStyle * getFontStyle(); + // 文本是否为空 + bool isEmpty() const; + + // 设置文字 + void setText(tstring text); + // 设置文字颜色 + void setColor(COLORREF color); + // 设置字体 + void setFontStyle(FontStyle * style); + + protected: + tstring m_sText; + COLORREF m_color; + FontStyle * m_pFontStyle; + + protected: + virtual void _onDraw() override; + }; + + + class Image : + public RectNode + { + friend class Sprite; + friend class ImageButton; + public: + Image(); + // 从图片文件获取图像 + Image(LPCTSTR ImageFile); + /** + * 从图片文件获取图像 + * 参数:图片文件名,图片裁剪坐标,图片裁剪宽度和高度 + */ + Image(LPCTSTR ImageFile, int x, int y, int width, int height); + virtual ~Image(); + + // 获取横向拉伸比例 + float getScaleX() const; + // 获取纵向拉伸比例 + float getScaleY() const; + // 获取透明度 + float getOpacity() const; + + /** + * 从图片文件获取图像 + * 返回值:图片加载是否成功 + */ + bool setImage(LPCTSTR ImageFile); + /** + * 从图片文件获取图像 + * 参数:图片文件名,图片裁剪起始坐标,图片裁剪宽度和高度 + * 返回值:图片加载是否成功 + */ + bool setImage(LPCTSTR ImageFile, int x, int y, int width, int height); + /** + * 从资源文件获取图像,不支持 png + * 返回值:图片加载是否成功 + */ + bool setImageFromRes(LPCTSTR pResName); + /** + * 从资源文件获取图像,不支持 png + * 参数:资源名称,图片裁剪坐标,图片裁剪宽度和高度 + * 返回值:图片加载是否成功 + */ + bool setImageFromRes(LPCTSTR pResName, int x, int y, int width, int height); + // 裁剪图片(裁剪后会恢复 stretch 拉伸) + void crop(int x, int y, int width, int height); + // 将图片拉伸到固定宽高 + void stretch(int width, int height); + // 按比例拉伸图片 + void setScale(float scaleX, float scaleY); + // 设置透明度,范围 0~1.0f(只对 png 图片生效) + void setOpacity(float value); + // 设置透明色 + void setTransparentColor(COLORREF value); + // 重置图片属性 + void reset(); + // 保存游戏截图 + static void saveScreenshot(); + + protected: + CImage m_Image; + CRect m_SrcRect; + BYTE m_nAlpha; + float m_fScaleX; + float m_fScaleY; + + protected: + virtual void _onDraw() override; + }; + + + class Sprite : + public RectNode + { + friend class BatchSprite; + public: + Sprite(); + Sprite(Image * image); + Sprite(LPCTSTR imageFileName); + virtual ~Sprite(); + + // 判断是否和另一个精灵碰撞 + bool isCollisionWith(Sprite * sprite); + // 修改精灵图片 + virtual void setImage(Image * image); + // 添加动作 + virtual void addAction(Action * action); + // 暂停所有动作 + virtual void pauseAllAction(); + // 继续所有动作 + virtual void resumeAllAction(); + // 停止所有动作 + virtual void stopAllAction(); + + virtual float getScaleX() const; + virtual float getScaleY() const; + virtual float getOpacity() const; + + virtual void setScale(float scaleX, float scaleY); + virtual void setOpacity(float opacity); + + protected: + float m_fScaleX; + float m_fScaleY; + BYTE m_nAlpha; + Image * m_pImage; + + protected: + bool _exec(bool active) override; + void _onDraw() override; + }; + + + class BatchSprite : + public Node + { + public: + BatchSprite(); + virtual ~BatchSprite(); + + // 添加精灵 + void addSprite(Sprite * sprite, int z_Order = 0); + // 删除精灵 + bool delSprite(Sprite * child); + // 删除所有精灵 + void clearAllSprites(); + // 判断是否有精灵产生碰撞 + // 返回值:若有碰撞,返回第一个产生碰撞的精灵,否则返回空指针 + Sprite * isCollisionWith(Sprite * sprite); + // 判断点是否在精灵内部 + // 返回值:若这个点在任意一个精灵内部,返回这个精灵,否则返回空指针 + Sprite * isPointIn(CPoint point); + // 同时修改所有精灵的图片 + virtual void setImage(Image * image); + + virtual float getScaleX() const; + virtual float getScaleY() const; + virtual float getOpacity() const; + + virtual void setScale(float scaleX, float scaleY); + virtual void setOpacity(float opacity); + + protected: + std::vector m_vSprites; + float m_fScaleX; + float m_fScaleY; + BYTE m_nAlpha; + + protected: + bool _exec(bool active) override; + void _onDraw() override; + }; + + + class MouseNode : + public RectNode + { + public: + MouseNode(); + virtual ~MouseNode(); + + // 鼠标是否移入 + virtual bool isMouseIn(); + // 鼠标是否选中 + virtual bool isSelected(); + // 设置回调函数 + virtual void setClickedCallback(const CLICK_CALLBACK & callback); + // 设置回调函数 + virtual void setMouseInCallback(const CLICK_CALLBACK & callback); + // 设置回调函数 + virtual void setMouseOutCallback(const CLICK_CALLBACK & callback); + // 设置回调函数 + virtual void setSelectCallback(const CLICK_CALLBACK & callback); + // 设置回调函数 + virtual void setUnselectCallback(const CLICK_CALLBACK & callback); + // 重置状态 + virtual void reset(); + // 设置节点是否阻塞鼠标消息 + void setBlock(bool block); + + protected: + bool m_bTarget; + bool m_bBlock; + enum Status { NORMAL, MOUSEIN, SELECTED } m_eStatus; + CLICK_CALLBACK m_OnMouseInCallback; + CLICK_CALLBACK m_OnMouseOutCallback; + CLICK_CALLBACK m_OnSelectCallback; + CLICK_CALLBACK m_OnUnselectCallback; + CLICK_CALLBACK m_ClickCallback; + + protected: + virtual bool _exec(bool active) override; + virtual void _onDraw() override; + + // 重写这个方法可以自定义按钮的判断方法 + virtual bool _isMouseIn(); + // 切换状态 + virtual void _setStatus(Status status); + // 正常状态 + virtual void _onNormal() = 0; + // 鼠标移入时 + virtual void _onMouseIn() = 0; + // 鼠标选中时 + virtual void _onSelected() = 0; + }; + + + class Button : + public MouseNode + { + public: + Button(); + virtual ~Button(); + + // 按钮是否启用 + virtual bool isEnable(); + // 设置是否启用 + virtual void setEnable(bool enable); + + // 设置按钮横坐标 + virtual void setX(int x) override; + // 设置按钮纵坐标 + virtual void setY(int y) override; + // 设置按钮坐标 + virtual void setPos(int x, int y) override; + // 设置按钮坐标 + virtual void setPos(CPoint p) override; + // 移动按钮 + virtual void move(int x, int y) override; + // 移动按钮 + virtual void move(CVector v) override; + + protected: + bool m_bEnable; + + protected: + virtual bool _exec(bool active) override; + virtual void _onDraw() override; + virtual void _resetPosition() = 0; + + virtual void _onNormal() = 0; + virtual void _onMouseIn() = 0; + virtual void _onSelected() = 0; + virtual void _onDisable() = 0; + }; + + + class TextButton : + public Button + { + public: + TextButton(); + TextButton(tstring text); + TextButton(Text * text); + virtual ~TextButton(); + + // 设置按钮文字 + void setNormal(Text * text); + // 设置鼠标移入时的按钮文字 + void setMouseIn(Text * text); + // 设置鼠标选中时的按钮文字 + void setSelected(Text * text); + // 设置按钮禁用时的按钮文字 + void setUnable(Text * text); + + protected: + Text * m_pNormalText; + Text * m_pMouseInText; + Text * m_pSelectedText; + Text * m_pUnableText; + + protected: + virtual void _resetPosition() override; + + virtual void _setStatus(Status status) override; + virtual void _onNormal() override; + virtual void _onMouseIn() override; + virtual void _onSelected() override; + virtual void _onDisable() override; + }; + + + class ImageButton : + public Button + { + public: + ImageButton(); + ImageButton(LPCTSTR image); + ImageButton(Image * image); + virtual ~ImageButton(); + + // 设置按钮图片 + void setNormal(Image * image); + // 设置鼠标移入时的按钮图片 + void setMouseIn(Image * image); + // 设置鼠标选中时的按钮图片 + void setSelected(Image * image); + // 设置按钮禁用时的按钮图片 + void setUnable(Image * image); + + protected: + Image * m_pNormalImage; + Image * m_pMouseInImage; + Image * m_pSelectedImage; + Image * m_pUnableImage; + + protected: + virtual void _resetPosition() override; + virtual void _setStatus(Status status) override; + virtual void _onNormal() override; + virtual void _onMouseIn() override; + virtual void _onSelected() override; + virtual void _onDisable() override; + }; + + + class Shape : + public Node + { + public: + Shape(); + virtual ~Shape(); + + // 形状填充样式 + enum STYLE { ROUND, SOLID, FILL } m_eStyle; + + // 获取形状的填充颜色 + COLORREF getFillColor() const; + // 获取形状的线条颜色 + COLORREF getLineColor() const; + // 设置填充颜色 + void setFillColor(COLORREF color); + // 设置线条颜色 + void setLineColor(COLORREF color); + // 设置填充样式 + void setStyle(STYLE style); + + protected: + COLORREF fillColor; + COLORREF lineColor; + + protected: + virtual void _onDraw() override; + virtual void solidShape() = 0; + virtual void fillShape() = 0; + virtual void roundShape() = 0; + }; + + + class Rect : + public Shape + { + public: + Rect(); + Rect(int x, int y, int width, int height); + virtual ~Rect(); + + // 获取矩形宽度 + int getWidth() const; + // 获取矩形高度 + int getHeight() const; + // 设置矩形宽度 + void setWidth(int width); + // 设置矩形高度 + void setHeight(int height); + // 设置矩形大小 + void setSize(int width, int height); + + protected: + CSize m_Size; + + protected: + virtual void solidShape() override; + virtual void fillShape() override; + virtual void roundShape() override; + }; + + + class Circle : + public Shape + { + public: + Circle(); + Circle(int x, int y, int radius); + virtual ~Circle(); + + // 获取圆形半径 + int getRadius() const; + // 设置圆形半径 + void setRadius(int m_nRadius); + + protected: + int m_nRadius; + + protected: + virtual void solidShape() override; + virtual void fillShape() override; + virtual void roundShape() override; + }; + +} // End of easy2d namespace \ No newline at end of file diff --git a/Easy2D/e2dstyle.h b/Easy2D/e2dstyle.h new file mode 100644 index 00000000..73a7ba03 --- /dev/null +++ b/Easy2D/e2dstyle.h @@ -0,0 +1,104 @@ +#pragma once +#include + +namespace easy2d +{ + class FontStyle : + public Object + { + friend class Text; + + public: + FontStyle(); + /** + * 使用 [字体名称、字号、粗细、字宽、斜体、下划线、删除线、字符串书写角度、 + * 每个字符书写角度、抗锯齿] 属性创建字体样式 + */ + FontStyle(LPCTSTR fontfamily, LONG height = 18, LONG weight = 0, LONG width = 0, + bool italic = 0, bool underline = 0, bool strikeout = 0, LONG escapement = 0, + LONG orientation = 0, bool quality = true); + virtual ~FontStyle(); + + // 获取默认字体 + static FontStyle * getDefault(); + // 设置字符平均高度 + void setHeight(LONG value); + // 设置字符平均宽度(0表示自适应) + void setWidth(LONG value); + // 设置字体 + void setFontFamily(LPCTSTR value); + // 设置字符笔画粗细,范围0~1000,默认为0 + void setWeight(LONG value); + // 设置斜体 + void setItalic(bool value); + // 设置下划线 + void setUnderline(bool value); + // 设置删除线 + void setStrikeOut(bool value); + // 设置字符串的书写角度,单位0.1度,默认为0 + void setEscapement(LONG value); + // 设置每个字符的书写角度,单位0.1度,默认为0 + void setOrientation(LONG value); + // 设置字体抗锯齿,默认为true + void setQuality(bool value); + + protected: + LOGFONT m_font; + }; + + + class FontWeight + { + public: + static const LONG dontcare; // 粗细值 0 + static const LONG thin; // 粗细值 100 + static const LONG extraLight; // 粗细值 200 + static const LONG light; // 粗细值 300 + static const LONG normal; // 粗细值 400 + static const LONG regular; // 粗细值 400 + static const LONG medium; // 粗细值 500 + static const LONG demiBlod; // 粗细值 600 + static const LONG blod; // 粗细值 700 + static const LONG extraBold; // 粗细值 800 + static const LONG black; // 粗细值 900 + static const LONG heavy; // 粗细值 900 + }; + + class Color + { + public: + static const COLORREF black; // 黑色 + static const COLORREF blue; // 蓝色 + static const COLORREF green; // 绿色 + static const COLORREF cyan; // 青色 + static const COLORREF red; // 红色 + static const COLORREF magenta; // 紫色 + static const COLORREF brown; // 棕色 + static const COLORREF lightgray; // 亮灰色 + static const COLORREF darkgray; // 深灰色 + static const COLORREF lightblue; // 亮蓝色 + static const COLORREF lightgreen; // 亮绿色 + static const COLORREF lightcyan; // 亮青色 + static const COLORREF lightred; // 亮红色 + static const COLORREF lightmagenta; // 亮紫色 + static const COLORREF yellow; // 亮黄色 + static const COLORREF white; // 白色 + + // 通过红、绿、蓝颜色分量合成颜色 + static COLORREF getFromRGB(BYTE r, BYTE g, BYTE b); + // 通过色相、饱和度、亮度合成颜色 + static COLORREF getFromHSL(float H, float S, float L); + // 通过色相、饱和度、明度合成颜色 + static COLORREF getFromHSV(float H, float S, float V); + + // 返回指定颜色中的红色值 + static BYTE getRValue(COLORREF color); + // 返回指定颜色中的绿色值 + static BYTE getGValue(COLORREF color); + // 返回指定颜色中的蓝色值 + static BYTE getBValue(COLORREF color); + // 返回与指定颜色对应的灰度值颜色 + static COLORREF getGray(COLORREF color); + }; + +} // End of easy2d namespace \ No newline at end of file diff --git a/Easy2D/e2dtool.h b/Easy2D/e2dtool.h new file mode 100644 index 00000000..41389ec0 --- /dev/null +++ b/Easy2D/e2dtool.h @@ -0,0 +1,174 @@ +#pragma once +#include + +namespace easy2d +{ + class Action; + + class FileUtils + { + public: + // 获取系统的 AppData\Local 路径 + static tstring getLocalAppDataPath(); + // 获取默认的保存路径 + static tstring getDefaultSavePath(); + // 保存 int 型的值 + static void saveInt(LPCTSTR key, int value); + // 保存 double 型的值 + static void saveDouble(LPCTSTR key, double value); + // 保存 字符串 型的值(不要在 Unicode 字符集下保存中文字符) + static void saveString(LPCTSTR key, tstring value); + // 获取 int 型的值(若不存在则返回 default 参数的值) + static int getInt(LPCTSTR key, int default); + // 获取 double 型的值(若不存在则返回 default 参数的值) + static double getDouble(LPCTSTR key, double default); + // 获取 字符串 型的值(若不存在则返回 default 参数的值) + static tstring getString(LPCTSTR key, tstring default); + // 得到文件扩展名(小写) + static tstring getFileExtension(const tstring& filePath); + /** + * 打开保存文件对话框,得到有效保存路径返回 true + * 参数:返回文件路径的字符串,窗口标题,设置扩展名过滤,设置默认扩展名 + */ + static bool getSaveFilePath(tstring& path, LPCTSTR title = _T("保存到"), LPCTSTR defExt = NULL); + }; + + + class MusicUtils + { + public: + // 播放背景音乐 + static void playBackgroundMusic(tstring pszFilePath, bool bLoop = true); + // 停止背景音乐 + static void stopBackgroundMusic(bool bReleaseData = false); + // 暂停背景音乐 + static void pauseBackgroundMusic(); + // 继续播放背景音乐 + static void resumeBackgroundMusic(); + // 从头播放背景音乐 + static void rewindBackgroundMusic(); + // 背景音乐是否正在播放 + static bool isBackgroundMusicPlaying(); + // 设置背景音乐音量,0 ~ 1.0f + static void setBackgroundMusicVolume(float volume); + + // 播放音效 + static unsigned int playMusic(tstring pszFilePath, bool loop = false); + // 停止音效 + static void stopMusic(unsigned int nSoundId); + // 预加载音效 + static void preloadMusic(tstring pszFilePath); + // 暂停音效 + static void pauseMusic(unsigned int nSoundId); + // 继续播放音效 + static void resumeMusic(unsigned int nSoundId); + // 卸载音效 + static void unloadMusic(LPCTSTR pszFilePath); + // 设置特定音乐的音量,0 ~ 1.0f + static void setVolume(tstring pszFilePath, float volume); + + // 暂停所有音乐 + static void pauseAllMusics(); + // 继续播放所有音乐 + static void resumeAllMusics(); + // 停止所有音乐 + static void stopAllMusics(); + // 停止所有音乐,并释放内存 + static void end(); + // 设置总音量,0 ~ 1.0f + static void setVolume(float volume); + }; + + + class Timer + { + friend class App; + + public: + Timer(tstring name, UINT ms, const TIMER_CALLBACK & callback); + ~Timer(); + + // 启动定时器 + void start(); + // 停止定时器 + void stop(); + // 定时器是否正在运行 + bool isRunning(); + // 设置间隔时间 + void setInterval(UINT ms); + // 设置回调函数 + void setCallback(const TIMER_CALLBACK& callback); + // 设置定时器名称 + void setName(tstring name); + // 获取定时器间隔时间 + UINT getInterval() const; + // 获取定时器名称 + tstring getName() const; + + // 添加定时器 + static void addTimer(Timer * timer); + // 添加定时器 + static void addTimer(tstring name, UINT ms, const TIMER_CALLBACK & callback); + // 根据名称获取定时器 + static Timer * getTimer(tstring name); + // 启动特定定时器 + static bool startTimer(tstring name); + // 停止特定定时器 + static bool stopTimer(tstring name); + // 删除特定定时器 + static bool delTimer(tstring name); + // 删除所有定时器 + static void clearAllTimers(); + + protected: + bool m_bRunning; + tstring m_sName; + TIMER_CALLBACK m_callback; + LARGE_INTEGER m_nLast; + LARGE_INTEGER m_nAnimationInterval; + UINT m_nMilliSeconds; + + private: + static void __exec(); + }; + + + class ActionManager + { + friend class App; + friend class Sprite; + public: + // 继续一个特定的动作 + static void startAction(Action * action); + // 继续一个特定的动作 + static void resumeAction(Action * action); + // 暂停一个特定的动作 + static void pauseAction(Action * action); + // 停止一个特定的动作 + static void stopAction(Action * action); + + // 继续一个 Sprite 的所有动作 + static void startSpriteAllActions(Sprite * sprite); + // 继续一个 Sprite 的所有动作 + static void resumeSpriteAllActions(Sprite * sprite); + // 暂停一个 Sprite 的所有动作 + static void pauseSpriteAllActions(Sprite * sprite); + // 停止一个 Sprite 的所有动作 + static void stopSpriteAllActions(Sprite * sprite); + + // 继续当前存在的所有动作 + static void startAllActions(); + // 继续当前存在的所有动作 + static void resumeAllActions(); + // 暂停当前存在的所有动作 + static void pauseAllActions(); + // 停止当前存在的所有动作 + static void stopAllActions(); + + private: + static void __exec(); + // 将一个动作添加进动作管理器 + static void addAction(Action * action); + }; + +} // End of easy2d namespace \ No newline at end of file diff --git a/Easy2D/easy2d.h b/Easy2D/easy2d.h index 52dac1b6..d95e36a9 100644 --- a/Easy2D/easy2d.h +++ b/Easy2D/easy2d.h @@ -1,5 +1,5 @@ /****************************************************** -* Easy2D Game Engine (v1.0.4) +* Easy2D Game Engine (v1.1.0) * http://www.easy2d.cn * * Depends on EasyX (Ver:20170827(beta)) @@ -16,30 +16,12 @@ #endif -// String macros - -#ifdef UNICODE - #define tstring std::wstring -#else - #define tstring std::string -#endif - - -// Safe macros - -#define SAFE_DELETE(p) { delete (p); (p) = nullptr; } -#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p) = nullptr; } } -#define SAFE_RELEASE(p) { if (p) p->release(); } - -#pragma warning (disable: 4099) - -#include -#include -#include -#include -#include -#include - +#include +#include "e2dmsg.h" +#include "e2dtool.h" +#include "e2dstyle.h" +#include "e2dobj.h" +#include "e2daction.h" #if defined(UNICODE) && (_DEBUG) #pragma comment(lib,"Easy2Ddw.lib") @@ -51,988 +33,4 @@ #pragma comment(lib,"Easy2D.lib") #endif - -// Class Declare - -namespace easy2d { - -// 基础类 -class App; -class Scene; -class KeyMsg; -class MouseMsg; -class FreePool; -// 样式类 -class Color; -class FontStyle; -// 工具类 -class Timer; -class MusicUtils; -class FileUtils; -// 对象 -class Object; -class Node; -class Layer; -class BatchNode; -class MouseNode; -class Image; -class Text; -class Shape; -class Rect; -class Circle; -class Button; -class TextButton; -class ImageButton; - - -typedef unsigned int VK_KEY; -typedef std::function CLICK_CALLBACK; -typedef std::function TIMER_CALLBACK; -typedef std::function KEY_CALLBACK; -typedef std::function MOUSE_CALLBACK; - - -class App -{ -public: - App(); - ~App(); - - // 窗口可选模式 - enum { SHOW_CONSOLE = 1, NO_CLOSE = 2, NO_MINI_MIZE = 4 }; - - // 获取程序实例 - static App * get(); - // 设置坐标原点 - static void setOrigin(int originX, int originY); - // 获取坐标原点的物理横坐标 - static int getOriginX(); - // 获取坐标原点的物理纵坐标 - static int getOriginY(); - // 启动程序 - int run(); - // 终止程序 - void quit(); - // 终止程序 - void end(); - // 定义绘图窗口 - void createWindow(int width, int height, int mode = 0); - // 定义绘图窗口 - void createWindow(tstring title, int width, int height, int mode = 0); - // 关闭窗口 - void close(); - // 修改窗口大小 - void setWindowSize(int width, int height); - // 设置窗口标题 - void setWindowTitle(tstring title); - // 获取窗口标题 - tstring getWindowTitle(); - // 获取窗口宽度 - int getWidth() const; - // 获取窗口高度 - int getHeight() const; - // 切换场景 - void enterScene(Scene *scene, bool save = true); - // 返回上一场景 - void backScene(); - // 清空之前保存的所有场景 - void clearScene(); - // 设置 AppName - void setAppName(tstring appname); - // 获取 AppName - tstring getAppName() const; - // 修改窗口背景色 - void setBkColor(COLORREF color); - // 设置帧率 - void setFPS(DWORD fps); - // 重置绘图样式为默认值 - void reset(); - // 释放所有内存资源 - void free(); - // 销毁该对象 - void destory(); - // 获取当前场景 - Scene * getCurrentScene(); - // 获取 Easy2D 版本号 - LPCTSTR getVersion(); - -protected: - tstring m_sTitle; - tstring m_sAppName; - Scene* m_currentScene; - Scene* m_nextScene; - std::stack m_sceneStack; - LARGE_INTEGER m_nAnimationInterval; - int m_nWidth; - int m_nHeight; - int m_nWindowMode; - bool m_bRunning; - bool m_bSaveScene; - -protected: - void _initGraph(); - void _mainLoop(); - void _enterNextScene(); -}; - -class FreePool -{ - friend class App; - friend class Object; - -private: - // 刷新内存池 - static void __flush(); - // 将一个节点放入释放池 - static void __add(Object * nptr); -}; - -class Scene -{ - friend class App; - friend class MouseMsg; - -public: - Scene(); - ~Scene(); - - // 重写这个函数,它将在进入这个场景时自动执行 - virtual void onEnter(); - // 重写这个函数,它将在离开这个场景时自动执行 - virtual void onExit(); - // 添加子成员到场景 - void add(Node * child, int zOrder = 0); - // 删除子成员 - bool del(Node * child); - // 清空所有子成员 - void clearAllChildren(); - -protected: - std::vector m_vChildren; - -protected: - void _exec(); - void _onDraw(); -}; - - -class MouseMsg -{ - friend class App; - -public: - MouseMsg(); - MouseMsg(tstring name, const MOUSE_CALLBACK& callback); - ~MouseMsg(); - - // 添加键盘监听 - static void addListener(tstring name, const MOUSE_CALLBACK& callback); - // 删除键盘监听 - static bool delListener(tstring name); - // 删除所有键盘监听 - static void clearAllListeners(); - // 左键是否按下 - static bool isLButtonDown(); - // 右键是否按下 - static bool isRButtonDown(); - // 中键是否按下 - static bool isMButtonDown(); - // 获取鼠标X坐标 - static int getX(); - // 获取鼠标Y坐标 - static int getY(); - // 获取鼠标滚轮值 - static int getWheel(); - // 鼠标移动消息 - static bool isOnMouseMoved(); - // 左键双击消息 - static bool isOnLButtonDBClicked(); - // 右键按下消息 - static bool isOnLButtonDown(); - // 左键弹起消息 - static bool isOnLButtonUp(); - // 右键双击消息 - static bool isOnRButtonDBClicked(); - // 右键按下消息 - static bool isOnRButtonDown(); - // 右键弹起消息 - static bool isOnRButtonUp(); - // 中键双击消息 - static bool isOnMButtonDBClicked(); - // 中键按下消息 - static bool isOnMButtonDown(); - // 中键弹起消息 - static bool isOnMButtonUp(); - // 鼠标滚轮拨动消息 - static bool isOnWheel(); - // 清空鼠标消息 - static void resetMouseMsg(); - -private: - static void __exec(); - -protected: - tstring m_sName; - MOUSE_CALLBACK m_callback; - -protected: - // 执行回调函数 - void onMouseMsg(); -}; - - -class KeyMsg -{ - friend class App; - -public: - KeyMsg(tstring name, const KEY_CALLBACK& callback); - ~KeyMsg(); - - // 执行回调函数 - void onKbHit(VK_KEY key); - - // 添加键盘监听 - static void addListener(tstring name, const KEY_CALLBACK& callback); - // 删除键盘监听 - static bool delListener(tstring name); - // 删除所有键盘监听 - static void clearAllListeners(); - // 判断键是否被按下,按下返回true - static bool isKeyDown(VK_KEY key); - -public: - // 字母键值 - static const VK_KEY A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z; - // 数字键值 - static const VK_KEY NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9, NUM_0; - // 小数字键盘值 - static const VK_KEY NUMPAD_1, NUMPAD_2, NUMPAD_3, NUMPAD_4, NUMPAD_5, NUMPAD_6, NUMPAD_7, NUMPAD_8, NUMPAD_9, NUMPAD_0; - // 控制键值 - static const VK_KEY Enter, Space, Up, Down, Left, Right, Esc, Shift, LShift, RShift, Ctrl, LCtrl, RCtrl; - // F 键值 - static const VK_KEY F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12; - -private: - static void __exec(); - -protected: - tstring m_sName; - KEY_CALLBACK m_callback; -}; - - -class FileUtils -{ -public: - // 获取系统的 AppData\Local 路径 - static tstring getLocalAppDataPath(); - // 获取默认的保存路径 - static tstring getDefaultSavePath(); - // 保存 int 型的值 - static void saveInt(LPCTSTR key, int value); - // 保存 double 型的值 - static void saveDouble(LPCTSTR key, double value); - // 保存 字符串 型的值(不要在 Unicode 字符集下保存中文字符) - static void saveString(LPCTSTR key, tstring value); - // 获取 int 型的值(若不存在则返回 default 参数的值) - static int getInt(LPCTSTR key, int default); - // 获取 double 型的值(若不存在则返回 default 参数的值) - static double getDouble(LPCTSTR key, double default); - // 获取 字符串 型的值(若不存在则返回 default 参数的值) - static tstring getString(LPCTSTR key, tstring default); - // 得到文件扩展名(小写) - static tstring getFileExtension(const tstring& filePath); - /** - * 打开保存文件对话框,得到有效保存路径返回 true - * 参数:返回文件路径的字符串,窗口标题,设置扩展名过滤,设置默认扩展名 - */ - static bool getSaveFilePath(tstring& path, LPCTSTR title = _T("保存到"), LPCTSTR defExt = NULL); -}; - - -class MusicUtils -{ -public: - // 播放背景音乐 - static void playBackgroundMusic(tstring pszFilePath, bool bLoop = true); - // 停止背景音乐 - static void stopBackgroundMusic(bool bReleaseData = false); - // 暂停背景音乐 - static void pauseBackgroundMusic(); - // 继续播放背景音乐 - static void resumeBackgroundMusic(); - // 从头播放背景音乐 - static void rewindBackgroundMusic(); - // 背景音乐是否正在播放 - static bool isBackgroundMusicPlaying(); - // 设置背景音乐音量,0 ~ 1.0f - static void setBackgroundMusicVolume(float volume); - - // 播放音效 - static unsigned int playMusic(tstring pszFilePath, bool loop = false); - // 停止音效 - static void stopMusic(unsigned int nSoundId); - // 预加载音效 - static void preloadMusic(tstring pszFilePath); - // 暂停音效 - static void pauseMusic(unsigned int nSoundId); - // 继续播放音效 - static void resumeMusic(unsigned int nSoundId); - // 卸载音效 - static void unloadMusic(LPCTSTR pszFilePath); - // 设置特定音乐的音量,0 ~ 1.0f - static void setVolume(tstring pszFilePath, float volume); - - // 暂停所有音乐 - static void pauseAllMusics(); - // 继续播放所有音乐 - static void resumeAllMusics(); - // 停止所有音乐 - static void stopAllMusics(); - // 停止所有音乐,并释放内存 - static void end(); - // 设置总音量,0 ~ 1.0f - static void setVolume(float volume); -}; - - -class Timer -{ - friend class App; - -public: - Timer(tstring name, UINT ms, const TIMER_CALLBACK & callback); - ~Timer(); - - // 启动定时器 - void start(); - // 停止定时器 - void stop(); - // 定时器是否正在运行 - bool isRunning(); - // 设置间隔时间 - void setInterval(UINT ms); - // 设置回调函数 - void setCallback(const TIMER_CALLBACK& callback); - // 设置定时器名称 - void setName(tstring name); - // 获取定时器间隔时间 - UINT getInterval() const; - // 获取定时器名称 - tstring getName() const; - - // 添加定时器 - static void addTimer(Timer * timer); - // 添加定时器 - static void addTimer(tstring name, UINT ms, const TIMER_CALLBACK & callback); - // 根据名称获取定时器 - static Timer * getTimer(tstring name); - // 启动特定定时器 - static bool startTimer(tstring name); - // 停止特定定时器 - static bool stopTimer(tstring name); - // 删除特定定时器 - static bool delTimer(tstring name); - // 删除所有定时器 - static void clearAllTimers(); - -protected: - bool m_bRunning; - tstring m_sName; - TIMER_CALLBACK m_callback; - LARGE_INTEGER m_nLast; - LARGE_INTEGER m_nAnimationInterval; - UINT m_nMilliSeconds; - -private: - static void __exec(); -}; - - -class Color -{ -public: - static const COLORREF black; // 黑色 - static const COLORREF blue; // 蓝色 - static const COLORREF green; // 绿色 - static const COLORREF cyan; // 青色 - static const COLORREF red; // 红色 - static const COLORREF magenta; // 紫色 - static const COLORREF brown; // 棕色 - static const COLORREF lightgray; // 亮灰色 - static const COLORREF darkgray; // 深灰色 - static const COLORREF lightblue; // 亮蓝色 - static const COLORREF lightgreen; // 亮绿色 - static const COLORREF lightcyan; // 亮青色 - static const COLORREF lightred; // 亮红色 - static const COLORREF lightmagenta; // 亮紫色 - static const COLORREF yellow; // 亮黄色 - static const COLORREF white; // 白色 - - // 通过红、绿、蓝颜色分量合成颜色 - static COLORREF getFromRGB(BYTE r, BYTE g, BYTE b); - // 通过色相、饱和度、亮度合成颜色 - static COLORREF getFromHSL(float H, float S, float L); - // 通过色相、饱和度、明度合成颜色 - static COLORREF getFromHSV(float H, float S, float V); - - // 返回指定颜色中的红色值 - static BYTE getRValue(COLORREF color); - // 返回指定颜色中的绿色值 - static BYTE getGValue(COLORREF color); - // 返回指定颜色中的蓝色值 - static BYTE getBValue(COLORREF color); - // 返回与指定颜色对应的灰度值颜色 - static COLORREF getGray(COLORREF color); -}; - - -class Object -{ - friend class FreePool; - -public: - Object(); - virtual ~Object(); - - void retain(); - void release(); - -protected: - int m_nRef; -}; - - -class FontStyle : - public virtual Object -{ - friend class Text; - -public: - FontStyle(); - /** - * 使用 [字体名称、字号、粗细、字宽、斜体、下划线、删除线、字符串书写角度、 - * 每个字符书写角度、抗锯齿] 属性创建字体样式 - */ - FontStyle(LPCTSTR fontfamily, LONG height = 18, LONG weight = 0, LONG width = 0, - bool italic = 0, bool underline = 0, bool strikeout = 0, LONG escapement = 0, - LONG orientation = 0, bool quality = true); - virtual ~FontStyle(); - - // 获取默认字体 - static FontStyle * getDefault(); - // 设置字符平均高度 - void setHeight(LONG value); - // 设置字符平均宽度(0表示自适应) - void setWidth(LONG value); - // 设置字体 - void setFontFamily(LPCTSTR value); - // 设置字符笔画粗细,范围0~1000,默认为0 - void setWeight(LONG value); - // 设置斜体 - void setItalic(bool value); - // 设置下划线 - void setUnderline(bool value); - // 设置删除线 - void setStrikeOut(bool value); - // 设置字符串的书写角度,单位0.1度,默认为0 - void setEscapement(LONG value); - // 设置每个字符的书写角度,单位0.1度,默认为0 - void setOrientation(LONG value); - // 设置字体抗锯齿,默认为true - void setQuality(bool value); - -protected: - LOGFONT m_font; -}; - - -class FontWeight -{ -public: - static const LONG dontcare; // 粗细值 0 - static const LONG thin; // 粗细值 100 - static const LONG extraLight; // 粗细值 200 - static const LONG light; // 粗细值 300 - static const LONG normal; // 粗细值 400 - static const LONG regular; // 粗细值 400 - static const LONG medium; // 粗细值 500 - static const LONG demiBlod; // 粗细值 600 - static const LONG blod; // 粗细值 700 - static const LONG extraBold; // 粗细值 800 - static const LONG black; // 粗细值 900 - static const LONG heavy; // 粗细值 900 -}; - - -class Node : - public virtual Object -{ - friend class Scene; - friend class BatchNode; - -public: - Node(); - Node(int x, int y); - virtual ~Node(); - - // 获取节点横坐标 - const int getX() const; - // 获取节点纵坐标 - const int getY() const; - // 设置节点横坐标 - virtual void setX(int x); - // 设置节点纵坐标 - virtual void setY(int y); - // 设置节点横纵坐标 - virtual void setPos(int x, int y); - // 移动节点 - virtual void move(int x, int y); - // 节点是否显示 - bool display() const; - // 设置节点是否显示 - void setDisplay(bool value); - // 获取节点绘图顺序 - virtual int getZOrder() const; - // 设置节点绘图顺序(0为最先绘制,显示在最底层) - virtual void setZOrder(int z); - // 获取节点所在场景 - Scene * getParentScene(); - -protected: - int m_nZOrder; - bool m_bDisplay; - Scene* m_pScene; - int m_nX; - int m_nY; - -protected: - virtual bool _exec(bool active); - virtual void _onDraw() = 0; - void setParentScene(Scene * scene); -}; - - -class BatchNode : - public virtual Node -{ -public: - BatchNode(); - virtual ~BatchNode(); - - // 添加子节点 - void add(Node *child, int z_Order = 0); - // 删除子节点 - bool del(Node * child); - // 清空所有子节点 - void clearAllChildren(); - -protected: - std::vector m_vChildren; - -protected: - virtual bool _exec(bool active) override; - virtual void _onDraw() override; -}; - - -class Layer : - public virtual BatchNode -{ -public: - Layer(); - virtual ~Layer(); - - // 图层是否阻塞消息 - int getBlock() const; - // 设置图层是否阻塞消息 - void setBlock(bool block); - -protected: - bool m_bBlock; - -protected: - virtual bool _exec(bool active) override; -}; - - -class Image : - public virtual Node -{ - friend class ImageButton; - -public: - Image(); - // 从图片文件获取图像 - Image(LPCTSTR ImageFile); - /** - * 从图片文件获取图像 - * 参数:图片文件名,图片裁剪坐标,图片裁剪宽度和高度 - */ - Image(LPCTSTR ImageFile, int x, int y, int width, int height); - virtual ~Image(); - - // 获取图像宽度 - int getWidth() const; - // 获取图像高度 - int getHeight() const; - // 获取横向拉伸比例 - float getScaleX() const; - // 获取纵向拉伸比例 - float getScaleY() const; - - /** - * 从图片文件获取图像 - * 返回值:图片加载是否成功 - */ - bool setImage(LPCTSTR ImageFile); - /** - * 从图片文件获取图像 - * 参数:图片文件名,图片裁剪起始坐标,图片裁剪宽度和高度 - * 返回值:图片加载是否成功 - */ - bool setImage(LPCTSTR ImageFile, int x, int y, int width, int height); - /** - * 从资源文件获取图像,不支持 png - * 返回值:图片加载是否成功 - */ - bool setImageFromRes(LPCTSTR pResName); - /** - * 从资源文件获取图像,不支持 png - * 参数:资源名称,图片裁剪坐标,图片裁剪宽度和高度 - * 返回值:图片加载是否成功 - */ - bool setImageFromRes(LPCTSTR pResName, int x, int y, int width, int height); - // 裁剪图片(裁剪后会恢复 stretch 拉伸) - void crop(int x, int y, int width, int height); - // 将图片拉伸到固定宽高 - void stretch(int width, int height); - // 按比例拉伸图片 - void scale(float scaleX = 1.0f, float scaleY = 1.0f); - // 设置图片位置 - void setPos(int x, int y) override; - // 移动图片 - void move(int x, int y) override; - // 设置图片横坐标 - void setX(int x) override; - // 设置图片纵坐标 - void setY(int y) override; - // 设置透明色 - void setTransparentColor(COLORREF value); - // 保存游戏截图 - static void saveScreenshot(); - -protected: - CImage m_Image; - CRect m_rDest; - CRect m_rSrc; - float m_fScaleX; - float m_fScaleY; - -protected: - virtual void _onDraw() override; -}; - - -class Text : - public virtual Node -{ - friend class TextButton; - -public: - Text(); - // 根据字符串、颜色和字体创建文字 - Text(tstring text, COLORREF color = Color::white, FontStyle * font = FontStyle::getDefault()); - // 根据横纵坐标、字符串、颜色和字体创建文字 - Text(int x, int y, tstring text, COLORREF color = Color::white, FontStyle * font = FontStyle::getDefault()); - virtual ~Text(); - - // 获取当前颜色 - COLORREF getColor() const; - // 获取当前文字 - tstring getText() const; - // 获取当前字体 - FontStyle * getFontStyle(); - // 获取文字宽度 - int getWidth(); - // 获取文字高度 - int getHeight(); - // 文本是否为空 - bool isEmpty() const; - - // 设置文字 - void setText(tstring text); - // 设置文字颜色 - void setColor(COLORREF color); - // 设置字体 - void setFontStyle(FontStyle * style); - -protected: - tstring m_sText; - COLORREF m_color; - FontStyle * m_pFontStyle; - -protected: - virtual void _onDraw() override; -}; - - -class MouseNode : - public virtual Node -{ -public: - MouseNode(); - virtual ~MouseNode(); - - // 鼠标是否移入 - virtual bool isMouseIn(); - // 鼠标是否选中 - virtual bool isSelected(); - // 设置回调函数 - virtual void setClickedCallback(const CLICK_CALLBACK & callback); - // 设置回调函数 - virtual void setMouseInCallback(const CLICK_CALLBACK & callback); - // 设置回调函数 - virtual void setMouseOutCallback(const CLICK_CALLBACK & callback); - // 设置回调函数 - virtual void setSelectCallback(const CLICK_CALLBACK & callback); - // 设置回调函数 - virtual void setUnselectCallback(const CLICK_CALLBACK & callback); - // 重置状态 - virtual void reset(); - // 设置节点是否阻塞鼠标消息 - void setBlock(bool block); - -private: - bool m_bTarget; - bool m_bBlock; - enum Status { NORMAL, MOUSEIN, SELECTED } m_eStatus; - CLICK_CALLBACK m_OnMouseInCallback; - CLICK_CALLBACK m_OnMouseOutCallback; - CLICK_CALLBACK m_OnSelectCallback; - CLICK_CALLBACK m_OnUnselectCallback; - CLICK_CALLBACK m_ClickCallback; - -protected: - int m_nWidth; - int m_nHeight; - -protected: - virtual bool _exec(bool active) override; - virtual void _onDraw() override; - - // 重写这个方法可以自定义按钮的判断方法 - virtual bool _judge(); - // 切换状态 - void _setStatus(Status status); - // 正常状态 - virtual void _onNormal() = 0; - // 鼠标移入时 - virtual void _onMouseIn() = 0; - // 鼠标选中时 - virtual void _onSelected() = 0; -}; - - -class Button : - public virtual MouseNode -{ -public: - Button(); - virtual ~Button(); - - // 按钮是否启用 - virtual bool isEnable(); - // 设置是否启用 - virtual void setEnable(bool enable); - -protected: - bool m_bEnable; - -protected: - virtual bool _exec(bool active) override; - virtual void _onDraw() override; - - virtual void _onNormal() = 0; - virtual void _onMouseIn() = 0; - virtual void _onSelected() = 0; - virtual void _onDisable() = 0; -}; - - - -class TextButton : - public virtual Button -{ -public: - TextButton(); - TextButton(tstring text); - TextButton(Text * text); - virtual ~TextButton(); - - // 设置按钮文字 - void setNormal(Text * text); - // 设置鼠标移入时的按钮文字 - void setMouseIn(Text * text); - // 设置鼠标选中时的按钮文字 - void setSelected(Text * text); - // 设置按钮禁用时的按钮文字 - void setUnable(Text * text); - - // 设置按钮横坐标 - virtual void setX(int x) override; - // 设置按钮纵坐标 - virtual void setY(int y) override; - // 设置按钮横纵坐标 - virtual void setPos(int x, int y) override; - -protected: - Text * m_pNormalText; - Text * m_pMouseInText; - Text * m_pSelectedText; - Text * m_pUnableText; - -protected: - // 重置文字位置(居中显示) - void resetTextPosition(); - - virtual void _onNormal() override; - virtual void _onMouseIn() override; - virtual void _onSelected() override; - virtual void _onDisable() override; -}; - - - -class ImageButton : - public virtual Button -{ -public: - ImageButton(); - ImageButton(LPCTSTR image); - ImageButton(Image * image); - virtual ~ImageButton(); - - // 设置按钮图片 - void setNormal(Image * image); - // 设置鼠标移入时的按钮图片 - void setMouseIn(Image * image); - // 设置鼠标选中时的按钮图片 - void setSelected(Image * image); - // 设置按钮禁用时的按钮图片 - void setUnable(Image * image); - - // 设置按钮横坐标 - virtual void setX(int x) override; - // 设置按钮纵坐标 - virtual void setY(int y) override; - // 设置按钮横纵坐标 - virtual void setPos(int x, int y) override; - -protected: - Image * m_pNormalImage; - Image * m_pMouseInImage; - Image * m_pSelectedImage; - Image * m_pUnableImage; - -protected: - // 重置图片位置(居中显示) - void resetImagePosition(); - - virtual void _onNormal() override; - virtual void _onMouseIn() override; - virtual void _onSelected() override; - virtual void _onDisable() override; -}; - - -class Shape : - public virtual Node -{ -public: - Shape(); - virtual ~Shape(); - - enum STYLE { ROUND, SOLID, FILL } m_eStyle; // 形状填充样式 - - // 获取形状的填充颜色 - COLORREF getFillColor() const; - // 获取形状的线条颜色 - COLORREF getLineColor() const; - // 设置填充颜色 - void setFillColor(COLORREF color); - // 设置线条颜色 - void setLineColor(COLORREF color); - // 设置填充样式 - void setStyle(STYLE style); - -protected: - COLORREF fillColor; - COLORREF lineColor; - -protected: - virtual void _onDraw() override; - virtual void solidShape() = 0; - virtual void fillShape() = 0; - virtual void roundShape() = 0; -}; - - -class Rect : - public virtual Shape -{ -public: - Rect(); - Rect(int x, int y, int width, int height); - virtual ~Rect(); - - // 获取矩形宽度 - int getWidth() const; - // 获取矩形高度 - int getHeight() const; - // 设置矩形宽度 - void setWidth(int width); - // 设置矩形高度 - void setHeight(int height); - // 设置矩形大小 - void setSize(int width, int height); - -protected: - int m_nWidth; - int m_nHeight; - -protected: - virtual void solidShape() override; - virtual void fillShape() override; - virtual void roundShape() override; -}; - - -class Circle : - public virtual Shape -{ -public: - Circle(); - Circle(int x, int y, int radius); - virtual ~Circle(); - - // 获取圆形半径 - int getRadius() const; - // 设置圆形半径 - void setRadius(int m_nRadius); - -protected: - int m_nRadius; - -protected: - virtual void solidShape() override; - virtual void fillShape() override; - virtual void roundShape() override; -}; - -} // End of easy2d namespace - - -// 默认使用 easy2d 命名空间 using namespace easy2d; \ No newline at end of file