[Scummvm-git-logs] scummvm master -> 7b7278096c565f7d376b0e38a42eeb2dd81ceda7

neuromancer noreply at scummvm.org
Sun Oct 5 12:45:01 UTC 2025


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

Summary:
c07f22beb6 FREESCAPE: corrected perspective when aiming direction is changed
620fc6ebe0 FREESCAPE: Small fixes for castle master (dos)
7b7278096c FREESCAPE: Implement dropping gate animation in castle


Commit: c07f22beb641c451318bfa458de9ec5f891c85cf
    https://github.com/scummvm/scummvm/commit/c07f22beb641c451318bfa458de9ec5f891c85cf
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2025-10-05T09:41:33-03:00

Commit Message:
FREESCAPE: corrected perspective when aiming direction is changed

Changed paths:
    engines/freescape/movement.cpp


diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index a19b4781e61..3f7edcbdffa 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -222,13 +222,20 @@ void FreescapeEngine::shoot() {
 	g_system->delayMillis(2);
 	_shootingFrames = 10;
 
-	Common::Point center(_viewArea.left + _viewArea.width() / 2, _viewArea.top + _viewArea.height() / 2);
-	float xoffset = _crossairPosition.x - center.x;
-	float yoffset = _crossairPosition.y - center.y;
-	xoffset = xoffset * 0.33;
-	yoffset = yoffset * 0.50;
+	// Convert to normalized coordinates [-1, 1]
+	float ndcX = (2.0f * (_crossairPosition.x - _viewArea.left) / _viewArea.width()) - 1.0f;
+	float ndcY = 1.0f - (2.0f * (_crossairPosition.y - _viewArea.top) / _viewArea.height());
 
-	Math::Vector3d direction = directionToVector(_pitch - yoffset, _yaw - xoffset, false);
+	// Calculate angular offsets using perspective projection
+	float fovHorizontalRad = 75.0f * M_PI / 180.0f;
+	float aspectRatio = isCastle() ? 1.6 : 2.18;
+	float fovVerticalRad = 2.0f * atan(tan(fovHorizontalRad / 2.0f) / aspectRatio);
+
+	// Convert NDC to angle offset
+	float angleOffsetX = atan(ndcX * tan(fovHorizontalRad / 2.0f)) * 180.0f / M_PI;
+	float angleOffsetY = atan(ndcY * tan(fovVerticalRad / 2.0f)) * 180.0f / M_PI;
+
+	Math::Vector3d direction = directionToVector(_pitch + angleOffsetY, _yaw - angleOffsetX, false);
 	Math::Ray ray(_position, direction);
 	Object *shot = _currentArea->checkCollisionRay(ray, 8192);
 	if (shot) {


Commit: 620fc6ebe033c9b76b0de0cfc10f5986f97db67f
    https://github.com/scummvm/scummvm/commit/620fc6ebe033c9b76b0de0cfc10f5986f97db67f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2025-10-05T09:41:33-03:00

Commit Message:
FREESCAPE: Small fixes for castle master (dos)

Changed paths:
    engines/freescape/freescape.h
    engines/freescape/games/castle/castle.cpp
    engines/freescape/language/instruction.cpp
    engines/freescape/movement.cpp


diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 8787af858bb..5b087a3a2e6 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -72,6 +72,7 @@ enum FreescapeAction {
 	kActionMoveLeft,
 	kActionMoveRight,
 	kActionShoot,
+	kActionActivate,
 	kActionIncreaseAngle,
 	kActionDecreaseAngle,
 	kActionChangeStepSize,
diff --git a/engines/freescape/games/castle/castle.cpp b/engines/freescape/games/castle/castle.cpp
index 07acd421919..45f9c546c8f 100644
--- a/engines/freescape/games/castle/castle.cpp
+++ b/engines/freescape/games/castle/castle.cpp
@@ -301,6 +301,11 @@ void CastleEngine::initKeymaps(Common::Keymap *engineKeyMap, Common::Keymap *inf
 	act->setCustomEngineActionEvent(kActionFaceForward);
 	act->addDefaultInputMapping("f");
 	engineKeyMap->addAction(act);
+
+	act = new Common::Action("ACTIVATE", _("Activate"));
+	act->setCustomEngineActionEvent(kActionActivate);
+	act->addDefaultInputMapping("a");
+	engineKeyMap->addAction(act);
 }
 
 void CastleEngine::beforeStarting() {
@@ -511,7 +516,8 @@ void CastleEngine::pressedKey(const int keycode) {
 	} else if (keycode == kActionFaceForward) {
 		_pitch = 0;
 		updateCamera();
-	}
+	} else if (keycode == kActionActivate) 
+		activate();
 }
 
 void CastleEngine::drawInfoMenu() {
@@ -1306,10 +1312,10 @@ void CastleEngine::checkSensors() {
 	if (_disableSensors)
 		return;
 
-	if (!_mixer->isSoundHandleActive(_soundFxGhostHandle)) {
+	/*if (!_mixer->isSoundHandleActive(_soundFxGhostHandle)) {
 		_speaker->play(Audio::PCSpeaker::kWaveFormSquare, 25.0f, -1);
 		_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundFxGhostHandle, _speaker, -1, kFreescapeDefaultVolume / 2, 0, DisposeAfterUse::NO);
-	}
+	}*/
 
 	// This is the frequency to shake the screen
 	if (_ticks % 5 == 0) {
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index 47e7ff1f40f..034cfeaccba 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -112,9 +112,11 @@ bool FreescapeEngine::executeObjectConditions(GeometricObject *obj, bool shot, b
 			debugC(1, kFreescapeDebugCode, "Executing with collision flag: %s", obj->_conditionSource.c_str());
 		} else if (shot)
 			debugC(1, kFreescapeDebugCode, "Executing with shot flag: %s", obj->_conditionSource.c_str());
-		else if (activated)
+		else if (activated) {
+			if (isCastle()) // TODO: add a 3DCK check here
+				clearTemporalMessages();
 			debugC(1, kFreescapeDebugCode, "Executing with activated flag: %s", obj->_conditionSource.c_str());
-		else
+		} else
 			error("Neither shot or collided flag is set!");
 		executed = executeCode(obj->_condition, shot, collided, false, activated); // TODO: check this last parameter
 	}
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index 3f7edcbdffa..7a3284e06b6 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -207,8 +207,10 @@ void FreescapeEngine::activate() {
 
 		executeObjectConditions(gobj, false, false, true);
 	} else {
-		if (!_outOfReachMessage.empty())
+		if (!_outOfReachMessage.empty()) {
+			clearTemporalMessages();
 			insertTemporaryMessage(_outOfReachMessage, _countdown - 2);
+		}
 	}
 	//executeLocalGlobalConditions(true, false, false); // Only execute "on shot" room/global conditions
 }


Commit: 7b7278096c565f7d376b0e38a42eeb2dd81ceda7
    https://github.com/scummvm/scummvm/commit/7b7278096c565f7d376b0e38a42eeb2dd81ceda7
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2025-10-05T09:41:33-03:00

Commit Message:
FREESCAPE: Implement dropping gate animation in castle

Changed paths:
    engines/freescape/games/castle/castle.cpp
    engines/freescape/games/castle/castle.h
    engines/freescape/games/castle/dos.cpp
    engines/freescape/games/castle/zx.cpp


diff --git a/engines/freescape/games/castle/castle.cpp b/engines/freescape/games/castle/castle.cpp
index 45f9c546c8f..5912154da05 100644
--- a/engines/freescape/games/castle/castle.cpp
+++ b/engines/freescape/games/castle/castle.cpp
@@ -435,6 +435,8 @@ void CastleEngine::initGameState() {
 	getTimeFromCountdown(seconds, minutes, hours);
 	_lastMinute = minutes;
 	_lastTenSeconds = seconds / 10;
+
+	_droppingGateStartTicks = 0;
 }
 
 bool CastleEngine::checkIfGameEnded() {
@@ -785,12 +787,6 @@ void CastleEngine::drawFullscreenEndGameAndWait() {
 }
 
 void CastleEngine::drawFullscreenGameOverAndWait() {
-	Graphics::Surface *surface = new Graphics::Surface();
-	surface->create(_screenW, _screenH, _gfx->_texturePixelFormat);
-	surface->fillRect(_fullscreenViewArea, _gfx->_texturePixelFormat.ARGBToColor(0x00, 0x00, 0x00, 0x00));
-	uint32 blue = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x00, 0x24, 0xA5);
-	surface->copyRectToSurfaceWithKey(*_gameOverBackgroundFrame, _viewArea.left, _viewArea.top, Common::Rect(0, 0, _gameOverBackgroundFrame->w, _gameOverBackgroundFrame->h), blue);
-
 	Common::Event event;
 	bool cont = true;
 
@@ -844,6 +840,13 @@ void CastleEngine::drawFullscreenGameOverAndWait() {
 
 	Common::replace(spiritsDestroyedString, "X", Common::String::format("%d", spiritsDestroyed));
 	spiritsDestroyedString = centerAndPadString(spiritsDestroyedString, 15);
+	_droppingGateStartTicks = _ticks;
+
+	if (isDOS()) {
+		// TODO: playSound(X, false, _soundFxHandle);
+	} else if (isSpectrum()) {
+		playSound(9, false, _soundFxHandle);
+	}
 
 	while (!shouldQuit() && cont) {
 		if (_temporaryMessageDeadlines.empty()) {
@@ -874,14 +877,10 @@ void CastleEngine::drawFullscreenGameOverAndWait() {
 		_gfx->clear(0, 0, 0, true);
 		drawFrame();
 
-		drawFullscreenSurface(surface);
 		_gfx->flipBuffer();
 		g_system->updateScreen();
 		g_system->delayMillis(15); // try to target ~60 FPS
 	}
-
-	surface->free();
-	delete surface;
 }
 
 // Same as FreescapeEngine::executeExecute but updates the spirits destroyed counter
@@ -1553,7 +1552,7 @@ void CastleEngine::drawLiftingGate(Graphics::Surface *surface) {
 	else if (isSpectrum())
 		duration = 100;
 
-	if ((_gameStateControl == kFreescapeGameStateStart || _gameStateControl == kFreescapeGameStateRestart)  && _ticks <= duration) { // Draw the _gameOverBackgroundFrame gate lifting up slowly
+	if ((_gameStateControl == kFreescapeGameStateStart || _gameStateControl == kFreescapeGameStateRestart) && _ticks <= duration) { // Draw the _gameOverBackgroundFrame gate lifting up slowly
 		int gate_w = _gameOverBackgroundFrame->w;
 		int gate_h = _gameOverBackgroundFrame->h;
 
@@ -1583,6 +1582,51 @@ void CastleEngine::drawLiftingGate(Graphics::Surface *surface) {
 	}
 }
 
+void CastleEngine::drawDroppingGate(Graphics::Surface *surface) {
+	if (_droppingGateStartTicks <= 0)
+		return;
+
+	uint32 keyColor = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x00, 0x24, 0xA5);
+	int duration = 60;
+	int ticks = _ticks - _droppingGateStartTicks;
+
+	if (_gameStateControl == kFreescapeGameStateEnd && _ticks <= _droppingGateStartTicks + duration) { // Draw the _gameOverBackgroundFrame gate dropping down slowly
+		int gate_w = _gameOverBackgroundFrame->w;
+		int gate_h = _gameOverBackgroundFrame->h;
+
+		// The gate should move down by the height of the view area to appear.
+		int y_offset = (duration - ticks) * _viewArea.height() / duration;
+
+		// Initial position is with the gate bottom at the view area bottom.
+		int dx = _viewArea.left + (_viewArea.width() - gate_w) / 2;
+		int dy = (_viewArea.bottom - gate_h) - y_offset;
+
+		// Define destination rect for the full gate
+		Common::Rect destRect(dx, dy, dx + gate_w, dy + gate_h);
+
+		// Find intersection with view area to clip
+		Common::Rect clippedDest = destRect.findIntersectingRect(_viewArea);
+
+		// If there is something to draw
+		if (clippedDest.isValidRect() && clippedDest.width() > 0 && clippedDest.height() > 0) {
+			// Adjust source rect based on clipping
+			int src_x = clippedDest.left - destRect.left;
+			int src_y = clippedDest.top - destRect.top;
+			Common::Rect clippedSrc(src_x, src_y, src_x + clippedDest.width(), src_y + clippedDest.height());
+
+			// Draw the clipped part
+			surface->copyRectToSurfaceWithKey(*_gameOverBackgroundFrame, clippedDest.left, clippedDest.top, clippedSrc, keyColor);
+		}
+	} else {
+		// Draw the gate fully down
+		int gate_w = _gameOverBackgroundFrame->w;
+		int gate_h = _gameOverBackgroundFrame->h;
+		int dx = _viewArea.left + (_viewArea.width() - gate_w) / 2;
+		int dy = (_viewArea.bottom - gate_h);
+		surface->copyRectToSurfaceWithKey(*_gameOverBackgroundFrame, dx, dy, Common::Rect(0, 0, gate_w, gate_h), keyColor);
+	}
+}
+
 Common::Error CastleEngine::saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave) {
 	stream->writeUint32LE(_keysCollected.size());
 	for (auto &it : _keysCollected) {
diff --git a/engines/freescape/games/castle/castle.h b/engines/freescape/games/castle/castle.h
index 6e884e804c4..5697ccfd6b4 100644
--- a/engines/freescape/games/castle/castle.h
+++ b/engines/freescape/games/castle/castle.h
@@ -75,6 +75,7 @@ public:
 	void drawAmigaAtariSTUI(Graphics::Surface *surface) override;
 	void drawEnergyMeter(Graphics::Surface *surface, Common::Point origin);
 	void drawLiftingGate(Graphics::Surface *surface);
+	void drawDroppingGate(Graphics::Surface *surface);
 	void pressedKey(const int keycode) override;
 	void checkSensors() override;
 	void updateTimeVariables() override;
@@ -149,6 +150,7 @@ private:
 	Audio::SoundHandle _soundFxGhostHandle;
 	Texture *_optionTexture;
 	Font _fontRiddle;
+	int _droppingGateStartTicks;
 };
 
 }
diff --git a/engines/freescape/games/castle/dos.cpp b/engines/freescape/games/castle/dos.cpp
index 719622ec5a7..ce641c7f7d1 100644
--- a/engines/freescape/games/castle/dos.cpp
+++ b/engines/freescape/games/castle/dos.cpp
@@ -429,6 +429,7 @@ void CastleEngine::drawDOSUI(Graphics::Surface *surface) {
 	uint32 black = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x00, 0x00, 0x00);
 	uint8 r, g, b;
 	drawLiftingGate(surface);
+	drawDroppingGate(surface);
 
 	_gfx->readFromPalette(color, r, g, b);
 	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
diff --git a/engines/freescape/games/castle/zx.cpp b/engines/freescape/games/castle/zx.cpp
index e3039b4cd0e..5881eef7309 100644
--- a/engines/freescape/games/castle/zx.cpp
+++ b/engines/freescape/games/castle/zx.cpp
@@ -249,6 +249,7 @@ void CastleEngine::drawZXUI(Graphics::Surface *surface) {
 	uint8 r, g, b;
 
 	drawLiftingGate(surface);
+	drawDroppingGate(surface);
 
 	_gfx->readFromPalette(color, r, g, b);
 	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);




More information about the Scummvm-git-logs mailing list