From 0e985293b50ec89a163f40222825b3c147135b9a Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 9 Mar 2014 22:04:29 +0100 Subject: A working POCPiece generator. --- src/Generating/POCPieceGenerator.cpp | 265 +++++++++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 src/Generating/POCPieceGenerator.cpp (limited to 'src/Generating/POCPieceGenerator.cpp') diff --git a/src/Generating/POCPieceGenerator.cpp b/src/Generating/POCPieceGenerator.cpp new file mode 100644 index 000000000..9edfcc64f --- /dev/null +++ b/src/Generating/POCPieceGenerator.cpp @@ -0,0 +1,265 @@ + +// POCPieceGenerator.cpp + +// Implements the cPOCPieceGenerator class representing a Proof-Of_Concept structure generator using the cPieceGenerator technique +// The generator generates a maze of rooms at {0, 100, 0} + +#include "Globals.h" +#include "POCPieceGenerator.h" +#include "ChunkDesc.h" + + + + + +/** POC pieces are simple boxes that have connectors in the middle of their walls. +Each wall has one connector, there are 3 connector types that get assigned semi-randomly. +The piece also knows how to imprint itself in a cChunkDesc, each piece has a different color glass +and each connector is uses a different color wool frame. */ +class cPOCPiece : + public cPiece +{ +public: + cPOCPiece(int a_Size) : + m_Size(a_Size) + { + m_Connectors.push_back(cConnector(m_Size / 2, 1, 0, 0, BLOCK_FACE_ZM)); + m_Connectors.push_back(cConnector(m_Size / 2, 1, m_Size - 1, 1, BLOCK_FACE_ZP)); + m_Connectors.push_back(cConnector(0, 1, m_Size / 2, 2, BLOCK_FACE_XM)); + m_Connectors.push_back(cConnector(m_Size - 1, 1, m_Size / 2, m_Size % 3, BLOCK_FACE_XP)); + } + + + /** Imprints the piece in the specified chunk. Assumes they intersect. */ + void ImprintInChunk(cChunkDesc & a_ChunkDesc, const Vector3i & a_Pos, int a_NumCCWRotations) + { + int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; + int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; + Vector3i Min = a_Pos; + Min.Move(-BlockX, 0, -BlockZ); + Vector3i Max = Min; + Max.Move(m_Size - 1, 2, m_Size - 1); + ASSERT(Min.x < cChunkDef::Width); + ASSERT(Min.z < cChunkDef::Width); + ASSERT(Max.x >= 0); + ASSERT(Max.z >= 0); + if (Min.x >= 0) + { + // Draw the XM wall: + a_ChunkDesc.FillRelCuboid(Min.x, Min.x, Min.y, Max.y, Min.z, Max.z, E_BLOCK_STAINED_GLASS, m_Size % 16); + } + if (Min.z >= 0) + { + // Draw the ZM wall: + a_ChunkDesc.FillRelCuboid(Min.x, Max.x, Min.y, Max.y, Min.z, Min.z, E_BLOCK_STAINED_GLASS, m_Size % 16); + } + if (Max.x < cChunkDef::Width) + { + // Draw the XP wall: + a_ChunkDesc.FillRelCuboid(Max.x, Max.x, Min.y, Max.y, Min.z, Max.z, E_BLOCK_STAINED_GLASS, m_Size % 16); + } + if (Max.z < cChunkDef::Width) + { + // Draw the ZP wall: + a_ChunkDesc.FillRelCuboid(Min.x, Max.x, Min.y, Max.y, Max.z, Max.z, E_BLOCK_STAINED_GLASS, m_Size % 16); + } + + // Draw all the connectors: + for (cConnectors::const_iterator itr = m_Connectors.begin(), end = m_Connectors.end(); itr != end; ++itr) + { + cConnector Conn = cPiece::RotateMoveConnector(*itr, a_NumCCWRotations, a_Pos.x, a_Pos.y, a_Pos.z); + Conn.m_Pos.Move(-BlockX, 0, -BlockZ); + if ( + (Conn.m_Pos.x >= 0) && (Conn.m_Pos.x < cChunkDef::Width) && + (Conn.m_Pos.z >= 0) && (Conn.m_Pos.z < cChunkDef::Width) + ) + { + a_ChunkDesc.SetBlockTypeMeta(Conn.m_Pos.x, Conn.m_Pos.y, Conn.m_Pos.z, E_BLOCK_WOOL, itr->m_Type % 16); + } + + /* + // TODO: Frame the connectors + switch (itr->m_Direction) + { + case BLOCK_FACE_XM: + case BLOCK_FACE_XP: + { + // TODO + break; + } + + case BLOCK_FACE_ZM: + case BLOCK_FACE_ZP: + { + // TODO + break; + } + } + */ + } // for itr - m_Connectors[] + } + +protected: + int m_Size; + cConnectors m_Connectors; + + // cPiece overrides: + virtual cConnectors GetConnectors(void) const override + { + return m_Connectors; + } + + virtual Vector3i GetSize(void) const override + { + return Vector3i(m_Size, 3, m_Size); + } + + virtual cCuboid GetHitBox(void) const override + { + return cCuboid(0, 0, 0, m_Size - 1, 2, m_Size - 1); + } + + virtual bool CanRotateCCW(int a_NumRotations) const override + { + return true; + } +}; + + + + + +static void DebugPieces(const cPlacedPieces & a_Pieces) +{ + size_t idx = 0; + for (cPlacedPieces::const_iterator itr = a_Pieces.begin(), end = a_Pieces.end(); itr != end; ++itr, ++idx) + { + const cCuboid & HitBox = (*itr)->GetHitBox(); + printf(" %u: %d rotations, {%d - %d, %d - %d}\n", + idx, (*itr)->GetNumCCWRotations(), + HitBox.p1.x, HitBox.p2.x, HitBox.p1.z, HitBox.p2.z + ); + } // for itr - a_Pieces[] +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cPOCPieceGenerator: + +cPOCPieceGenerator::cPOCPieceGenerator(int a_Seed) : + m_Seed(a_Seed) +{ + // Prepare a vector of available pieces: + m_AvailPieces.push_back(new cPOCPiece(5)); + m_AvailPieces.push_back(new cPOCPiece(7)); + m_AvailPieces.push_back(new cPOCPiece(9)); + + // Generate the structure: + cBFSPieceGenerator Gen(*this, a_Seed); + Gen.PlacePieces(0, 50, 0, 6, m_Pieces); + + // DebugPieces(m_Pieces); + + // Get the smallest cuboid encompassing the entire generated structure: + cCuboid Bounds(0, 50, 0, 0, 50, 0); + for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr) + { + Vector3i MinCoords = (*itr)->GetCoords(); + Bounds.Engulf(MinCoords); + Bounds.Engulf(MinCoords + (*itr)->GetPiece().GetSize()); + } // for itr - m_Pieces[] + m_Bounds = Bounds; +} + + + + + +cPOCPieceGenerator::~cPOCPieceGenerator() +{ + cPieceGenerator::FreePieces(m_Pieces); +} + + + + + +void cPOCPieceGenerator::GenFinish(cChunkDesc & a_ChunkDesc) +{ + int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; + int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; + if ( + (BlockX + 16 < m_Bounds.p1.x) || (BlockX > m_Bounds.p2.x) || // X coords out of bounds of the generated structure + (BlockZ + 16 < m_Bounds.p1.z) || (BlockZ > m_Bounds.p2.z) // Z coords out of bounds of the generated structure + ) + { + return; + } + + // Imprint each piece in the chunk: + for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr) + { + const Vector3i & Pos = (*itr)->GetCoords(); + Vector3i Size = (*itr)->GetPiece().GetSize(); + if (((*itr)->GetNumCCWRotations() % 2) == 1) + { + std::swap(Size.x, Size.z); + } + if ( + (Pos.x >= BlockX + 16) || (Pos.x + Size.x - 1 < BlockX) || + (Pos.z >= BlockZ + 16) || (Pos.z + Size.z - 1 < BlockZ) + ) + { + // This piece doesn't intersect the chunk + continue; + } + + ((cPOCPiece &)(*itr)->GetPiece()).ImprintInChunk(a_ChunkDesc, Pos, (*itr)->GetNumCCWRotations()); + } // for itr - m_Pieces[] + a_ChunkDesc.UpdateHeightmap(); +} + + + + + +cPieces cPOCPieceGenerator::GetPiecesWithConnector(int a_ConnectorType) +{ + // Each piece has each connector + return m_AvailPieces; +} + + + + + +cPieces cPOCPieceGenerator::GetStartingPieces(void) +{ + // Any piece can be a starting piece + return m_AvailPieces; +} + + + + + +void cPOCPieceGenerator::PiecePlaced(const cPiece & a_Piece) +{ + UNUSED(a_Piece); +} + + + + + +void cPOCPieceGenerator::Reset(void) +{ + // Nothing needed +} + + + + -- cgit v1.2.3