Browse Source

Merge pull request #270 from djeada/copilot/prevent-biome-spawning-in-rivers

🌿 Prevent Biome Object Spawning in River Areas
Adam Djellouli 1 month ago
parent
commit
900e9ff6d7

+ 23 - 0
game/map/terrain.cpp

@@ -392,6 +392,29 @@ TerrainType TerrainHeightMap::getTerrainType(int gridX, int gridZ) const {
   return m_terrainTypes[indexAt(gridX, gridZ)];
 }
 
+bool TerrainHeightMap::isRiverOrNearby(int gridX, int gridZ, int margin) const {
+  if (!inBounds(gridX, gridZ))
+    return false;
+
+  if (m_terrainTypes[indexAt(gridX, gridZ)] == TerrainType::River)
+    return true;
+
+  for (int dz = -margin; dz <= margin; ++dz) {
+    for (int dx = -margin; dx <= margin; ++dx) {
+      if (dx == 0 && dz == 0)
+        continue;
+      int nx = gridX + dx;
+      int nz = gridZ + dz;
+      if (inBounds(nx, nz) &&
+          m_terrainTypes[indexAt(nx, nz)] == TerrainType::River) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
 int TerrainHeightMap::indexAt(int x, int z) const { return z * m_width + x; }
 
 bool TerrainHeightMap::inBounds(int x, int z) const {

+ 2 - 0
game/map/terrain.h

@@ -87,6 +87,8 @@ public:
 
   TerrainType getTerrainType(int gridX, int gridZ) const;
 
+  bool isRiverOrNearby(int gridX, int gridZ, int margin = 1) const;
+
   int getWidth() const { return m_width; }
   int getHeight() const { return m_height; }
   float getTileSize() const { return m_tileSize; }

+ 27 - 3
render/ground/biome_renderer.cpp

@@ -219,6 +219,24 @@ void BiomeRenderer::generateGrassInstances() {
         m_terrainTypes[normalIdx] == Game::Map::TerrainType::Hill)
       return false;
 
+    if (m_terrainTypes[normalIdx] == Game::Map::TerrainType::River)
+      return false;
+
+    constexpr int kRiverMargin = 1;
+    for (int dz = -kRiverMargin; dz <= kRiverMargin; ++dz) {
+      for (int dx = -kRiverMargin; dx <= kRiverMargin; ++dx) {
+        if (dx == 0 && dz == 0)
+          continue;
+        int nx = ix + dx;
+        int nz = iz + dz;
+        if (nx >= 0 && nx < m_width && nz >= 0 && nz < m_height) {
+          int nIdx = nz * m_width + nx;
+          if (m_terrainTypes[nIdx] == Game::Map::TerrainType::River)
+            return false;
+        }
+      }
+    }
+
     QVector3D normal = normals[normalIdx];
     float slope = 1.0f - std::clamp(normal.y(), 0.0f, 1.0f);
     if (slope > 0.92f)
@@ -302,7 +320,11 @@ void BiomeRenderer::generateGrassInstances() {
           if (m_terrainTypes[idx0] == Game::Map::TerrainType::Mountain ||
               m_terrainTypes[idx1] == Game::Map::TerrainType::Mountain ||
               m_terrainTypes[idx2] == Game::Map::TerrainType::Mountain ||
-              m_terrainTypes[idx3] == Game::Map::TerrainType::Mountain) {
+              m_terrainTypes[idx3] == Game::Map::TerrainType::Mountain ||
+              m_terrainTypes[idx0] == Game::Map::TerrainType::River ||
+              m_terrainTypes[idx1] == Game::Map::TerrainType::River ||
+              m_terrainTypes[idx2] == Game::Map::TerrainType::River ||
+              m_terrainTypes[idx3] == Game::Map::TerrainType::River) {
             mountainCount++;
           } else if (m_terrainTypes[idx0] == Game::Map::TerrainType::Hill ||
                      m_terrainTypes[idx1] == Game::Map::TerrainType::Hill ||
@@ -367,7 +389,8 @@ void BiomeRenderer::generateGrassInstances() {
             int cx = std::clamp(int(std::round(candidateGX)), 0, m_width - 1);
             int cz = std::clamp(int(std::round(candidateGZ)), 0, m_height - 1);
             int centerIdx = cz * m_width + cx;
-            if (m_terrainTypes[centerIdx] == Game::Map::TerrainType::Mountain)
+            if (m_terrainTypes[centerIdx] == Game::Map::TerrainType::Mountain ||
+                m_terrainTypes[centerIdx] == Game::Map::TerrainType::River)
               continue;
 
             QVector3D centerNormal = normals[centerIdx];
@@ -414,7 +437,8 @@ void BiomeRenderer::generateGrassInstances() {
         int idx = z * m_width + x;
 
         if (m_terrainTypes[idx] == Game::Map::TerrainType::Mountain ||
-            m_terrainTypes[idx] == Game::Map::TerrainType::Hill)
+            m_terrainTypes[idx] == Game::Map::TerrainType::Hill ||
+            m_terrainTypes[idx] == Game::Map::TerrainType::River)
           continue;
 
         QVector3D normal = normals[idx];

+ 20 - 1
render/ground/plant_renderer.cpp

@@ -204,6 +204,24 @@ void PlantRenderer::generatePlantInstances() {
     if (m_terrainTypes[normalIdx] == Game::Map::TerrainType::Mountain)
       return false;
 
+    if (m_terrainTypes[normalIdx] == Game::Map::TerrainType::River)
+      return false;
+
+    constexpr int kRiverMargin = 1;
+    for (int dz = -kRiverMargin; dz <= kRiverMargin; ++dz) {
+      for (int dx = -kRiverMargin; dx <= kRiverMargin; ++dx) {
+        if (dx == 0 && dz == 0)
+          continue;
+        int nx = ix + dx;
+        int nz = iz + dz;
+        if (nx >= 0 && nx < m_width && nz >= 0 && nz < m_height) {
+          int nIdx = nz * m_width + nx;
+          if (m_terrainTypes[nIdx] == Game::Map::TerrainType::River)
+            return false;
+        }
+      }
+    }
+
     QVector3D normal = normals[normalIdx];
     float slope = 1.0f - std::clamp(normal.y(), 0.0f, 1.0f);
 
@@ -259,7 +277,8 @@ void PlantRenderer::generatePlantInstances() {
       cellsChecked++;
       int idx = z * m_width + x;
 
-      if (m_terrainTypes[idx] == Game::Map::TerrainType::Mountain)
+      if (m_terrainTypes[idx] == Game::Map::TerrainType::Mountain ||
+          m_terrainTypes[idx] == Game::Map::TerrainType::River)
         continue;
 
       QVector3D normal = normals[idx];

+ 13 - 0
render/ground/stone_renderer.cpp

@@ -191,6 +191,19 @@ void StoneRenderer::generateStoneInstances() {
     if (m_terrainTypes[normalIdx] != Game::Map::TerrainType::Flat)
       return false;
 
+    constexpr int kRiverMargin = 1;
+    for (int dz = -kRiverMargin; dz <= kRiverMargin; ++dz) {
+      for (int dx = -kRiverMargin; dx <= kRiverMargin; ++dx) {
+        int nx = ix + dx;
+        int nz = iz + dz;
+        if (nx >= 0 && nx < m_width && nz >= 0 && nz < m_height) {
+          int nIdx = nz * m_width + nx;
+          if (m_terrainTypes[nIdx] == Game::Map::TerrainType::River)
+            return false;
+        }
+      }
+    }
+
     QVector3D normal = normals[normalIdx];
     float slope = 1.0f - std::clamp(normal.y(), 0.0f, 1.0f);