[Scummvm-cvs-logs] SF.net SVN: scummvm:[42627] scummvm/branches/gsoc2009-draci/engines/draci

dkasak13 at users.sourceforge.net dkasak13 at users.sourceforge.net
Mon Jul 20 19:25:57 CEST 2009


Revision: 42627
          http://scummvm.svn.sourceforge.net/scummvm/?rev=42627&view=rev
Author:   dkasak13
Date:     2009-07-20 17:25:57 +0000 (Mon, 20 Jul 2009)

Log Message:
-----------
* Added scaling support
* Made the dragon scale when it is in different parts of the room
* Added getters for relative coordinates (Animation::getRelativeX() and Animation::getRelativeY())
* Commented Game::loop() and Sprite::draw*() methods in more detail

Modified Paths:
--------------
    scummvm/branches/gsoc2009-draci/engines/draci/animation.cpp
    scummvm/branches/gsoc2009-draci/engines/draci/animation.h
    scummvm/branches/gsoc2009-draci/engines/draci/game.cpp
    scummvm/branches/gsoc2009-draci/engines/draci/game.h
    scummvm/branches/gsoc2009-draci/engines/draci/sprite.cpp
    scummvm/branches/gsoc2009-draci/engines/draci/sprite.h

Modified: scummvm/branches/gsoc2009-draci/engines/draci/animation.cpp
===================================================================
--- scummvm/branches/gsoc2009-draci/engines/draci/animation.cpp	2009-07-20 09:19:27 UTC (rev 42626)
+++ scummvm/branches/gsoc2009-draci/engines/draci/animation.cpp	2009-07-20 17:25:57 UTC (rev 42627)
@@ -33,6 +33,8 @@
 	_z = 0;
 	_relX = 0;
 	_relY = 0;
+	_scaleX = 1.0;
+	_scaleY = 1.0;
 	setPlaying(false);
 	_looping = false;
 	_tick = _vm->_system->getMillis();
@@ -50,7 +52,14 @@
 void Animation::setRelative(int relx, int rely) {
 
 	// Delete the previous frame
-	Common::Rect frameRect = _frames[_currentFrame]->getRect();
+	Common::Rect frameRect;
+
+	if (isScaled()) {
+		frameRect = getFrame()->getScaledRect(_scaleX, _scaleY);
+	} else {
+		frameRect = getFrame()->getRect();
+	}
+
 	frameRect.translate(_relX, _relY);
 	_vm->_screen->getSurface()->markDirtyRect(frameRect);
 
@@ -58,6 +67,24 @@
 	_relY = rely;
 }
 
+void Animation::setScaling(double scalex, double scaley) {
+	
+	_scaleX = scalex;
+	_scaleY = scaley;
+}
+
+bool Animation::isScaled() const {
+	return !(_scaleX == 1.0 && _scaleY == 1.0);
+}
+
+double Animation::getScaleX() const {
+	return _scaleX;
+}
+
+double Animation::getScaleY() const {
+	return _scaleY;
+}
+
 void Animation::setLooping(bool looping) {
 	_looping = looping;
 	debugC(7, kDraciAnimationDebugLevel, "Setting looping to %d on animation %d", 
@@ -72,7 +99,13 @@
 
 	Drawable *frame = _frames[_currentFrame];
 
-	Common::Rect frameRect = frame->getRect();
+	Common::Rect frameRect;
+
+	if (isScaled()) {
+		frameRect = frame->getScaledRect(_scaleX, _scaleY);
+	} else {
+		frameRect = frame->getRect();
+	}
 	
 	// Translate rectangle to compensate for relative coordinates	
 	frameRect.translate(_relX, _relY);
@@ -111,19 +144,29 @@
 		return;
 
 	if (_id == kOverlayImage) {			
-		_frames[_currentFrame]->draw(surface, false);
+		_frames[_currentFrame]->drawScaled(surface, _scaleX, _scaleY, false);
 	}
 	else {
 		Drawable *ptr = _frames[_currentFrame];
+
 		int x = ptr->getX();
 		int y = ptr->getY();
+
+		// Take account relative coordinates
 		int newX = x + _relX;
 		int newY = y + _relY;
 
+		// Translate the frame to those relative coordinates
 		ptr->setX(newX);
 		ptr->setY(newY);
-		ptr->draw(surface, true);
 
+		// Draw frame
+		if (isScaled())
+			ptr->drawScaled(surface, _scaleX, _scaleY, true);
+		else
+			ptr->drawScaled(surface, _scaleX, _scaleY, true);
+
+		// Revert back to old coordinates
 		ptr->setX(x);
 		ptr->setY(y);
 	}
@@ -145,6 +188,14 @@
 	return _z;
 }
 
+int Animation::getRelativeX() {
+	return _relX;
+}
+
+int Animation::getRelativeY() {
+	return _relY;
+}
+
 bool Animation::isPlaying() {
 	return _playing;
 }
@@ -208,8 +259,15 @@
 	Animation *anim = getAnimation(id);
 	
 	// Clean up the last frame that was drawn before stopping
-	Common::Rect frameRect = anim->getFrame()->getRect();
-	frameRect.translate(anim->_relX, anim->_relY);
+	Common::Rect frameRect;
+
+	if (anim->isScaled()) {
+		frameRect = anim->getFrame()->getScaledRect(anim->getScaleX(), anim->getScaleY());
+	} else {
+		frameRect = anim->getFrame()->getRect();
+	}
+
+	frameRect.translate(anim->getRelativeX(), anim->getRelativeY());
 	_vm->_screen->getSurface()->markDirtyRect(frameRect);
 
 	if (anim) {

Modified: scummvm/branches/gsoc2009-draci/engines/draci/animation.h
===================================================================
--- scummvm/branches/gsoc2009-draci/engines/draci/animation.h	2009-07-20 09:19:27 UTC (rev 42626)
+++ scummvm/branches/gsoc2009-draci/engines/draci/animation.h	2009-07-20 17:25:57 UTC (rev 42627)
@@ -37,7 +37,7 @@
 class DraciEngine;
 
 class Animation {
-
+	
 public:
 	Animation(DraciEngine *vm);
 	~Animation();	
@@ -62,11 +62,15 @@
 	bool isLooping();
 	void setLooping(bool looping);
 
+	double getScaleX() const;
+	double getScaleY() const;
+	void setScaling(double scalex, double scaley);
+	bool isScaled() const;
+
 	void setRelative(int relx, int rely);
+	int getRelativeX();
+	int getRelativeY();
 
-	int _relX;
-	int _relY;
-
 private:
 	
 	uint nextFrameNum();
@@ -75,6 +79,12 @@
 	uint _currentFrame;
 	uint _z;
 
+	int _relX;
+	int _relY;
+
+	double _scaleX;
+	double _scaleY;
+
 	uint _tick;
 	bool _playing;
 	bool _looping;

Modified: scummvm/branches/gsoc2009-draci/engines/draci/game.cpp
===================================================================
--- scummvm/branches/gsoc2009-draci/engines/draci/game.cpp	2009-07-20 09:19:27 UTC (rev 42626)
+++ scummvm/branches/gsoc2009-draci/engines/draci/game.cpp	2009-07-20 17:25:57 UTC (rev 42627)
@@ -171,16 +171,33 @@
 
 		if (_vm->_mouse->lButtonPressed() && _currentRoom._walkingMap.isWalkable(x, y)) {
 			
+			// Fetch dragon's animation ID
+			// FIXME: Need to add proper walking (this only warps the dragon to position)
 			int animID = getObject(kDragonObject)->_anims[0];
 
 			Animation *anim = _vm->_anims->getAnimation(animID);
 			Drawable *frame = anim->getFrame();
 
+			// Calculate scaling factor
+			double scaleX = _currentRoom._pers0 + _currentRoom._persStep * y;
+			double scaleY = scaleX;
+
+			// Calculate scaled height of sprite
+			int height = frame->getScaledHeight(scaleY);
+
+			// Set the Z coordinate for the dragon's animation
 			anim->setZ(y+1);
 
-			y -= frame->getHeight();
-			anim->setRelative(x, y); 
+			// We naturally want the dragon to position its feet to the location of the
+			// click but sprites are drawn from their top-left corner so we subtract
+			// the height of the dragon's sprite
+			y -= height;
+			anim->setRelative(x, y);
 
+			// Set the scaling factor
+			anim->setScaling(scaleX, scaleY);
+
+			// Play the animation
 			_vm->_anims->play(animID);
 
 			debugC(4, kDraciLogicDebugLevel, "Walk to x: %d y: %d", x, y);
@@ -221,6 +238,7 @@
 
 	for (int i = 5; i >= 0; --i) {
 		real[i] = roomReader.readByte();
+		debug(2, "%d", real[i]);
 	}
 
 	_currentRoom._pers0 = real_to_double(real);

Modified: scummvm/branches/gsoc2009-draci/engines/draci/game.h
===================================================================
--- scummvm/branches/gsoc2009-draci/engines/draci/game.h	2009-07-20 09:19:27 UTC (rev 42626)
+++ scummvm/branches/gsoc2009-draci/engines/draci/game.h	2009-07-20 17:25:57 UTC (rev 42627)
@@ -134,6 +134,9 @@
 
 class Game {
 
+	// HACK: Remove this before committing; if anyone sees this, remind me :D
+	friend class Animation;
+
 public:
 
 	Game(DraciEngine *vm);

Modified: scummvm/branches/gsoc2009-draci/engines/draci/sprite.cpp
===================================================================
--- scummvm/branches/gsoc2009-draci/engines/draci/sprite.cpp	2009-07-20 09:19:27 UTC (rev 42626)
+++ scummvm/branches/gsoc2009-draci/engines/draci/sprite.cpp	2009-07-20 17:25:57 UTC (rev 42627)
@@ -29,6 +29,8 @@
 #include "draci/sprite.h"
 #include "draci/font.h"
 
+#include <cmath>
+
 namespace Draci {
 
 /**
@@ -115,6 +117,87 @@
 	_mirror = false;
 }
 
+// TODO: Research what kind of sampling the original player uses
+void Sprite::drawScaled(Surface *surface, double scaleX, double scaleY, bool markDirty) const {
+
+	Common::Rect sourceRect(0, 0, _width, _height);
+	Common::Rect destRect(_x, _y, _x + getScaledWidth(scaleX), _y + getScaledHeight(scaleY));
+	Common::Rect surfaceRect(0, 0, surface->w, surface->h);
+	Common::Rect clippedDestRect(destRect);
+
+	clippedDestRect.clip(surfaceRect);
+
+	// Calculate by how much we need to adjust the source rectangle to account for cropping
+	const int adjustLeft = clippedDestRect.left - destRect.left;
+	const int adjustRight = clippedDestRect.right - destRect.right;
+	const int adjustTop = clippedDestRect.top - destRect.top;
+	const int adjustBottom = clippedDestRect.bottom - destRect.bottom;
+
+	// Resize source rectangle
+	sourceRect.left += adjustLeft;
+	sourceRect.right += adjustRight;
+	sourceRect.top += adjustTop;
+	sourceRect.bottom += adjustBottom;
+
+	// Get pointers to source and destination buffers
+	byte *dst = (byte *)surface->getBasePtr(clippedDestRect.left, clippedDestRect.top);
+	byte *src = _data;
+
+	const int transparent = surface->getTransparentColour();
+
+	// Calculate how many rows and columns we need to draw
+	const int rows = clippedDestRect.bottom - clippedDestRect.top;
+	const int columns = clippedDestRect.right - clippedDestRect.left;
+
+	int *rowIndices = new int[rows];
+	int *columnIndices = new int[columns];
+
+	// Precalculate pixel indexes
+	for (int i = 0; i < rows; ++i) {
+		rowIndices[i] = lround(i / scaleY);
+	}
+
+	for (int j = 0; j < columns; ++j) {
+		columnIndices[j] = lround(j / scaleX);
+	}
+
+	// Blit the sprite to the surface
+	for (int i = 0; i < rows; ++i) {
+
+		// Fetch index of current row to be drawn
+		int row = rowIndices[i];
+		
+		for (int j = 0, q = sourceRect.left; j < columns; ++j, ++q) {
+			
+			// Fetch index of current column to be drawn
+			int column = columnIndices[j];
+
+			// Don't blit if the pixel is transparent on the target surface
+			if (src[row * _width + column] != transparent) {
+
+				// Draw the sprite mirrored if the _mirror flag is set						
+				if (_mirror) {
+					dst[sourceRect.right - q - 1] = src[row * _width + column];
+				} else {
+					dst[q] = src[row * _width + column];
+				}
+			}
+		}
+
+		// Advance to next row
+		dst += surface->pitch;
+	}
+
+	// Mark the sprite's rectangle dirty
+	if (markDirty) {	
+		surface->markDirtyRect(destRect);
+	}
+
+	delete[] rowIndices;
+	delete[] columnIndices;
+}
+	
+
 /**
  *  @brief Draws the sprite to a Draci::Surface
  *  @param surface Pointer to a Draci::Surface
@@ -131,16 +214,19 @@
 
 	clippedDestRect.clip(surfaceRect);
 
-	int adjustLeft = clippedDestRect.left - destRect.left;
-	int adjustRight = clippedDestRect.right - destRect.right;
-	int adjustTop = clippedDestRect.top - destRect.top;
-	int adjustBottom = clippedDestRect.bottom - destRect.bottom;
+	// Calculate by how much we need to adjust the source rectangle to account for cropping
+	const int adjustLeft = clippedDestRect.left - destRect.left;
+	const int adjustRight = clippedDestRect.right - destRect.right;
+	const int adjustTop = clippedDestRect.top - destRect.top;
+ 	const int adjustBottom = clippedDestRect.bottom - destRect.bottom;
 
+	// Resize source rectangle
 	sourceRect.left += adjustLeft;
 	sourceRect.right += adjustRight;
 	sourceRect.top += adjustTop;
 	sourceRect.bottom += adjustBottom;
 
+	// Get pointers to source and destination buffers
 	byte *dst = (byte *)surface->getBasePtr(clippedDestRect.left, clippedDestRect.top);
 	byte *src = _data;
 
@@ -162,6 +248,7 @@
 			}		
 		}
 
+		// Advance to next row
 		dst += surface->pitch;
 	}
 
@@ -175,6 +262,18 @@
 	return Common::Rect(_x, _y, _x + _width, _y + _height);
 }
 
+Common::Rect Sprite::getScaledRect(double scaleX, double scaleY) const {
+	return Common::Rect(_x, _y, _x + getScaledWidth(scaleX), _y + getScaledHeight(scaleY));
+}
+
+uint Sprite::getScaledHeight(double scaleY) const {
+	return lround(scaleY * _height);
+}
+
+uint Sprite::getScaledWidth(double scaleX) const {
+	return lround(scaleX * _width);
+}
+
 Text::Text(const Common::String &str, Font *font, byte fontColour, 
 				int x, int y, uint spacing) {
 	uint len = str.size();

Modified: scummvm/branches/gsoc2009-draci/engines/draci/sprite.h
===================================================================
--- scummvm/branches/gsoc2009-draci/engines/draci/sprite.h	2009-07-20 09:19:27 UTC (rev 42626)
+++ scummvm/branches/gsoc2009-draci/engines/draci/sprite.h	2009-07-20 17:25:57 UTC (rev 42627)
@@ -38,11 +38,17 @@
 
 public:
 	virtual void draw(Surface *surface, bool markDirty = true) const = 0;
+	virtual void drawScaled(Surface *surface, double scaleX, double scaleY, 
+		bool markDirty = true) const = 0;
+
 	virtual ~Drawable() {};
 	
 	virtual uint16 getWidth() { return _width; }
 	virtual uint16 getHeight() { return _height; }
 
+	virtual uint getScaledWidth(double scaleX) const = 0;
+	virtual uint getScaledHeight(double scaleY) const = 0;
+
 	virtual int getX() { return _x; }
 	virtual int getY() { return _y; }
 
@@ -53,6 +59,7 @@
 	int getDelay() { return _delay; }	
 
 	virtual Common::Rect getRect() const = 0;
+	virtual	Common::Rect getScaledRect(double scaleX, double scaleY) const = 0;
 	
 private:
 	uint16 _width;	//!< Width of the sprite
@@ -89,11 +96,17 @@
 	~Sprite();
 
 	void draw(Surface *surface, bool markDirty = true) const;
+	void drawScaled(Surface *surface, double scaleX, double scaleY, bool markDirty = true) const;
 	
 	void setMirrorOn();
 	void setMirrorOff();
 
 	virtual Common::Rect getRect() const;
+	Common::Rect getScaledRect(double scaleX, double scaleY) const;
+
+	virtual uint getScaledWidth(double scaleX) const;
+	virtual uint getScaledHeight(double scaleY) const;
+
 	const byte *getBuffer() const { return _data; }
 
 private:


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list