Move doors to door manager

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-03-14 00:34:09 +01:00
parent 09c28028ad
commit 5c9dafbbdf
4 changed files with 126 additions and 37 deletions

View File

@@ -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<String, Door> doors = {};
void initDoors(List<List<int>> 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<String, double> getOffsetsForRenderer() {
Map<String, double> 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
}
}

View File

@@ -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;
}
}
}

View File

@@ -117,8 +117,6 @@ class Player {
ammo = newAmmo;
}
// --- Interaction & Firing ---
bool tryPickup(Collectible item) {
bool pickedUp = false;

View File

@@ -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<WolfRenderer>
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<WolfRenderer>
List<Entity> entities = [];
Map<String, double> doorOffsets = {};
Map<String, int> doorStates = {};
@override
void initState() {
super.initState();
@@ -64,6 +64,8 @@ class _WolfRendererState extends State<WolfRenderer>
gameMap = demo ? await WolfMap.loadDemo() : await WolfMap.load();
currentLevel = gameMap.levels[0].wallGrid;
doorManager.initDoors(currentLevel);
final Matrix<int> objectLevel = gameMap.levels[0].objectGrid;
for (int y = 0; y < 64; y++) {
@@ -170,10 +172,7 @@ class _WolfRendererState extends State<WolfRenderer>
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<WolfRenderer>
// 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<WolfRenderer>
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<WolfRenderer>
textures: gameMap.textures,
player: player,
fov: fov,
doorOffsets: doorOffsets,
doorOffsets: doorManager.getOffsetsForRenderer(),
entities: entities,
sprites: gameMap.sprites,
),