[Scummvm-cvs-logs] scummvm master -> 04d0ec8d03d46f59f950929321fef43b52ea740a

DrMcCoy drmccoy at drmccoy.de
Wed Jun 6 03:34:00 CEST 2012


This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
93dda1b227 GOB: const correctness
b83ac21f60 GOB: Implement Penetration submarine shooting and dying
1782012f9f GOB: Clean up the Penetration map handling a bit
04d0ec8d03 GOB: Implement exiting floors


Commit: 93dda1b227fa11d1da2d923ca63a580343f6ba4e
    https://github.com/scummvm/scummvm/commit/93dda1b227fa11d1da2d923ca63a580343f6ba4e
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2012-06-05T18:33:34-07:00

Commit Message:
GOB: const correctness

Changed paths:
    engines/gob/minigames/geisha/evilfish.cpp
    engines/gob/minigames/geisha/evilfish.h



diff --git a/engines/gob/minigames/geisha/evilfish.cpp b/engines/gob/minigames/geisha/evilfish.cpp
index c7ef9d5..05ae9d0 100644
--- a/engines/gob/minigames/geisha/evilfish.cpp
+++ b/engines/gob/minigames/geisha/evilfish.cpp
@@ -171,7 +171,7 @@ void EvilFish::mutate(uint16 animSwimLeft, uint16 animSwimRight,
 	}
 }
 
-bool EvilFish::isDead() {
+bool EvilFish::isDead() const {
 	return !isVisible() || (_state == kStateNone) || (_state == kStateDie);
 }
 
diff --git a/engines/gob/minigames/geisha/evilfish.h b/engines/gob/minigames/geisha/evilfish.h
index 81efb67..4c82629 100644
--- a/engines/gob/minigames/geisha/evilfish.h
+++ b/engines/gob/minigames/geisha/evilfish.h
@@ -58,7 +58,7 @@ public:
 	            uint16 animTurnLeft, uint16 animTurnRight, uint16 animDie);
 
 	/** Is the fish dead? */
-	bool isDead();
+	bool isDead() const;
 
 private:
 	enum State {


Commit: b83ac21f6008287414d59ad7f9c88b63bd93bac5
    https://github.com/scummvm/scummvm/commit/b83ac21f6008287414d59ad7f9c88b63bd93bac5
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2012-06-05T18:33:35-07:00

Commit Message:
GOB: Implement Penetration submarine shooting and dying

Shots don't result in bullets yet, though

Changed paths:
  A engines/gob/minigames/geisha/submarine.cpp
  A engines/gob/minigames/geisha/submarine.h
    engines/gob/minigames/geisha/mouth.cpp
    engines/gob/minigames/geisha/penetration.cpp
    engines/gob/minigames/geisha/penetration.h
    engines/gob/module.mk



diff --git a/engines/gob/minigames/geisha/mouth.cpp b/engines/gob/minigames/geisha/mouth.cpp
index 605ffe4..7ba9f86 100644
--- a/engines/gob/minigames/geisha/mouth.cpp
+++ b/engines/gob/minigames/geisha/mouth.cpp
@@ -21,7 +21,6 @@
  */
 
 #include "common/util.h"
-#include "common/textconsole.h"
 
 #include "gob/minigames/geisha/mouth.h"
 
diff --git a/engines/gob/minigames/geisha/penetration.cpp b/engines/gob/minigames/geisha/penetration.cpp
index a188995..2c1a491 100644
--- a/engines/gob/minigames/geisha/penetration.cpp
+++ b/engines/gob/minigames/geisha/penetration.cpp
@@ -73,27 +73,6 @@ enum Sprite {
 };
 
 enum Animation {
-	kAnimationDriveS    =  4,
-	kAnimationDriveE    =  5,
-	kAnimationDriveN    =  6,
-	kAnimationDriveW    =  7,
-	kAnimationDriveSE   =  8,
-	kAnimationDriveNE   =  9,
-	kAnimationDriveSW   = 10,
-	kAnimationDriveNW   = 11,
-	kAnimationShootS    = 12,
-	kAnimationShootN    = 13,
-	kAnimationShootW    = 14,
-	kAnimationShootE    = 15,
-	kAnimationShootNE   = 16,
-	kAnimationShootSE   = 17,
-	kAnimationShootSW   = 18,
-	kAnimationShootNW   = 19,
-	kAnimationExplodeN  = 28,
-	kAnimationExplodeS  = 29,
-	kAnimationExplodeW  = 30,
-	kAnimationExplodeE  = 31,
-	kAnimationExit      = 32,
 	kAnimationMouthKiss = 33,
 	kAnimationMouthBite = 34
 };
@@ -220,9 +199,18 @@ Penetration::ManagedMouth::~ManagedMouth() {
 }
 
 
+Penetration::ManagedSub::ManagedSub(uint16 pX, uint16 pY) : Position(pX, pY), sub(0) {
+	mapX = x * kMapTileWidth;
+	mapY = y * kMapTileHeight;
+}
+
+Penetration::ManagedSub::~ManagedSub() {
+	delete sub;
+}
+
+
 Penetration::Penetration(GobEngine *vm) : _vm(vm), _background(0), _sprites(0), _objects(0), _sub(0),
-	_shieldMeter(0), _healthMeter(0), _floor(0), _mapX(0), _mapY(0),
-	_subTileX(0), _subTileY(0) {
+	_shieldMeter(0), _healthMeter(0), _floor(0) {
 
 	_background = new Surface(320, 200, 1);
 
@@ -255,7 +243,7 @@ bool Penetration::play(bool hasAccessPass, bool hasMaxEnergy, bool testMode) {
 	_vm->_draw->blitInvalidated();
 	_vm->_video->retrace();
 
-	while (!_vm->shouldQuit()) {
+	while (!_vm->shouldQuit() && !isDead() && !hasWon()) {
 		updateAnims();
 
 		// Draw and wait for the end of the frame
@@ -278,7 +266,8 @@ bool Penetration::play(bool hasAccessPass, bool hasMaxEnergy, bool testMode) {
 	}
 
 	deinit();
-	return false;
+
+	return hasWon();
 }
 
 void Penetration::init() {
@@ -286,6 +275,7 @@ void Penetration::init() {
 	_vm->_sound->sampleLoad(&_soundShield, SOUND_SND, "boucl.snd");
 	_vm->_sound->sampleLoad(&_soundBite  , SOUND_SND, "pervet.snd");
 	_vm->_sound->sampleLoad(&_soundKiss  , SOUND_SND, "baise.snd");
+	_vm->_sound->sampleLoad(&_soundShoot , SOUND_SND, "tirgim.snd");
 
 	_background->clear();
 
@@ -310,19 +300,14 @@ void Penetration::init() {
 	for (Common::List<ManagedMouth>::iterator m = _mouths.begin(); m != _mouths.end(); m++)
 		_mapAnims.push_back(m->mouth);
 
-	_sub = new ANIObject(*_objects);
-
-	_sub->setAnimation(kAnimationDriveN);
-	_sub->setPosition(kPlayAreaX + kPlayAreaBorderWidth, kPlayAreaY + kPlayAreaBorderHeight);
-	_sub->setVisible(true);
-
-	_anims.push_back(_sub);
+	_anims.push_back(_sub->sub);
 }
 
 void Penetration::deinit() {
 	_soundShield.free();
 	_soundBite.free();
 	_soundKiss.free();
+	_soundShoot.free();
 
 	_mapAnims.clear();
 	_anims.clear();
@@ -349,8 +334,10 @@ void Penetration::createMap() {
 	// Copy the correct map
 	memcpy(_mapTiles, kMaps[_testMode ? 1 : 0][_floor], kMapWidth * kMapHeight);
 
-	_shields.clear();
+	delete _sub;
+	_sub = 0;
 
+	_shields.clear();
 	_mouths.clear();
 
 	_map->fill(kColorBlack);
@@ -441,17 +428,22 @@ void Penetration::createMap() {
 
 			case 57: // Start position
 				_sprites->draw(*_map, kSpriteFloor, posX, posY);
+
 				*mapTile = 0;
 
-				_subTileX = x;
-				_subTileY = y;
+				delete _sub;
+
+				_sub = new ManagedSub(x, y);
 
-				_mapX = _subTileX * kMapTileWidth;
-				_mapY = _subTileY * kMapTileHeight;
+				_sub->sub = new Submarine(*_objects);
+				_sub->sub->setPosition(kPlayAreaX + kPlayAreaBorderWidth, kPlayAreaY + kPlayAreaBorderHeight);
 				break;
 			}
 		}
 	}
+
+	if (!_sub)
+		error("Geisha: No starting position in floor %d (testmode: %d", _floor, _testMode);
 }
 
 void Penetration::initScreen() {
@@ -491,51 +483,64 @@ bool Penetration::isWalkable(byte tile) const {
 
 void Penetration::handleSub(int16 key) {
 	if      (key == kKeyLeft)
-		moveSub(-5,  0, kAnimationDriveW);
+		subMove(-5,  0, Submarine::kDirectionW);
 	else if (key == kKeyRight)
-		moveSub( 5,  0, kAnimationDriveE);
+		subMove( 5,  0, Submarine::kDirectionE);
 	else if (key == kKeyUp)
-		moveSub( 0, -5, kAnimationDriveN);
+		subMove( 0, -5, Submarine::kDirectionN);
 	else if (key == kKeyDown)
-		moveSub( 0,  5, kAnimationDriveS);
+		subMove( 0,  5, Submarine::kDirectionS);
+	else if (key == kKeySpace)
+		subShoot();
 }
 
-void Penetration::moveSub(int x, int y, uint16 animation) {
+void Penetration::subMove(int x, int y, Submarine::Direction direction) {
+	if (!_sub->sub->canMove())
+		return;
+
 	// Limit the movement to walkable tiles
 
 	int16 minX = 0;
-	if ((_subTileX > 0) && !isWalkable(_mapTiles[_subTileY * kMapWidth + (_subTileX - 1)]))
-		minX = _subTileX * kMapTileWidth;
+	if ((_sub->x > 0) && !isWalkable(_mapTiles[_sub->y * kMapWidth + (_sub->x - 1)]))
+		minX = _sub->x * kMapTileWidth;
 
 	int16 maxX = kMapWidth * kMapTileWidth;
-	if ((_subTileX < (kMapWidth - 1)) && !isWalkable(_mapTiles[_subTileY * kMapWidth + (_subTileX + 1)]))
-		maxX = _subTileX * kMapTileWidth;
+	if ((_sub->x < (kMapWidth - 1)) && !isWalkable(_mapTiles[_sub->y * kMapWidth + (_sub->x + 1)]))
+		maxX = _sub->x * kMapTileWidth;
 
 	int16 minY = 0;
-	if ((_subTileY > 0) && !isWalkable(_mapTiles[(_subTileY - 1) * kMapWidth + _subTileX]))
-		minY = _subTileY * kMapTileHeight;
+	if ((_sub->y > 0) && !isWalkable(_mapTiles[(_sub->y - 1) * kMapWidth + _sub->x]))
+		minY = _sub->y * kMapTileHeight;
 
 	int16 maxY = kMapHeight * kMapTileHeight;
-	if ((_subTileY < (kMapHeight - 1)) && !isWalkable(_mapTiles[(_subTileY + 1) * kMapWidth + _subTileX]))
-		maxY = _subTileY * kMapTileHeight;
+	if ((_sub->y < (kMapHeight - 1)) && !isWalkable(_mapTiles[(_sub->y + 1) * kMapWidth + _sub->x]))
+		maxY = _sub->y * kMapTileHeight;
 
-	_mapX = CLIP<int16>(_mapX + x, minX, maxX);
-	_mapY = CLIP<int16>(_mapY + y, minY, maxY);
+	_sub->mapX = CLIP<int16>(_sub->mapX + x, minX, maxX);
+	_sub->mapY = CLIP<int16>(_sub->mapY + y, minY, maxY);
 
 	// The tile the sub is on is where its mid-point is
-	_subTileX = (_mapX + (kMapTileWidth  / 2)) / kMapTileWidth;
-	_subTileY = (_mapY + (kMapTileHeight / 2)) / kMapTileHeight;
+	_sub->x = (_sub->mapX + (kMapTileWidth  / 2)) / kMapTileWidth;
+	_sub->y = (_sub->mapY + (kMapTileHeight / 2)) / kMapTileHeight;
 
-	if (_sub->getAnimation() != animation)
-		_sub->setAnimation(animation);
+	_sub->sub->turn(direction);
 
 	checkShields();
 	checkMouths();
 }
 
+void Penetration::subShoot() {
+	if (!_sub->sub->canMove())
+		return;
+
+	_sub->sub->shoot();
+
+	_vm->_sound->blasterPlay(&_soundShoot, 1, 0);
+}
+
 void Penetration::checkShields() {
 	for (Common::List<Position>::iterator pos = _shields.begin(); pos != _shields.end(); ++pos) {
-		if ((pos->x == _subTileX) && (pos->y == _subTileY)) {
+		if ((pos->x == _sub->x) && (pos->y == _sub->y)) {
 			// Charge shields
 			_shieldMeter->setMaxValue();
 
@@ -558,13 +563,13 @@ void Penetration::checkMouths() {
 		if (!m->mouth->isDeactivated())
 			continue;
 
-		if ((( m->x      == _subTileX) && (m->y == _subTileY)) ||
-		    (((m->x + 1) == _subTileX) && (m->y == _subTileY))) {
+		if ((( m->x      == _sub->x) && (m->y == _sub->y)) ||
+		    (((m->x + 1) == _sub->x) && (m->y == _sub->y))) {
 
 			m->mouth->activate();
 
 			// Play the mouth sound and do health gain/loss
-			if      (m->type == kMouthTypeBite) {
+			if        (m->type == kMouthTypeBite) {
 				_vm->_sound->blasterPlay(&_soundBite, 1, 0);
 				healthLose(230);
 			} else if (m->type == kMouthTypeKiss) {
@@ -584,6 +589,17 @@ void Penetration::healthGain(int amount) {
 
 void Penetration::healthLose(int amount) {
 	_healthMeter->decrease(_shieldMeter->decrease(amount));
+
+	if (_healthMeter->getValue() == 0)
+		_sub->sub->die();
+}
+
+bool Penetration::isDead() const {
+	return _sub && _sub->sub->isDead();
+}
+
+bool Penetration::hasWon() const {
+	return _floor > kFloorCount;
 }
 
 void Penetration::updateAnims() {
@@ -612,11 +628,14 @@ void Penetration::updateAnims() {
 			_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
 	}
 
-	// Draw the map
-	_vm->_draw->_backSurface->blit(*_map, _mapX, _mapY,
-			_mapX + kPlayAreaWidth - 1, _mapY + kPlayAreaHeight - 1, kPlayAreaX, kPlayAreaY);
-	_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, kPlayAreaX, kPlayAreaY,
-			kPlayAreaX + kPlayAreaWidth - 1, kPlayAreaY + kPlayAreaHeight - 1);
+	if (_sub) {
+		// Draw the map
+
+		_vm->_draw->_backSurface->blit(*_map, _sub->mapX, _sub->mapY,
+				_sub->mapX + kPlayAreaWidth - 1, _sub->mapY + kPlayAreaHeight - 1, kPlayAreaX, kPlayAreaY);
+		_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, kPlayAreaX, kPlayAreaY,
+				kPlayAreaX + kPlayAreaWidth - 1, kPlayAreaY + kPlayAreaHeight - 1);
+	}
 
 	// Draw the current animation frames
 	for (Common::List<ANIObject *>::iterator a = _anims.begin();
diff --git a/engines/gob/minigames/geisha/penetration.h b/engines/gob/minigames/geisha/penetration.h
index 488396e..0582b99 100644
--- a/engines/gob/minigames/geisha/penetration.h
+++ b/engines/gob/minigames/geisha/penetration.h
@@ -28,6 +28,8 @@
 
 #include "gob/sound/sounddesc.h"
 
+#include "gob/minigames/geisha/submarine.h"
+
 namespace Gob {
 
 class GobEngine;
@@ -77,6 +79,18 @@ private:
 		~ManagedMouth();
 	};
 
+	struct ManagedSub : public Position {
+		Submarine *sub;
+
+		uint16 mapX;
+		uint16 mapY;
+
+		ManagedSub(uint16 pX, uint16 pY);
+		~ManagedSub();
+
+		void setPosition(uint16 pX, uint16 pY);
+	};
+
 	GobEngine *_vm;
 
 	bool _hasAccessPass;
@@ -87,8 +101,6 @@ private:
 	CMPFile *_sprites;
 	ANIFile *_objects;
 
-	ANIObject *_sub;
-
 	Common::List<ANIObject *> _anims;
 	Common::List<ANIObject *> _mapAnims;
 
@@ -100,11 +112,7 @@ private:
 	Surface *_map;
 	byte _mapTiles[kMapWidth * kMapHeight];
 
-	uint16 _mapX;
-	uint16 _mapY;
-
-	uint8 _subTileX;
-	uint8 _subTileY;
+	ManagedSub *_sub;
 
 	Common::List<Position>     _shields;
 	Common::List<ManagedMouth> _mouths;
@@ -112,6 +120,7 @@ private:
 	SoundDesc _soundShield;
 	SoundDesc _soundBite;
 	SoundDesc _soundKiss;
+	SoundDesc _soundShoot;
 
 
 	void init();
@@ -126,7 +135,8 @@ private:
 	int16 checkInput(int16 &mouseX, int16 &mouseY, MouseButtons &mouseButtons);
 
 	void handleSub(int16 key);
-	void moveSub(int x, int y, uint16 animation);
+	void subMove(int x, int y, Submarine::Direction direction);
+	void subShoot();
 
 	bool isWalkable(byte tile) const;
 
@@ -135,6 +145,9 @@ private:
 
 	void healthGain(int amount);
 	void healthLose(int amount);
+
+	bool isDead() const;
+	bool hasWon() const;
 };
 
 } // End of namespace Geisha
diff --git a/engines/gob/minigames/geisha/submarine.cpp b/engines/gob/minigames/geisha/submarine.cpp
new file mode 100644
index 0000000..4a18c6e
--- /dev/null
+++ b/engines/gob/minigames/geisha/submarine.cpp
@@ -0,0 +1,233 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "gob/minigames/geisha/submarine.h"
+
+namespace Gob {
+
+namespace Geisha {
+
+enum Animation {
+	kAnimationDriveS   =  4,
+	kAnimationDriveE   =  5,
+	kAnimationDriveN   =  6,
+	kAnimationDriveW   =  7,
+	kAnimationDriveSE  =  8,
+	kAnimationDriveNE  =  9,
+	kAnimationDriveSW  = 10,
+	kAnimationDriveNW  = 11,
+	kAnimationShootS   = 12,
+	kAnimationShootN   = 13,
+	kAnimationShootW   = 14,
+	kAnimationShootE   = 15,
+	kAnimationShootNE  = 16,
+	kAnimationShootSE  = 17,
+	kAnimationShootSW  = 18,
+	kAnimationShootNW  = 19,
+	kAnimationExplodeN = 28,
+	kAnimationExplodeS = 29,
+	kAnimationExplodeW = 30,
+	kAnimationExplodeE = 31,
+	kAnimationExit     = 32
+};
+
+
+Submarine::Submarine(const ANIFile &ani) : ANIObject(ani), _state(kStateNone) {
+	turn(kDirectionN);
+}
+
+Submarine::~Submarine() {
+}
+
+void Submarine::turn(Direction to) {
+	// Nothing to do
+	if ((_state == kStateMove) && (_direction == to))
+		return;
+
+	_state = kStateMove;
+	_direction = to;
+
+	setAnimation(directionToMove(_direction));
+	setMode(kModeContinuous);
+	setPause(false);
+	setVisible(true);
+}
+
+void Submarine::shoot() {
+	_state = kStateShoot;
+
+	setAnimation(directionToShoot(_direction));
+	setMode(kModeOnce);
+	setPause(false);
+	setVisible(true);
+}
+
+void Submarine::die() {
+	_state = kStateDie;
+
+	setAnimation(directionToExplode(_direction));
+	setMode(kModeOnce);
+	setPause(false);
+	setVisible(true);
+}
+
+void Submarine::leave() {
+	_state = kStateExit;
+
+	setAnimation(kAnimationExit);
+	setMode(kModeOnce);
+	setPause(false);
+	setVisible(true);
+}
+
+void Submarine::advance() {
+	ANIObject::advance();
+
+	switch (_state) {
+	case kStateShoot:
+		if (isPaused())
+			turn(_direction);
+		break;
+
+	case kStateExit:
+		if (isPaused()) {
+			_state = kStateExited;
+
+			setVisible(true);
+		}
+
+		break;
+
+	case kStateDie:
+		if (isPaused())
+			_state = kStateDead;
+		break;
+
+	default:
+		break;
+	}
+}
+
+bool Submarine::canMove() const {
+	return (_state == kStateMove) || (_state == kStateShoot);
+}
+
+bool Submarine::isDead() const {
+	return _state == kStateDead;
+}
+
+uint16 Submarine::directionToMove(Direction direction) const {
+	switch (direction) {
+	case kDirectionN:
+		return kAnimationDriveN;
+
+	case kDirectionNE:
+		return kAnimationDriveNE;
+
+	case kDirectionE:
+		return kAnimationDriveE;
+
+	case kDirectionSE:
+		return kAnimationDriveSE;
+
+	case kDirectionS:
+		return kAnimationDriveS;
+
+	case kDirectionSW:
+		return kAnimationDriveSW;
+
+	case kDirectionW:
+		return kAnimationDriveW;
+
+	case kDirectionNW:
+		return kAnimationDriveNW;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+uint16 Submarine::directionToShoot(Direction direction) const {
+	switch (direction) {
+	case kDirectionN:
+		return kAnimationShootN;
+
+	case kDirectionNE:
+		return kAnimationShootNE;
+
+	case kDirectionE:
+		return kAnimationShootE;
+
+	case kDirectionSE:
+		return kAnimationShootSE;
+
+	case kDirectionS:
+		return kAnimationShootS;
+
+	case kDirectionSW:
+		return kAnimationShootSW;
+
+	case kDirectionW:
+		return kAnimationShootW;
+
+	case kDirectionNW:
+		return kAnimationShootNW;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+uint16 Submarine::directionToExplode(Direction direction) const {
+	// Only 4 exploding animations (spinning clockwise)
+
+	switch (direction) {
+	case kDirectionNW:
+	case kDirectionN:
+		return kAnimationExplodeN;
+
+	case kDirectionNE:
+	case kDirectionE:
+		return kAnimationExplodeE;
+
+	case kDirectionSE:
+	case kDirectionS:
+		return kAnimationExplodeS;
+
+	case kDirectionSW:
+	case kDirectionW:
+		return kAnimationExplodeW;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+} // End of namespace Geisha
+
+} // End of namespace Gob
diff --git a/engines/gob/minigames/geisha/submarine.h b/engines/gob/minigames/geisha/submarine.h
new file mode 100644
index 0000000..e8ae72d
--- /dev/null
+++ b/engines/gob/minigames/geisha/submarine.h
@@ -0,0 +1,96 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_MINIGAMES_GEISHA_SUBMARINE_H
+#define GOB_MINIGAMES_GEISHA_SUBMARINE_H
+
+#include "gob/aniobject.h"
+
+namespace Gob {
+
+namespace Geisha {
+
+/** The submarine Geisha's "Penetration" minigame. */
+class Submarine : public ANIObject {
+public:
+	enum Direction {
+		kDirectionN,
+		kDirectionNE,
+		kDirectionE,
+		kDirectionSE,
+		kDirectionS,
+		kDirectionSW,
+		kDirectionW,
+		kDirectionNW
+	};
+
+	Submarine(const ANIFile &ani);
+	~Submarine();
+
+	/** Turn to the specified direction. */
+	void turn(Direction to);
+
+	/** Play the shoot animation. */
+	void shoot();
+
+	/** Play the exploding animation. */
+	void die();
+
+	/** Play the exiting animation. */
+	void leave();
+
+	/** Advance the animation to the next frame. */
+	void advance();
+
+	/** Can the submarine move at the moment? */
+	bool canMove() const;
+
+	/** Is the submarine dead? */
+	bool isDead() const;
+
+private:
+	enum State {
+		kStateNone = 0,
+		kStateMove,
+		kStateShoot,
+		kStateExit,
+		kStateExited,
+		kStateDie,
+		kStateDead
+	};
+
+	State _state;
+	Direction _direction;
+
+	/** Map the directions to move animation indices. */
+	uint16 directionToMove(Direction direction) const;
+	/** Map the directions to shoot animation indices. */
+	uint16 directionToShoot(Direction direction) const;
+	/** Map the directions to explode animation indices. */
+	uint16 directionToExplode(Direction direction) const;
+};
+
+} // End of namespace Geisha
+
+} // End of namespace Gob
+
+#endif // GOB_MINIGAMES_GEISHA_SUBMARINE_H
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index c5ae947..b9680fa 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -81,6 +81,7 @@ MODULE_OBJS := \
 	minigames/geisha/meter.o \
 	minigames/geisha/diving.o \
 	minigames/geisha/mouth.o \
+	minigames/geisha/submarine.o \
 	minigames/geisha/penetration.o \
 	save/savefile.o \
 	save/savehandler.o \


Commit: 1782012f9f9ec368689fb2e232543a5aea3c1073
    https://github.com/scummvm/scummvm/commit/1782012f9f9ec368689fb2e232543a5aea3c1073
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2012-06-05T18:33:35-07:00

Commit Message:
GOB: Clean up the Penetration map handling a bit

Changed paths:
    engines/gob/minigames/geisha/penetration.cpp
    engines/gob/minigames/geisha/penetration.h



diff --git a/engines/gob/minigames/geisha/penetration.cpp b/engines/gob/minigames/geisha/penetration.cpp
index 2c1a491..22cb06f 100644
--- a/engines/gob/minigames/geisha/penetration.cpp
+++ b/engines/gob/minigames/geisha/penetration.cpp
@@ -309,84 +309,88 @@ void Penetration::deinit() {
 	_soundKiss.free();
 	_soundShoot.free();
 
+	clearMap();
+
+	delete _objects;
+	delete _sprites;
+
+	_objects = 0;
+	_sprites = 0;
+}
+
+void Penetration::clearMap() {
 	_mapAnims.clear();
 	_anims.clear();
 
+	_exits.clear();
 	_shields.clear();
-
 	_mouths.clear();
 
 	delete _sub;
 
-	delete _objects;
-	delete _sprites;
-
-	_objects = 0;
-	_sprites = 0;
-
 	_sub = 0;
+
+	_map->fill(kColorBlack);
 }
 
 void Penetration::createMap() {
 	if (_floor >= kFloorCount)
 		error("Geisha: Invalid floor %d in minigame penetration", _floor);
 
-	// Copy the correct map
-	memcpy(_mapTiles, kMaps[_testMode ? 1 : 0][_floor], kMapWidth * kMapHeight);
-
-	delete _sub;
-	_sub = 0;
+	clearMap();
 
-	_shields.clear();
-	_mouths.clear();
+	const byte *mapTiles = kMaps[_testMode ? 1 : 0][_floor];
 
-	_map->fill(kColorBlack);
+	bool exitWorks;
 
 	// Draw the map tiles
 	for (int y = 0; y < kMapHeight; y++) {
 		for (int x = 0; x < kMapWidth; x++) {
-			byte *mapTile = _mapTiles + (y * kMapWidth + x);
+			const byte mapTile = mapTiles[y * kMapWidth + x];
+
+			bool *walkMap = _walkMap + (y * kMapWidth + x);
 
 			const int posX = kPlayAreaBorderWidth  + x * kMapTileWidth;
 			const int posY = kPlayAreaBorderHeight + y * kMapTileHeight;
 
-			switch (*mapTile) {
+			*walkMap = true;
+
+			switch (mapTile) {
 			case 0: // Floor
 				_sprites->draw(*_map, kSpriteFloor, posX, posY);
 				break;
 
 			case 49: // Emergency exit (needs access pass)
 
-				if (_hasAccessPass) {
+				exitWorks = _hasAccessPass;
+				if (exitWorks) {
+					_exits.push_back(Position(x, y));
 					_sprites->draw(*_map, kSpriteExit, posX, posY);
-					*mapTile = 51; // Now works like a normal exit
-				} else
+				} else {
 					_sprites->draw(*_map, kSpriteWall, posX, posY);
+					*walkMap = false;
+				}
 
 				break;
 
 			case 50: // Wall
 				_sprites->draw(*_map, kSpriteWall, posX, posY);
+				*walkMap = false;
 				break;
 
 			case 51: // Regular exit
 
-				if (!_testMode) {
-					// When we're not in test mode, the last exit only works with an access pass
-
-					if (_floor == 2) {
-						if (!_hasAccessPass) {
-							_sprites->draw(*_map, kSpriteWall, posX, posY);
-							*mapTile = 50; // It's now a wall
-						} else
-							_sprites->draw(*_map, kSpriteExit, posX, posY);
-
-					} else
-						_sprites->draw(*_map, kSpriteExit, posX, posY);
+				// A regular exit works always in test mode.
+				// But if we're in real mode, and on the last floor, it needs an access pass
+				exitWorks = _testMode || (_floor < 2) || _hasAccessPass;
 
-				} else
-					// Always works in test mode
+				if (exitWorks) {
+					_exits.push_back(Position(x, y));
 					_sprites->draw(*_map, kSpriteExit, posX, posY);
+				} else {
+					_sprites->draw(*_map, kSpriteWall, posX, posY);
+					*walkMap = false;
+				}
 
 				break;
 
@@ -400,7 +404,6 @@ void Penetration::createMap() {
 				break;
 
 			case 53: // Right side of biting mouth
-				*mapTile = 0; // Works like a floor
 				break;
 
 			case 54: // Left side of kissing mouth
@@ -413,7 +416,6 @@ void Penetration::createMap() {
 				break;
 
 			case 55: // Right side of kissing mouth
-				*mapTile = 0; // Works like a floor
 				break;
 
 			case 56: // Shield lying on the floor
@@ -429,8 +431,6 @@ void Penetration::createMap() {
 			case 57: // Start position
 				_sprites->draw(*_map, kSpriteFloor, posX, posY);
 
-				*mapTile = 0;
-
 				delete _sub;
 
 				_sub = new ManagedSub(x, y);
@@ -472,13 +472,11 @@ int16 Penetration::checkInput(int16 &mouseX, int16 &mouseY, MouseButtons &mouseB
 	return _vm->_util->checkKey();
 }
 
-bool Penetration::isWalkable(byte tile) const {
-	// Only walls are nonwalkable
-
-	if (tile == 50)
+bool Penetration::isWalkable(int16 x, int16 y) const {
+	if ((x < 0) || (x >= kMapWidth) || (y < 0) || (y >= kMapHeight))
 		return false;
 
-	return true;
+	return _walkMap[y * kMapWidth + x];
 }
 
 void Penetration::handleSub(int16 key) {
@@ -501,19 +499,19 @@ void Penetration::subMove(int x, int y, Submarine::Direction direction) {
 	// Limit the movement to walkable tiles
 
 	int16 minX = 0;
-	if ((_sub->x > 0) && !isWalkable(_mapTiles[_sub->y * kMapWidth + (_sub->x - 1)]))
+	if (!isWalkable(_sub->x - 1, _sub->y))
 		minX = _sub->x * kMapTileWidth;
 
 	int16 maxX = kMapWidth * kMapTileWidth;
-	if ((_sub->x < (kMapWidth - 1)) && !isWalkable(_mapTiles[_sub->y * kMapWidth + (_sub->x + 1)]))
+	if (!isWalkable(_sub->x + 1, _sub->y))
 		maxX = _sub->x * kMapTileWidth;
 
 	int16 minY = 0;
-	if ((_sub->y > 0) && !isWalkable(_mapTiles[(_sub->y - 1) * kMapWidth + _sub->x]))
+	if (!isWalkable(_sub->x, _sub->y - 1))
 		minY = _sub->y * kMapTileHeight;
 
 	int16 maxY = kMapHeight * kMapTileHeight;
-	if ((_sub->y < (kMapHeight - 1)) && !isWalkable(_mapTiles[(_sub->y + 1) * kMapWidth + _sub->x]))
+	if (!isWalkable(_sub->x, _sub->y + 1))
 		maxY = _sub->y * kMapTileHeight;
 
 	_sub->mapX = CLIP<int16>(_sub->mapX + x, minX, maxX);
diff --git a/engines/gob/minigames/geisha/penetration.h b/engines/gob/minigames/geisha/penetration.h
index 0582b99..a574038 100644
--- a/engines/gob/minigames/geisha/penetration.h
+++ b/engines/gob/minigames/geisha/penetration.h
@@ -110,10 +110,11 @@ private:
 	uint8 _floor;
 
 	Surface *_map;
-	byte _mapTiles[kMapWidth * kMapHeight];
+	bool _walkMap[kMapWidth * kMapHeight];
 
 	ManagedSub *_sub;
 
+	Common::List<Position>     _exits;
 	Common::List<Position>     _shields;
 	Common::List<ManagedMouth> _mouths;
 
@@ -126,6 +127,7 @@ private:
 	void init();
 	void deinit();
 
+	void clearMap();
 	void createMap();
 
 	void initScreen();
@@ -138,7 +140,7 @@ private:
 	void subMove(int x, int y, Submarine::Direction direction);
 	void subShoot();
 
-	bool isWalkable(byte tile) const;
+	bool isWalkable(int16 x, int16 y) const;
 
 	void checkShields();
 	void checkMouths();


Commit: 04d0ec8d03d46f59f950929321fef43b52ea740a
    https://github.com/scummvm/scummvm/commit/04d0ec8d03d46f59f950929321fef43b52ea740a
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2012-06-05T18:33:35-07:00

Commit Message:
GOB: Implement exiting floors

Changed paths:
    engines/gob/minigames/geisha/penetration.cpp
    engines/gob/minigames/geisha/penetration.h
    engines/gob/minigames/geisha/submarine.cpp
    engines/gob/minigames/geisha/submarine.h



diff --git a/engines/gob/minigames/geisha/penetration.cpp b/engines/gob/minigames/geisha/penetration.cpp
index 22cb06f..856c063 100644
--- a/engines/gob/minigames/geisha/penetration.cpp
+++ b/engines/gob/minigames/geisha/penetration.cpp
@@ -263,6 +263,8 @@ bool Penetration::play(bool hasAccessPass, bool hasMaxEnergy, bool testMode) {
 
 		// Handle the sub movement
 		handleSub(key);
+
+		checkExited();
 	}
 
 	deinit();
@@ -276,6 +278,7 @@ void Penetration::init() {
 	_vm->_sound->sampleLoad(&_soundBite  , SOUND_SND, "pervet.snd");
 	_vm->_sound->sampleLoad(&_soundKiss  , SOUND_SND, "baise.snd");
 	_vm->_sound->sampleLoad(&_soundShoot , SOUND_SND, "tirgim.snd");
+	_vm->_sound->sampleLoad(&_soundExit  , SOUND_SND, "trouve.snd");
 
 	_background->clear();
 
@@ -296,11 +299,6 @@ void Penetration::init() {
 	_floor = 0;
 
 	createMap();
-
-	for (Common::List<ManagedMouth>::iterator m = _mouths.begin(); m != _mouths.end(); m++)
-		_mapAnims.push_back(m->mouth);
-
-	_anims.push_back(_sub->sub);
 }
 
 void Penetration::deinit() {
@@ -308,6 +306,7 @@ void Penetration::deinit() {
 	_soundBite.free();
 	_soundKiss.free();
 	_soundShoot.free();
+	_soundExit.free();
 
 	clearMap();
 
@@ -443,7 +442,12 @@ void Penetration::createMap() {
 	}
 
 	if (!_sub)
-		error("Geisha: No starting position in floor %d (testmode: %d", _floor, _testMode);
+		error("Geisha: No starting position in floor %d (testmode: %d)", _floor, _testMode);
+
+	for (Common::List<ManagedMouth>::iterator m = _mouths.begin(); m != _mouths.end(); m++)
+		_mapAnims.push_back(m->mouth);
+
+	_anims.push_back(_sub->sub);
 }
 
 void Penetration::initScreen() {
@@ -525,6 +529,7 @@ void Penetration::subMove(int x, int y, Submarine::Direction direction) {
 
 	checkShields();
 	checkMouths();
+	checkExits();
 }
 
 void Penetration::subShoot() {
@@ -578,6 +583,23 @@ void Penetration::checkMouths() {
 	}
 }
 
+void Penetration::checkExits() {
+	if (!_sub->sub->canMove())
+		return;
+
+	for (Common::List<Position>::iterator e = _exits.begin(); e != _exits.end(); ++e) {
+		if ((e->x == _sub->x) && (e->y == _sub->y)) {
+			_sub->mapX = e->x * kMapTileWidth;
+			_sub->mapY = e->y * kMapTileHeight;
+
+			_sub->sub->leave();
+
+			_vm->_sound->blasterPlay(&_soundExit, 1, 0);
+			break;
+		}
+	}
+}
+
 void Penetration::healthGain(int amount) {
 	if (_shieldMeter->getValue() > 0)
 		_healthMeter->increase(_shieldMeter->increase(amount));
@@ -592,12 +614,23 @@ void Penetration::healthLose(int amount) {
 		_sub->sub->die();
 }
 
+void Penetration::checkExited() {
+	if (_sub->sub->hasExited()) {
+		_floor++;
+
+		if (_floor >= kFloorCount)
+			return;
+
+		createMap();
+	}
+}
+
 bool Penetration::isDead() const {
 	return _sub && _sub->sub->isDead();
 }
 
 bool Penetration::hasWon() const {
-	return _floor > kFloorCount;
+	return _floor >= kFloorCount;
 }
 
 void Penetration::updateAnims() {
diff --git a/engines/gob/minigames/geisha/penetration.h b/engines/gob/minigames/geisha/penetration.h
index a574038..f717e72 100644
--- a/engines/gob/minigames/geisha/penetration.h
+++ b/engines/gob/minigames/geisha/penetration.h
@@ -122,6 +122,7 @@ private:
 	SoundDesc _soundBite;
 	SoundDesc _soundKiss;
 	SoundDesc _soundShoot;
+	SoundDesc _soundExit;
 
 
 	void init();
@@ -142,12 +143,15 @@ private:
 
 	bool isWalkable(int16 x, int16 y) const;
 
+	void checkExits();
 	void checkShields();
 	void checkMouths();
 
 	void healthGain(int amount);
 	void healthLose(int amount);
 
+	void checkExited();
+
 	bool isDead() const;
 	bool hasWon() const;
 };
diff --git a/engines/gob/minigames/geisha/submarine.cpp b/engines/gob/minigames/geisha/submarine.cpp
index 4a18c6e..0f3f936 100644
--- a/engines/gob/minigames/geisha/submarine.cpp
+++ b/engines/gob/minigames/geisha/submarine.cpp
@@ -109,12 +109,9 @@ void Submarine::advance() {
 		break;
 
 	case kStateExit:
-		if (isPaused()) {
+		if (isPaused())
 			_state = kStateExited;
 
-			setVisible(true);
-		}
-
 		break;
 
 	case kStateDie:
@@ -135,6 +132,10 @@ bool Submarine::isDead() const {
 	return _state == kStateDead;
 }
 
+bool Submarine::hasExited() const {
+	return _state == kStateExited;
+}
+
 uint16 Submarine::directionToMove(Direction direction) const {
 	switch (direction) {
 	case kDirectionN:
diff --git a/engines/gob/minigames/geisha/submarine.h b/engines/gob/minigames/geisha/submarine.h
index e8ae72d..d14e4e9 100644
--- a/engines/gob/minigames/geisha/submarine.h
+++ b/engines/gob/minigames/geisha/submarine.h
@@ -67,6 +67,9 @@ public:
 	/** Is the submarine dead? */
 	bool isDead() const;
 
+	/** Has the submarine finished exiting the level? */
+	bool hasExited() const;
+
 private:
 	enum State {
 		kStateNone = 0,






More information about the Scummvm-git-logs mailing list