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

dkasak13 at users.sourceforge.net dkasak13 at users.sourceforge.net
Sun Aug 9 06:09:25 CEST 2009


Revision: 43160
          http://scummvm.svn.sourceforge.net/scummvm/?rev=43160&view=rev
Author:   dkasak13
Date:     2009-08-09 04:09:24 +0000 (Sun, 09 Aug 2009)

Log Message:
-----------
* Implemented Game::loadWalkingMap().
* Extracted title updating from the main loop to a new method, Game::updateTitle().
* Added Game::updateCursor().
* Restructured the main loop to fix many subtle bugs and enable some new functionality concerning object scripts (like support for room-global use scripts).
* Added support for tracking currently selected icons (items, probably should be renamed).
* Changed walkDir, lookDir and useDir members of GameObject to int and adjusted them for zero-based indexing.
* Added Game::getCurrentIcon().
* Return from WalkingMap::findNearestWalkable immediately if the starting point is walkable.

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-09 03:59:39 UTC (rev 43159)
+++ scummvm/branches/gsoc2009-draci/engines/draci/game.cpp	2009-08-09 04:09:24 UTC (rev 43160)
@@ -197,6 +197,10 @@
 	_shouldQuit = false;
 	_shouldExitLoop = false;
 
+	_currentIcon = kNoIcon;
+
+	_vm->_mouse->setCursorType(kNormalCursor);
+
 	// HACK: Won't be needed once I've implemented the loop properly
 	_roomChange = false;
 
@@ -236,8 +240,6 @@
 
 	Surface *surface = _vm->_screen->getSurface();
 
-	const int smallFontHeight = _vm->_smallFont->getFontHeight();
-
 	do {
 
 		_vm->handleEvents();
@@ -248,45 +250,37 @@
 			int x = _vm->_mouse->getPosX();
 			int y = _vm->_mouse->getPosY();
 
-			// Find the game object under the cursor
-			// (to be more precise, one that corresponds to the animation under the cursor)
-			int animUnderCursor = _vm->_anims->getTopAnimationID(x, y);
-			int curObject = getObjectWithAnimation(animUnderCursor);
-			GameObject *obj = &_objects[curObject];
-
 			// Fetch the dedicated objects' title animation / current frame
 			Animation *titleAnim = _vm->_anims->getAnimation(kTitleText);
 			Text *title = reinterpret_cast<Text *>(titleAnim->getFrame());
 
-			if (_loopStatus == kStatusOrdinary) {
-				// If there is an object under the cursor, display its title and enable
-				// executing its look and use scripts
-				if (curObject != kObjectNotFound) {					
+			if (_loopStatus == kStatusOrdinary && _loopSubstatus == kStatusOrdinary) {
+				if(_vm->_mouse->isCursorOn()) {
+					// Find the game object under the cursor
+					// (to be more precise, one that corresponds to the animation under the cursor)
+					int animUnderCursor = _vm->_anims->getTopAnimationID(x, y);
+					int curObject = getObjectWithAnimation(animUnderCursor);
 
-					if(_vm->_mouse->isCursorOn()) {
-						// Mark dirty rectangle to delete the previous text
-						titleAnim->markDirtyRect(surface);	
+					updateTitle();
 
-						// Set the title for the current object
-						title->setText(obj->_title);
-
-						// Move the title to the correct place (just above the cursor)
-						int newX = surface->centerOnX(x, title->getWidth());
-						int newY = surface->centerOnY(y - smallFontHeight / 2, title->getHeight() * 2);
-						titleAnim->setRelative(newX, newY);
+					_objUnderCursor = curObject;
+					if (_objUnderCursor != _oldObjUnderCursor) {
+						_oldObjUnderCursor = _objUnderCursor;
+						updateCursor();
 					}
 
-					if (_loopSubstatus == kStatusOrdinary) {
+					if (_vm->_mouse->lButtonPressed()) {
+						_vm->_mouse->lButtonSet(false);				
 
-						if (_vm->_mouse->lButtonPressed()) {
-							// Delete title text
+						if (_objUnderCursor != kObjectNotFound) {
+							GameObject *obj = &_objects[_objUnderCursor];
+			
+							_vm->_mouse->cursorOff();
+							titleAnim->markDirtyRect(surface);
 							title->setText("");
 
-							_vm->_mouse->cursorOff();
-							_vm->_mouse->lButtonSet(false);				
-							
 							if (!obj->_imLook) {
-								if (obj->_lookDir == 0) {
+								if (obj->_lookDir == -1) {
 									walkHero(x, y);
 								} else {
 									walkHero(obj->_lookX, obj->_lookY);
@@ -295,21 +289,24 @@
 
 							_vm->_script->run(obj->_program, obj->_look);
 							_vm->_mouse->cursorOn();
+						} else {
+							walkHero(x, y);
 						}
+					}
 
-						// TODO: Handle global use scripts (the use script for the room itself)
+					if (_vm->_mouse->rButtonPressed()) {
+						_vm->_mouse->rButtonSet(false);
 
-						if (_vm->_mouse->rButtonPressed()) {
-							// Delete title text
-							title->setText("");
+						if (_objUnderCursor != kObjectNotFound) {
+							GameObject *obj = &_objects[_objUnderCursor];
 
-							_vm->_mouse->rButtonSet(false);
-
 							if (_vm->_script->testExpression(obj->_program, obj->_canUse)) {
 								_vm->_mouse->cursorOff();
+								titleAnim->markDirtyRect(surface);
+								title->setText("");
 
 								if (!obj->_imUse) {
-									if (obj->_useDir == 0) {
+									if (obj->_useDir == -1) {
 										walkHero(x, y);
 									} else {
 										walkHero(obj->_useX, obj->_useY);
@@ -320,26 +317,23 @@
 								_vm->_mouse->cursorOn();
 							} else {
 								walkHero(x, y);
-							}	
-						}
-					}
-				} else {
-					// We haven't found an object under the cursor
+							}
+						} else {
+							if (_vm->_script->testExpression(_currentRoom._program, _currentRoom._canUse)) {
+								_vm->_mouse->cursorOff();
+								titleAnim->markDirtyRect(surface);
+								title->setText("");
 
-					// Delete the previous title				
-					titleAnim->markDirtyRect(surface);
-					title->setText("");
 
-					// If we are in the appropriate loop status and the player clicked
-					// on the room, move the dragon to the nearest walkable point
-					if (_vm->_mouse->lButtonPressed() && 
-						_loopSubstatus == kStatusOrdinary) {
-
-						walkHero(x, y);
+								_vm->_script->run(_currentRoom._program, _currentRoom._use);
+								_vm->_mouse->cursorOn();
+							} else {
+								walkHero(x, y);
+							}
+						}
 					}
+					debugC(2, kDraciAnimationDebugLevel, "Anim under cursor: %d", animUnderCursor); 
 				}
-
-				debugC(2, kDraciAnimationDebugLevel, "Anim under cursor: %d", animUnderCursor); 
 			}
 		}
 
@@ -371,7 +365,9 @@
 			return;
 
 		// Advance animations and redraw screen
-		_vm->_anims->drawScene(_vm->_screen->getSurface());
+		if (_loopStatus != kStatusInventory) {
+			_vm->_anims->drawScene(surface);
+		}
 		_vm->_screen->copyToScreen();
 		_vm->_system->delayMillis(20);
 
@@ -381,6 +377,75 @@
 	} while (!shouldExitLoop());
 }
 
+void Game::updateCursor() {
+
+	_vm->_mouse->setCursorType(kNormalCursor);
+
+	if (_currentIcon != kNoIcon) {
+		_vm->_mouse->loadItemCursor(_currentIcon);
+	}
+
+	if (_objUnderCursor == kObjectNotFound) {					
+
+		if (_vm->_script->testExpression(_currentRoom._program, _currentRoom._canUse)) {
+			if (_currentIcon == kNoIcon) {
+				_vm->_mouse->setCursorType(kHighlightedCursor);
+			} else {
+				_vm->_mouse->loadItemCursor(_currentIcon, true);
+			}
+		}
+	} else {
+		GameObject *obj = &_objects[_objUnderCursor];
+
+		_vm->_mouse->setCursorType((CursorType)obj->_walkDir);
+		
+		if (!(obj->_walkDir > 0)) {
+			if (_vm->_script->testExpression(obj->_program, obj->_canUse)) {
+				if (_currentIcon == kNoIcon) {
+					_vm->_mouse->setCursorType(kHighlightedCursor);
+				} else {
+					_vm->_mouse->loadItemCursor(_currentIcon, true);
+				}
+			}
+		}
+	}
+}
+
+void Game::updateTitle() {
+
+	Surface *surface = _vm->_screen->getSurface();
+	const int smallFontHeight = _vm->_smallFont->getFontHeight();
+
+	// Fetch mouse coordinates			
+	int x = _vm->_mouse->getPosX();
+	int y = _vm->_mouse->getPosY();
+
+	// Fetch the dedicated objects' title animation / current frame
+	Animation *titleAnim = _vm->_anims->getAnimation(kTitleText);
+	Text *title = reinterpret_cast<Text *>(titleAnim->getFrame());
+
+	// Mark dirty rectangle to delete the previous text
+	titleAnim->markDirtyRect(surface);	
+	
+	if (_objUnderCursor == kObjectNotFound) {
+		title->setText("");
+	} else {
+		GameObject *obj = &_objects[_objUnderCursor];	
+		title->setText(obj->_title);
+	}
+
+	// Move the title to the correct place (just above the cursor)
+	int newX = surface->centerOnX(x, title->getWidth());
+	int newY = surface->centerOnY(y - smallFontHeight / 2, title->getHeight() * 2);
+	titleAnim->setRelative(newX, newY);
+
+	if (titleAnim->isPlaying()) {
+		titleAnim->markDirtyRect(surface);
+	} else {
+		_vm->_anims->play(titleAnim->getID());
+	}
+}	
+
 int Game::getObjectWithAnimation(int animID) {
 	for (uint i = 0; i < _info._numObjects; ++i) {
 		GameObject *obj = &_objects[i];
@@ -398,11 +463,14 @@
 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;
 
+	debugC(4, kDraciLogicDebugLevel, "Walk to x: %d y: %d", 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];
@@ -426,19 +494,18 @@
   	_persons[kDragonObject]._x = x + (lround(scaleX) * width) / 2;
 	_persons[kDragonObject]._y = y - lround(scaleY) * height;
 
+	// Set the per-animation scaling factor
+	anim->setScaleFactors(scaleX, scaleY);
+
 	// 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 current height of the dragon's sprite
 	y -= (int)(scaleY * height);
+	//x -= (int)(scaleX * width) / 2;
 	anim->setRelative(x, y);
 
-	// Set the per-animation scaling factor
-	anim->setScaleFactors(scaleX, scaleY);
-
 	// Play the animation
 	_vm->_anims->play(animID);
-
-	debugC(4, kDraciLogicDebugLevel, "Walk to x: %d y: %d", x, y);
 }
 
 void Game::loadRoom(int roomNum) {
@@ -453,9 +520,8 @@
 
 	_currentRoom._music = roomReader.readByte();
 
-	int mapIdx = roomReader.readByte() - 1;
-	f = _vm->_walkingMapsArchive->getFile(mapIdx);
-	_currentRoom._walkingMap.load(f->_data, f->_length);
+	int mapID = roomReader.readByte() - 1;
+	loadWalkingMap(mapID);
 
 	_currentRoom._palette = roomReader.readByte() - 1;
 	_currentRoom._numOverlays = roomReader.readSint16LE();
@@ -488,7 +554,7 @@
 	_currentRoom._numGates = roomReader.readByte();
 
 	debugC(4, kDraciLogicDebugLevel, "Music: %d", _currentRoom._music);
-	debugC(4, kDraciLogicDebugLevel, "Map: %d", mapIdx);
+	debugC(4, kDraciLogicDebugLevel, "Map: %d", mapID);
 	debugC(4, kDraciLogicDebugLevel, "Palette: %d", _currentRoom._palette);
 	debugC(4, kDraciLogicDebugLevel, "Overlays: %d", _currentRoom._numOverlays);
 	debugC(4, kDraciLogicDebugLevel, "Init: %d", _currentRoom._init);
@@ -558,8 +624,6 @@
 		_vm->_mouse->cursorOff();
 	}
 
-	_vm->_mouse->setCursorType(kNormalCursor);
-
 	// HACK: Create a visible overlay from the walking map so we can test it
 	byte *wlk = new byte[kScreenWidth * kScreenHeight];
 	memset(wlk, 255, kScreenWidth * kScreenHeight);
@@ -651,7 +715,7 @@
 	obj->_imInit = objReader.readByte();
 	obj->_imLook = objReader.readByte();
 	obj->_imUse = objReader.readByte();
-	obj->_walkDir = objReader.readByte();
+	obj->_walkDir = objReader.readByte() - 1;
 	obj->_z = objReader.readByte();
 	objReader.readUint16LE(); // idxSeq field, not used
 	objReader.readUint16LE(); // numSeq field, not used
@@ -659,8 +723,8 @@
 	obj->_lookY = objReader.readUint16LE();
 	obj->_useX = objReader.readUint16LE();
 	obj->_useY = objReader.readUint16LE();
-	obj->_lookDir = objReader.readByte();
-	obj->_useDir = objReader.readByte();
+	obj->_lookDir = objReader.readByte() - 1;
+	obj->_useDir = objReader.readByte() - 1;
 	
 	obj->_absNum = objNum;
 	
@@ -676,6 +740,13 @@
 	obj->_program._length = file->_length;
 }
 
+void Game::loadWalkingMap(int mapID) {
+
+	BAFile *f;
+	f = _vm->_walkingMapsArchive->getFile(mapID);
+	_currentRoom._walkingMap.load(f->_data, f->_length);
+}
+
 GameObject *Game::getObject(uint objNum) {
 	return _objects + objNum;
 }
@@ -829,6 +900,10 @@
 	return _iconStatus[iconID];
 }
 
+int Game::getCurrentIcon() {
+	return _currentIcon;
+}
+
 Person *Game::getPerson(int personID) {
 	return &_persons[personID];
 }
@@ -894,6 +969,12 @@
  */
 Common::Point WalkingMap::findNearestWalkable(int startX, int startY, Common::Rect searchRect) {
 
+	// If the starting point is walkable, just return that
+	if (searchRect.contains(startX, startY) && isWalkable(startX, startY)) {
+		return Common::Point(startX, startY);
+	}
+	
+
 	int signs[] = { 1, -1 };
 	const uint kSignsNum = 2;
 
@@ -945,6 +1026,13 @@
 				}
 			}
 
+			if (x == y) {
+				// If the starting point is walkable, just return that
+				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];
 

Modified: scummvm/branches/gsoc2009-draci/engines/draci/game.h
===================================================================
--- scummvm/branches/gsoc2009-draci/engines/draci/game.h	2009-08-09 03:59:39 UTC (rev 43159)
+++ scummvm/branches/gsoc2009-draci/engines/draci/game.h	2009-08-09 04:09:24 UTC (rev 43160)
@@ -56,6 +56,18 @@
 	kNoEscRoom = -1
 };
 
+// Used as a value to Game::_currentIcon and means there is no icon (game item) selected
+// and a "real" cursor image is used
+enum {
+	kNoIcon = -1
+};
+
+// Used as a default parameter in Game::loadWalkingMap() to specify that the default
+// walking map to the room is to be loaded.
+enum {
+	kDefaultRoomMap = -1
+};
+
 enum SpeechConstants {
 	kBaseSpeechDuration = 200,
 	kSpeechTimeUnit = 400
@@ -103,10 +115,10 @@
 	
 	uint _init, _look, _use, _canUse;
 	bool _imInit, _imLook, _imUse;
-	byte _walkDir;
+	int _walkDir;
 	byte _z;
 	uint _lookX, _lookY, _useX, _useY;
-	byte _lookDir, _useDir;
+	int _lookDir, _useDir;
 	uint _absNum;
 	Common::Array<int> _anims;
 	GPL2Program _program;
@@ -211,6 +223,7 @@
 	int loadAnimation(uint animNum, uint z);
 	void loadOverlays();
 	void loadObject(uint numObj);
+	void loadWalkingMap(int mapID = kDefaultRoomMap);
 
 	uint getNumObjects();
 	GameObject *getObject(uint objNum);
@@ -228,6 +241,7 @@
 	void setGateNum(int gate);
 
 	int getIconStatus(int iconID);
+	int getCurrentIcon();
 
 	int getEscRoom();
 
@@ -249,6 +263,9 @@
 
 	void setSpeechTick(uint tick);
 
+	void updateTitle();
+	void updateCursor();
+
 	bool _roomChange;
 
 private:
@@ -267,6 +284,8 @@
 	int _newRoom;
 	int _newGate;
 
+	int _currentIcon;
+
 	LoopStatus _loopStatus;
 	LoopStatus _loopSubstatus;
 
@@ -276,6 +295,8 @@
 	uint _speechTick;
 
 	int _objUnderCursor;
+	int _oldObjUnderCursor;	
+
 	int _markedAnimationIndex; //!< Used by the Mark GPL command
 };
 


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