From c340159486b499783c297453a14b4df76b4aa535 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Sun, 11 Mar 2012 20:41:57 +0100 Subject: GOB: Extend ANIObject to also handle CMP sprite "animations" --- engines/gob/aniobject.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) (limited to 'engines/gob/aniobject.cpp') diff --git a/engines/gob/aniobject.cpp b/engines/gob/aniobject.cpp index 0ca850d1fb..154f8e04ed 100644 --- a/engines/gob/aniobject.cpp +++ b/engines/gob/aniobject.cpp @@ -22,11 +22,20 @@ #include "gob/surface.h" #include "gob/anifile.h" +#include "gob/cmpfile.h" #include "gob/aniobject.h" namespace Gob { -ANIObject::ANIObject(const ANIFile &ani) : _ani(&ani), +ANIObject::ANIObject(const ANIFile &ani) : _ani(&ani), _cmp(0), + _visible(false), _paused(false), _mode(kModeContinuous), + _x(0), _y(0), _background(0), _drawn(false) { + + setAnimation(0); + setPosition(); +} + +ANIObject::ANIObject(const CMPFile &cmp) : _ani(0), _cmp(&cmp), _visible(false), _paused(false), _mode(kModeContinuous), _x(0), _y(0), _background(0), _drawn(false) { @@ -68,6 +77,10 @@ void ANIObject::rewind() { } void ANIObject::setPosition() { + // CMP "animations" have no default position + if (_cmp) + return; + if (_animation >= _ani->getAnimationCount()) return; @@ -88,6 +101,12 @@ void ANIObject::getPosition(int16 &x, int16 &y) const { } void ANIObject::getFramePosition(int16 &x, int16 &y) const { + // CMP "animations" have no specific frame positions + if (_cmp) { + getPosition(x, y); + return; + } + if (_animation >= _ani->getAnimationCount()) return; @@ -100,6 +119,13 @@ void ANIObject::getFramePosition(int16 &x, int16 &y) const { } void ANIObject::getFrameSize(int16 &width, int16 &height) const { + if (_cmp) { + width = _cmp->getWidth (_animation); + height = _cmp->getHeight(_animation); + + return; + } + if (_animation >= _ani->getAnimationCount()) return; @@ -147,6 +173,47 @@ void ANIObject::draw(Surface &dest, int16 &left, int16 &top, if (!_visible) return; + if (_cmp) + drawCMP(dest, left, top, right, bottom); + else if (_ani) + drawANI(dest, left, top, right, bottom); +} + +void ANIObject::drawCMP(Surface &dest, int16 &left, int16 &top, + int16 &right, int16 &bottom) { + + if (!_background) { + uint16 width, height; + + _cmp->getMaxSize(width, height); + + _background = new Surface(width, height, dest.getBPP()); + } + + const uint16 cR = _cmp->getWidth (_animation) - 1; + const uint16 cB = _cmp->getHeight(_animation) - 1; + + _backgroundLeft = CLIP( + _x, 0, dest.getWidth () - 1); + _backgroundTop = CLIP( + _y, 0, dest.getHeight() - 1); + _backgroundRight = CLIP(cR + _x, 0, dest.getWidth () - 1); + _backgroundBottom = CLIP(cB + _y, 0, dest.getHeight() - 1); + + _background->blit(dest, _backgroundLeft , _backgroundTop, + _backgroundRight, _backgroundBottom, 0, 0); + + _cmp->draw(dest, _animation, _x, _y, 0); + + _drawn = true; + + left = _backgroundLeft; + top = _backgroundTop; + right = _backgroundRight; + bottom = _backgroundBottom; +} + +void ANIObject::drawANI(Surface &dest, int16 &left, int16 &top, + int16 &right, int16 &bottom) { + if (!_background) { uint16 width, height; @@ -202,6 +269,10 @@ void ANIObject::advance() { if (_paused) return; + // CMP "animations" have only one frame + if (_cmp) + return; + if (_animation >= _ani->getAnimationCount()) return; @@ -229,6 +300,10 @@ uint16 ANIObject::getFrame() const { } bool ANIObject::lastFrame() const { + // CMP "animations" have only one frame + if (_cmp) + return true; + if (_animation >= _ani->getAnimationCount()) return true; -- cgit v1.2.3 From db99d23717ce4f39f9d9f55ce1abf0d8b73cc630 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Sun, 3 Jun 2012 18:58:03 +0200 Subject: GOB: Fix invalid reads in Geisha's minigames --- engines/gob/aniobject.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'engines/gob/aniobject.cpp') diff --git a/engines/gob/aniobject.cpp b/engines/gob/aniobject.cpp index 154f8e04ed..54534cd60b 100644 --- a/engines/gob/aniobject.cpp +++ b/engines/gob/aniobject.cpp @@ -167,19 +167,21 @@ bool ANIObject::isIn(const ANIObject &obj) const { obj.isIn(frameX + frameWidth - 1, frameY + frameHeight - 1); } -void ANIObject::draw(Surface &dest, int16 &left, int16 &top, +bool ANIObject::draw(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) { if (!_visible) - return; + return false; if (_cmp) - drawCMP(dest, left, top, right, bottom); + return drawCMP(dest, left, top, right, bottom); else if (_ani) - drawANI(dest, left, top, right, bottom); + return drawANI(dest, left, top, right, bottom); + + return false; } -void ANIObject::drawCMP(Surface &dest, int16 &left, int16 &top, +bool ANIObject::drawCMP(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) { if (!_background) { @@ -209,9 +211,11 @@ void ANIObject::drawCMP(Surface &dest, int16 &left, int16 &top, top = _backgroundTop; right = _backgroundRight; bottom = _backgroundBottom; + + return true; } -void ANIObject::drawANI(Surface &dest, int16 &left, int16 &top, +bool ANIObject::drawANI(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) { if (!_background) { @@ -224,7 +228,7 @@ void ANIObject::drawANI(Surface &dest, int16 &left, int16 &top, const ANIFile::Animation &animation = _ani->getAnimationInfo(_animation); if (_frame >= animation.frameCount) - return; + return false; const ANIFile::FrameArea &area = animation.frameAreas[_frame]; @@ -244,13 +248,15 @@ void ANIObject::drawANI(Surface &dest, int16 &left, int16 &top, top = _backgroundTop; right = _backgroundRight; bottom = _backgroundBottom; + + return true; } -void ANIObject::clear(Surface &dest, int16 &left, int16 &top, +bool ANIObject::clear(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) { if (!_drawn) - return; + return false; const int16 bgRight = _backgroundRight - _backgroundLeft; const int16 bgBottom = _backgroundBottom - _backgroundTop; @@ -263,6 +269,8 @@ void ANIObject::clear(Surface &dest, int16 &left, int16 &top, top = _backgroundTop; right = _backgroundRight; bottom = _backgroundBottom; + + return true; } void ANIObject::advance() { -- cgit v1.2.3 From 3d537e763c85bb3f16825c8b47894335568278a0 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Thu, 7 Jun 2012 04:20:41 +0200 Subject: GOB: Handle Penetration shooting animations more cleverly Still no bullets, though :P --- engines/gob/aniobject.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines/gob/aniobject.cpp') diff --git a/engines/gob/aniobject.cpp b/engines/gob/aniobject.cpp index 54534cd60b..8d739fb3a4 100644 --- a/engines/gob/aniobject.cpp +++ b/engines/gob/aniobject.cpp @@ -76,6 +76,10 @@ void ANIObject::rewind() { _frame = 0; } +void ANIObject::setFrame(uint16 frame) { + _frame = frame % _ani->getAnimationInfo(_animation).frameCount; +} + void ANIObject::setPosition() { // CMP "animations" have no default position if (_cmp) -- cgit v1.2.3 From 9af01cd58417e796b82cf6bb36e1bd30b0875f0e Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Fri, 6 Jul 2012 06:50:04 +0200 Subject: GOB: Move the background saving into its own class BackBuffer --- engines/gob/aniobject.cpp | 73 ++++++++++++----------------------------------- 1 file changed, 19 insertions(+), 54 deletions(-) (limited to 'engines/gob/aniobject.cpp') diff --git a/engines/gob/aniobject.cpp b/engines/gob/aniobject.cpp index 8d739fb3a4..8d3a6897bf 100644 --- a/engines/gob/aniobject.cpp +++ b/engines/gob/aniobject.cpp @@ -28,23 +28,20 @@ namespace Gob { ANIObject::ANIObject(const ANIFile &ani) : _ani(&ani), _cmp(0), - _visible(false), _paused(false), _mode(kModeContinuous), - _x(0), _y(0), _background(0), _drawn(false) { + _visible(false), _paused(false), _mode(kModeContinuous), _x(0), _y(0) { setAnimation(0); setPosition(); } ANIObject::ANIObject(const CMPFile &cmp) : _ani(0), _cmp(&cmp), - _visible(false), _paused(false), _mode(kModeContinuous), - _x(0), _y(0), _background(0), _drawn(false) { + _visible(false), _paused(false), _mode(kModeContinuous), _x(0), _y(0) { setAnimation(0); setPosition(); } ANIObject::~ANIObject() { - delete _background; } void ANIObject::setVisible(bool visible) { @@ -188,46 +185,36 @@ bool ANIObject::draw(Surface &dest, int16 &left, int16 &top, bool ANIObject::drawCMP(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) { - if (!_background) { + if (!hasBuffer()) { uint16 width, height; _cmp->getMaxSize(width, height); - _background = new Surface(width, height, dest.getBPP()); + resizeBuffer(width, height); } - const uint16 cR = _cmp->getWidth (_animation) - 1; - const uint16 cB = _cmp->getHeight(_animation) - 1; + left = _x; + top = _y; + right = _x + _cmp->getWidth (_animation) - 1; + bottom = _y + _cmp->getHeight(_animation) - 1; - _backgroundLeft = CLIP( + _x, 0, dest.getWidth () - 1); - _backgroundTop = CLIP( + _y, 0, dest.getHeight() - 1); - _backgroundRight = CLIP(cR + _x, 0, dest.getWidth () - 1); - _backgroundBottom = CLIP(cB + _y, 0, dest.getHeight() - 1); - - _background->blit(dest, _backgroundLeft , _backgroundTop, - _backgroundRight, _backgroundBottom, 0, 0); + if (!saveScreen(dest, left, top, right, bottom)) + return false; _cmp->draw(dest, _animation, _x, _y, 0); - _drawn = true; - - left = _backgroundLeft; - top = _backgroundTop; - right = _backgroundRight; - bottom = _backgroundBottom; - return true; } bool ANIObject::drawANI(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) { - if (!_background) { + if (!hasBuffer()) { uint16 width, height; _ani->getMaxSize(width, height); - _background = new Surface(width, height, dest.getBPP()); + resizeBuffer(width, height); } const ANIFile::Animation &animation = _ani->getAnimationInfo(_animation); @@ -236,45 +223,23 @@ bool ANIObject::drawANI(Surface &dest, int16 &left, int16 &top, const ANIFile::FrameArea &area = animation.frameAreas[_frame]; - _backgroundLeft = CLIP(area.left + _x, 0, dest.getWidth () - 1); - _backgroundTop = CLIP(area.top + _y, 0, dest.getHeight() - 1); - _backgroundRight = CLIP(area.right + _x, 0, dest.getWidth () - 1); - _backgroundBottom = CLIP(area.bottom + _y, 0, dest.getHeight() - 1); + left = _x + area.left; + top = _y + area.top; + right = _x + area.right; + bottom = _y + area.bottom; - _background->blit(dest, _backgroundLeft , _backgroundTop, - _backgroundRight, _backgroundBottom, 0, 0); + if (!saveScreen(dest, left, top, right, bottom)) + return false; _ani->draw(dest, _animation, _frame, _x, _y); - _drawn = true; - - left = _backgroundLeft; - top = _backgroundTop; - right = _backgroundRight; - bottom = _backgroundBottom; - return true; } bool ANIObject::clear(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) { - if (!_drawn) - return false; - - const int16 bgRight = _backgroundRight - _backgroundLeft; - const int16 bgBottom = _backgroundBottom - _backgroundTop; - - dest.blit(*_background, 0, 0, bgRight, bgBottom, _backgroundLeft, _backgroundTop); - - _drawn = false; - - left = _backgroundLeft; - top = _backgroundTop; - right = _backgroundRight; - bottom = _backgroundBottom; - - return true; + return restoreScreen(dest, left, top, right, bottom); } void ANIObject::advance() { -- cgit v1.2.3 From a547633911afa31964c10ed0222410aa9e66db80 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Thu, 5 Jul 2012 06:11:46 +0200 Subject: GOB: ANIObject can now predict the position/size of future frames --- engines/gob/aniobject.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'engines/gob/aniobject.cpp') diff --git a/engines/gob/aniobject.cpp b/engines/gob/aniobject.cpp index 8d3a6897bf..7e3668a0ce 100644 --- a/engines/gob/aniobject.cpp +++ b/engines/gob/aniobject.cpp @@ -101,7 +101,7 @@ void ANIObject::getPosition(int16 &x, int16 &y) const { y = _y; } -void ANIObject::getFramePosition(int16 &x, int16 &y) const { +void ANIObject::getFramePosition(int16 &x, int16 &y, uint16 n) const { // CMP "animations" have no specific frame positions if (_cmp) { getPosition(x, y); @@ -115,11 +115,24 @@ void ANIObject::getFramePosition(int16 &x, int16 &y) const { if (_frame >= animation.frameCount) return; - x = _x + animation.frameAreas[_frame].left; - y = _y + animation.frameAreas[_frame].top; + // If we're paused, we don't advance any frames + if (_paused) + n = 0; + + // Number of cycles run through after n frames + uint16 cycles = (_frame + n) / animation.frameCount; + // Frame position after n frames + uint16 frame = (_frame + n) % animation.frameCount; + + // Only doing one cycle? + if (_mode == kModeOnce) + cycles = MAX(cycles, 1); + + x = _x + animation.frameAreas[frame].left + cycles * animation.deltaX; + y = _y + animation.frameAreas[frame].top + cycles * animation.deltaY; } -void ANIObject::getFrameSize(int16 &width, int16 &height) const { +void ANIObject::getFrameSize(int16 &width, int16 &height, uint16 n) const { if (_cmp) { width = _cmp->getWidth (_animation); height = _cmp->getHeight(_animation); @@ -134,8 +147,15 @@ void ANIObject::getFrameSize(int16 &width, int16 &height) const { if (_frame >= animation.frameCount) return; - width = animation.frameAreas[_frame].right - animation.frameAreas[_frame].left + 1; - height = animation.frameAreas[_frame].bottom - animation.frameAreas[_frame].top + 1; + // If we're paused, we don't advance any frames + if (_paused) + n = 0; + + // Frame position after n frames + uint16 frame = (_frame + n) % animation.frameCount; + + width = animation.frameAreas[frame].right - animation.frameAreas[frame].left + 1; + height = animation.frameAreas[frame].bottom - animation.frameAreas[frame].top + 1; } bool ANIObject::isIn(int16 x, int16 y) const { -- cgit v1.2.3