Can now open secret walls and pick up machine gun
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
121
lib/features/entities/pushwall_manager.dart
Normal file
121
lib/features/entities/pushwall_manager.dart
Normal file
@@ -0,0 +1,121 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:wolf_dart/classes/matrix.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++) {
|
||||
// Map ID 98 in the object grid marks a pushwall!
|
||||
if (objectGrid[y][x] == 98) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user