/************************************************************************************************ * CRMPathManager::GenerateRivers * Creates a river which intersects the main path * * inputs: * none * * return: * none * ************************************************************************************************/ void CRMPathManager::GenerateRivers () { if (mRiverBedDepth == 1) // no rivers return; mMaxDepth = mRiverDepth; mDepth = 0; int cell_x = 0; int cell_y = 0; // choose starting cell along an edge int edge = TheRandomMissionManager->GetLandScape()->irand(0, 7); switch ( edge ) { case 0: cell_x = mXNodes / 2; cell_y = 0; break; case 1: cell_x = mXNodes; cell_y = 0; break; case 2: cell_x = mXNodes; cell_y = mYNodes / 2; break; case 3: cell_x = mXNodes; cell_y = mYNodes; break; case 4: cell_x = mXNodes / 2; cell_y = mYNodes; break; case 5: cell_x = 0; cell_y = mYNodes; break; case 6: cell_x = 0; cell_y = mYNodes / 2; break; case 7: cell_x = 0; cell_y = 0; break; } ClearCells(mXNodes+1, mYNodes+1); mRiverCount = mPathCount; // visit the first cell RiverVisit(cell_x,cell_y); mRiverCount = mPathCount - mRiverCount; return; }
void CRMPathManager::RiverVisit(const int c_x, const int c_y) { // does this cell have any neighbors with all walls intact? int i,off; // look at neighbors in random order off = TheRandomMissionManager->GetLandScape()->irand(DIR_FIRST, DIR_MAX-1); ++mDepth; // track our depth of recursion for (i = DIR_FIRST; i<DIR_MAX && mDepth <= mMaxDepth; i+=2) { int d = (i + off) % DIR_MAX; if ( !Cell(c_x, c_y).Border(d) ) { // we can move this way, since no border int new_c_x = c_x + neighbor_x[d]; int new_c_y = c_y + neighbor_y[d]; if (RiverCell(new_c_x,new_c_y).Wall() == DIR_ALL) { // we have a new cell that has not been visited! int new_dir; // d is the direction relative to the current cell // new_dir is the direction relative to the next cell (N becomes S, NE becomes SW, etc...) if( d < HALF_DIR_MAX ) { new_dir = d + HALF_DIR_MAX; } else { new_dir = d - HALF_DIR_MAX; } // knock down walls RiverCell(c_x,c_y).RemoveWall(d); RiverCell(new_c_x,new_c_y).RemoveWall(new_dir); //DIR_MAX - d); // create river between cells mTerrain->CreatePath ( mPathCount++, -1, 0, mRiverPoints, GetRiverPos(c_x,c_y)[0], GetRiverPos(c_x,c_y)[1], GetRiverPos(new_c_x,new_c_y)[0], GetRiverPos(new_c_x,new_c_y)[1], mRiverMinWidth, mRiverMaxWidth, mRiverBedDepth, mRiverDeviation, mRiverBreadth ); // flatten a small spot CArea area; float flat_radius = mRiverMinWidth * fabs(TheRandomMissionManager->GetLandScape()->GetBounds()[1][0] - TheRandomMissionManager->GetLandScape()->GetBounds()[0][0]); area.Init( GetRiverPos(c_x,c_y), flat_radius, 0.0f, AT_NONE, 0, 0 ); TheRandomMissionManager->GetLandScape()->FlattenArea (&area, 255 * mRiverBedDepth, false, true, true ); // recurse RiverVisit(new_c_x, new_c_y); } } } // --mDepth; }