122 lines
3.3 KiB
Dart
122 lines
3.3 KiB
Dart
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<String, Pushwall> pushwalls = {};
|
|
Pushwall? activePushwall;
|
|
|
|
void initPushwalls(Matrix<int> wallGrid, Matrix<int> 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] == MapObjectId.secretDoor) {
|
|
pushwalls['$x,$y'] = Pushwall(x, y, wallGrid[y][x]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void update(Duration elapsed, Matrix<int> 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<int> 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;
|
|
}
|
|
}
|
|
}
|
|
}
|