diff --git a/packages/wolf_3d_dart/lib/src/engine/player_locomotion_constants.dart b/packages/wolf_3d_dart/lib/src/engine/player_locomotion_constants.dart new file mode 100644 index 0000000..79c1f76 --- /dev/null +++ b/packages/wolf_3d_dart/lib/src/engine/player_locomotion_constants.dart @@ -0,0 +1,41 @@ +import 'dart:math' as math; + +/// Canonical player movement and rotation constants derived directly from the +/// original Wolfenstein 3D source code (WL_PLAY.C / WL_AGENT.C). +/// +/// Source constants (keyboard, walking state): +/// BASEMOVE = 35, RUNMOVE = 70 +/// MOVESCALE = 150, BACKMOVESCALE = 100 +/// BASETURN = 35, RUNTURN = 70, ANGLESCALE = 20 +/// TILEGLOBAL = 65536 (fixed-point units per tile), TICRATE = 70 +abstract final class PlayerLocomotionConstants { + static const double basemove = 35.0; + static const double runmove = 70.0; + static const double movescale = 150.0; + static const double backmovescale = 100.0; + static const double baseturn = 35.0; + static const double runturn = 70.0; + static const double anglescale = 20.0; + static const double tileglobal = 65536.0; + static const double ticrate = 70.0; + + /// Walking forward speed in tiles per second. + /// + /// Derived from: `(BASEMOVE * MOVESCALE * TICRATE) / TILEGLOBAL` + static const double forwardTilesPerSecond = + (basemove * movescale * ticrate) / tileglobal; + + /// Walking backward speed in tiles per second (intentionally slower than + /// forward in the original game). + /// + /// Derived from: `(BASEMOVE * BACKMOVESCALE * TICRATE) / TILEGLOBAL` + static const double backwardTilesPerSecond = + (basemove * backmovescale * ticrate) / tileglobal; + + /// Walking turn rate in radians per second. + /// + /// Derived from: `(BASETURN / ANGLESCALE) * TICRATE` in degrees/sec, + /// then converted to radians. + static const double turnRadiansPerSecond = + (baseturn / anglescale) * ticrate * (math.pi / 180.0); +} diff --git a/packages/wolf_3d_dart/lib/src/engine/wolf_3d_engine_base.dart b/packages/wolf_3d_dart/lib/src/engine/wolf_3d_engine_base.dart index f5ce7a3..aabd338 100644 --- a/packages/wolf_3d_dart/lib/src/engine/wolf_3d_engine_base.dart +++ b/packages/wolf_3d_dart/lib/src/engine/wolf_3d_engine_base.dart @@ -877,9 +877,15 @@ class WolfEngine { // Standardize movement to 60 FPS (16.66ms per frame) final double timeScale = delta.inMilliseconds / 16.666; - // Apply the timeScale multiplier to ensure consistent speed at any framerate - final double moveSpeed = 0.10 * timeScale; - final double turnSpeed = 0.08 * timeScale; + // Apply the timeScale multiplier to ensure consistent speed at any framerate. + // Rates are derived from the canonical Wolf3D source constants; see + // PlayerLocomotionConstants for the full derivation. + final double forwardMoveSpeed = + PlayerLocomotionConstants.forwardTilesPerSecond / 60.0 * timeScale; + final double backwardMoveSpeed = + PlayerLocomotionConstants.backwardTilesPerSecond / 60.0 * timeScale; + final double turnSpeed = + PlayerLocomotionConstants.turnRadiansPerSecond / 60.0 * timeScale; Coordinate2D movement = const Coordinate2D(0, 0); double dAngle = 0.0; @@ -910,8 +916,8 @@ class WolfEngine { math.cos(player.angle), math.sin(player.angle), ); - if (input.isMovingForward) movement += forwardVec * moveSpeed; - if (input.isMovingBackward) movement -= forwardVec * moveSpeed; + if (input.isMovingForward) movement += forwardVec * forwardMoveSpeed; + if (input.isMovingBackward) movement -= forwardVec * backwardMoveSpeed; if (input.isInteracting) { int targetX = (player.x + math.cos(player.angle)).toInt(); diff --git a/packages/wolf_3d_dart/lib/src/registry/built_in/retail_hud_module.dart b/packages/wolf_3d_dart/lib/src/registry/built_in/retail_hud_module.dart index 354a965..a5a0521 100644 --- a/packages/wolf_3d_dart/lib/src/registry/built_in/retail_hud_module.dart +++ b/packages/wolf_3d_dart/lib/src/registry/built_in/retail_hud_module.dart @@ -48,6 +48,9 @@ class RetailHudModule extends HudModule { HudKey.pistolIcon: 89, HudKey.machineGunIcon: 90, HudKey.chainGunIcon: 91, + HudKey.noKeyIcon: 92, + HudKey.goldKeyIcon: 93, + HudKey.silverKeyIcon: 94, }; @override diff --git a/packages/wolf_3d_dart/lib/src/registry/built_in/shareware_hud_module.dart b/packages/wolf_3d_dart/lib/src/registry/built_in/shareware_hud_module.dart index c459b94..5451af4 100644 --- a/packages/wolf_3d_dart/lib/src/registry/built_in/shareware_hud_module.dart +++ b/packages/wolf_3d_dart/lib/src/registry/built_in/shareware_hud_module.dart @@ -47,6 +47,9 @@ class SharewareHudModule extends HudModule { HudKey.pistolIcon: 89, HudKey.machineGunIcon: 90, HudKey.chainGunIcon: 91, + HudKey.noKeyIcon: 92, + HudKey.goldKeyIcon: 93, + HudKey.silverKeyIcon: 94, }; int? _offset; @@ -65,7 +68,8 @@ class SharewareHudModule extends HudModule { return 0; } - int get _effectiveOffset => useOriginalWl1Map ? _originalWl1Offset : (_offset ?? 0); + int get _effectiveOffset => + useOriginalWl1Map ? _originalWl1Offset : (_offset ?? 0); @override HudAssetRef? resolve(HudKey key) { diff --git a/packages/wolf_3d_dart/lib/src/registry/built_in/spear_demo_hud_module.dart b/packages/wolf_3d_dart/lib/src/registry/built_in/spear_demo_hud_module.dart index d0071c6..87c8679 100644 --- a/packages/wolf_3d_dart/lib/src/registry/built_in/spear_demo_hud_module.dart +++ b/packages/wolf_3d_dart/lib/src/registry/built_in/spear_demo_hud_module.dart @@ -40,6 +40,9 @@ class SpearDemoHudModule extends HudModule { HudKey.pistolIcon: 77, // GUNPIC HudKey.machineGunIcon: 78, // MACHINEGUNPIC HudKey.chainGunIcon: 79, // GATLINGGUNPIC + HudKey.noKeyIcon: 80, + HudKey.goldKeyIcon: 81, + HudKey.silverKeyIcon: 82, }; @override diff --git a/packages/wolf_3d_dart/lib/src/registry/keys/hud_key.dart b/packages/wolf_3d_dart/lib/src/registry/keys/hud_key.dart index 7de9c58..e7cf0bf 100644 --- a/packages/wolf_3d_dart/lib/src/registry/keys/hud_key.dart +++ b/packages/wolf_3d_dart/lib/src/registry/keys/hud_key.dart @@ -28,7 +28,12 @@ enum HudKey { // --- Weapon icons --- pistolIcon('pistolIcon'), machineGunIcon('machineGunIcon'), - chainGunIcon('chainGunIcon') + chainGunIcon('chainGunIcon'), + + // --- Key icons --- + noKeyIcon('noKeyIcon'), + goldKeyIcon('goldKeyIcon'), + silverKeyIcon('silverKeyIcon') ; const HudKey(this.id); diff --git a/packages/wolf_3d_dart/lib/src/rendering/ascii_renderer.dart b/packages/wolf_3d_dart/lib/src/rendering/ascii_renderer.dart index c3e7816..111d8ba 100644 --- a/packages/wolf_3d_dart/lib/src/rendering/ascii_renderer.dart +++ b/packages/wolf_3d_dart/lib/src/rendering/ascii_renderer.dart @@ -416,11 +416,15 @@ class AsciiRenderer extends CliRendererBackend { final int mapBgColor = ColorPalette.vga32Bit[0]; final int floorColor = ColorPalette.vga32Bit[8]; final int wallColor = ColorPalette.vga32Bit[7]; - final int doorColor = ColorPalette.vga32Bit[14]; + final int doorColor = ColorPalette.vga32Bit[9]; final int pushwallColor = ColorPalette.vga32Bit[6]; + final int normalExitColor = ColorPalette.vga32Bit[2]; + final int secretExitColor = ColorPalette.vga32Bit[10]; + final int goldKeyColor = ColorPalette.vga32Bit[11]; + final int silverKeyColor = ColorPalette.vga32Bit[16]; final int enemyColor = ColorPalette.vga32Bit[12]; - final int playerColor = ColorPalette.vga32Bit[10]; - final int facingColor = ColorPalette.vga32Bit[15]; + final int playerColor = ColorPalette.vga32Bit[15]; + final int facingColor = ColorPalette.vga32Bit[14]; final int viewportY = 0; final int viewportX = _usesTerminalLayout ? projectionOffsetX : 0; @@ -471,15 +475,24 @@ class AsciiRenderer extends CliRendererBackend { for (int y = 0; y < 64; y++) { for (int x = 0; x < 64; x++) { - final int tileId = engine.currentLevel[y][x]; + final int wallTile = engine.currentLevel[y][x]; + final int objTile = engine.activeLevel.objectGrid[y][x]; final bool isPushwall = engine.pushwallManager.pushwalls.containsKey( '$x,$y', ); final int color = isPushwall ? pushwallColor - : (tileId == 0 - ? floorColor - : (tileId >= 90 ? doorColor : wallColor)); + : objTile == MapObject.normalExitTrigger + ? normalExitColor + : objTile == MapObject.secretExitTrigger + ? secretExitColor + : objTile == MapObject.goldKey + ? goldKeyColor + : objTile == MapObject.silverKey + ? silverKeyColor + : (wallTile == 0 + ? floorColor + : (wallTile >= 90 ? doorColor : wallColor)); _fillMapRect( mapStartX + (x * tileSize), mapStartY + (y * tileSize), diff --git a/packages/wolf_3d_dart/lib/src/rendering/renderer_backend.dart b/packages/wolf_3d_dart/lib/src/rendering/renderer_backend.dart index 58792fa..4725a3a 100644 --- a/packages/wolf_3d_dart/lib/src/rendering/renderer_backend.dart +++ b/packages/wolf_3d_dart/lib/src/rendering/renderer_backend.dart @@ -184,6 +184,7 @@ abstract class RendererBackend _drawHudNumber(engine, vgaImages, engine.player.ammo, 232, 176); _drawHudFace(engine, vgaImages); _drawHudWeaponIcon(engine, vgaImages); + _drawHudKeys(engine, vgaImages); } void _drawHudNumber( @@ -243,6 +244,41 @@ abstract class RendererBackend } } + void _drawHudKeys(WolfEngine engine, List vgaImages) { + _drawHudKeySlot( + engine, + vgaImages, + startX: 30, + startY: 164, + hasKey: engine.player.hasGoldKey, + presentKey: HudKey.goldKeyIcon, + ); + _drawHudKeySlot( + engine, + vgaImages, + startX: 30, + startY: 180, + hasKey: engine.player.hasSilverKey, + presentKey: HudKey.silverKeyIcon, + ); + } + + void _drawHudKeySlot( + WolfEngine engine, + List vgaImages, { + required int startX, + required int startY, + required bool hasKey, + required HudKey presentKey, + }) { + final HudKey keyIcon = hasKey ? presentKey : HudKey.noKeyIcon; + final keyRef = engine.data.registry.hud.resolve(keyIcon); + final int keyIndex = keyRef?.vgaIndex ?? -1; + if (keyIndex >= 0 && keyIndex < vgaImages.length) { + blitHudVgaImage(vgaImages[keyIndex], startX, startY); + } + } + /// Calculates depth-based lighting falloff (0.0 to 1.0). /// While the original Wolf3D didn't use depth fog, this provides a great /// atmospheric effect for custom backends (like ASCII dithering). diff --git a/packages/wolf_3d_dart/lib/src/rendering/sixel_renderer.dart b/packages/wolf_3d_dart/lib/src/rendering/sixel_renderer.dart index de69131..ced1a28 100644 --- a/packages/wolf_3d_dart/lib/src/rendering/sixel_renderer.dart +++ b/packages/wolf_3d_dart/lib/src/rendering/sixel_renderer.dart @@ -370,11 +370,15 @@ class SixelRenderer extends CliRendererBackend { const int mapBgColor = 0; const int floorColor = 8; const int wallColor = 7; - const int doorColor = 14; + const int doorColor = 9; const int pushwallColor = 6; + const int normalExitColor = 2; + const int secretExitColor = 10; + const int goldKeyColor = 11; + const int silverKeyColor = 16; const int enemyColor = 12; - const int playerColor = 10; - const int facingColor = 15; + const int playerColor = 15; + const int facingColor = 14; _fillMapRect(0, 0, width, viewHeight, mapBgColor); @@ -395,15 +399,24 @@ class SixelRenderer extends CliRendererBackend { for (int y = 0; y < 64; y++) { for (int x = 0; x < 64; x++) { - final int tileId = engine.currentLevel[y][x]; + final int wallTile = engine.currentLevel[y][x]; + final int objTile = engine.activeLevel.objectGrid[y][x]; final bool isPushwall = engine.pushwallManager.pushwalls.containsKey( '$x,$y', ); final int color = isPushwall ? pushwallColor - : (tileId == 0 - ? floorColor - : (tileId >= 90 ? doorColor : wallColor)); + : objTile == MapObject.normalExitTrigger + ? normalExitColor + : objTile == MapObject.secretExitTrigger + ? secretExitColor + : objTile == MapObject.goldKey + ? goldKeyColor + : objTile == MapObject.silverKey + ? silverKeyColor + : (wallTile == 0 + ? floorColor + : (wallTile >= 90 ? doorColor : wallColor)); _fillMapRect( mapStartX + (x * tileSize), mapStartY + (y * tileSize), diff --git a/packages/wolf_3d_dart/lib/src/rendering/software_renderer.dart b/packages/wolf_3d_dart/lib/src/rendering/software_renderer.dart index e10c978..cfd00ac 100644 --- a/packages/wolf_3d_dart/lib/src/rendering/software_renderer.dart +++ b/packages/wolf_3d_dart/lib/src/rendering/software_renderer.dart @@ -150,11 +150,15 @@ class SoftwareRenderer extends RendererBackend { final int mapBgColor = ColorPalette.vga32Bit[0]; final int floorColor = ColorPalette.vga32Bit[8]; final int wallColor = ColorPalette.vga32Bit[7]; - final int doorColor = ColorPalette.vga32Bit[14]; + final int doorColor = ColorPalette.vga32Bit[9]; final int pushwallColor = ColorPalette.vga32Bit[6]; + final int normalExitColor = ColorPalette.vga32Bit[2]; + final int secretExitColor = ColorPalette.vga32Bit[10]; + final int goldKeyColor = ColorPalette.vga32Bit[11]; + final int silverKeyColor = ColorPalette.vga32Bit[16]; final int enemyColor = ColorPalette.vga32Bit[12]; - final int playerColor = ColorPalette.vga32Bit[10]; - final int facingColor = ColorPalette.vga32Bit[15]; + final int playerColor = ColorPalette.vga32Bit[15]; + final int facingColor = ColorPalette.vga32Bit[14]; _fillMenuPanel(0, 0, width, viewHeight, mapBgColor); @@ -175,15 +179,20 @@ class SoftwareRenderer extends RendererBackend { for (int y = 0; y < 64; y++) { for (int x = 0; x < 64; x++) { - final int tileId = engine.currentLevel[y][x]; + final int wallTile = engine.currentLevel[y][x]; + final int objTile = engine.activeLevel.objectGrid[y][x]; final bool isPushwall = engine.pushwallManager.pushwalls.containsKey( '$x,$y', ); final int color = isPushwall ? pushwallColor - : (tileId == 0 + : objTile == MapObject.normalExitTrigger + ? normalExitColor + : objTile == MapObject.secretExitTrigger + ? secretExitColor + : (wallTile == 0 ? floorColor - : (tileId >= 90 ? doorColor : wallColor)); + : (wallTile >= 90 ? doorColor : wallColor)); _fillMenuPanel( mapStartX + (x * tileSize), mapStartY + (y * tileSize), diff --git a/packages/wolf_3d_dart/lib/wolf_3d_engine.dart b/packages/wolf_3d_dart/lib/wolf_3d_engine.dart index 97a0b0e..df4ab66 100644 --- a/packages/wolf_3d_dart/lib/wolf_3d_engine.dart +++ b/packages/wolf_3d_dart/lib/wolf_3d_engine.dart @@ -11,6 +11,7 @@ export 'src/engine/input/engine_input.dart'; export 'src/engine/managers/door_manager.dart'; export 'src/engine/managers/pushwall_manager.dart'; export 'src/engine/player/player.dart'; +export 'src/engine/player_locomotion_constants.dart'; export 'src/engine/rendering/renderer_settings.dart'; export 'src/engine/rendering/renderer_settings_persistence.dart'; export 'src/engine/wolf_3d_engine_base.dart'; diff --git a/packages/wolf_3d_dart/test/engine/player_movement_parity_test.dart b/packages/wolf_3d_dart/test/engine/player_movement_parity_test.dart new file mode 100644 index 0000000..90791c7 --- /dev/null +++ b/packages/wolf_3d_dart/test/engine/player_movement_parity_test.dart @@ -0,0 +1,129 @@ +import 'dart:typed_data'; + +import 'package:test/test.dart'; +import 'package:wolf_3d_dart/wolf_3d_data_types.dart'; +import 'package:wolf_3d_dart/wolf_3d_engine.dart'; +import 'package:wolf_3d_dart/wolf_3d_input.dart'; + +void main() { + group('Player movement parity', () { + test('matches classic Wolf3D forward walking speed', () { + final input = _HeldMoveInput(forward: true, backward: false); + final engine = _buildEngine(input: input); + + engine.init(); + final startX = engine.player.x; + + engine.tick(const Duration(milliseconds: 1000)); + + final movedForward = engine.player.x - startX; + + expect( + movedForward, + closeTo(PlayerLocomotionConstants.forwardTilesPerSecond, 0.01), + ); + }); + + test('matches classic Wolf3D backward walking speed', () { + final input = _HeldMoveInput(forward: false, backward: true); + final engine = _buildEngine(input: input); + + engine.init(); + final startX = engine.player.x; + + engine.tick(const Duration(milliseconds: 1000)); + + final movedBackward = startX - engine.player.x; + + expect( + movedBackward, + closeTo(PlayerLocomotionConstants.backwardTilesPerSecond, 0.01), + ); + }); + }); +} + +class _HeldMoveInput extends Wolf3dInput { + _HeldMoveInput({required this.forward, required this.backward}); + + final bool forward; + final bool backward; + + @override + void update() { + isMovingForward = forward; + isMovingBackward = backward; + + isTurningLeft = false; + isTurningRight = false; + isMapToggle = false; + isInteracting = false; + isFiring = false; + isBack = false; + requestedWeapon = null; + menuTapX = null; + menuTapY = null; + } +} + +WolfEngine _buildEngine({ + required Wolf3dInput input, +}) { + final wallGrid = _buildGrid(); + final objectGrid = _buildGrid(); + _fillBoundaries(wallGrid, 2); + objectGrid[20][20] = MapObject.playerEast; + + return WolfEngine( + data: WolfensteinData( + version: GameVersion.shareware, + dataVersion: DataVersion.unknown, + registry: RetailAssetRegistry(), + walls: [ + _solidSprite(1), + _solidSprite(1), + _solidSprite(2), + _solidSprite(2), + ], + sprites: List.generate(436, (_) => _solidSprite(255)), + sounds: const [], + adLibSounds: const [], + music: const [], + vgaImages: const [], + episodes: [ + Episode( + name: 'Episode 1', + levels: [ + WolfLevel( + name: 'Level 1', + wallGrid: wallGrid, + areaGrid: List.generate(64, (_) => List.filled(64, -1)), + objectGrid: objectGrid, + music: Music.level01, + ), + ], + ), + ], + ), + difficulty: Difficulty.medium, + startingEpisode: 0, + frameBuffer: FrameBuffer(64, 64), + input: input, + onGameWon: () {}, + ); +} + +SpriteMap _buildGrid() => List.generate(64, (_) => List.filled(64, 0)); + +void _fillBoundaries(SpriteMap grid, int wallId) { + for (int i = 0; i < 64; i++) { + grid[0][i] = wallId; + grid[63][i] = wallId; + grid[i][0] = wallId; + grid[i][63] = wallId; + } +} + +Sprite _solidSprite(int colorIndex) { + return Sprite(Uint8List.fromList(List.filled(64 * 64, colorIndex))); +} diff --git a/packages/wolf_3d_dart/test/engine/player_rotation_parity_test.dart b/packages/wolf_3d_dart/test/engine/player_rotation_parity_test.dart new file mode 100644 index 0000000..292e615 --- /dev/null +++ b/packages/wolf_3d_dart/test/engine/player_rotation_parity_test.dart @@ -0,0 +1,111 @@ +import 'dart:typed_data'; + +import 'package:test/test.dart'; +import 'package:wolf_3d_dart/wolf_3d_data_types.dart'; +import 'package:wolf_3d_dart/wolf_3d_engine.dart'; +import 'package:wolf_3d_dart/wolf_3d_input.dart'; + +void main() { + group('Player rotation parity', () { + test('matches classic Wolf3D keyboard walking turn rate', () { + final input = _HeldTurnInput(turnRight: true); + final engine = _buildEngine(input: input); + + engine.init(); + final startingAngle = engine.player.angle; + + engine.tick(const Duration(milliseconds: 1000)); + + final turned = engine.player.angle - startingAngle; + + expect( + turned, + closeTo(PlayerLocomotionConstants.turnRadiansPerSecond, 0.01), + ); + }); + }); +} + +class _HeldTurnInput extends Wolf3dInput { + _HeldTurnInput({required this.turnRight}); + + final bool turnRight; + + @override + void update() { + isTurningRight = turnRight; + isTurningLeft = !turnRight; + + isMovingForward = false; + isMovingBackward = false; + isMapToggle = false; + isInteracting = false; + isFiring = false; + isBack = false; + requestedWeapon = null; + menuTapX = null; + menuTapY = null; + } +} + +WolfEngine _buildEngine({ + required Wolf3dInput input, +}) { + final wallGrid = _buildGrid(); + final objectGrid = _buildGrid(); + _fillBoundaries(wallGrid, 2); + objectGrid[2][2] = MapObject.playerEast; + + return WolfEngine( + data: WolfensteinData( + version: GameVersion.shareware, + dataVersion: DataVersion.unknown, + registry: RetailAssetRegistry(), + walls: [ + _solidSprite(1), + _solidSprite(1), + _solidSprite(2), + _solidSprite(2), + ], + sprites: List.generate(436, (_) => _solidSprite(255)), + sounds: const [], + adLibSounds: const [], + music: const [], + vgaImages: const [], + episodes: [ + Episode( + name: 'Episode 1', + levels: [ + WolfLevel( + name: 'Level 1', + wallGrid: wallGrid, + areaGrid: List.generate(64, (_) => List.filled(64, -1)), + objectGrid: objectGrid, + music: Music.level01, + ), + ], + ), + ], + ), + difficulty: Difficulty.medium, + startingEpisode: 0, + frameBuffer: FrameBuffer(64, 64), + input: input, + onGameWon: () {}, + ); +} + +SpriteMap _buildGrid() => List.generate(64, (_) => List.filled(64, 0)); + +void _fillBoundaries(SpriteMap grid, int wallId) { + for (int i = 0; i < 64; i++) { + grid[0][i] = wallId; + grid[63][i] = wallId; + grid[i][0] = wallId; + grid[i][63] = wallId; + } +} + +Sprite _solidSprite(int colorIndex) { + return Sprite(Uint8List.fromList(List.filled(64 * 64, colorIndex))); +} diff --git a/packages/wolf_3d_dart/test/rendering/hud_lives_rendering_test.dart b/packages/wolf_3d_dart/test/rendering/hud_lives_rendering_test.dart index 3ee7dcc..bcc1741 100644 --- a/packages/wolf_3d_dart/test/rendering/hud_lives_rendering_test.dart +++ b/packages/wolf_3d_dart/test/rendering/hud_lives_rendering_test.dart @@ -27,6 +27,36 @@ void main() { expect(livesDigitCall.imageIndex, expectedDigitIndex); }); + + test('standard VGA HUD renders gold key icon when collected', () { + final engine = _buildEngine(); + engine.init(); + engine.player.hasGoldKey = true; + + final renderer = _HudProbeRenderer(vgaImages: engine.data.vgaImages); + renderer.drawHudForTest(engine); + + final expectedGoldKeyIndex = engine.data.registry.hud + .resolve(HudKey.goldKeyIcon) + ?.vgaIndex; + final expectedNoKeyIndex = engine.data.registry.hud + .resolve(HudKey.noKeyIcon) + ?.vgaIndex; + expect(expectedGoldKeyIndex, isNotNull); + expect(expectedNoKeyIndex, isNotNull); + + final goldKeyCall = renderer.drawCalls.firstWhere( + (call) => call.startY == 164 && call.startX == 30, + orElse: () => throw StateError('Gold key slot was not rendered.'), + ); + final silverKeyCall = renderer.drawCalls.firstWhere( + (call) => call.startY == 180 && call.startX == 30, + orElse: () => throw StateError('Silver key slot was not rendered.'), + ); + + expect(goldKeyCall.imageIndex, expectedGoldKeyIndex); + expect(silverKeyCall.imageIndex, expectedNoKeyIndex); + }); } class _HudProbeRenderer extends RendererBackend { diff --git a/packages/wolf_3d_dart/test/rendering/map_overlay_renderer_test.dart b/packages/wolf_3d_dart/test/rendering/map_overlay_renderer_test.dart index 6682a66..2dec58e 100644 --- a/packages/wolf_3d_dart/test/rendering/map_overlay_renderer_test.dart +++ b/packages/wolf_3d_dart/test/rendering/map_overlay_renderer_test.dart @@ -45,7 +45,8 @@ void main() { expect(changedPixels, greaterThan(mapPixels.length ~/ 5)); expect(mapPixels.contains(ColorPalette.vga32Bit[6]), isTrue); expect(mapPixels.contains(ColorPalette.vga32Bit[12]), isTrue); - expect(mapPixels.contains(ColorPalette.vga32Bit[10]), isTrue); + expect(mapPixels.contains(ColorPalette.vga32Bit[15]), isTrue); + expect(mapPixels.contains(ColorPalette.vga32Bit[2]), isTrue); expect(mapPixels[hudProbeIndex], equals(normalPixels[hudProbeIndex])); }); }); @@ -78,6 +79,7 @@ WolfEngine _buildEngine() { wallGrid[5][5] = 1; objectGrid[2][2] = MapObject.playerEast; objectGrid[5][5] = MapObject.pushwallTrigger; + objectGrid[10][10] = MapObject.normalExitTrigger; return WolfEngine( data: WolfensteinData(