diff --git a/.gitignore b/.gitignore
index 2e612965..e456e94c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,8 @@
# ignore all files in the /Easy2D/** directory
Easy2D/Win32/
-Easy2D/x64/
\ No newline at end of file
+Easy2D/x64/
+Win32
+x64
+backup
+*.lnk
+.vs
\ No newline at end of file
diff --git a/Easy2D/App.cpp b/Easy2D/App.cpp
index 5a109ab5..b834aa5d 100644
--- a/Easy2D/App.cpp
+++ b/Easy2D/App.cpp
@@ -18,7 +18,6 @@ App::App() :
m_currentScene(nullptr),
m_nextScene(nullptr),
m_bRunning(false),
- m_bPause(false),
m_nWidth(0),
m_nHeight(0),
m_nWindowMode(0)
@@ -154,11 +153,6 @@ void App::_initGraph()
void App::_mainLoop()
{
- // 游戏暂停
- if (m_bPause)
- {
- return;
- }
// 进入下一场景
if (m_nextScene)
{
@@ -294,16 +288,6 @@ void App::end()
m_bRunning = false;
}
-void App::pause()
-{
- m_bPause = true;
-}
-
-bool App::isRunning()
-{
- return m_bRunning && !m_bPause;
-}
-
void App::reset()
{
// 重置绘图环境
@@ -320,7 +304,7 @@ Scene * App::getCurrentScene()
LPCTSTR easy2d::App::getVersion()
{
- return _T("1.0.0");
+ return _T("1.0.2");
}
void App::setFPS(DWORD fps)
diff --git a/Easy2D/Easy2D.vcxproj b/Easy2D/Easy2D.vcxproj
index 2390ea2a..c95d3354 100644
--- a/Easy2D/Easy2D.vcxproj
+++ b/Easy2D/Easy2D.vcxproj
@@ -334,9 +334,6 @@
EasyX\x64
-
-
-
diff --git a/Easy2D/Easy2D.vcxproj.filters b/Easy2D/Easy2D.vcxproj.filters
index f3559bc9..fc9489b6 100644
--- a/Easy2D/Easy2D.vcxproj.filters
+++ b/Easy2D/Easy2D.vcxproj.filters
@@ -35,9 +35,6 @@
{bdcd902b-b53d-4537-9632-76ea14c141a0}
-
-
-
婧愭枃浠
diff --git a/Easy2D/FreePool.cpp b/Easy2D/FreePool.cpp
index 01b5a72b..924a189d 100644
--- a/Easy2D/FreePool.cpp
+++ b/Easy2D/FreePool.cpp
@@ -32,7 +32,11 @@ void FreePool::__flush()
}
}
-void FreePool::add(Object * nptr)
+void FreePool::__add(Object * nptr)
{
- pool.push_back(nptr); // 将一个对象放入释放池中
+ for (auto o : pool)
+ {
+ if (o == nptr) return; // 不得有重复的指针存在
+ }
+ pool.push_back(nptr); // 将一个对象放入释放池中
}
diff --git a/Easy2D/Msg/KeyMsg.cpp b/Easy2D/Msg/KeyMsg.cpp
index 6ed05471..6fb0ddd8 100644
--- a/Easy2D/Msg/KeyMsg.cpp
+++ b/Easy2D/Msg/KeyMsg.cpp
@@ -134,7 +134,7 @@ void KeyMsg::addListener(tstring name, const KEY_CALLBACK & callback)
s_vKeyMsg.push_back(key);
}
-bool easy2d::KeyMsg::delListener(tstring name)
+bool KeyMsg::delListener(tstring name)
{
// 创建迭代器
std::vector::iterator iter;
@@ -154,12 +154,12 @@ bool easy2d::KeyMsg::delListener(tstring name)
return false;
}
-void easy2d::KeyMsg::clearAllListener()
+void KeyMsg::clearAllListener()
{
// 删除所有监听器
- for (auto t : s_vKeyMsg)
+ for (auto k : s_vKeyMsg)
{
- delete t;
+ delete k;
}
// 清空容器
s_vKeyMsg.clear();
diff --git a/Easy2D/Msg/MouseMsg.cpp b/Easy2D/Msg/MouseMsg.cpp
index 98b8de6a..6a3084d9 100644
--- a/Easy2D/Msg/MouseMsg.cpp
+++ b/Easy2D/Msg/MouseMsg.cpp
@@ -1,13 +1,16 @@
#include "..\easy2d.h"
#include "..\EasyX\easyx.h"
+// 鼠标监听回调函数的容器
+static std::vector s_vMouseMsg;
+
// 鼠标消息
static MouseMsg s_mouseMsg = MouseMsg();
// 将 EasyX 的 MOUSEMSG 转换为 MouseMsg
static void ConvertMsg(MOUSEMSG msg);
-void easy2d::MouseMsg::__exec()
+void MouseMsg::__exec()
{
// 获取鼠标消息
while (MouseHit())
@@ -16,9 +19,72 @@ void easy2d::MouseMsg::__exec()
ConvertMsg(GetMouseMsg());
// 执行场景程序
App::get()->getCurrentScene()->_exec();
+ // 执行鼠标监听回调函数
+ for (auto m : s_vMouseMsg) // 循环遍历所有的鼠标监听
+ {
+ m->onMouseMsg(s_mouseMsg); // 执行回调函数
+ }
}
}
+MouseMsg::MouseMsg()
+{
+}
+
+MouseMsg::MouseMsg(tstring name, const MOUSE_CALLBACK & callback)
+{
+ m_sName = name;
+ m_callback = callback;
+}
+
+MouseMsg::~MouseMsg()
+{
+}
+
+void MouseMsg::onMouseMsg(MouseMsg mouse)
+{
+ m_callback(mouse);
+}
+
+void MouseMsg::addListener(tstring name, const MOUSE_CALLBACK & callback)
+{
+ // 创建新的监听对象
+ auto mouse = new MouseMsg(name, callback);
+ // 添加新的按键回调函数
+ s_vMouseMsg.push_back(mouse);
+}
+
+bool MouseMsg::delListener(tstring name)
+{
+ // 创建迭代器
+ std::vector::iterator iter;
+ // 循环遍历所有监听器
+ for (iter = s_vMouseMsg.begin(); iter != s_vMouseMsg.end(); iter++)
+ {
+ // 查找相同名称的监听器
+ if ((*iter)->m_sName == name)
+ {
+ // 删除该定时器
+ delete (*iter);
+ s_vMouseMsg.erase(iter);
+ return true;
+ }
+ }
+ // 若未找到同样名称的监听器,返回 false
+ return false;
+}
+
+void MouseMsg::clearAllListener()
+{
+ // 删除所有监听器
+ for (auto m : s_vMouseMsg)
+ {
+ delete m;
+ }
+ // 清空容器
+ s_vMouseMsg.clear();
+}
+
MouseMsg MouseMsg::getMsg()
{
return s_mouseMsg; // 获取当前鼠标消息
diff --git a/Easy2D/Node/Button/Button.cpp b/Easy2D/Node/Button/Button.cpp
index 8c52a4ca..112d3c74 100644
--- a/Easy2D/Node/Button/Button.cpp
+++ b/Easy2D/Node/Button/Button.cpp
@@ -14,7 +14,7 @@ Button::~Button()
bool Button::_exec(bool active)
{
// 按钮是否启用
- if (!m_bEnable || !m_bDisplay)
+ if (!m_bEnable)
{
return false;
}
@@ -33,27 +33,6 @@ void Button::_onDraw()
MouseNode::_onDraw();
}
-void Button::_judge()
-{
- // 判断按钮当前的状态
- // 若鼠标位置在按钮所在的矩形区域中
- if (MouseMsg::getMsg().x >= m_nX && MouseMsg::getMsg().x <= m_nX + m_nWidth &&
- MouseMsg::getMsg().y >= m_nY && MouseMsg::getMsg().y <= m_nY + m_nHeight)
- {
- _setMouseIn();
-
- // 若鼠标在按钮上,且鼠标左键按下
- if (MouseMsg::isLButtonDown())
- {
- _setSelected();
- }
- }
- else
- {
- _setNormal();
- }
-}
-
bool Button::isEnable()
{
return m_bEnable;
diff --git a/Easy2D/Node/Image.cpp b/Easy2D/Node/Image.cpp
index 3b4a48fc..2ceab9a0 100644
--- a/Easy2D/Node/Image.cpp
+++ b/Easy2D/Node/Image.cpp
@@ -52,10 +52,25 @@ float Image::getScaleY() const
return m_fScaleY;
}
-void Image::setImageFile(LPCTSTR ImageFile, int x, int y, int width, int height)
+bool Image::setImageFile(LPCTSTR ImageFile, int x, int y, int width, int height)
{
+ //判断图片路径是否存在
+ if (!PathFileExists(ImageFile))
+ {
+ return false;
+ }
+ // 清空原资源
+ if (!m_Image.IsNull())
+ {
+ m_Image.Destroy();
+ }
// 加载图片
m_Image.Load(ImageFile);
+ // 加载失败
+ if (m_Image.IsNull())
+ {
+ return false;
+ }
// 获取扩展名,对 PNG 图片进行特殊处理
if (_T(".png") == FileUtils::getFileExtension(ImageFile))
{
@@ -68,18 +83,27 @@ void Image::setImageFile(LPCTSTR ImageFile, int x, int y, int width, int height)
m_rDest.SetRect(0, 0, m_Image.GetWidth(), m_Image.GetHeight());
// 裁剪图片大小
crop(x, y, width, height);
+
+ return true;
}
-void Image::setImageRes(LPCTSTR pResName, int x, int y, int width, int height)
+bool Image::setImageRes(LPCTSTR pResName, int x, int y, int width, int height)
{
// 从资源加载图片(不支持 PNG)
m_Image.LoadFromResource(GetModuleHandle(NULL), pResName);
+ // 加载失败
+ if (m_Image.IsNull())
+ {
+ return false;
+ }
// 重置缩放属性
m_fScaleX = 0, m_fScaleY = 0;
// 设置目标矩形(即绘制到窗口的位置和大小)
m_rDest.SetRect(0, 0, m_Image.GetWidth(), m_Image.GetHeight());
// 裁剪图片大小
crop(x, y, width, height);
+
+ return true;
}
void Image::crop(int x, int y, int width, int height)
diff --git a/Easy2D/Node/MouseNode.cpp b/Easy2D/Node/MouseNode.cpp
index c70c870b..a648b327 100644
--- a/Easy2D/Node/MouseNode.cpp
+++ b/Easy2D/Node/MouseNode.cpp
@@ -4,7 +4,11 @@
MouseNode::MouseNode() :
m_bBlock(true),
m_bTarget(false),
- m_callback([]() {})
+ m_ClickCallback([]() {}),
+ m_OnMouseInCallback([]() {}),
+ m_OnMouseOutCallback([]() {}),
+ m_OnSelectCallback([]() {}),
+ m_OnUnselectCallback([]() {})
{
}
@@ -19,15 +23,40 @@ bool MouseNode::_exec(bool active)
{
return false;
}
- // 判断节点状态
- _judge();
- // 鼠标在节点上(被选中时鼠标也在节点上)
- if (m_eStatus == MOUSEIN || m_eStatus == SELECTED)
+ // 判断节点当前的状态
+ // 若节点未取得焦点,则重新判断节点状态
+ if (!m_bTarget)
{
- // 节点被鼠标选中,且鼠标左键抬起
- if (m_bTarget && MouseMsg::isOnLButtonUp())
+ // 若鼠标位置在节点所在的矩形区域中
+ if (_judge())
{
- onClicked(); // 执行回调函数
+ // 状态设为 MOUSEIN
+ _setStatus(MOUSEIN);
+ // 若此时按下鼠标左键
+ if (MouseMsg::isOnLButtonDown())
+ {
+ m_bTarget = true; // 取得焦点标记
+ _setStatus(SELECTED); // 状态设为 SELECTED
+ }
+ // 若节点不阻塞鼠标消息,则取得画面焦点
+ if (!m_bBlock) return true;
+ }
+ else
+ {
+ reset(); // 恢复默认状态
+ }
+ }
+ else
+ {
+ // 节点取得焦点时鼠标左键抬起
+ if (MouseMsg::isOnLButtonUp())
+ {
+ // 若左键抬起时鼠标仍在节点内
+ if (_judge())
+ {
+ m_ClickCallback(); // 执行回调函数
+ }
+ reset(); // 恢复默认状态
}
// 若节点不阻塞鼠标消息,则取得画面焦点
if (!m_bBlock) return true;
@@ -61,26 +90,36 @@ void MouseNode::_onDraw()
}
}
-void MouseNode::_setNormal()
+bool MouseNode::_judge()
{
- m_bTarget = false; // 失去焦点标记
- m_eStatus = NORMAL;
+ return (MouseMsg::getMsg().x >= m_nX && MouseMsg::getMsg().x <= m_nX + m_nWidth) &&
+ (MouseMsg::getMsg().y >= m_nY && MouseMsg::getMsg().y <= m_nY + m_nHeight);
}
-void MouseNode::_setMouseIn()
+void MouseNode::_setStatus(Status status)
{
- m_eStatus = MOUSEIN;
-}
-
-void MouseNode::_setSelected()
-{
- m_bTarget = true; // 取得焦点标记
- m_eStatus = SELECTED;
-}
-
-void MouseNode::onClicked()
-{
- m_callback();
+ if (m_eStatus != status)
+ {
+ // 退出某个状态的回调函数
+ if (m_eStatus == MOUSEIN)
+ {
+ m_OnMouseOutCallback();
+ }
+ else if (m_eStatus == SELECTED)
+ {
+ m_OnUnselectCallback();
+ }
+ // 进入某个状态的回调函数
+ if (status == MOUSEIN)
+ {
+ m_OnMouseInCallback();
+ }
+ else if (status == SELECTED)
+ {
+ m_OnSelectCallback();
+ }
+ m_eStatus = status;
+ }
}
bool MouseNode::isMouseIn()
@@ -93,14 +132,35 @@ bool MouseNode::isSelected()
return m_eStatus == SELECTED;
}
-void MouseNode::setOnMouseClicked(const CLICK_CALLBACK & callback)
+void MouseNode::setClickedCallback(const CLICK_CALLBACK & callback)
{
- m_callback = callback;
+ m_ClickCallback = callback;
+}
+
+void MouseNode::setMouseInCallback(const CLICK_CALLBACK & callback)
+{
+ m_OnMouseInCallback = callback;
+}
+
+void MouseNode::setMouseOutCallback(const CLICK_CALLBACK & callback)
+{
+ m_OnMouseOutCallback = callback;
+}
+
+void MouseNode::setSelectCallback(const CLICK_CALLBACK & callback)
+{
+ m_OnSelectCallback = callback;
+}
+
+void MouseNode::setUnselectCallback(const CLICK_CALLBACK & callback)
+{
+ m_OnUnselectCallback = callback;
}
void MouseNode::reset()
{
- m_eStatus = NORMAL;
+ m_bTarget = false; // 失去焦点标记
+ _setStatus(NORMAL); // 恢复默认状态
}
void MouseNode::setBlock(bool block)
diff --git a/Easy2D/Object.cpp b/Easy2D/Object.cpp
index 08ca53aa..8d77e82e 100644
--- a/Easy2D/Object.cpp
+++ b/Easy2D/Object.cpp
@@ -3,7 +3,7 @@
Object::Object() :
m_nRef(0)
{
- FreePool::add(this); // 将该对象放入释放池中
+ FreePool::__add(this); // 将该对象放入释放池中
}
Object::~Object()
diff --git a/Easy2D/Tool/MusicUtils.cpp b/Easy2D/Tool/MusicUtils.cpp
index e5575f35..33fed5da 100644
--- a/Easy2D/Tool/MusicUtils.cpp
+++ b/Easy2D/Tool/MusicUtils.cpp
@@ -266,6 +266,14 @@ void MusicUtils::end()
// BackgroundMusic
//////////////////////////////////////////////////////////////////////////
+/*
+void MusicUtils::setVolume(float volume)
+{
+ if (volume < 0 || volume > 1) return;
+ waveOutSetVolume(NULL, DWORD(volume * 65535));
+}
+*/
+
void MusicUtils::playBackgroundMusic(tstring pszFilePath, bool bLoop)
{
if (pszFilePath.empty())
diff --git a/Easy2D/easy2d.h b/Easy2D/easy2d.h
index 1b0125fe..9b4f4af6 100644
--- a/Easy2D/easy2d.h
+++ b/Easy2D/easy2d.h
@@ -1,5 +1,5 @@
/******************************************************
-* Easy2D Game Engine (v1.0.0)
+* Easy2D Game Engine (v1.0.2)
* http://www.easy2d.cn
*
* Depends on EasyX (Ver:20170827(beta))
@@ -31,6 +31,7 @@
#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
@@ -83,10 +84,12 @@ class TextButton;
class ImageButton;
+typedef BatchNode Layer;
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
@@ -101,7 +104,6 @@ protected:
int m_nHeight;
int m_nWindowMode;
bool m_bRunning;
- bool m_bPause;
bool m_bSaveScene;
protected:
@@ -125,8 +127,6 @@ public:
static int getOriginY();
// 启动程序
int run();
- // 暂停程序
- void pause();
// 终止程序
void quit();
// 终止程序
@@ -151,8 +151,6 @@ public:
void backScene();
// 修改窗口背景色
void setBkColor(COLORREF color);
- // 游戏是否正在运行
- bool isRunning();
// 设置帧率
void setFPS(DWORD fps);
// 重置绘图样式为默认值
@@ -170,13 +168,13 @@ public:
class FreePool
{
friend class App;
+ friend class Object;
private:
+ // 刷新内存池
static void __flush();
-
-public:
// 将一个节点放入释放池
- static void add(Object * nptr);
+ static void __add(Object * nptr);
};
class Scene
@@ -211,6 +209,10 @@ class MouseMsg
private:
static void __exec();
+protected:
+ tstring m_sName;
+ MOUSE_CALLBACK m_callback;
+
public:
UINT uMsg; // 当前鼠标消息
bool mkLButton; // 鼠标左键是否按下
@@ -220,6 +222,21 @@ public:
short y; // 当前鼠标 y 坐标
short wheel; // 鼠标滚轮滚动值 (120 的倍数)
+public:
+ MouseMsg();
+ MouseMsg(tstring name, const MOUSE_CALLBACK& callback);
+ ~MouseMsg();
+
+ // 执行回调函数
+ void onMouseMsg(MouseMsg mouse);
+
+ // 添加键盘监听
+ static void addListener(tstring name, const MOUSE_CALLBACK& callback);
+ // 删除键盘监听
+ static bool delListener(tstring name);
+ // 删除所有键盘监听
+ static void clearAllListener();
+
public:
// 获取当前鼠标消息
static MouseMsg getMsg();
@@ -530,7 +547,6 @@ class Node :
public virtual Object
{
friend class Scene;
- friend class Layer;
friend class BatchNode;
protected:
@@ -634,13 +650,15 @@ public:
/**
* 从图片文件获取图像(png/bmp/jpg/gif/emf/wmf/ico)
* 参数:图片文件名,图片裁剪坐标,图片裁剪宽度和高度
+ * 返回值:图片加载是否成功
*/
- void setImageFile(LPCTSTR ImageFile, int x = 0, int y = 0, int width = 0, int height = 0);
+ bool setImageFile(LPCTSTR ImageFile, int x = 0, int y = 0, int width = 0, int height = 0);
/**
* 从资源文件获取图像,不支持 png (bmp/jpg/gif/emf/wmf/ico)
* 参数:资源名称,图片裁剪坐标,图片裁剪宽度和高度
+ * 返回值:图片加载是否成功
*/
- void setImageRes(LPCTSTR pResName, int x = 0, int y = 0, int width = 0, int height = 0);
+ bool setImageRes(LPCTSTR pResName, int x = 0, int y = 0, int width = 0, int height = 0);
// 裁剪图片(裁剪后会恢复 stretch 拉伸)
void crop(int x = 0, int y = 0, int width = 0, int height = 0);
// 将图片拉伸到固定宽高
@@ -711,19 +729,25 @@ class MouseNode :
private:
bool m_bTarget;
bool m_bBlock;
- enum { NORMAL, MOUSEIN, SELECTED } m_eStatus;
- CLICK_CALLBACK m_callback;
+ 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;
- void _setNormal();
- void _setMouseIn();
- void _setSelected();
-
- // 重写该函数,实现鼠标位置的判定
- virtual void _judge() = 0;
+ // 重写这个方法可以自定义按钮的判断方法
+ virtual bool _judge();
+ // 切换状态
+ void _setStatus(Status status);
// 正常状态
virtual void _onNormal() = 0;
// 鼠标移入时
@@ -735,14 +759,20 @@ public:
MouseNode();
virtual ~MouseNode();
- // 鼠标点击时
- virtual void onClicked();
// 鼠标是否移入
virtual bool isMouseIn();
// 鼠标是否选中
virtual bool isSelected();
// 设置回调函数
- virtual void setOnMouseClicked(const CLICK_CALLBACK & callback);
+ 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();
// 设置节点是否阻塞鼠标消息
@@ -754,14 +784,11 @@ class Button :
public virtual MouseNode
{
protected:
- int m_nWidth;
- int m_nHeight;
bool m_bEnable;
protected:
virtual bool _exec(bool active) override;
virtual void _onDraw() override;
- virtual void _judge() override;
virtual void _onNormal() = 0;
virtual void _onMouseIn() = 0;