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

dkasak13 at users.sourceforge.net dkasak13 at users.sourceforge.net
Sat Aug 8 14:31:49 CEST 2009


Revision: 43125
          http://scummvm.svn.sourceforge.net/scummvm/?rev=43125&view=rev
Author:   dkasak13
Date:     2009-08-08 12:31:49 +0000 (Sat, 08 Aug 2009)

Log Message:
-----------
* Implemented WalkingMap::findNearestWalkable() which mimics a heuristic from the original game that attempts to find walkable spots near the given point
* Implemented moving to the right place when looking / using objects.

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

Modified: scummvm/branches/gsoc2009-draci/engines/draci/game.cpp
===================================================================
--- scummvm/branches/gsoc2009-draci/engines/draci/game.cpp	2009-08-08 12:25:29 UTC (rev 43124)
+++ scummvm/branches/gsoc2009-draci/engines/draci/game.cpp	2009-08-08 12:31:49 UTC (rev 43125)
@@ -38,6 +38,7 @@
 static double real_to_double(byte real[6]);
 
 Game::Game(DraciEngine *vm) : _vm(vm) {
+	
 	unsigned int i;
 	
 	BArchive *initArchive = _vm->_initArchive;
@@ -283,6 +284,15 @@
 
 							_vm->_mouse->cursorOff();
 							_vm->_mouse->lButtonSet(false);				
+							
+							if (!obj->_imLook) {
+								if (obj->_lookDir == 0) {
+									walkHero(x, y);
+								} else {
+									walkHero(obj->_lookX, obj->_lookY);
+								}
+							}
+
 							_vm->_script->run(obj->_program, obj->_look);
 							_vm->_mouse->cursorOn();
 						}
@@ -293,6 +303,15 @@
 
 							_vm->_mouse->cursorOff();
 							_vm->_mouse->rButtonSet(false);
+
+							if (!obj->_imUse) {
+								if (obj->_useDir == 0) {
+									walkHero(x, y);
+								} else {
+									walkHero(obj->_useX, obj->_useY);
+								}
+							}
+
 							_vm->_script->run(obj->_program, obj->_use);
 							_vm->_mouse->cursorOn();
 						}
@@ -311,7 +330,6 @@
 					// If the player clicked on a walkable position and we are in the
 					// appropriate loop status, move the dragon there
 					if (_vm->_mouse->lButtonPressed() && 
-						_currentRoom._walkingMap.isWalkable(x, y) &&
 						_loopSubstatus == kStatusOrdinary) {
 
 						walkHero(x, y);
@@ -375,6 +393,13 @@
 }
 	
 void Game::walkHero(int x, int y) {
+
+	Surface *surface = _vm->_screen->getSurface();
+	Common::Point p = _currentRoom._walkingMap.findNearestWalkable(x, y, surface->getRect());
+
+	x = p.x;
+	y = p.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];
@@ -852,6 +877,103 @@
 	return mapByte & (1 << pixelIndex % 8);
 }
 
+/** 
+ * @brief For a given point, find a nearest walkable point on the walking map
+ *
+ * @param startX 	x coordinate of the point
+ * @param startY	y coordinate of the point
+ *
+ * @return A Common::Point representing the nearest walkable point
+ *
+ *	The algorithm was copied from the original engine for exactness.
+ *	TODO: Study this algorithm in more detail so it can be documented properly and
+ * 	possibly improved / simplified.
+ */
+Common::Point WalkingMap::findNearestWalkable(int startX, int startY, Common::Rect searchRect) {
+
+	int signs[] = { 1, -1 };
+	const uint kSignsNum = 2;
+
+	int radius = 0;
+	int x, y;
+	int dx, dy;
+	int prediction;
+
+	// The place where, eventually, the result coordinates will be stored
+	int finalX, finalY; 	
+
+	// The algorithm appears to start off with an ellipse with the minor radius equal to
+	// zero and the major radius equal to the walking map delta (the number of pixels
+	// one map pixel represents). It then uses a heuristic to gradually reshape it into
+	// a circle (by shortening the major radius and lengthening the minor one). At each
+	// such resizing step, it checks some select points on the ellipse for walkability.
+	// It also does the same check for the ellipse perpendicular to it (rotated by 90 degrees).
+
+	while(1) {
+
+		// The default major radius
+		radius += _deltaX;
+
+		// The ellipse radii (minor, major) that get resized
+		x = 0;
+		y = radius;
+
+		// Heuristic variables
+		prediction = 1 - radius;
+		dx = 3;
+		dy = 2 * radius - 2;
+		
+		do {
+			
+			// The following two loops serve the purpose of checking the points on the two
+			// ellipses for walkability. The signs[] array is there to obliterate the need
+			// of writing out all combinations manually.
+	
+			for (uint i = 0; i < kSignsNum; ++i) {
+				finalY = startY + y * signs[i];
+	
+				for (uint j = 0; j < kSignsNum; ++j) {
+					finalX = startX + x * signs[j];
+
+					// If the current point is walkable, return it
+					if (searchRect.contains(finalX, finalY) && isWalkable(finalX, finalY)) {
+						return Common::Point(finalX, finalY);
+					}
+				}
+			}
+
+			for (uint i = 0; i < kSignsNum; ++i) {
+				finalY = startY + x * signs[i];
+
+				for (uint j = 0; j < kSignsNum; ++j) {
+					finalX = startX + y * signs[j];
+
+					// If the current point is walkable, return it
+					if (searchRect.contains(finalX, finalY) && isWalkable(finalX, finalY)) {
+						return Common::Point(finalX, finalY);
+					}
+				}
+			}
+
+			// If prediction is non-negative, we need to decrease the major radius of the
+			// ellipse
+			if (prediction >= 0) {
+				prediction -= dy;
+				dy -= 2 * _deltaX;
+				y -= _deltaX;
+			}
+
+			// Increase the minor radius of the ellipse and update heuristic variables
+			prediction += dx;
+			dx += 2 * _deltaX;
+			x += _deltaX;
+
+		// If the current ellipse has been reshaped into a circle, 
+		// end this loop and enlarge the radius
+		} while (x <= y); 
+	}
+}
+
 static double real_to_double(byte real[6]) {
 
 	// Extract sign bit

Modified: scummvm/branches/gsoc2009-draci/engines/draci/game.h
===================================================================
--- scummvm/branches/gsoc2009-draci/engines/draci/game.h	2009-08-08 12:25:29 UTC (rev 43124)
+++ scummvm/branches/gsoc2009-draci/engines/draci/game.h	2009-08-08 12:31:49 UTC (rev 43125)
@@ -89,6 +89,7 @@
 	}
 
 	bool isWalkable(int x, int y);
+	Common::Point findNearestWalkable(int x, int y, Common::Rect searchRect);
 
 private:
 	int _realWidth, _realHeight;


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