diff --git a/lib/features/entities/door_manager.dart b/lib/features/entities/door_manager.dart new file mode 100644 index 0000000..0dcdc05 --- /dev/null +++ b/lib/features/entities/door_manager.dart @@ -0,0 +1,56 @@ +import 'dart:math' as math; + +import 'package:wolf_dart/features/map/door.dart'; + +class DoorManager { + // Key is '$x,$y' + final Map doors = {}; + + void initDoors(List> wallGrid) { + doors.clear(); + for (int y = 0; y < wallGrid.length; y++) { + for (int x = 0; x < wallGrid[y].length; x++) { + int id = wallGrid[y][x]; + if (id >= 90) { + // Assuming 90+ are doors based on your previous code + doors['$x,$y'] = Door(x: x, y: y, mapId: id); + } + } + } + } + + void update(Duration elapsed) { + for (final door in doors.values) { + door.update(elapsed.inMilliseconds); + } + } + + void handleInteraction(double playerX, double playerY, double playerAngle) { + int targetX = (playerX + math.cos(playerAngle)).toInt(); + int targetY = (playerY + math.sin(playerAngle)).toInt(); + + String key = '$targetX,$targetY'; + if (doors.containsKey(key)) { + doors[key]!.interact(); + } + } + + // Helper method for the raycaster + Map getOffsetsForRenderer() { + Map offsets = {}; + for (var entry in doors.entries) { + if (entry.value.offset > 0.0) { + offsets[entry.key] = entry.value.offset; + } + } + return offsets; + } + + bool isDoorOpenEnough(int x, int y) { + String key = '$x,$y'; + if (doors.containsKey(key)) { + return doors[key]!.offset > 0.7; + } + return false; // Not a door we manage + } +} diff --git a/lib/features/map/door.dart b/lib/features/map/door.dart new file mode 100644 index 0000000..3acdff4 --- /dev/null +++ b/lib/features/map/door.dart @@ -0,0 +1,56 @@ +enum DoorState { closed, opening, open, closing } + +class Door { + final int x; + final int y; + final int mapId; // To differentiate between regular doors and elevator doors + + DoorState state = DoorState.closed; + double offset = 0.0; + int openTime = 0; // When did the door fully open? + + // How long a door stays open before auto-closing + static const int openDurationMs = 3000; + + Door({ + required this.x, + required this.y, + required this.mapId, + }); + + // Returns true if the door state changed this frame (useful for playing sounds later) + bool update(int currentTimeMs) { + bool stateChanged = false; + + if (state == DoorState.opening) { + offset += 0.02; // Slide speed + if (offset >= 1.0) { + offset = 1.0; + state = DoorState.open; + openTime = currentTimeMs; + stateChanged = true; + } + } else if (state == DoorState.open) { + if (currentTimeMs - openTime > openDurationMs) { + state = DoorState.closing; + stateChanged = true; + } + } else if (state == DoorState.closing) { + // Note: We don't check for entities blocking the door yet! + offset -= 0.02; + if (offset <= 0.0) { + offset = 0.0; + state = DoorState.closed; + stateChanged = true; + } + } + + return stateChanged; + } + + void interact() { + if (state == DoorState.closed || state == DoorState.closing) { + state = DoorState.opening; + } + } +} diff --git a/lib/features/player/player.dart b/lib/features/player/player.dart index 7082e8f..90a3ab5 100644 --- a/lib/features/player/player.dart +++ b/lib/features/player/player.dart @@ -117,8 +117,6 @@ class Player { ammo = newAmmo; } - // --- Interaction & Firing --- - bool tryPickup(Collectible item) { bool pickedUp = false; diff --git a/lib/features/renderer/renderer.dart b/lib/features/renderer/renderer.dart index 79168a7..6174990 100644 --- a/lib/features/renderer/renderer.dart +++ b/lib/features/renderer/renderer.dart @@ -6,6 +6,7 @@ import 'package:wolf_dart/classes/linear_coordinates.dart'; import 'package:wolf_dart/classes/matrix.dart'; import 'package:wolf_dart/features/difficulty/difficulty.dart'; import 'package:wolf_dart/features/entities/collectible.dart'; +import 'package:wolf_dart/features/entities/door_manager.dart'; import 'package:wolf_dart/features/entities/enemies/enemy.dart'; import 'package:wolf_dart/features/entities/entity.dart'; import 'package:wolf_dart/features/entities/entity_registry.dart'; @@ -36,6 +37,8 @@ class WolfRenderer extends StatefulWidget { class _WolfRendererState extends State with SingleTickerProviderStateMixin { final InputManager inputManager = InputManager(); + final DoorManager doorManager = DoorManager(); + late Ticker _gameLoop; final FocusNode _focusNode = FocusNode(); late WolfMap gameMap; @@ -51,9 +54,6 @@ class _WolfRendererState extends State List entities = []; - Map doorOffsets = {}; - Map doorStates = {}; - @override void initState() { super.initState(); @@ -64,6 +64,8 @@ class _WolfRendererState extends State gameMap = demo ? await WolfMap.loadDemo() : await WolfMap.load(); currentLevel = gameMap.levels[0].wallGrid; + doorManager.initDoors(currentLevel); + final Matrix objectLevel = gameMap.levels[0].objectGrid; for (int y = 0; y < 64; y++) { @@ -170,10 +172,7 @@ class _WolfRendererState extends State bool _isWalkable(int x, int y) { if (currentLevel[y][x] == 0) return true; if (currentLevel[y][x] >= 90) { - String key = '$x,$y'; - if (doorOffsets[key] != null && doorOffsets[key]! > 0.7) { - return true; - } + return doorManager.isDoorOpenEnough(x, y); } return false; } @@ -183,9 +182,10 @@ class _WolfRendererState extends State // 1. Process intentions and receive movement vectors final movement = _processInputs(elapsed); + doorManager.update(elapsed); + // 2. Explicit State Updates player.updateWeaponSwitch(); - _updateDoors(); _applyMovementAndCollision(movement.dx, movement.dy); _updateEntities(elapsed); @@ -241,37 +241,16 @@ class _WolfRendererState extends State if (player.angle > 2 * math.pi) player.angle -= 2 * math.pi; if (inputManager.isInteracting) { - int targetX = (player.x + math.cos(player.angle)).toInt(); - int targetY = (player.y + math.sin(player.angle)).toInt(); - - if (targetY > 0 && - targetY < currentLevel.length && - targetX > 0 && - targetX < currentLevel[0].length) { - if (currentLevel[targetY][targetX] >= 90) { - String key = '$targetX,$targetY'; - if (!doorStates.containsKey(key) || doorStates[key] == 0) { - doorStates[key] = 1; - } - } - } + doorManager.handleInteraction( + player.x, + player.y, + player.angle, + ); } return (dx: dx, dy: dy); } - void _updateDoors() { - doorStates.forEach((key, state) { - if (state == 1) { - doorOffsets[key] = (doorOffsets[key] ?? 0.0) + 0.02; - if (doorOffsets[key]! >= 1.0) { - doorOffsets[key] = 1.0; - doorStates[key] = 2; - } - } - }); - } - // Now receives dx and dy explicitly void _applyMovementAndCollision(double dx, double dy) { const double margin = 0.3; @@ -364,7 +343,7 @@ class _WolfRendererState extends State textures: gameMap.textures, player: player, fov: fov, - doorOffsets: doorOffsets, + doorOffsets: doorManager.getOffsetsForRenderer(), entities: entities, sprites: gameMap.sprites, ),