修复了无法完全回收游戏资源的问题

This commit is contained in:
Nomango 2018-04-21 18:22:01 +08:00
parent afc17339b1
commit b2e655226b
19 changed files with 130 additions and 66 deletions

View File

@ -14,7 +14,6 @@ e2d::Action::Action()
e2d::Action::~Action()
{
ActionManager::__remove(this);
}
bool e2d::Action::isRunning()
@ -74,6 +73,11 @@ e2d::Node * e2d::Action::getTarget()
return m_pTarget;
}
void e2d::Action::destroy()
{
ActionManager::__remove(this);
}
void e2d::Action::_init()
{
m_bInit = true;

View File

@ -12,7 +12,6 @@ e2d::ActionLoop::ActionLoop(Action * action, int times /* = -1 */)
e2d::ActionLoop::~ActionLoop()
{
SafeRelease(&m_pAction);
}
e2d::ActionLoop * e2d::ActionLoop::clone() const
@ -56,6 +55,12 @@ void e2d::ActionLoop::reset()
m_nTimes = 0;
}
void e2d::ActionLoop::destroy()
{
Action::destroy();
SafeRelease(&m_pAction);
}
void e2d::ActionLoop::_resetTime()
{
m_pAction->_resetTime();

View File

@ -29,10 +29,6 @@ e2d::ActionSequence::ActionSequence(int number, Action * action1, ...) :
e2d::ActionSequence::~ActionSequence()
{
FOR_LOOP(action, m_vActions)
{
SafeRelease(&action);
}
}
void e2d::ActionSequence::_init()
@ -50,6 +46,15 @@ void e2d::ActionSequence::_init()
m_vActions[0]->_init();
}
void e2d::ActionSequence::destroy()
{
Action::destroy();
FOR_LOOP(action, m_vActions)
{
SafeRelease(&action);
}
}
void e2d::ActionSequence::_update()
{
Action::_update();

View File

@ -12,8 +12,6 @@ e2d::ActionTwo::ActionTwo(Action * pActionFirst, Action * pActionSecond, bool bA
e2d::ActionTwo::~ActionTwo()
{
SafeRelease(&m_pFirstAction);
SafeRelease(&m_pSecondAction);
}
e2d::ActionTwo * e2d::ActionTwo::clone() const
@ -83,6 +81,13 @@ void e2d::ActionTwo::reset()
m_pSecondAction->reset();
}
void e2d::ActionTwo::destroy()
{
Action::destroy();
SafeRelease(&m_pFirstAction);
SafeRelease(&m_pSecondAction);
}
void e2d::ActionTwo::_resetTime()
{
m_pFirstAction->_resetTime();

View File

@ -64,10 +64,6 @@ e2d::Animation::Animation(double interval, int number, Image * frame, ...)
e2d::Animation::~Animation()
{
FOR_LOOP(frame, m_vFrames)
{
SafeRelease(&frame);
}
}
void e2d::Animation::setInterval(double interval)
@ -113,6 +109,15 @@ void e2d::Animation::reset()
m_nFrameIndex = 0;
}
void e2d::Animation::destroy()
{
Action::destroy();
FOR_LOOP(frame, m_vFrames)
{
SafeRelease(&frame);
}
}
void e2d::Animation::add(Image * frame)
{
if (frame)

View File

@ -164,14 +164,14 @@ void e2d::Game::destroy()
ColliderManager::__uninit();
// 删除动画
ActionManager::__uninit();
// 删除所有对象
ObjectManager::__clear();
// 清空图片缓存
Image::clearCache();
// 关闭输入
Input::__uninit();
// 恢复计时操作
Time::__uninit();
// 清空图片缓存
Image::clearCache();
// 刷新内存池
ObjectManager::__clear();
// 删除渲染相关资源
Renderer::__discardResources();
// 销毁窗口

View File

@ -2,6 +2,8 @@
#include "..\emanager.h"
#include "..\enode.h"
static bool s_bShowFps = false;
static IDWriteTextFormat * s_pTextFormat = nullptr;
static ID2D1Factory * s_pDirect2dFactory = nullptr;
static ID2D1HwndRenderTarget * s_pRenderTarget = nullptr;
static ID2D1SolidColorBrush * s_pSolidBrush = nullptr;
@ -9,13 +11,6 @@ static IWICImagingFactory * s_pIWICFactory = nullptr;
static IDWriteFactory * s_pDWriteFactory = nullptr;
static D2D1_COLOR_F s_nClearColor = D2D1::ColorF(D2D1::ColorF::Black);
static bool s_bShowFps = false;
static int s_nRenderTimes = 0;
static double s_fLastRenderTime = 0;
static e2d::String s_sFpsText = L"";
static IDWriteTextFormat * s_pTextFormat = nullptr;
bool e2d::Renderer::__createDeviceIndependentResources()
{
@ -64,6 +59,11 @@ bool e2d::Renderer::__createDeviceIndependentResources()
L"",
&s_pTextFormat
);
if (s_pTextFormat)
{
s_pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
}
}
return SUCCEEDED(hr);
@ -146,6 +146,10 @@ void e2d::Renderer::__render()
// äÖȾ FPS
if (s_bShowFps)
{
static int s_nRenderTimes = 0;
static double s_fLastRenderTime = 0;
static e2d::String s_sFpsText = L"";
s_nRenderTimes++;
double fDelay = Time::getTotalTime() - s_fLastRenderTime;
@ -156,12 +160,9 @@ void e2d::Renderer::__render()
s_nRenderTimes = 0;
}
D2D1_SIZE_F renderTargetSize = s_pRenderTarget->GetSize();
D2D1_RECT_F rect = D2D1::RectF(0, 0, renderTargetSize.width, renderTargetSize.height);
s_pSolidBrush->SetColor(D2D1::ColorF(D2D1::ColorF::White));
s_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
s_pRenderTarget->DrawTextW(s_sFpsText, (UINT32)s_sFpsText.getLength(), s_pTextFormat, rect, s_pSolidBrush);
s_pRenderTarget->DrawTextW(s_sFpsText, (UINT32)s_sFpsText.getLength(), s_pTextFormat, D2D1::RectF(), s_pSolidBrush);
}
// ÖÕÖ¹äÖȾ

View File

@ -3,9 +3,8 @@
e2d::Object::Object()
: m_nRefCount(0)
, m_bManaged(false)
{
ObjectManager::add(this); // 将该对象放入释放池中
ObjectManager::__add(this);
}
e2d::Object::~Object()
@ -26,7 +25,7 @@ void e2d::Object::release()
ObjectManager::flush();
}
int e2d::Object::getReferenceCount() const
int e2d::Object::getRefCount() const
{
return m_nRefCount;
}

View File

@ -16,7 +16,6 @@ e2d::Scene::Scene()
e2d::Scene::~Scene()
{
SafeRelease(&m_pRoot);
}
void e2d::Scene::_render()
@ -77,3 +76,8 @@ void e2d::Scene::showCollider(bool visiable)
{
m_bColliderVisiable = visiable;
}
void e2d::Scene::destroy()
{
SafeRelease(&m_pRoot);
}

View File

@ -2,14 +2,13 @@
#include "..\ebase.h"
// ObjectManager 释放池的实现机制:
// Object 类中的引用计数m_nRefCount保证了指针的使用安全
// Object 类中的引用计数m_nRefCount在一定程度上保证了指针的使用安全
// 它记录了对象被使用的次数,当计数为 0 时ObjectManager 会自动释放这个对象
// 所有的 Object 对象都应在被使用时(例如 Text 添加到了场景中)
// 调用 retain 函数保证该对象不被删除,并在不再使用时调用 release 函数
// 让其自动释放
// 对象管理池
static std::vector<e2d::Object*> s_vObjectPool;
static std::set<e2d::Object*> s_vObjectPool;
// 标志释放池执行状态
static bool s_bNotifyed = false;
@ -18,14 +17,13 @@ void e2d::ObjectManager::__update()
if (!s_bNotifyed) return;
s_bNotifyed = false;
// 创建迭代器
static std::vector<e2d::Object*>::iterator iter;
// 循环遍历容器中的所有对象
for (iter = s_vObjectPool.begin(); iter != s_vObjectPool.end();)
for (auto iter = s_vObjectPool.begin(); iter != s_vObjectPool.end();)
{
if ((*iter)->getReferenceCount() <= 0)
if ((*iter)->getRefCount() <= 0)
{
// 若对象的引用的计数小于等于 0, 释放该对象
(*iter)->destroy();
delete (*iter);
// 从释放池中删除该对象
iter = s_vObjectPool.erase(iter);
@ -39,19 +37,18 @@ void e2d::ObjectManager::__update()
void e2d::ObjectManager::__clear()
{
if (s_vObjectPool.size() != 0)
FOR_LOOP(pObj, s_vObjectPool)
{
s_bNotifyed = true;
ObjectManager::__update();
delete pObj;
}
s_vObjectPool.clear();
}
void e2d::ObjectManager::add(e2d::Object * nptr)
void e2d::ObjectManager::__add(e2d::Object * pObject)
{
if (!nptr->m_bManaged)
if (pObject)
{
nptr->m_bManaged = true;
s_vObjectPool.push_back(nptr); // 将一个对象放入释放池中
s_vObjectPool.insert(pObject);
}
}

View File

@ -170,7 +170,7 @@ void e2d::TimerManager::__uninit()
{
FOR_LOOP(timer, s_vTimers)
{
timer->release();
SafeRelease(&timer);
}
s_vTimers.clear();
}

View File

@ -46,12 +46,6 @@ e2d::Node::Node()
e2d::Node::~Node()
{
ActionManager::__clearAllBindedWith(this);
ColliderManager::__removeCollider(m_pCollider);
FOR_LOOP(child, m_vChildren)
{
SafeRelease(&child);
}
}
void e2d::Node::_update()
@ -1014,6 +1008,16 @@ void e2d::Node::setDefaultColliderEnable(bool bEnable)
s_fDefaultColliderEnabled = bEnable;
}
void e2d::Node::destroy()
{
ActionManager::__clearAllBindedWith(this);
ColliderManager::__removeCollider(m_pCollider);
FOR_LOOP(child, m_vChildren)
{
SafeRelease(&child);
}
}
void e2d::Node::resumeAllActions()
{
ActionManager::__resumeAllBindedWith(this);

View File

@ -27,7 +27,6 @@ e2d::Sprite::Sprite(String imageFileName, double x, double y, double width, doub
e2d::Sprite::~Sprite()
{
SafeRelease(&m_pImage);
}
void e2d::Sprite::open(Image * image)
@ -83,3 +82,9 @@ void e2d::Sprite::onRender()
);
}
}
void e2d::Sprite::destroy()
{
Node::destroy();
SafeRelease(&m_pImage);
}

View File

@ -18,8 +18,6 @@ e2d::Transition::Transition(double duration)
e2d::Transition::~Transition()
{
SafeRelease(&m_pPrevScene);
SafeRelease(&m_pNextScene);
SafeReleaseInterface(&m_pPrevLayer);
SafeReleaseInterface(&m_pNextLayer);
}
@ -29,6 +27,12 @@ bool e2d::Transition::isEnding()
return m_bEnd;
}
void e2d::Transition::destroy()
{
SafeRelease(&m_pPrevScene);
SafeRelease(&m_pNextScene);
}
void e2d::Transition::_init(Scene * prev, Scene * next)
{
// ´´½¨Í¼²ã

View File

@ -63,6 +63,9 @@ public:
// 获取该动作的执行目标
virtual Node * getTarget();
// 销毁对象
virtual void destroy() override;
protected:
// 初始化动作
virtual void _init();
@ -376,6 +379,9 @@ public:
// 重置动作
virtual void reset() override;
// 销毁对象
virtual void destroy() override;
protected:
// 初始化动作
virtual void _init() override;
@ -446,6 +452,9 @@ public:
// 重置动作
virtual void reset() override;
// 销毁对象
virtual void destroy() override;
protected:
// 初始化动作
virtual void _init() override;
@ -504,6 +513,9 @@ public:
// 重置动作
virtual void reset() override;
// 销毁对象
virtual void destroy() override;
protected:
// 初始化动作
virtual void _init() override;
@ -596,6 +608,9 @@ public:
// 重置动作
virtual void reset() override;
// 销毁对象
virtual void destroy() override;
protected:
// 初始化动作
virtual void _init() override;

View File

@ -464,13 +464,9 @@ struct Font
};
class ObjectManager;
// 基础对象
class Object
{
friend ObjectManager;
public:
Object();
@ -483,11 +479,13 @@ public:
void release();
// 获取引用计数
int getReferenceCount() const;
int getRefCount() const;
// 销毁对象
virtual void destroy() {}
private:
int m_nRefCount;
bool m_bManaged;
};
@ -641,6 +639,9 @@ public:
bool visiable = true
);
// 销毁对象
virtual void destroy() override;
protected:
// 渲染场景画面
void _render();

View File

@ -21,17 +21,18 @@ class CollisionListener;
class ObjectManager
{
friend Game;
friend Object;
public:
// 将一个对象放入内存池
static void add(
Object * nptr
);
// 释放垃圾对象的内存空间
static void flush();
private:
// 将对象放入内存池进行管理
static void __add(
Object * pObject
);
// 更新对象管理器
static void __update();

View File

@ -402,6 +402,9 @@ public:
bool bEnable
);
// 销毁对象
virtual void destroy() override;
protected:
// 更新节点
void _update();
@ -522,6 +525,9 @@ public:
// 渲染精灵
virtual void onRender() override;
// 销毁对象
virtual void destroy() override;
protected:
Image * m_pImage;
};

View File

@ -20,6 +20,9 @@ public:
// 场景切换动画是否结束
bool isEnding();
// 销毁对象
virtual void destroy() override;
protected:
// 初始化场景动画
virtual void _init(