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:
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:wolf_dart/classes/coordinate_2d.dart';
|
||||
import 'package:wolf_dart/classes/matrix.dart';
|
||||
import 'package:wolf_dart/features/entities/entity.dart';
|
||||
import 'package:wolf_dart/features/entities/pushwall_manager.dart'; // NEW IMPORT
|
||||
import 'package:wolf_dart/features/player/player.dart';
|
||||
import 'package:wolf_dart/features/renderer/color_palette.dart';
|
||||
|
||||
@@ -13,6 +14,7 @@ class RaycasterPainter extends CustomPainter {
|
||||
final Player player;
|
||||
final double fov;
|
||||
final Map<String, double> doorOffsets;
|
||||
final Pushwall? activePushwall; // NEW
|
||||
final List<Matrix<int>> sprites;
|
||||
final List<Entity> entities;
|
||||
|
||||
@@ -22,6 +24,7 @@ class RaycasterPainter extends CustomPainter {
|
||||
required this.player,
|
||||
required this.fov,
|
||||
required this.doorOffsets,
|
||||
this.activePushwall, // NEW
|
||||
required this.sprites,
|
||||
required this.entities,
|
||||
});
|
||||
@@ -49,13 +52,11 @@ class RaycasterPainter extends CustomPainter {
|
||||
|
||||
List<double> zBuffer = List.filled(renderWidth, 0.0);
|
||||
|
||||
// --- Coordinate2D Camera Vectors ---
|
||||
Coordinate2D dir = Coordinate2D(
|
||||
math.cos(player.angle),
|
||||
math.sin(player.angle),
|
||||
);
|
||||
|
||||
// The camera plane is perpendicular to the direction vector, scaled by FOV
|
||||
Coordinate2D plane = Coordinate2D(-dir.y, dir.x) * math.tan(fov / 2);
|
||||
|
||||
// --- 1. CAST WALLS ---
|
||||
@@ -70,7 +71,7 @@ class RaycasterPainter extends CustomPainter {
|
||||
double sideDistY;
|
||||
double deltaDistX = (rayDir.x == 0) ? 1e30 : (1.0 / rayDir.x).abs();
|
||||
double deltaDistY = (rayDir.y == 0) ? 1e30 : (1.0 / rayDir.y).abs();
|
||||
double perpWallDist;
|
||||
double perpWallDist = 0.0;
|
||||
|
||||
int stepX;
|
||||
int stepY;
|
||||
@@ -78,7 +79,9 @@ class RaycasterPainter extends CustomPainter {
|
||||
bool hitOutOfBounds = false;
|
||||
int side = 0;
|
||||
int hitWallId = 0;
|
||||
double doorOffset = 0.0;
|
||||
|
||||
double textureOffset = 0.0; // Replaces doorOffset to handle both
|
||||
bool customDistCalculated = false; // Flag to skip standard distance
|
||||
Set<String> ignoredDoors = {};
|
||||
|
||||
if (rayDir.x < 0) {
|
||||
@@ -115,9 +118,11 @@ class RaycasterPainter extends CustomPainter {
|
||||
hit = true;
|
||||
hitOutOfBounds = true;
|
||||
} else if (map[mapY][mapX] > 0) {
|
||||
String doorKey = '$mapX,$mapY';
|
||||
if (map[mapY][mapX] >= 90 && !ignoredDoors.contains(doorKey)) {
|
||||
double currentOffset = doorOffsets[doorKey] ?? 0.0;
|
||||
String mapKey = '$mapX,$mapY';
|
||||
|
||||
// --- DOOR LOGIC ---
|
||||
if (map[mapY][mapX] >= 90 && !ignoredDoors.contains(mapKey)) {
|
||||
double currentOffset = doorOffsets[mapKey] ?? 0.0;
|
||||
if (currentOffset > 0.0) {
|
||||
double perpWallDistTemp = (side == 0)
|
||||
? (sideDistX - deltaDistX)
|
||||
@@ -127,23 +132,98 @@ class RaycasterPainter extends CustomPainter {
|
||||
: player.x + perpWallDistTemp * rayDir.x;
|
||||
wallXTemp -= wallXTemp.floor();
|
||||
if (wallXTemp < currentOffset) {
|
||||
ignoredDoors.add(doorKey);
|
||||
continue;
|
||||
ignoredDoors.add(mapKey);
|
||||
continue; // Ray passed through the open door gap
|
||||
}
|
||||
}
|
||||
doorOffset = currentOffset;
|
||||
hit = true;
|
||||
hitWallId = map[mapY][mapX];
|
||||
textureOffset = currentOffset;
|
||||
}
|
||||
// --- PUSHWALL LOGIC ---
|
||||
else if (activePushwall != null &&
|
||||
mapX == activePushwall!.x &&
|
||||
mapY == activePushwall!.y) {
|
||||
hit = true;
|
||||
hitWallId = map[mapY][mapX];
|
||||
|
||||
double pOffset = activePushwall!.offset;
|
||||
int pDirX = activePushwall!.dirX;
|
||||
int pDirY = activePushwall!.dirY;
|
||||
|
||||
perpWallDist = (side == 0)
|
||||
? (sideDistX - deltaDistX)
|
||||
: (sideDistY - deltaDistY);
|
||||
|
||||
// Did we hit the face that is being pushed deeper?
|
||||
if (side == 0 && pDirX != 0) {
|
||||
if (pDirX == stepX) {
|
||||
double intersect = perpWallDist + pOffset * deltaDistX;
|
||||
if (intersect < sideDistY) {
|
||||
perpWallDist = intersect; // Hit the recessed front face
|
||||
} else {
|
||||
side =
|
||||
1; // Missed the front face, hit the newly exposed side!
|
||||
perpWallDist = sideDistY - deltaDistY;
|
||||
}
|
||||
} else {
|
||||
perpWallDist -= (1.0 - pOffset) * deltaDistX;
|
||||
}
|
||||
} else if (side == 1 && pDirY != 0) {
|
||||
if (pDirY == stepY) {
|
||||
double intersect = perpWallDist + pOffset * deltaDistY;
|
||||
if (intersect < sideDistX) {
|
||||
perpWallDist = intersect;
|
||||
} else {
|
||||
side = 0;
|
||||
perpWallDist = sideDistX - deltaDistX;
|
||||
}
|
||||
} else {
|
||||
perpWallDist -= (1.0 - pOffset) * deltaDistY;
|
||||
}
|
||||
} else {
|
||||
// We hit the side of the sliding block. Did the ray slip behind it?
|
||||
double wallFraction = (side == 0)
|
||||
? player.y + perpWallDist * rayDir.y
|
||||
: player.x + perpWallDist * rayDir.x;
|
||||
wallFraction -= wallFraction.floor();
|
||||
|
||||
if (side == 0) {
|
||||
if (pDirY == 1 && wallFraction < pOffset) hit = false;
|
||||
if (pDirY == -1 && wallFraction > (1.0 - pOffset)) hit = false;
|
||||
if (hit) {
|
||||
textureOffset =
|
||||
pOffset * pDirY; // Stick the texture to the block
|
||||
}
|
||||
} else {
|
||||
if (pDirX == 1 && wallFraction < pOffset) hit = false;
|
||||
if (pDirX == -1 && wallFraction > (1.0 - pOffset)) hit = false;
|
||||
if (hit) {
|
||||
textureOffset =
|
||||
pOffset * pDirX; // Stick the texture to the block
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hit) continue; // The ray slipped past! Keep looping.
|
||||
customDistCalculated = true; // Lock in our custom distance math
|
||||
}
|
||||
// --- STANDARD WALL ---
|
||||
else {
|
||||
hit = true;
|
||||
hitWallId = map[mapY][mapX];
|
||||
}
|
||||
hit = true;
|
||||
hitWallId = map[mapY][mapX];
|
||||
}
|
||||
}
|
||||
|
||||
if (hitOutOfBounds) continue;
|
||||
|
||||
if (side == 0) {
|
||||
perpWallDist = (sideDistX - deltaDistX);
|
||||
} else {
|
||||
perpWallDist = (sideDistY - deltaDistY);
|
||||
// Apply standard math ONLY if we didn't calculate a sub-tile pushwall distance
|
||||
if (!customDistCalculated) {
|
||||
if (side == 0) {
|
||||
perpWallDist = (sideDistX - deltaDistX);
|
||||
} else {
|
||||
perpWallDist = (sideDistY - deltaDistY);
|
||||
}
|
||||
}
|
||||
|
||||
zBuffer[x] = perpWallDist;
|
||||
@@ -164,15 +244,15 @@ class RaycasterPainter extends CustomPainter {
|
||||
size,
|
||||
hitWallId,
|
||||
textures,
|
||||
doorOffset,
|
||||
textureOffset,
|
||||
columnPaint,
|
||||
);
|
||||
}
|
||||
|
||||
// --- 2. DRAW SPRITES ---
|
||||
// (Keep your existing sprite rendering logic exactly the same)
|
||||
List<Entity> activeSprites = List.from(entities);
|
||||
|
||||
// Sort sprites from furthest to closest using Coordinate2D
|
||||
activeSprites.sort((a, b) {
|
||||
double distA = player.position.distanceTo(a.position);
|
||||
double distB = player.position.distanceTo(b.position);
|
||||
@@ -180,10 +260,8 @@ class RaycasterPainter extends CustomPainter {
|
||||
});
|
||||
|
||||
for (Entity entity in activeSprites) {
|
||||
// Relative position to player
|
||||
Coordinate2D spritePos = entity.position - player.position;
|
||||
|
||||
// Transform sprite with the inverse camera matrix
|
||||
double invDet = 1.0 / (plane.x * dir.y - dir.x * plane.y);
|
||||
double transformX = invDet * (dir.y * spritePos.x - dir.x * spritePos.y);
|
||||
double transformY =
|
||||
@@ -245,7 +323,7 @@ class RaycasterPainter extends CustomPainter {
|
||||
Size size,
|
||||
int hitWallId,
|
||||
List<Matrix<int>> textures,
|
||||
double doorOffset,
|
||||
double textureOffset,
|
||||
Paint paint,
|
||||
) {
|
||||
if (distance <= 0.01) distance = 0.01;
|
||||
@@ -253,15 +331,19 @@ class RaycasterPainter extends CustomPainter {
|
||||
double wallHeight = size.height / distance;
|
||||
int drawStart = ((size.height / 2) - (wallHeight / 2)).toInt();
|
||||
|
||||
int texNum = ((hitWallId - 1) * 2).clamp(0, textures.length - 2);
|
||||
int texX = (wallX * 64).toInt().clamp(0, 63);
|
||||
int texNum;
|
||||
int texX;
|
||||
|
||||
if (hitWallId >= 90) {
|
||||
// DOORS
|
||||
texNum = 98.clamp(0, textures.length - 1);
|
||||
texX = ((wallX - doorOffset) * 64).toInt().clamp(0, 63);
|
||||
texX = ((wallX - textureOffset) * 64).toInt().clamp(0, 63);
|
||||
} else {
|
||||
// WALLS & PUSHWALLS
|
||||
texNum = ((hitWallId - 1) * 2).clamp(0, textures.length - 2);
|
||||
if (side == 1) texNum += 1;
|
||||
// We apply the modulo % 1.0 to handle negative texture offsets smoothly!
|
||||
texX = (((wallX - textureOffset) % 1.0) * 64).toInt().clamp(0, 63);
|
||||
}
|
||||
|
||||
if (side == 0 && math.cos(player.angle) > 0) texX = 63 - texX;
|
||||
|
||||
Reference in New Issue
Block a user