From c0727c426572745c72a61d26a84754d5a641d562 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 11 May 2014 22:35:41 +0200 Subject: Initial VillageGen implementation. WIP, doesn't generate anything yet. Ref.: 740. --- src/Generating/VillageGen.cpp | 116 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/Generating/VillageGen.cpp (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp new file mode 100644 index 000000000..fb6191df2 --- /dev/null +++ b/src/Generating/VillageGen.cpp @@ -0,0 +1,116 @@ + +// VillageGen.cpp + +// Implements the cVillageGen class representing the village generator + +#include "Globals.h" +#include "VillageGen.h" +#include "Prefabs/PlainsVillagePrefabs.h" +#include "Prefabs/SandVillagePrefabs.h" + + + + + +class cVillageGen::cVillage : + public cGridStructGen::cStructure +{ + typedef cGridStructGen::cStructure super; + +public: + cVillage(int a_Seed, int a_OriginX, int a_OriginZ, cPrefabPiecePool & a_Prefabs) : + super(a_OriginX, a_OriginZ), + m_Seed(a_Seed), + m_Prefabs(a_Prefabs) + { + } + +protected: + /** Seed for the random functions */ + int m_Seed; + + /** Prefabs to use for buildings */ + cPrefabPiecePool & m_Prefabs; + + // cGrdStructGen::cStructure overrides: + virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override + { + // TODO + } +} ; + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cVillageGen: + +cPrefabPiecePool cVillageGen::m_SandVillage (g_SandVillagePrefabs, g_SandVillagePrefabsCount, g_SandVillageStartingPrefabs, g_SandVillageStartingPrefabsCount); +cPrefabPiecePool cVillageGen::m_PlainsVillage(g_PlainsVillagePrefabs, g_PlainsVillagePrefabsCount, g_PlainsVillageStartingPrefabs, g_PlainsVillageStartingPrefabsCount); + + + + + +cVillageGen::cVillageGen(int a_Seed, int a_GridSize, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen) : + super(a_Seed, a_GridSize, a_GridSize, 128, 128, 100), + m_BiomeGen(a_BiomeGen), + m_HeightGen(a_HeightGen) +{ +} + + + + + +cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_OriginZ) +{ + // Generate the biomes for the chunk surrounding the origin: + int ChunkX, ChunkZ; + cChunkDef::BlockToChunk(a_OriginX, a_OriginZ, ChunkX, ChunkZ); + cChunkDef::BiomeMap Biomes; + m_BiomeGen.GenBiomes(ChunkX, ChunkZ, Biomes); + + // Check if all the biomes are village-friendly: + // If just one is not, no village is created, because it's likely that an unfriendly biome is too close + cPrefabPiecePool * VillagePrefabs = NULL; + for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++) + { + switch (Biomes[i]) + { + case biDesert: + case biDesertM: + { + // These biomes allow sand villages + VillagePrefabs = &m_SandVillage; + break; + } + case biPlains: + case biSavanna: + case biSavannaM: + case biSunflowerPlains: + { + // These biomes allow plains-style villages + VillagePrefabs = &m_PlainsVillage; + break; + } + default: + { + // Village-unfriendly biome, bail out with zero structure: + return cStructurePtr(); + } + } // switch (Biomes[i]) + } // for i - Biomes[] + + // Create a village based on the chosen prefabs: + if (VillagePrefabs == NULL) + { + return cStructurePtr(); + } + return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, *VillagePrefabs)); +} + + + + -- cgit v1.2.3 From 9c8e8ef7aece2f881ef97c387600c8a751579b20 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 12 May 2014 22:43:59 +0200 Subject: VillageGen: Added well placement and the general algorithm description. --- src/Generating/VillageGen.cpp | 147 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 142 insertions(+), 5 deletions(-) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index fb6191df2..3d89d7aa2 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -12,30 +12,167 @@ +/* +How village generating works: +By descending from a cGridStructGen, a semi-random grid is generated. A village may be generated for each of +the grid's cells. Each cell checks the biomes in an entire chunk around it, only generating a village if all +biomes are village-friendly. If yes, the entire village structure is built for that cell. If not, the cell +is left village-less. + +A village is generated starting by its well. The well is placed in the grid's origin point. Then a set of +random lengths roads is generated - 4 roads going from the well, then at the end of each road another set of +roads, crossing them perpendicular, then at the end of those another set, up to a set maximum branching +depth. The roads are placed in a T or L shape, with the old road being the center stem of the T. Roads avoid +crossing each other and going further away from the well than the maximum block size of the village. +Finally, houses are places along the roads, avoiding collisions with already-existing items. + +When the village is about to be drawn into a chunk, it queries the heights for each item intersecting the +chunk. The prefabs are shifted so that their pivot points lie on the surface, and the roads are drawn +directly by turning the surface blocks into gravel / sandstone. +*/ + class cVillageGen::cVillage : public cGridStructGen::cStructure { typedef cGridStructGen::cStructure super; public: - cVillage(int a_Seed, int a_OriginX, int a_OriginZ, cPrefabPiecePool & a_Prefabs) : + cVillage( + int a_Seed, + int a_OriginX, int a_OriginZ, + int a_MaxRoadDepth, + int a_MaxSize, + cPrefabPiecePool & a_Prefabs, + cTerrainHeightGen & a_HeightGen + ) : super(a_OriginX, a_OriginZ), m_Seed(a_Seed), - m_Prefabs(a_Prefabs) + m_Noise(a_Seed), + m_MaxSize(a_MaxSize), + m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, 255, a_OriginZ + a_MaxSize), + m_Prefabs(a_Prefabs), + m_HeightGen(a_HeightGen) { + PlaceWell(); + BuildRoads(a_MaxRoadDepth); + PlaceHouses(); } protected: + class cItem + { + public: + /* The position of the item, X/Z-wise: */ + int m_MinX, m_MaxX, m_MinZ, m_MaxZ; + + /** The prefab to use. If NULL, this is a road. */ + cPrefab * m_Prefab; + + /** Number of rotations that should be applied to the prefab. */ + int m_NumRotations; + + /* The bottom of the prefab. Only valid if the item is a prefab, not valid for roads. */ + int m_BaseY; + + /** Creates a new item with the specified parameters. + m_BaseY is set to -1 and will be adjusted later on when drawing. */ + cItem(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, cPrefab * a_Prefab, int a_NumRotations) : + m_MinX(a_MinX), + m_MaxX(a_MaxX), + m_MinZ(a_MinZ), + m_MaxZ(a_MaxZ), + m_Prefab(a_Prefab), + m_NumRotations(a_NumRotations), + m_BaseY(-1) + { + } + } ; + typedef SharedPtr cItemPtr; + typedef std::vector cItemPtrs; + + /** Seed for the random functions */ int m_Seed; + /** The noise used as a pseudo-random generator */ + cNoise m_Noise; + + /** Maximum size, in X/Z blocks, of the village (radius from the origin) */ + int m_MaxSize; + + /** Borders of the vilalge - no item may reach out of this cuboid. */ + cCuboid m_Borders; + /** Prefabs to use for buildings */ cPrefabPiecePool & m_Prefabs; + /** The underlying height generator, used for placing the structures on top of the terrain. */ + cTerrainHeightGen & m_HeightGen; + + /** The items that are generated in the village (houses, roads). */ + cItemPtrs m_Items; + + + /** Places the well at the center of the village */ + void PlaceWell(void) + { + // Pick a prefab from the starting pieces: + cPieces StartingPieces = ((cPiecePool &)m_Prefabs).GetStartingPieces(); + ASSERT(!StartingPieces.empty()); + int TotalWeight = 0; + for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr) + { + TotalWeight += ((const cPrefab *)(*itr))->GetDefaultWeight(); + } + ASSERT(TotalWeight > 0); + int rnd = (m_Noise.IntNoise2DInt(m_OriginX, m_OriginZ) / 7) % TotalWeight; + cPiece * WellPiece = StartingPieces[0]; + for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr) + { + rnd -= ((const cPrefab *)(*itr))->GetDefaultWeight(); + if (rnd <= 0) + { + WellPiece = *itr; + break; + } + } + ASSERT(WellPiece != NULL); + + // Pick a rotation: + // TODO + int NumRotations = 0; + Vector3i Size = WellPiece->GetSize(); + + // Put the well in the placed items array: + m_Items.push_back(cItemPtr(new cItem(m_OriginX, m_OriginX + Size.x, m_OriginZ, m_OriginZ + Size.z, (cPrefab *)WellPiece, NumRotations))); + } + + + /** Places the roads going from the well outwards. */ + void BuildRoads(int a_MaxRoadDepth) + { + /* + ASSERT(m_Items.size() == 1); + const cItem & Well = *m_Items[0]; + */ + // TODO + } + + + /** Places houses along the roads. */ + void PlaceHouses(void) + { + // TODO + } + + // cGrdStructGen::cStructure overrides: virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override { // TODO + // Iterate over all items + // Each intersecting prefab is placed on ground (if not already placed), then drawn + // Each intersecting road is drawn by replacing top soil blocks with gravel / sandstone blocks } } ; @@ -53,8 +190,8 @@ cPrefabPiecePool cVillageGen::m_PlainsVillage(g_PlainsVillagePrefabs, g_PlainsVi -cVillageGen::cVillageGen(int a_Seed, int a_GridSize, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen) : - super(a_Seed, a_GridSize, a_GridSize, 128, 128, 100), +cVillageGen::cVillageGen(int a_Seed, int a_GridSize, int a_MaxRoadDepth, int a_MaxSize, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen) : + super(a_Seed, a_GridSize, a_GridSize, a_MaxSize, a_MaxSize, 100), m_BiomeGen(a_BiomeGen), m_HeightGen(a_HeightGen) { @@ -108,7 +245,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ { return cStructurePtr(); } - return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, *VillagePrefabs)); + return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, m_MaxRoadDepth, m_MaxSize, *VillagePrefabs, m_HeightGen)); } -- cgit v1.2.3 From f5fdbdaf29738f51fdb8a4a0e5aa78631c6540cf Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 15 May 2014 00:14:06 +0200 Subject: VillageGen rewritten using BFSPieceGenerator. Piece composition is not good yet, the buildings aren't height-adjusted and the road pieces will need special processing. This is mainly for adjusting the per-piece params. --- src/Generating/VillageGen.cpp | 196 ++++++++++++++++++++---------------------- 1 file changed, 91 insertions(+), 105 deletions(-) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index 3d89d7aa2..3358bc531 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -7,6 +7,7 @@ #include "VillageGen.h" #include "Prefabs/PlainsVillagePrefabs.h" #include "Prefabs/SandVillagePrefabs.h" +#include "PieceGenerator.h" @@ -19,18 +20,79 @@ the grid's cells. Each cell checks the biomes in an entire chunk around it, only biomes are village-friendly. If yes, the entire village structure is built for that cell. If not, the cell is left village-less. -A village is generated starting by its well. The well is placed in the grid's origin point. Then a set of -random lengths roads is generated - 4 roads going from the well, then at the end of each road another set of -roads, crossing them perpendicular, then at the end of those another set, up to a set maximum branching -depth. The roads are placed in a T or L shape, with the old road being the center stem of the T. Roads avoid -crossing each other and going further away from the well than the maximum block size of the village. -Finally, houses are places along the roads, avoiding collisions with already-existing items. +A village is generated using the regular BFS piece generator. The well piece is used as the starting piece, +the roads and houses are then used as the following pieces. Only the houses are read from the prefabs, +though, the roads are generated by code and their content is ignored. A special subclass of the cPiecePool +class is used, so that the roads connect to each other and to the well only in predefined manners. -When the village is about to be drawn into a chunk, it queries the heights for each item intersecting the -chunk. The prefabs are shifted so that their pivot points lie on the surface, and the roads are drawn +The well has connectors of type "1". The houses have connectors of type "-1". The roads have connectors of +both types, type "-1" at the far ends and type "1" on the long edges. + +When the village is about to be drawn into a chunk, it queries the heights for each piece intersecting the +chunk. The pieces are shifted so that their pivot points lie on the surface, and the roads are drawn directly by turning the surface blocks into gravel / sandstone. */ +class cVillagePiecePool : + public cPrefabPiecePool +{ + typedef cPrefabPiecePool super; +public: + cVillagePiecePool( + const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs, + const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs + ) : + super(a_PieceDefs, a_NumPieceDefs, a_StartingPieceDefs, a_NumStartingPieceDefs) + { + // Add the road piece: + cBlockArea BA; + BA.Create(5, 1, 3, cBlockArea::baTypes | cBlockArea::baMetas); + BA.Fill(cBlockArea::baTypes | cBlockArea::baMetas, E_BLOCK_GRAVEL, 0); + cPrefab * RoadPiece = new cPrefab(BA, 7); + RoadPiece->AddConnector(0, 0, 1, BLOCK_FACE_XM, -1); + RoadPiece->AddConnector(4, 0, 1, BLOCK_FACE_XP, -1); + RoadPiece->AddConnector(4, 0, 1, BLOCK_FACE_XP, 1); + RoadPiece->AddConnector(1, 0, 0, BLOCK_FACE_ZM, 1); + RoadPiece->AddConnector(3, 0, 0, BLOCK_FACE_ZM, 1); + RoadPiece->AddConnector(1, 0, 2, BLOCK_FACE_ZP, 1); + RoadPiece->AddConnector(3, 0, 2, BLOCK_FACE_ZP, 1); + RoadPiece->SetAddWeightIfSame(10000); + m_AllPieces.push_back(RoadPiece); + m_PiecesByConnector[-1].push_back(RoadPiece); + m_PiecesByConnector[1].push_back(RoadPiece); + } + + + // cPrefabPiecePool overrides: + virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override + { + // Only roads are allowed to connect to the well: + if ((a_PlacedPiece.GetDepth() == 0) && (a_NewPiece.GetSize().y != 1)) + { + return 0; + } + + // Roads cannot branch T-wise: + if ( + (a_PlacedPiece.GetPiece().GetSize().y == 1) && // Connecting to a road + ( + (a_ExistingConnector.m_Direction == BLOCK_FACE_ZP) || + (a_ExistingConnector.m_Direction == BLOCK_FACE_ZM) + ) && // Through the long-edge connector + (a_NewPiece.GetSize().y == 1) // And the new piece is a road + ) + { + return 0; + } + + return ((const cPrefab &)a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector); + } +} ; + + + + + class cVillageGen::cVillage : public cGridStructGen::cStructure { @@ -53,44 +115,11 @@ public: m_Prefabs(a_Prefabs), m_HeightGen(a_HeightGen) { - PlaceWell(); - BuildRoads(a_MaxRoadDepth); - PlaceHouses(); + cBFSPieceGenerator pg(m_Prefabs, a_Seed); + pg.PlacePieces(a_OriginX, 10, a_OriginZ, a_MaxRoadDepth + 1, m_Pieces); } protected: - class cItem - { - public: - /* The position of the item, X/Z-wise: */ - int m_MinX, m_MaxX, m_MinZ, m_MaxZ; - - /** The prefab to use. If NULL, this is a road. */ - cPrefab * m_Prefab; - - /** Number of rotations that should be applied to the prefab. */ - int m_NumRotations; - - /* The bottom of the prefab. Only valid if the item is a prefab, not valid for roads. */ - int m_BaseY; - - /** Creates a new item with the specified parameters. - m_BaseY is set to -1 and will be adjusted later on when drawing. */ - cItem(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, cPrefab * a_Prefab, int a_NumRotations) : - m_MinX(a_MinX), - m_MaxX(a_MaxX), - m_MinZ(a_MinZ), - m_MaxZ(a_MaxZ), - m_Prefab(a_Prefab), - m_NumRotations(a_NumRotations), - m_BaseY(-1) - { - } - } ; - typedef SharedPtr cItemPtr; - typedef std::vector cItemPtrs; - - /** Seed for the random functions */ int m_Seed; @@ -109,61 +138,8 @@ protected: /** The underlying height generator, used for placing the structures on top of the terrain. */ cTerrainHeightGen & m_HeightGen; - /** The items that are generated in the village (houses, roads). */ - cItemPtrs m_Items; - - - /** Places the well at the center of the village */ - void PlaceWell(void) - { - // Pick a prefab from the starting pieces: - cPieces StartingPieces = ((cPiecePool &)m_Prefabs).GetStartingPieces(); - ASSERT(!StartingPieces.empty()); - int TotalWeight = 0; - for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr) - { - TotalWeight += ((const cPrefab *)(*itr))->GetDefaultWeight(); - } - ASSERT(TotalWeight > 0); - int rnd = (m_Noise.IntNoise2DInt(m_OriginX, m_OriginZ) / 7) % TotalWeight; - cPiece * WellPiece = StartingPieces[0]; - for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr) - { - rnd -= ((const cPrefab *)(*itr))->GetDefaultWeight(); - if (rnd <= 0) - { - WellPiece = *itr; - break; - } - } - ASSERT(WellPiece != NULL); - - // Pick a rotation: - // TODO - int NumRotations = 0; - Vector3i Size = WellPiece->GetSize(); - - // Put the well in the placed items array: - m_Items.push_back(cItemPtr(new cItem(m_OriginX, m_OriginX + Size.x, m_OriginZ, m_OriginZ + Size.z, (cPrefab *)WellPiece, NumRotations))); - } - - - /** Places the roads going from the well outwards. */ - void BuildRoads(int a_MaxRoadDepth) - { - /* - ASSERT(m_Items.size() == 1); - const cItem & Well = *m_Items[0]; - */ - // TODO - } - - - /** Places houses along the roads. */ - void PlaceHouses(void) - { - // TODO - } + /** The village pieces, placed by the generator. */ + cPlacedPieces m_Pieces; // cGrdStructGen::cStructure overrides: @@ -173,6 +149,11 @@ protected: // Iterate over all items // Each intersecting prefab is placed on ground (if not already placed), then drawn // Each intersecting road is drawn by replacing top soil blocks with gravel / sandstone blocks + for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr) + { + const cPrefab & Prefab = (const cPrefab &)((*itr)->GetPiece()); + Prefab.Draw(a_Chunk, *itr); + } // for itr - m_PlacedPieces[] } } ; @@ -183,15 +164,20 @@ protected: /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cVillageGen: -cPrefabPiecePool cVillageGen::m_SandVillage (g_SandVillagePrefabs, g_SandVillagePrefabsCount, g_SandVillageStartingPrefabs, g_SandVillageStartingPrefabsCount); -cPrefabPiecePool cVillageGen::m_PlainsVillage(g_PlainsVillagePrefabs, g_PlainsVillagePrefabsCount, g_PlainsVillageStartingPrefabs, g_PlainsVillageStartingPrefabsCount); +/** The prefabs for the sand village. */ +static cVillagePiecePool g_SandVillage (g_SandVillagePrefabs, g_SandVillagePrefabsCount, g_SandVillageStartingPrefabs, g_SandVillageStartingPrefabsCount); + +/** The prefabs for the plains village. */ +static cVillagePiecePool g_PlainsVillage(g_PlainsVillagePrefabs, g_PlainsVillagePrefabsCount, g_PlainsVillageStartingPrefabs, g_PlainsVillageStartingPrefabsCount); -cVillageGen::cVillageGen(int a_Seed, int a_GridSize, int a_MaxRoadDepth, int a_MaxSize, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen) : +cVillageGen::cVillageGen(int a_Seed, int a_GridSize, int a_MaxDepth, int a_MaxSize, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen) : super(a_Seed, a_GridSize, a_GridSize, a_MaxSize, a_MaxSize, 100), + m_MaxDepth(a_MaxDepth), + m_MaxSize(a_MaxSize), m_BiomeGen(a_BiomeGen), m_HeightGen(a_HeightGen) { @@ -211,7 +197,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ // Check if all the biomes are village-friendly: // If just one is not, no village is created, because it's likely that an unfriendly biome is too close - cPrefabPiecePool * VillagePrefabs = NULL; + cVillagePiecePool * VillagePrefabs = NULL; for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++) { switch (Biomes[i]) @@ -220,7 +206,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ case biDesertM: { // These biomes allow sand villages - VillagePrefabs = &m_SandVillage; + VillagePrefabs = &g_SandVillage; break; } case biPlains: @@ -229,7 +215,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ case biSunflowerPlains: { // These biomes allow plains-style villages - VillagePrefabs = &m_PlainsVillage; + VillagePrefabs = &g_PlainsVillage; break; } default: @@ -245,7 +231,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ { return cStructurePtr(); } - return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, m_MaxRoadDepth, m_MaxSize, *VillagePrefabs, m_HeightGen)); + return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, *VillagePrefabs, m_HeightGen)); } -- cgit v1.2.3 From 34e5f0c16422f93d3f8f0f802522fa113fa9aa20 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 15 May 2014 10:43:54 +0200 Subject: Changed village road generation to use multiple prefabs. --- src/Generating/VillageGen.cpp | 61 +++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 31 deletions(-) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index 3358bc531..b514a90cd 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -44,43 +44,42 @@ public: ) : super(a_PieceDefs, a_NumPieceDefs, a_StartingPieceDefs, a_NumStartingPieceDefs) { - // Add the road piece: - cBlockArea BA; - BA.Create(5, 1, 3, cBlockArea::baTypes | cBlockArea::baMetas); - BA.Fill(cBlockArea::baTypes | cBlockArea::baMetas, E_BLOCK_GRAVEL, 0); - cPrefab * RoadPiece = new cPrefab(BA, 7); - RoadPiece->AddConnector(0, 0, 1, BLOCK_FACE_XM, -1); - RoadPiece->AddConnector(4, 0, 1, BLOCK_FACE_XP, -1); - RoadPiece->AddConnector(4, 0, 1, BLOCK_FACE_XP, 1); - RoadPiece->AddConnector(1, 0, 0, BLOCK_FACE_ZM, 1); - RoadPiece->AddConnector(3, 0, 0, BLOCK_FACE_ZM, 1); - RoadPiece->AddConnector(1, 0, 2, BLOCK_FACE_ZP, 1); - RoadPiece->AddConnector(3, 0, 2, BLOCK_FACE_ZP, 1); - RoadPiece->SetAddWeightIfSame(10000); - m_AllPieces.push_back(RoadPiece); - m_PiecesByConnector[-1].push_back(RoadPiece); - m_PiecesByConnector[1].push_back(RoadPiece); + // Add the road pieces: + for (int len = 19; len < 60; len += 8) + { + cBlockArea BA; + BA.Create(len, 1, 3, cBlockArea::baTypes | cBlockArea::baMetas); + BA.Fill(cBlockArea::baTypes | cBlockArea::baMetas, E_BLOCK_GRAVEL, 0); + cPrefab * RoadPiece = new cPrefab(BA, 1); + RoadPiece->AddConnector(0, 0, 1, BLOCK_FACE_XM, -2); + RoadPiece->AddConnector(len - 1, 0, 1, BLOCK_FACE_XP, -2); + + // Add the road connectors: + for (int x = 1; x < len; x += 8) + { + RoadPiece->AddConnector(x, 0, 0, BLOCK_FACE_ZM, 2); + RoadPiece->AddConnector(x, 0, 2, BLOCK_FACE_ZP, 2); + } + + // Add the buildings connectors: + for (int x = 5; x < len; x += 8) + { + RoadPiece->AddConnector(x, 0, 0, BLOCK_FACE_ZM, 1); + RoadPiece->AddConnector(x, 0, 2, BLOCK_FACE_ZP, 1); + } + m_AllPieces.push_back(RoadPiece); + m_PiecesByConnector[-2].push_back(RoadPiece); + m_PiecesByConnector[1].push_back(RoadPiece); + m_PiecesByConnector[2].push_back(RoadPiece); + } // for len - roads of varying length } // cPrefabPiecePool overrides: virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override { - // Only roads are allowed to connect to the well: - if ((a_PlacedPiece.GetDepth() == 0) && (a_NewPiece.GetSize().y != 1)) - { - return 0; - } - - // Roads cannot branch T-wise: - if ( - (a_PlacedPiece.GetPiece().GetSize().y == 1) && // Connecting to a road - ( - (a_ExistingConnector.m_Direction == BLOCK_FACE_ZP) || - (a_ExistingConnector.m_Direction == BLOCK_FACE_ZM) - ) && // Through the long-edge connector - (a_NewPiece.GetSize().y == 1) // And the new piece is a road - ) + // Roads cannot branch T-wise (appending -2 connector to a +2 connector): + if ((a_ExistingConnector.m_Type == 2) && (a_PlacedPiece.GetDepth() > 0)) { return 0; } -- cgit v1.2.3 From 7004043c6164c6b22346f94489cb823f9495738f Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 17 May 2014 21:54:04 +0200 Subject: Village houses are height-adjusted onto the terrain. --- src/Generating/VillageGen.cpp | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index b514a90cd..db81fb521 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -115,7 +115,9 @@ public: m_HeightGen(a_HeightGen) { cBFSPieceGenerator pg(m_Prefabs, a_Seed); - pg.PlacePieces(a_OriginX, 10, a_OriginZ, a_MaxRoadDepth + 1, m_Pieces); + // Generate the pieces at very negative Y coords, so that we can later test + // Piece has negative Y coord -> hasn't been height-adjusted yet + pg.PlacePieces(a_OriginX, -1000, a_OriginZ, a_MaxRoadDepth + 1, m_Pieces); } protected: @@ -144,16 +146,45 @@ protected: // cGrdStructGen::cStructure overrides: virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override { - // TODO // Iterate over all items - // Each intersecting prefab is placed on ground (if not already placed), then drawn + // Each intersecting prefab is placed on ground, then drawn // Each intersecting road is drawn by replacing top soil blocks with gravel / sandstone blocks - for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr) + cChunkDef::HeightMap HeightMap; // Heightmap for this chunk, used by roads + m_HeightGen.GenHeightMap(a_Chunk.GetChunkX(), a_Chunk.GetChunkZ(), HeightMap); + for (cPlacedPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr) { - const cPrefab & Prefab = (const cPrefab &)((*itr)->GetPiece()); + cPrefab & Prefab = (cPrefab &)((*itr)->GetPiece()); + if ((*itr)->GetPiece().GetSize().y == 1) + { + // It's a road, special handling (change top terrain blocks + // TODO + Prefab.Draw(a_Chunk, (*itr)->GetCoords() + Vector3i(0, 1100, 0), (*itr)->GetNumCCWRotations()); + continue; + } + if ((*itr)->GetCoords().y < 0) + { + PlacePieceOnGround(**itr); + } Prefab.Draw(a_Chunk, *itr); } // for itr - m_PlacedPieces[] } + + + /** Adjusts the Y coord of the given piece so that the piece is on the ground. + Ground level is assumed to be represented by the first connector in the piece. */ + void PlacePieceOnGround(cPlacedPiece & a_Piece) + { + cPiece::cConnector FirstConnector = a_Piece.GetRotatedConnector(0); + int ChunkX, ChunkZ; + int BlockX = FirstConnector.m_Pos.x; + int BlockZ = FirstConnector.m_Pos.z; + int BlockY; + cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ); + cChunkDef::HeightMap HeightMap; + m_HeightGen.GenHeightMap(ChunkX, ChunkZ, HeightMap); + int TerrainHeight = cChunkDef::GetHeight(HeightMap, BlockX, BlockZ); + a_Piece.GetCoords().y += TerrainHeight - FirstConnector.m_Pos.y + 1; + } } ; -- cgit v1.2.3 From a7e52e51dc3665ac2c2f27ed52e732ef7bbad32e Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 17 May 2014 22:26:09 +0200 Subject: Village roads are drawn properly. --- src/Generating/VillageGen.cpp | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index db81fb521..520d63029 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -104,7 +104,8 @@ public: int a_MaxRoadDepth, int a_MaxSize, cPrefabPiecePool & a_Prefabs, - cTerrainHeightGen & a_HeightGen + cTerrainHeightGen & a_HeightGen, + BLOCKTYPE a_RoadBlock ) : super(a_OriginX, a_OriginZ), m_Seed(a_Seed), @@ -112,7 +113,8 @@ public: m_MaxSize(a_MaxSize), m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, 255, a_OriginZ + a_MaxSize), m_Prefabs(a_Prefabs), - m_HeightGen(a_HeightGen) + m_HeightGen(a_HeightGen), + m_RoadBlock(a_RoadBlock) { cBFSPieceGenerator pg(m_Prefabs, a_Seed); // Generate the pieces at very negative Y coords, so that we can later test @@ -142,6 +144,9 @@ protected: /** The village pieces, placed by the generator. */ cPlacedPieces m_Pieces; + /** The block to use for the roads. */ + BLOCKTYPE m_RoadBlock; + // cGrdStructGen::cStructure overrides: virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override @@ -156,9 +161,8 @@ protected: cPrefab & Prefab = (cPrefab &)((*itr)->GetPiece()); if ((*itr)->GetPiece().GetSize().y == 1) { - // It's a road, special handling (change top terrain blocks - // TODO - Prefab.Draw(a_Chunk, (*itr)->GetCoords() + Vector3i(0, 1100, 0), (*itr)->GetNumCCWRotations()); + // It's a road, special handling (change top terrain blocks to m_RoadBlock) + DrawRoad(a_Chunk, **itr, HeightMap); continue; } if ((*itr)->GetCoords().y < 0) @@ -185,6 +189,27 @@ protected: int TerrainHeight = cChunkDef::GetHeight(HeightMap, BlockX, BlockZ); a_Piece.GetCoords().y += TerrainHeight - FirstConnector.m_Pos.y + 1; } + + + /** Draws the road into the chunk. + The heightmap is not queried from the heightgen, but is given via parameter, so that it may be queried just + once for all roads in a chunk. */ + void DrawRoad(cChunkDesc & a_Chunk, cPlacedPiece & a_Road, cChunkDef::HeightMap & a_HeightMap) + { + cCuboid RoadCoords = a_Road.GetHitBox(); + RoadCoords.Sort(); + int MinX = std::max(RoadCoords.p1.x - a_Chunk.GetChunkX() * cChunkDef::Width, 0); + int MaxX = std::min(RoadCoords.p2.x - a_Chunk.GetChunkX() * cChunkDef::Width, cChunkDef::Width - 1); + int MinZ = std::max(RoadCoords.p1.z - a_Chunk.GetChunkZ() * cChunkDef::Width, 0); + int MaxZ = std::min(RoadCoords.p2.z - a_Chunk.GetChunkZ() * cChunkDef::Width, cChunkDef::Width - 1); + for (int z = MinZ; z <= MaxZ; z++) + { + for (int x = MinX; x <= MaxX; x++) + { + a_Chunk.SetBlockType(x, cChunkDef::GetHeight(a_HeightMap, x, z), z, m_RoadBlock); + } + } + } } ; @@ -228,6 +253,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ // Check if all the biomes are village-friendly: // If just one is not, no village is created, because it's likely that an unfriendly biome is too close cVillagePiecePool * VillagePrefabs = NULL; + BLOCKTYPE RoadBlock = E_BLOCK_GRAVEL; for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++) { switch (Biomes[i]) @@ -237,6 +263,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ { // These biomes allow sand villages VillagePrefabs = &g_SandVillage; + RoadBlock = E_BLOCK_SANDSTONE; break; } case biPlains: @@ -261,7 +288,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ { return cStructurePtr(); } - return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, *VillagePrefabs, m_HeightGen)); + return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, *VillagePrefabs, m_HeightGen, RoadBlock)); } -- cgit v1.2.3 From efcae77828d52680f9521793520ffc4325b465b8 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 21 May 2014 23:16:43 +0200 Subject: Added second kind of desert village (FlatRoof). --- src/Generating/VillageGen.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index 520d63029..862aa966f 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -7,6 +7,7 @@ #include "VillageGen.h" #include "Prefabs/PlainsVillagePrefabs.h" #include "Prefabs/SandVillagePrefabs.h" +#include "Prefabs/SandFlatRoofVillagePrefabs.h" #include "PieceGenerator.h" @@ -25,8 +26,8 @@ the roads and houses are then used as the following pieces. Only the houses are though, the roads are generated by code and their content is ignored. A special subclass of the cPiecePool class is used, so that the roads connect to each other and to the well only in predefined manners. -The well has connectors of type "1". The houses have connectors of type "-1". The roads have connectors of -both types, type "-1" at the far ends and type "1" on the long edges. +The well has connectors of type "2". The houses have connectors of type "-1". The roads have connectors of +both types' opposites, type "-2" at the far ends and type "1" on the long edges. When the village is about to be drawn into a chunk, it queries the heights for each piece intersecting the chunk. The pieces are shifted so that their pivot points lie on the surface, and the roads are drawn @@ -220,7 +221,10 @@ protected: // cVillageGen: /** The prefabs for the sand village. */ -static cVillagePiecePool g_SandVillage (g_SandVillagePrefabs, g_SandVillagePrefabsCount, g_SandVillageStartingPrefabs, g_SandVillageStartingPrefabsCount); +static cVillagePiecePool g_SandVillage(g_SandVillagePrefabs, g_SandVillagePrefabsCount, g_SandVillageStartingPrefabs, g_SandVillageStartingPrefabsCount); + +/** The prefabs for the flat-roofed sand village. */ +static cVillagePiecePool g_SandFlatRoofVillage(g_SandFlatRoofVillagePrefabs, g_SandFlatRoofVillagePrefabsCount, g_SandFlatRoofVillageStartingPrefabs, g_SandFlatRoofVillageStartingPrefabsCount); /** The prefabs for the plains village. */ static cVillagePiecePool g_PlainsVillage(g_PlainsVillagePrefabs, g_PlainsVillagePrefabsCount, g_PlainsVillageStartingPrefabs, g_PlainsVillageStartingPrefabsCount); @@ -254,6 +258,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ // If just one is not, no village is created, because it's likely that an unfriendly biome is too close cVillagePiecePool * VillagePrefabs = NULL; BLOCKTYPE RoadBlock = E_BLOCK_GRAVEL; + int rnd = (a_OriginX + 21 * a_OriginZ + 985) / 11; for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++) { switch (Biomes[i]) @@ -262,7 +267,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ case biDesertM: { // These biomes allow sand villages - VillagePrefabs = &g_SandVillage; + VillagePrefabs = (rnd % 2 == 0) ? &g_SandVillage : &g_SandFlatRoofVillage; RoadBlock = E_BLOCK_SANDSTONE; break; } -- cgit v1.2.3 From 85fc0dbd97bbf72ba98dfb69351d5c8fa6a8ddfd Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 21 May 2014 23:17:09 +0200 Subject: Changed desert village roads to gravel. --- src/Generating/VillageGen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index 862aa966f..a899d5837 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -268,7 +268,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ { // These biomes allow sand villages VillagePrefabs = (rnd % 2 == 0) ? &g_SandVillage : &g_SandFlatRoofVillage; - RoadBlock = E_BLOCK_SANDSTONE; + // RoadBlock = E_BLOCK_SANDSTONE; break; } case biPlains: -- cgit v1.2.3 From 6aa7df367f8db7506a8a5ab853c26e3c9fd60253 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 22 May 2014 21:47:56 +0200 Subject: Villages have min and max density setting. Also made roads use 3+9 scheme, instead of 3+5, for the house connectors. Fixes #1020. --- src/Generating/VillageGen.cpp | 92 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 12 deletions(-) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index a899d5837..bcce62af5 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -27,11 +27,16 @@ though, the roads are generated by code and their content is ignored. A special class is used, so that the roads connect to each other and to the well only in predefined manners. The well has connectors of type "2". The houses have connectors of type "-1". The roads have connectors of -both types' opposites, type "-2" at the far ends and type "1" on the long edges. +both types' opposites, type "-2" at the far ends and type "1" on the long edges. Additionally, there are +type "2" connectors along the long edges of the roads as well, so that the roads create T junctions. When the village is about to be drawn into a chunk, it queries the heights for each piece intersecting the chunk. The pieces are shifted so that their pivot points lie on the surface, and the roads are drawn directly by turning the surface blocks into gravel / sandstone. + +The village prefabs are stored in global piecepools (one pool per village type). In order to support +per-village density setting, the cVillage class itself implements the cPiecePool interface, relaying the +calls to the underlying cVillagePiecePool, after processing the density check. */ class cVillagePiecePool : @@ -46,7 +51,7 @@ public: super(a_PieceDefs, a_NumPieceDefs, a_StartingPieceDefs, a_NumStartingPieceDefs) { // Add the road pieces: - for (int len = 19; len < 60; len += 8) + for (int len = 27; len < 60; len += 12) { cBlockArea BA; BA.Create(len, 1, 3, cBlockArea::baTypes | cBlockArea::baMetas); @@ -56,14 +61,14 @@ public: RoadPiece->AddConnector(len - 1, 0, 1, BLOCK_FACE_XP, -2); // Add the road connectors: - for (int x = 1; x < len; x += 8) + for (int x = 1; x < len; x += 12) { RoadPiece->AddConnector(x, 0, 0, BLOCK_FACE_ZM, 2); RoadPiece->AddConnector(x, 0, 2, BLOCK_FACE_ZP, 2); } // Add the buildings connectors: - for (int x = 5; x < len; x += 8) + for (int x = 7; x < len; x += 12) { RoadPiece->AddConnector(x, 0, 0, BLOCK_FACE_ZM, 1); RoadPiece->AddConnector(x, 0, 2, BLOCK_FACE_ZP, 1); @@ -94,7 +99,8 @@ public: class cVillageGen::cVillage : - public cGridStructGen::cStructure + public cGridStructGen::cStructure, + protected cPiecePool { typedef cGridStructGen::cStructure super; @@ -104,7 +110,8 @@ public: int a_OriginX, int a_OriginZ, int a_MaxRoadDepth, int a_MaxSize, - cPrefabPiecePool & a_Prefabs, + int a_Density, + cPiecePool & a_Prefabs, cTerrainHeightGen & a_HeightGen, BLOCKTYPE a_RoadBlock ) : @@ -112,12 +119,13 @@ public: m_Seed(a_Seed), m_Noise(a_Seed), m_MaxSize(a_MaxSize), + m_Density(a_Density), m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, 255, a_OriginZ + a_MaxSize), m_Prefabs(a_Prefabs), m_HeightGen(a_HeightGen), m_RoadBlock(a_RoadBlock) { - cBFSPieceGenerator pg(m_Prefabs, a_Seed); + cBFSPieceGenerator pg(*this, a_Seed); // Generate the pieces at very negative Y coords, so that we can later test // Piece has negative Y coord -> hasn't been height-adjusted yet pg.PlacePieces(a_OriginX, -1000, a_OriginZ, a_MaxRoadDepth + 1, m_Pieces); @@ -133,11 +141,14 @@ protected: /** Maximum size, in X/Z blocks, of the village (radius from the origin) */ int m_MaxSize; + /** The density for this village. Used to refrain from populating all house connectors. Range [0, 100] */ + int m_Density; + /** Borders of the vilalge - no item may reach out of this cuboid. */ cCuboid m_Borders; /** Prefabs to use for buildings */ - cPrefabPiecePool & m_Prefabs; + cPiecePool & m_Prefabs; /** The underlying height generator, used for placing the structures on top of the terrain. */ cTerrainHeightGen & m_HeightGen; @@ -149,7 +160,7 @@ protected: BLOCKTYPE m_RoadBlock; - // cGrdStructGen::cStructure overrides: + // cGridStructGen::cStructure overrides: virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override { // Iterate over all items @@ -211,6 +222,49 @@ protected: } } } + + + // cPiecePool overrides: + virtual cPieces GetPiecesWithConnector(int a_ConnectorType) + { + return m_Prefabs.GetPiecesWithConnector(a_ConnectorType); + } + + virtual cPieces GetStartingPieces(void) + { + return m_Prefabs.GetStartingPieces(); + } + + virtual int GetPieceWeight( + const cPlacedPiece & a_PlacedPiece, + const cPiece::cConnector & a_ExistingConnector, + const cPiece & a_NewPiece + ) override + { + // Check against the density: + if (a_ExistingConnector.m_Type == 1) + { + const Vector3i & Coords = a_PlacedPiece.GetRotatedConnector(a_ExistingConnector).m_Pos; + int rnd = (m_Noise.IntNoise3DInt(Coords.x, Coords.y, Coords.z) / 7) % 100; + if (rnd > m_Density) + { + return 0; + } + } + + // Density check passed, relay to m_Prefabs: + return m_Prefabs.GetPieceWeight(a_PlacedPiece, a_ExistingConnector, a_NewPiece); + } + + virtual void PiecePlaced(const cPiece & a_Piece) override + { + m_Prefabs.PiecePlaced(a_Piece); + } + + virtual void Reset(void) override + { + m_Prefabs.Reset(); + } } ; @@ -233,10 +287,13 @@ static cVillagePiecePool g_PlainsVillage(g_PlainsVillagePrefabs, g_PlainsVillage -cVillageGen::cVillageGen(int a_Seed, int a_GridSize, int a_MaxDepth, int a_MaxSize, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen) : +cVillageGen::cVillageGen(int a_Seed, int a_GridSize, int a_MaxDepth, int a_MaxSize, int a_MinDensity, int a_MaxDensity, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen) : super(a_Seed, a_GridSize, a_GridSize, a_MaxSize, a_MaxSize, 100), + m_Noise(a_Seed + 1000), m_MaxDepth(a_MaxDepth), m_MaxSize(a_MaxSize), + m_MinDensity(a_MinDensity), + m_MaxDensity(a_MaxDensity), m_BiomeGen(a_BiomeGen), m_HeightGen(a_HeightGen) { @@ -258,7 +315,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ // If just one is not, no village is created, because it's likely that an unfriendly biome is too close cVillagePiecePool * VillagePrefabs = NULL; BLOCKTYPE RoadBlock = E_BLOCK_GRAVEL; - int rnd = (a_OriginX + 21 * a_OriginZ + 985) / 11; + int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 11; for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++) { switch (Biomes[i]) @@ -288,12 +345,23 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ } // switch (Biomes[i]) } // for i - Biomes[] + // Choose density for the village, random between m_MinDensity and m_MaxDensity: + int Density; + if (m_MaxDensity > m_MinDensity) + { + Density = m_MinDensity + rnd % (m_MaxDensity - m_MinDensity); + } + else + { + Density = m_MinDensity; + } + // Create a village based on the chosen prefabs: if (VillagePrefabs == NULL) { return cStructurePtr(); } - return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, *VillagePrefabs, m_HeightGen, RoadBlock)); + return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, Density, *VillagePrefabs, m_HeightGen, RoadBlock)); } -- cgit v1.2.3 From 96a22cd82c350b1205985a9b8e01f5e6c11f069a Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 24 May 2014 15:03:39 +0200 Subject: Added Japanese village prefabs. --- src/Generating/VillageGen.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index bcce62af5..62822c33b 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -5,6 +5,7 @@ #include "Globals.h" #include "VillageGen.h" +#include "Prefabs/JapaneseVillagePrefabs.h" #include "Prefabs/PlainsVillagePrefabs.h" #include "Prefabs/SandVillagePrefabs.h" #include "Prefabs/SandFlatRoofVillagePrefabs.h" @@ -59,6 +60,7 @@ public: cPrefab * RoadPiece = new cPrefab(BA, 1); RoadPiece->AddConnector(0, 0, 1, BLOCK_FACE_XM, -2); RoadPiece->AddConnector(len - 1, 0, 1, BLOCK_FACE_XP, -2); + RoadPiece->SetDefaultWeight(100); // Add the road connectors: for (int x = 1; x < len; x += 12) @@ -84,8 +86,8 @@ public: // cPrefabPiecePool overrides: virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override { - // Roads cannot branch T-wise (appending -2 connector to a +2 connector): - if ((a_ExistingConnector.m_Type == 2) && (a_PlacedPiece.GetDepth() > 0)) + // Roads cannot branch T-wise (appending -2 connector to a +2 connector on a 1-high piece): + if ((a_ExistingConnector.m_Type == 2) && (a_PlacedPiece.GetDepth() > 0) && (a_PlacedPiece.GetPiece().GetSize().y == 1)) { return 0; } @@ -283,6 +285,9 @@ static cVillagePiecePool g_SandFlatRoofVillage(g_SandFlatRoofVillagePrefabs, g_S /** The prefabs for the plains village. */ static cVillagePiecePool g_PlainsVillage(g_PlainsVillagePrefabs, g_PlainsVillagePrefabsCount, g_PlainsVillageStartingPrefabs, g_PlainsVillageStartingPrefabsCount); +/** The prefabs for the Japanese village. */ +static cVillagePiecePool g_JapaneseVillage(g_JapaneseVillagePrefabs, g_JapaneseVillagePrefabsCount, g_JapaneseVillageStartingPrefabs, g_JapaneseVillageStartingPrefabsCount); + @@ -316,6 +321,8 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ cVillagePiecePool * VillagePrefabs = NULL; BLOCKTYPE RoadBlock = E_BLOCK_GRAVEL; int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 11; + cVillagePiecePool * PlainsVillage = (rnd % 2 == 0) ? &g_PlainsVillage : &g_JapaneseVillage; + cVillagePiecePool * DesertVillage = (rnd % 2 == 0) ? &g_SandVillage : &g_SandFlatRoofVillage; for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++) { switch (Biomes[i]) @@ -324,7 +331,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ case biDesertM: { // These biomes allow sand villages - VillagePrefabs = (rnd % 2 == 0) ? &g_SandVillage : &g_SandFlatRoofVillage; + VillagePrefabs = DesertVillage; // RoadBlock = E_BLOCK_SANDSTONE; break; } @@ -334,7 +341,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ case biSunflowerPlains: { // These biomes allow plains-style villages - VillagePrefabs = &g_PlainsVillage; + VillagePrefabs = PlainsVillage; break; } default: -- cgit v1.2.3 From 1a742a2b52d32bd22cd57b4d462bee312717e010 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 25 May 2014 23:50:16 +0200 Subject: Added support for Miners' Village. The village contains both prefabs that snap to ground and prefabs that connect strictly via connectors. Fixes #1027. --- src/Generating/VillageGen.cpp | 45 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index 62822c33b..cb1f4fe0d 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -127,10 +127,23 @@ public: m_HeightGen(a_HeightGen), m_RoadBlock(a_RoadBlock) { + // Generate the pieces for this village; don't care about the Y coord: cBFSPieceGenerator pg(*this, a_Seed); - // Generate the pieces at very negative Y coords, so that we can later test - // Piece has negative Y coord -> hasn't been height-adjusted yet - pg.PlacePieces(a_OriginX, -1000, a_OriginZ, a_MaxRoadDepth + 1, m_Pieces); + pg.PlacePieces(a_OriginX, 0, a_OriginZ, a_MaxRoadDepth + 1, m_Pieces); + if (m_Pieces.empty()) + { + return; + } + + // If the central piece should be moved to ground, move it, and + // check all of its dependents and move those that are strictly connector-driven based on its new Y coord: + if (((cPrefab &)m_Pieces[0]->GetPiece()).ShouldMoveToGround()) + { + int OrigPosY = m_Pieces[0]->GetCoords().y; + PlacePieceOnGround(*m_Pieces[0]); + int NewPosY = m_Pieces[0]->GetCoords().y; + MoveAllDescendants(m_Pieces, 0, NewPosY - OrigPosY); + } } protected: @@ -179,7 +192,7 @@ protected: DrawRoad(a_Chunk, **itr, HeightMap); continue; } - if ((*itr)->GetCoords().y < 0) + if (Prefab.ShouldMoveToGround() && !(*itr)->HasBeenMovedToGround()) { PlacePieceOnGround(**itr); } @@ -201,7 +214,7 @@ protected: cChunkDef::HeightMap HeightMap; m_HeightGen.GenHeightMap(ChunkX, ChunkZ, HeightMap); int TerrainHeight = cChunkDef::GetHeight(HeightMap, BlockX, BlockZ); - a_Piece.GetCoords().y += TerrainHeight - FirstConnector.m_Pos.y + 1; + a_Piece.MoveToGroundBy(TerrainHeight - FirstConnector.m_Pos.y + 1); } @@ -232,11 +245,13 @@ protected: return m_Prefabs.GetPiecesWithConnector(a_ConnectorType); } + virtual cPieces GetStartingPieces(void) { return m_Prefabs.GetStartingPieces(); } + virtual int GetPieceWeight( const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, @@ -258,15 +273,35 @@ protected: return m_Prefabs.GetPieceWeight(a_PlacedPiece, a_ExistingConnector, a_NewPiece); } + virtual void PiecePlaced(const cPiece & a_Piece) override { m_Prefabs.PiecePlaced(a_Piece); } + virtual void Reset(void) override { m_Prefabs.Reset(); } + + + void MoveAllDescendants(cPlacedPieces & a_PlacedPieces, size_t a_Pivot, int a_HeightDifference) + { + size_t num = a_PlacedPieces.size(); + cPlacedPiece * Pivot = a_PlacedPieces[a_Pivot]; + for (size_t i = a_Pivot + 1; i < num; i++) + { + if ( + (a_PlacedPieces[i]->GetParent() == Pivot) && // It is a direct dependant of the pivot + !((const cPrefab &)a_PlacedPieces[i]->GetPiece()).ShouldMoveToGround() // It attaches strictly by connectors + ) + { + a_PlacedPieces[i]->MoveToGroundBy(a_HeightDifference); + MoveAllDescendants(a_PlacedPieces, i, a_HeightDifference); + } + } // for i - a_PlacedPieces[] + } } ; -- cgit v1.2.3 From 6b41d1a4220aa032f53b67637bbc3276272e5047 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 27 May 2014 22:08:20 +0200 Subject: Added AlchemistVillage prefabs (Thanks, KingsCraftAu). --- src/Generating/VillageGen.cpp | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index cb1f4fe0d..dfcdf6ef7 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -5,6 +5,7 @@ #include "Globals.h" #include "VillageGen.h" +#include "Prefabs/AlchemistVillagePrefabs.h" #include "Prefabs/JapaneseVillagePrefabs.h" #include "Prefabs/PlainsVillagePrefabs.h" #include "Prefabs/SandVillagePrefabs.h" @@ -274,6 +275,12 @@ protected: } + virtual int GetStartingPieceWeight(const cPiece & a_NewPiece) override + { + return m_Prefabs.GetStartingPieceWeight(a_NewPiece); + } + + virtual void PiecePlaced(const cPiece & a_Piece) override { m_Prefabs.PiecePlaced(a_Piece); @@ -311,18 +318,25 @@ protected: /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cVillageGen: -/** The prefabs for the sand village. */ static cVillagePiecePool g_SandVillage(g_SandVillagePrefabs, g_SandVillagePrefabsCount, g_SandVillageStartingPrefabs, g_SandVillageStartingPrefabsCount); - -/** The prefabs for the flat-roofed sand village. */ static cVillagePiecePool g_SandFlatRoofVillage(g_SandFlatRoofVillagePrefabs, g_SandFlatRoofVillagePrefabsCount, g_SandFlatRoofVillageStartingPrefabs, g_SandFlatRoofVillageStartingPrefabsCount); - -/** The prefabs for the plains village. */ +static cVillagePiecePool g_AlchemistVillage(g_AlchemistVillagePrefabs, g_AlchemistVillagePrefabsCount, g_AlchemistVillageStartingPrefabs, g_AlchemistVillageStartingPrefabsCount); static cVillagePiecePool g_PlainsVillage(g_PlainsVillagePrefabs, g_PlainsVillagePrefabsCount, g_PlainsVillageStartingPrefabs, g_PlainsVillageStartingPrefabsCount); - -/** The prefabs for the Japanese village. */ static cVillagePiecePool g_JapaneseVillage(g_JapaneseVillagePrefabs, g_JapaneseVillagePrefabsCount, g_JapaneseVillageStartingPrefabs, g_JapaneseVillageStartingPrefabsCount); +static cVillagePiecePool * g_DesertVillagePools[] = +{ + &g_SandVillage, + &g_SandFlatRoofVillage, + &g_AlchemistVillage, +} ; + +static cVillagePiecePool * g_PlainsVillagePools[] = +{ + &g_PlainsVillage, + &g_JapaneseVillage, +} ; + @@ -356,8 +370,8 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ cVillagePiecePool * VillagePrefabs = NULL; BLOCKTYPE RoadBlock = E_BLOCK_GRAVEL; int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 11; - cVillagePiecePool * PlainsVillage = (rnd % 2 == 0) ? &g_PlainsVillage : &g_JapaneseVillage; - cVillagePiecePool * DesertVillage = (rnd % 2 == 0) ? &g_SandVillage : &g_SandFlatRoofVillage; + cVillagePiecePool * PlainsVillage = g_PlainsVillagePools[rnd % ARRAYCOUNT(g_PlainsVillagePools)]; + cVillagePiecePool * DesertVillage = g_DesertVillagePools[rnd % ARRAYCOUNT(g_DesertVillagePools)]; for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++) { switch (Biomes[i]) -- cgit v1.2.3 From f4e9c88dcdefee2b6e4ca7f97483d4cdfba939ae Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 31 May 2014 10:33:12 +0200 Subject: Fixed a memory leak in VillagGen. --- src/Generating/VillageGen.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index dfcdf6ef7..b9cb056ad 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -147,6 +147,11 @@ public: } } + ~cVillage() + { + cPieceGenerator::FreePieces(m_Pieces); + } + protected: /** Seed for the random functions */ int m_Seed; -- cgit v1.2.3 From 7cf544079f910ac8068b67ad39178ad040816367 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Wed, 11 Jun 2014 19:12:29 +0200 Subject: Roads in villages are made out of wooden planks if they generate on water. --- src/Generating/VillageGen.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/Generating/VillageGen.cpp') diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index b9cb056ad..9917141ed 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -116,7 +116,8 @@ public: int a_Density, cPiecePool & a_Prefabs, cTerrainHeightGen & a_HeightGen, - BLOCKTYPE a_RoadBlock + BLOCKTYPE a_RoadBlock, + BLOCKTYPE a_WaterRoadBlock ) : super(a_OriginX, a_OriginZ), m_Seed(a_Seed), @@ -126,7 +127,8 @@ public: m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, 255, a_OriginZ + a_MaxSize), m_Prefabs(a_Prefabs), m_HeightGen(a_HeightGen), - m_RoadBlock(a_RoadBlock) + m_RoadBlock(a_RoadBlock), + m_WaterRoadBlock(a_WaterRoadBlock) { // Generate the pieces for this village; don't care about the Y coord: cBFSPieceGenerator pg(*this, a_Seed); @@ -179,6 +181,9 @@ protected: /** The block to use for the roads. */ BLOCKTYPE m_RoadBlock; + + /** The block used for the roads if the road is on water. */ + BLOCKTYPE m_WaterRoadBlock; // cGridStructGen::cStructure overrides: @@ -239,7 +244,14 @@ protected: { for (int x = MinX; x <= MaxX; x++) { - a_Chunk.SetBlockType(x, cChunkDef::GetHeight(a_HeightMap, x, z), z, m_RoadBlock); + if (IsBlockWater(a_Chunk.GetBlockType(x, cChunkDef::GetHeight(a_HeightMap, x, z), z))) + { + a_Chunk.SetBlockType(x, cChunkDef::GetHeight(a_HeightMap, x, z), z, m_WaterRoadBlock); + } + else + { + a_Chunk.SetBlockType(x, cChunkDef::GetHeight(a_HeightMap, x, z), z, m_RoadBlock); + } } } } @@ -374,6 +386,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ // If just one is not, no village is created, because it's likely that an unfriendly biome is too close cVillagePiecePool * VillagePrefabs = NULL; BLOCKTYPE RoadBlock = E_BLOCK_GRAVEL; + BLOCKTYPE WaterRoadBlock = E_BLOCK_PLANKS; int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 11; cVillagePiecePool * PlainsVillage = g_PlainsVillagePools[rnd % ARRAYCOUNT(g_PlainsVillagePools)]; cVillagePiecePool * DesertVillage = g_DesertVillagePools[rnd % ARRAYCOUNT(g_DesertVillagePools)]; @@ -422,7 +435,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_ { return cStructurePtr(); } - return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, Density, *VillagePrefabs, m_HeightGen, RoadBlock)); + return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, Density, *VillagePrefabs, m_HeightGen, RoadBlock, WaterRoadBlock)); } -- cgit v1.2.3