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;
|
ammo = newAmmo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Interaction & Firing ---
|
|
||||||
|
|
||||||
bool tryPickup(Collectible item) {
|
bool tryPickup(Collectible item) {
|
||||||
bool pickedUp = false;
|
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/classes/matrix.dart';
|
||||||
import 'package:wolf_dart/features/difficulty/difficulty.dart';
|
import 'package:wolf_dart/features/difficulty/difficulty.dart';
|
||||||
import 'package:wolf_dart/features/entities/collectible.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/enemies/enemy.dart';
|
||||||
import 'package:wolf_dart/features/entities/entity.dart';
|
import 'package:wolf_dart/features/entities/entity.dart';
|
||||||
import 'package:wolf_dart/features/entities/entity_registry.dart';
|
import 'package:wolf_dart/features/entities/entity_registry.dart';
|
||||||
@@ -36,6 +37,8 @@ class WolfRenderer extends StatefulWidget {
|
|||||||
class _WolfRendererState extends State<WolfRenderer>
|
class _WolfRendererState extends State<WolfRenderer>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
final InputManager inputManager = InputManager();
|
final InputManager inputManager = InputManager();
|
||||||
|
final DoorManager doorManager = DoorManager();
|
||||||
|
|
||||||
late Ticker _gameLoop;
|
late Ticker _gameLoop;
|
||||||
final FocusNode _focusNode = FocusNode();
|
final FocusNode _focusNode = FocusNode();
|
||||||
late WolfMap gameMap;
|
late WolfMap gameMap;
|
||||||
@@ -51,9 +54,6 @@ class _WolfRendererState extends State<WolfRenderer>
|
|||||||
|
|
||||||
List<Entity> entities = [];
|
List<Entity> entities = [];
|
||||||
|
|
||||||
Map<String, double> doorOffsets = {};
|
|
||||||
Map<String, int> doorStates = {};
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -64,6 +64,8 @@ class _WolfRendererState extends State<WolfRenderer>
|
|||||||
gameMap = demo ? await WolfMap.loadDemo() : await WolfMap.load();
|
gameMap = demo ? await WolfMap.loadDemo() : await WolfMap.load();
|
||||||
currentLevel = gameMap.levels[0].wallGrid;
|
currentLevel = gameMap.levels[0].wallGrid;
|
||||||
|
|
||||||
|
doorManager.initDoors(currentLevel);
|
||||||
|
|
||||||
final Matrix<int> objectLevel = gameMap.levels[0].objectGrid;
|
final Matrix<int> objectLevel = gameMap.levels[0].objectGrid;
|
||||||
|
|
||||||
for (int y = 0; y < 64; y++) {
|
for (int y = 0; y < 64; y++) {
|
||||||
@@ -170,10 +172,7 @@ class _WolfRendererState extends State<WolfRenderer>
|
|||||||
bool _isWalkable(int x, int y) {
|
bool _isWalkable(int x, int y) {
|
||||||
if (currentLevel[y][x] == 0) return true;
|
if (currentLevel[y][x] == 0) return true;
|
||||||
if (currentLevel[y][x] >= 90) {
|
if (currentLevel[y][x] >= 90) {
|
||||||
String key = '$x,$y';
|
return doorManager.isDoorOpenEnough(x, y);
|
||||||
if (doorOffsets[key] != null && doorOffsets[key]! > 0.7) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -183,9 +182,10 @@ class _WolfRendererState extends State<WolfRenderer>
|
|||||||
// 1. Process intentions and receive movement vectors
|
// 1. Process intentions and receive movement vectors
|
||||||
final movement = _processInputs(elapsed);
|
final movement = _processInputs(elapsed);
|
||||||
|
|
||||||
|
doorManager.update(elapsed);
|
||||||
|
|
||||||
// 2. Explicit State Updates
|
// 2. Explicit State Updates
|
||||||
player.updateWeaponSwitch();
|
player.updateWeaponSwitch();
|
||||||
_updateDoors();
|
|
||||||
_applyMovementAndCollision(movement.dx, movement.dy);
|
_applyMovementAndCollision(movement.dx, movement.dy);
|
||||||
_updateEntities(elapsed);
|
_updateEntities(elapsed);
|
||||||
|
|
||||||
@@ -241,37 +241,16 @@ class _WolfRendererState extends State<WolfRenderer>
|
|||||||
if (player.angle > 2 * math.pi) player.angle -= 2 * math.pi;
|
if (player.angle > 2 * math.pi) player.angle -= 2 * math.pi;
|
||||||
|
|
||||||
if (inputManager.isInteracting) {
|
if (inputManager.isInteracting) {
|
||||||
int targetX = (player.x + math.cos(player.angle)).toInt();
|
doorManager.handleInteraction(
|
||||||
int targetY = (player.y + math.sin(player.angle)).toInt();
|
player.x,
|
||||||
|
player.y,
|
||||||
if (targetY > 0 &&
|
player.angle,
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (dx: dx, dy: dy);
|
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
|
// Now receives dx and dy explicitly
|
||||||
void _applyMovementAndCollision(double dx, double dy) {
|
void _applyMovementAndCollision(double dx, double dy) {
|
||||||
const double margin = 0.3;
|
const double margin = 0.3;
|
||||||
@@ -364,7 +343,7 @@ class _WolfRendererState extends State<WolfRenderer>
|
|||||||
textures: gameMap.textures,
|
textures: gameMap.textures,
|
||||||
player: player,
|
player: player,
|
||||||
fov: fov,
|
fov: fov,
|
||||||
doorOffsets: doorOffsets,
|
doorOffsets: doorManager.getOffsetsForRenderer(),
|
||||||
entities: entities,
|
entities: entities,
|
||||||
sprites: gameMap.sprites,
|
sprites: gameMap.sprites,
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user