diff --git a/core/Action/Action.cpp b/core/Action/Action.cpp index e1dac817..20cab13c 100644 --- a/core/Action/Action.cpp +++ b/core/Action/Action.cpp @@ -46,12 +46,6 @@ void e2d::Action::setName(const String& name) _name = name; } -e2d::Action * e2d::Action::reverse() const -{ - ASSERT(false, "Action cannot be reversed!"); - return nullptr; -} - e2d::Node * e2d::Action::getTarget() { return _target; diff --git a/core/Action/Animate.cpp b/core/Action/Animate.cpp index 2bf7e0fb..68bff3b0 100644 --- a/core/Action/Animate.cpp +++ b/core/Action/Animate.cpp @@ -64,9 +64,9 @@ void e2d::Animate::_update() target->open(frames[_frameIndex]); } - _frameIndex++; _last += _animation->getInterval(); - + _frameIndex++; + if (_frameIndex == frames.size()) { this->stop(); @@ -99,10 +99,7 @@ e2d::Animate * e2d::Animate::clone() const { return new (std::nothrow) Animate(_animation); } - else - { - return nullptr; - } + return nullptr; } e2d::Animate * e2d::Animate::reverse() const diff --git a/core/Action/CallFunc.cpp b/core/Action/CallFunc.cpp index 4b6f7c6f..d13c3ca5 100644 --- a/core/Action/CallFunc.cpp +++ b/core/Action/CallFunc.cpp @@ -10,6 +10,11 @@ e2d::CallFunc * e2d::CallFunc::clone() const return new (std::nothrow) CallFunc(_func); } +e2d::CallFunc * e2d::CallFunc::reverse() const +{ + return new (std::nothrow) CallFunc(_func); +} + void e2d::CallFunc::_init() { } diff --git a/core/Action/Delay.cpp b/core/Action/Delay.cpp index c5e01319..443b0ecb 100644 --- a/core/Action/Delay.cpp +++ b/core/Action/Delay.cpp @@ -11,6 +11,11 @@ e2d::Delay * e2d::Delay::clone() const return new (std::nothrow) Delay(_delay); } +e2d::Delay * e2d::Delay::reverse() const +{ + return new (std::nothrow) Delay(_delay); +} + void e2d::Delay::reset() { Action::reset(); diff --git a/core/Action/Loop.cpp b/core/Action/Loop.cpp index 4065ec5b..e43baba3 100644 --- a/core/Action/Loop.cpp +++ b/core/Action/Loop.cpp @@ -31,6 +31,11 @@ e2d::Loop * e2d::Loop::clone() const } } +e2d::Loop * e2d::Loop::reverse() const +{ + return new (std::nothrow) Loop(_action); +} + void e2d::Loop::_init() { Action::_init(); diff --git a/core/Action/Sequence.cpp b/core/Action/Sequence.cpp index 2be812dc..0f208c71 100644 --- a/core/Action/Sequence.cpp +++ b/core/Action/Sequence.cpp @@ -111,13 +111,17 @@ e2d::Sequence * e2d::Sequence::clone() const e2d::Sequence * e2d::Sequence::reverse() const { auto sequence = new (std::nothrow) Sequence(); - for (const auto& action : _actions) + if (!_actions.empty()) { - if (action) + std::vector newActions(_actions.size()); + for (auto iter = _actions.crbegin(), iterCrend = _actions.crend(); iter != iterCrend; ++iter) { - sequence->add(action->reverse()); + if (*iter) + { + newActions.push_back(*iter); + } } + sequence->add(newActions); } - sequence->_actions.reserve(_actions.size()); return sequence; } \ No newline at end of file diff --git a/core/Action/Spawn.cpp b/core/Action/Spawn.cpp index 741509e3..c6de4d91 100644 --- a/core/Action/Spawn.cpp +++ b/core/Action/Spawn.cpp @@ -109,13 +109,17 @@ e2d::Spawn * e2d::Spawn::clone() const e2d::Spawn * e2d::Spawn::reverse() const { auto spawn = new (std::nothrow) Spawn(); - for (const auto& action : _actions) + if (!_actions.empty()) { - if (action) + std::vector newActions(_actions.size()); + for (auto iter = _actions.crbegin(), iterCrend = _actions.crend(); iter != iterCrend; ++iter) { - spawn->add(action->reverse()); + if (*iter) + { + newActions.push_back(*iter); + } } + spawn->add(newActions); } - spawn->_actions.reserve(_actions.size()); return spawn; } \ No newline at end of file diff --git a/core/Base/Renderer.cpp b/core/Base/Renderer.cpp index 2d86e693..78903e55 100644 --- a/core/Base/Renderer.cpp +++ b/core/Base/Renderer.cpp @@ -223,8 +223,7 @@ void e2d::Renderer::__render() if (FAILED(hr)) { - // 渲染时产生了未知的错误,退出游戏 - ASSERT(false, L"Renderer error: %#X!", hr); + Window::error(L"Device loss recovery failed. Exiting game."); Game::quit(); } } diff --git a/core/Common/Animation.cpp b/core/Common/Animation.cpp index 7b5ffd3a..cb72923f 100644 --- a/core/Common/Animation.cpp +++ b/core/Common/Animation.cpp @@ -68,10 +68,10 @@ const std::vector& e2d::Animation::getFrames() const e2d::Animation * e2d::Animation::clone() const { - auto a = new Animation(_interval); + auto animation = new (std::nothrow) Animation(_interval); for (auto frame : _frames) { - a->add(frame); + animation->add(frame); } - return a; + return animation; } diff --git a/core/Common/Image.cpp b/core/Common/Image.cpp index f817a90d..9375e6a3 100644 --- a/core/Common/Image.cpp +++ b/core/Common/Image.cpp @@ -1,8 +1,10 @@ -#include "..\e2dnode.h" +#include "..\e2dcommon.h" +#include "..\e2dbase.h" #include static std::map s_mBitmapsFromFile; static std::map s_mBitmapsFromResource; +static std::set s_vBitmaps; e2d::Image::Image() @@ -26,6 +28,12 @@ e2d::Image::Image(int resNameId, const String& resType) this->open(resNameId, resType); } +e2d::Image::Image(ID2D1Bitmap * bitmap) + : _bitmap(nullptr) +{ + this->open(bitmap); +} + e2d::Image::Image(const String& filePath, double cropX, double cropY, double cropWidth, double cropHeight) : _bitmap(nullptr) { @@ -46,7 +54,7 @@ e2d::Image::~Image() bool e2d::Image::open(const String& filePath) { - WARN_IF(filePath.isEmpty(), "Image cannot load bitmap from NULL file name."); + WARN_IF(filePath.isEmpty(), "Image open failed! Invalid file name."); if (filePath.isEmpty()) return false; @@ -57,10 +65,7 @@ bool e2d::Image::open(const String& filePath) return false; } - _bitmap = s_mBitmapsFromFile.at(filePath.getHashCode()); - _cropX = _cropY = 0; - _cropWidth = _bitmap->GetSize().width; - _cropHeight = _bitmap->GetSize().height; + this->_setBitmap(s_mBitmapsFromFile.at(filePath.getHashCode())); return true; } @@ -72,13 +77,24 @@ bool e2d::Image::open(int resNameId, const String& resType) return false; } - _bitmap = s_mBitmapsFromResource.at(resNameId); - _cropX = _cropY = 0; - _cropWidth = _bitmap->GetSize().width; - _cropHeight = _bitmap->GetSize().height; + this->_setBitmap(s_mBitmapsFromResource.at(resNameId)); return true; } +bool e2d::Image::open(ID2D1Bitmap * bitmap) +{ + if (bitmap) + { + if (s_vBitmaps.find(bitmap) != s_vBitmaps.end()) + { + s_vBitmaps.insert(bitmap); + } + this->_setBitmap(bitmap); + return true; + } + return false; +} + void e2d::Image::crop(double x, double y, double width, double height) { if (_bitmap) @@ -156,9 +172,9 @@ e2d::Point e2d::Image::getCropPos() const return Point(_cropX, _cropY); } -bool e2d::Image::preload(const String& fileName) +bool e2d::Image::preload(const String& filePath) { - if (s_mBitmapsFromFile.find(fileName.getHashCode()) != s_mBitmapsFromFile.end()) + if (s_mBitmapsFromFile.find(filePath.getHashCode()) != s_mBitmapsFromFile.end()) { return true; } @@ -173,7 +189,7 @@ bool e2d::Image::preload(const String& fileName) // 创建解码器 hr = Renderer::getIWICImagingFactory()->CreateDecoderFromFilename( - fileName, + filePath, NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, @@ -221,7 +237,7 @@ bool e2d::Image::preload(const String& fileName) // 保存图片指针和图片的 Hash 名 s_mBitmapsFromFile.insert( std::map::value_type( - fileName.getHashCode(), + filePath.getHashCode(), pBitmap) ); } @@ -375,6 +391,23 @@ void e2d::Image::clearCache() SafeReleaseInterface(bitmap.second); } s_mBitmapsFromResource.clear(); + + for (auto bitmap : s_vBitmaps) + { + SafeReleaseInterface(bitmap); + } + s_vBitmaps.clear(); +} + +void e2d::Image::_setBitmap(ID2D1Bitmap * bitmap) +{ + if (bitmap) + { + _bitmap = bitmap; + _cropX = _cropY = 0; + _cropWidth = _bitmap->GetSize().width; + _cropHeight = _bitmap->GetSize().height; + } } ID2D1Bitmap * e2d::Image::getBitmap() diff --git a/core/Manager/ObjectManager.cpp b/core/Manager/ObjectManager.cpp index e9113436..2111df92 100644 --- a/core/Manager/ObjectManager.cpp +++ b/core/Manager/ObjectManager.cpp @@ -27,7 +27,7 @@ void e2d::ObjectManager::__update() } else { - iter++; // 移动迭代器 + iter++; } } } diff --git a/core/e2daction.h b/core/e2daction.h index 17cd8187..f79d5936 100644 --- a/core/e2daction.h +++ b/core/e2daction.h @@ -49,7 +49,7 @@ public: virtual Action * clone() const = 0; // 获取动作的倒转 - virtual Action * reverse() const; + virtual Action * reverse() const = 0; // 重置动作 virtual void reset(); @@ -161,6 +161,13 @@ public: // 获取该动作的拷贝对象 virtual MoveTo * clone() const override; + // 获取该动作的倒转 + virtual MoveTo * reverse() const override + { + ASSERT(false, "reverse() not supported in MoveTo"); + return nullptr; + } + protected: // 初始化动作 virtual void _init() override; @@ -221,6 +228,13 @@ public: // 获取该动作的拷贝对象 virtual JumpTo * clone() const override; + // 获取该动作的倒转 + virtual JumpTo * reverse() const override + { + ASSERT(false, "reverse() not supported in JumpTo"); + return nullptr; + } + protected: // 初始化动作 virtual void _init() override; @@ -290,6 +304,13 @@ public: // 获取该动作的拷贝对象 virtual ScaleTo * clone() const override; + // 获取该动作的倒转 + virtual ScaleTo * reverse() const override + { + ASSERT(false, "reverse() not supported in ScaleTo"); + return nullptr; + } + protected: // 初始化动作 virtual void _init() override; @@ -344,6 +365,13 @@ public: // 获取该动作的拷贝对象 virtual OpacityTo * clone() const override; + // 获取该动作的倒转 + virtual OpacityTo * reverse() const override + { + ASSERT(false, "reverse() not supported in OpacityTo"); + return nullptr; + } + protected: // 初始化动作 virtual void _init() override; @@ -427,6 +455,13 @@ public: // 获取该动作的拷贝对象 virtual RotateTo * clone() const override; + // 获取该动作的倒转 + virtual RotateTo * reverse() const override + { + ASSERT(false, "reverse() not supported in RotateTo"); + return nullptr; + } + protected: // 初始化动作 virtual void _init() override; @@ -449,6 +484,9 @@ public: // 获取该动作的拷贝对象 virtual Delay * clone() const override; + // 获取该动作的倒转 + virtual Delay * reverse() const override; + // 重置动作 virtual void reset() override; @@ -484,6 +522,9 @@ public: // 获取该动作的拷贝对象 virtual Loop * clone() const override; + // 获取该动作的倒转 + virtual Loop * reverse() const override; + // 重置动作 virtual void reset() override; @@ -520,6 +561,9 @@ public: // 获取该动作的拷贝对象 virtual CallFunc * clone() const override; + // 获取该动作的倒转 + virtual CallFunc * reverse() const override; + protected: // 初始化动作 virtual void _init() override; diff --git a/core/e2dcommon.h b/core/e2dcommon.h index 58ab49b9..4d412115 100644 --- a/core/e2dcommon.h +++ b/core/e2dcommon.h @@ -619,6 +619,11 @@ public: const String& resType /* 图片资源类型 */ ); + // 加载位图 + Image( + ID2D1Bitmap * bitmap /* 位图资源 */ + ); + // 加载图片文件并裁剪 Image( const String& filePath, /* 图片文件路径 */ @@ -642,7 +647,7 @@ public: // 加载图片文件 bool open( - const String& filePath + const String& filePath /* 图片文件路径 */ ); // 加载图片资源 @@ -651,6 +656,11 @@ public: const String& resType /* 图片资源类型 */ ); + // 加载位图 + bool open( + ID2D1Bitmap * bitmap /* 位图资源 */ + ); + // 将图片裁剪为矩形 void crop( double cropX, /* 裁剪位置 X 坐标 */ @@ -703,6 +713,12 @@ public: // 清空缓存 static void clearCache(); +protected: + // 设置 Bitmap + void _setBitmap( + ID2D1Bitmap * bitmap + ); + protected: double _cropX; double _cropY; @@ -720,9 +736,14 @@ public: // 创建帧动画 Animation(); - // 创建特定间隔的帧动画 + // 创建帧动画 Animation( - double interval /* 帧间隔(秒) */ + const std::vector& frames /* 关键帧数组 */ + ); + + // 创建特定帧间隔的帧动画 + Animation( + double interval /* 帧间隔(秒) */ ); // 创建特定帧间隔的帧动画 @@ -731,16 +752,11 @@ public: const std::vector& frames /* 关键帧数组 */ ); - // 创建帧动画 - Animation( - const std::vector& frames /* 关键帧列表 */ - ); - virtual ~Animation(); // 添加关键帧 void add( - Image * frame /* 关键帧 */ + Image * frame /* 关键帧 */ ); // 添加多个关键帧 @@ -756,7 +772,7 @@ public: // 设置每一帧的时间间隔 void setInterval( - double interval /* 帧间隔(秒) */ + double interval /* 帧间隔(秒) */ ); // 获取动画的拷贝对象 diff --git a/core/e2dnode.h b/core/e2dnode.h index d4d71de0..6abf7753 100644 --- a/core/e2dnode.h +++ b/core/e2dnode.h @@ -551,6 +551,7 @@ protected: }; +// 文本 class Text : public Node {