diff --git a/desktop_version/src/Terrain.cpp b/desktop_version/src/Terrain.cpp index d6b483c88b..d1ca16bbb3 100644 --- a/desktop_version/src/Terrain.cpp +++ b/desktop_version/src/Terrain.cpp @@ -12,7 +12,7 @@ namespace Terrain { - bool precomputed_rooms[20][20] = { { false } }; + RoomInfo precomputed_rooms[20][20] = { { RoomInfo() } }; CollisionKind collision_kind = CollisionKind::Walls; std::vector nav_corners; @@ -41,6 +41,14 @@ namespace Terrain { } } + precomputed_rooms[rx][ry].min_x_pos = min_x_pos; + precomputed_rooms[rx][ry].max_x_pos = max_x_pos; + precomputed_rooms[rx][ry].min_y_pos = min_y_pos; + precomputed_rooms[rx][ry].max_y_pos = max_y_pos; + precomputed_rooms[rx][ry].warpx = map.warpx; + precomputed_rooms[rx][ry].warpy = map.warpy; + precomputed_rooms[rx][ry].towermode = map.towermode; + // Create all corners for (int x = min_x_pos; x <= max_x_pos; x++) { for (int y = min_y_pos; y <= max_y_pos; y++) { @@ -261,6 +269,23 @@ namespace Terrain { continue; } + // Check no wall intersections + bool any_intersections = false; + for (int k = 0; k < num_walls; k++) { + Wall& w = nav_walls.at(k); + if (w.room_x != c.room_x || w.room_y != c.room_y) { + continue; + } + if (w.RayIntersect(c.x, c.y, dx, dy)) { + any_intersections = true; + break; + } + } + if (any_intersections) { + // Intersected a wall, continue + continue; + } + // Add edges to the corners NavEdge e1, e2; e1.target = i; e1.dx = dx; e1.dy = dy; @@ -270,6 +295,18 @@ namespace Terrain { new_corner.edges.push_back(e2); } } + + + + precomputed_rooms[rx][ry].precomputed = true; + } + + bool TryConnectCorners(NavCorner& source, NavCorner& target) { + if (IsConcave(source) || IsConcave(target)) { + return false; + } + + } bool CheckPlayerCollisionCurrentRoom(int x, int y) { @@ -297,9 +334,8 @@ namespace Terrain { int rx = game.roomx; int ry = game.roomy; - if (!precomputed_rooms[rx][ry]) { + if (!precomputed_rooms[rx][ry].precomputed) { PrecomputeCurrentRoomTerrain(); - precomputed_rooms[rx][ry] = true; } } @@ -310,7 +346,7 @@ namespace Terrain { void AfterTileRenderHook(void) { int rx = game.roomx; int ry = game.roomy; - if (precomputed_rooms[rx][ry]) { + if (precomputed_rooms[rx][ry].precomputed) { int px = obj.entities[0].xp; int py = obj.entities[0].yp; int num_walls = nav_walls.size(); diff --git a/desktop_version/src/Terrain.h b/desktop_version/src/Terrain.h index 04e1067714..7e69bc54cb 100644 --- a/desktop_version/src/Terrain.h +++ b/desktop_version/src/Terrain.h @@ -47,6 +47,22 @@ namespace Terrain { QuadBLTR, }; + bool IsConvex(NavCornerType type) { + switch (type) { + case NavCornerType::TopLeft: + case NavCornerType::TopRight: + case NavCornerType::BottomLeft: + case NavCornerType::BottomRight: + return true; + default: + return false; + } + } + + bool IsConcave(NavCornerType type) { + return !IsConvex(type); + } + struct NavEdge { int target; // Index of destination corner int dx, dy; // Horizontal and vertical distance @@ -189,11 +205,10 @@ namespace Terrain { // we can assume 0 < t < 1 because of min/max checks float i_x = ((float)ox) + ((float)dx) * t; - float x_dist = orientation == Up ? i_x - x : x - i_x; + float x_dist = orientation == Down ? x - i_x : i_x - x; // Intersection is within wall's range - return x_dist < width; - } - else { + return 0 < x_dist && x_dist < width; + } else { // assume(orientation == Right || Orientation == Left) int min_x, max_x; if (dx == 0) { @@ -212,7 +227,7 @@ namespace Terrain { // Ray doesn't cross extended wall return false; } - else if (dy == 0 && (oy == y || oy == y + (orientation == Left ? -width : width))) { + else if (dy == 0 && (oy == y || oy == y + (orientation == Left ? width : -width))) { // Ray exactly touches the end of the wall, let it through return false; } @@ -220,9 +235,9 @@ namespace Terrain { float t = ((float)(x - ox)) / ((float)dx); float i_y = ((float)oy) + ((float)dy) * t; - float y_dist = orientation == Right ? i_y - y : y - i_y; + float y_dist = orientation == Left ? y - i_y : i_y - y; // Intersection is within wall's range - return y_dist < width; + return 0 < y_dist && y_dist < width; } } }; @@ -267,6 +282,23 @@ namespace Terrain { } }; + struct RoomInfo { + int min_x_pos, max_x_pos, min_y_pos, max_y_pos; + bool precomputed, warpx, warpy, towermode; + + RoomInfo() { + min_x_pos = min_y_pos = INT_MAX; + max_x_pos = max_y_pos = INT_MIN; + precomputed = warpx = warpy = towermode = false; + } + + RoomInfo(int min_x, int max_x, int min_y, int max_y) : min_x_pos(min_x), max_x_pos(max_x), min_y_pos(min_y), max_y_pos(max_y) { + precomputed = true; + warpx = warpy = towermode = false; + } + + RoomInfo(int min_x, int max_x, int min_y, int max_y, bool pre, bool warp_x, bool warp_y, bool tower) : min_x_pos(min_x), max_x_pos(max_x), min_y_pos(min_y), max_y_pos(max_y), precomputed(pre), warpx(warpx), warpy(warpy), towermode(tower) { } + }; void PrecomputeCurrentRoomTerrain(void); bool CheckPlayerCollisionCurrentRoom(int x, int y);