import 'dart:math' as math; import 'package:wolf_dart/classes/matrix.dart'; import 'package:wolf_dart/features/entities/map_objects.dart'; class Pushwall { int x; int y; int mapId; // The wall texture ID int dirX = 0; int dirY = 0; double offset = 0.0; int tilesMoved = 0; Pushwall(this.x, this.y, this.mapId); } class PushwallManager { final Map pushwalls = {}; Pushwall? activePushwall; void initPushwalls(Matrix wallGrid, Matrix objectGrid) { pushwalls.clear(); activePushwall = null; for (int y = 0; y < objectGrid.length; y++) { for (int x = 0; x < objectGrid[y].length; x++) { if (objectGrid[y][x] == MapObject.pushwallTrigger) { pushwalls['$x,$y'] = Pushwall(x, y, wallGrid[y][x]); } } } } void update(Duration elapsed, Matrix wallGrid) { if (activePushwall == null) return; final pw = activePushwall!; // Original logic: 1/128 tile per tick. // At 70 ticks/sec, that is roughly 0.54 tiles per second. const double originalSpeed = 0.546875; pw.offset += (elapsed.inMilliseconds / 1000.0) * originalSpeed; // Once it crosses a full tile boundary, we update the collision grid! if (pw.offset >= 1.0) { pw.offset -= 1.0; pw.tilesMoved++; int nextX = pw.x + pw.dirX; int nextY = pw.y + pw.dirY; // Move the solid block in the physical grid wallGrid[nextY][nextX] = pw.mapId; wallGrid[pw.y][pw.x] = 0; // Clear the old space so the player can walk in // Update the dictionary key pushwalls.remove('${pw.x},${pw.y}'); pw.x = nextX; pw.y = nextY; pushwalls['${pw.x},${pw.y}'] = pw; // Check if we should keep sliding bool blocked = false; int checkX = pw.x + pw.dirX; int checkY = pw.y + pw.dirY; if (checkX < 0 || checkX >= wallGrid[0].length || checkY < 0 || checkY >= wallGrid.length) { blocked = true; } else if (wallGrid[checkY][checkX] != 0) { blocked = true; // Blocked by another wall or a door } // Standard Wolf3D pushwalls move exactly 2 tiles (or 1 if blocked) if (pw.tilesMoved >= 2 || blocked) { activePushwall = null; pw.offset = 0.0; } } } void handleInteraction( double playerX, double playerY, double playerAngle, Matrix wallGrid, ) { // Only one pushwall can move at a time in the original engine! if (activePushwall != null) return; int targetX = (playerX + math.cos(playerAngle)).toInt(); int targetY = (playerY + math.sin(playerAngle)).toInt(); String key = '$targetX,$targetY'; if (pushwalls.containsKey(key)) { final pw = pushwalls[key]!; // Determine the push direction based on the player's relative position double dx = (targetX + 0.5) - playerX; double dy = (targetY + 0.5) - playerY; if (dx.abs() > dy.abs()) { pw.dirX = dx > 0 ? 1 : -1; pw.dirY = 0; } else { pw.dirX = 0; pw.dirY = dy > 0 ? 1 : -1; } // Make sure the tile behind the wall is empty before starting the push int checkX = targetX + pw.dirX; int checkY = targetY + pw.dirY; if (wallGrid[checkY][checkX] == 0) { activePushwall = pw; } } } }