Move doors to door manager
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
56
lib/features/entities/door_manager.dart
Normal file
56
lib/features/entities/door_manager.dart
Normal 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
|
||||
}
|
||||
}
|
||||
56
lib/features/map/door.dart
Normal file
56
lib/features/map/door.dart
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,8 +117,6 @@ class Player {
|
||||
ammo = newAmmo;
|
||||
}
|
||||
|
||||
// --- Interaction & Firing ---
|
||||
|
||||
bool tryPickup(Collectible item) {
|
||||
bool pickedUp = false;
|
||||
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user