/// <summary> /// Adds an IViewer to this grid. /// </summary> /// <param name="viewerToAdd">The viewer to add.</param> public void AddViewer(IViewer viewerToAdd) { int localGridDimension = MathFunctions.RoundToInt(viewerToAdd.WorldViewRadius / mGridSpacing) * 2 + 1; VisibilityGrid localVisibilityGrid = new VisibilityGrid(0, 0, mGridSpacing, localGridDimension, localGridDimension); ViewerInformation viewerInformation = new ViewerInformation(); viewerInformation.LocalVisibilityGrid = localVisibilityGrid; if (mFogFactor > 0) { localVisibilityGrid.FogColor = FogColor; localVisibilityGrid.FogShade = FogShade; localVisibilityGrid.FogResolution = FogResolution; } int xIndex; int yIndex; mViewers.Add(viewerToAdd, viewerInformation); WorldToIndex(viewerToAdd.X, viewerToAdd.Y, out xIndex, out yIndex); int radiusAsInt = MathFunctions.RoundToInt(viewerToAdd.WorldViewRadius / mGridSpacing); if (xIndex >= radiusAsInt && yIndex >= radiusAsInt && xIndex + radiusAsInt < mNumberOfXTiles && yIndex + radiusAsInt < mNumberOfYTiles) { UpdateViewersLocalVisibilityGrid(viewerToAdd, viewerInformation); } UpdateRevealedFromViewers(); }
private void UpdateRevealedFromViewers() { MakeAllHidden(); int x; int y; int xIndex; int yIndex; int radiusAsInt; foreach (KeyValuePair <IViewer, ViewerInformation> kvp in mViewers) { IViewer viewer = kvp.Key; WorldToIndex(viewer.X, viewer.Y, out xIndex, out yIndex); radiusAsInt = MathFunctions.RoundToInt(viewer.WorldViewRadius / mGridSpacing); if (xIndex >= radiusAsInt && yIndex >= radiusAsInt && xIndex + radiusAsInt < mNumberOfXTiles && yIndex + radiusAsInt < mNumberOfYTiles) { ViewerInformation info = kvp.Value; VisibilityGrid gridToPlace = info.LocalVisibilityGrid; int xOffset = MathFunctions.RoundToInt((gridToPlace.mXSeed - mXSeed) / mGridSpacing); int yOffset = MathFunctions.RoundToInt((gridToPlace.mYSeed - mYSeed) / mGridSpacing); int fogX, fogY; Color sourceColor; Color destinationColor; for (x = 0; x < gridToPlace.mNumberOfXTiles; x++) { for (y = 0; y < gridToPlace.mNumberOfYTiles; y++) { mRevealedTiles[x + xOffset][y + yOffset] |= gridToPlace.mRevealedTiles[x][y]; if (mFogFactor > 0) { for (fogX = 0; fogX < mFogFactor; fogX++) { for (fogY = 0; fogY < mFogFactor; fogY++) { sourceColor = gridToPlace.mFogImageData.GetPixelColor(x * mFogFactor + fogX, y * mFogFactor + fogY); destinationColor = mFogImageData.GetPixelColor((x + xOffset) * mFogFactor + fogX, (y + yOffset) * mFogFactor + fogY); if (sourceColor.R > destinationColor.R) { destinationColor = sourceColor; } mFogImageData.SetPixel((x + xOffset) * mFogFactor + fogX, (y + yOffset) * mFogFactor + fogY, destinationColor); } } } } } } } if (mFogFactor > 0 && mFogTexture != null) { mFogImageData.ToTexture2D(mFogTexture); } }
/// <summary> /// Returns whether a given world position is in view of a given viewer. /// </summary> /// <param name="viewer">The viewer to check visibility for.</param> /// <param name="targetPosition">The world coordinates.</param> /// <returns>Whether in view.</returns> public bool IsPositionInDirectView(IViewer viewer, ref Vector3 targetPosition) { if (mViewers.ContainsKey(viewer)) { VisibilityGrid grid = mViewers[viewer].LocalVisibilityGrid; return(grid.IsRevealedWorld(targetPosition.X, targetPosition.Y)); } #if DEBUG else { throw new InvalidOperationException("Viewer does not exist in Visbility grid"); } #else return(false); #endif }
private void UpdateViewersLocalVisibilityGrid(IViewer viewer, ViewerInformation viewerInformation) { VisibilityGrid localGrid = viewerInformation.LocalVisibilityGrid; localGrid.MakeAllHidden(); localGrid.ClearBlockedTiles(); int viewRadius = MathFunctions.RoundToInt(viewer.WorldViewRadius / mGridSpacing); int xIndex; int yIndex; WorldToIndex(viewer.X, viewer.Y, out xIndex, out yIndex); float tileCenteredXPosition; float tileCenteredYPosition; IndexToWorld(xIndex, yIndex, out tileCenteredXPosition, out tileCenteredYPosition); viewerInformation.LastX = xIndex; viewerInformation.LastY = yIndex; localGrid.mXSeed = tileCenteredXPosition - viewer.WorldViewRadius; localGrid.mYSeed = tileCenteredYPosition - viewer.WorldViewRadius; int xOffset = MathFunctions.RoundToInt((localGrid.mXSeed - mXSeed) / mGridSpacing); int yOffset = MathFunctions.RoundToInt((localGrid.mYSeed - mYSeed) / mGridSpacing); // copy over the blocked areas to the viewer int y; int fogX, fogY; byte shadedValue; Color shadedColor; float invertedFogFactor = 1.0f; if (mFogFactor > 1) { invertedFogFactor = 1.0f / mFogFactor; } for (int x = 0; x < localGrid.mNumberOfXTiles; x++) { for (y = 0; y < localGrid.mNumberOfYTiles; y++) { localGrid.mBlockedTiles[x][y] = mBlockedTiles[x + xOffset][y + yOffset]; } } localGrid.MakeAllHidden(); localGrid.RevealCircle(viewRadius, viewRadius, viewRadius); localGrid.BleedDirectlyVisibleToWalls(); if (mFogFactor > 0) { for (int x = 0; x < localGrid.mNumberOfXTiles; x++) { for (y = 0; y < localGrid.mNumberOfYTiles; y++) { for (fogX = 0; fogX < mFogFactor; fogX++) { for (fogY = 0; fogY < mFogFactor; fogY++) { shadedColor = localGrid.mFogImageData.GetPixelColor(x * mFogFactor + fogX, y * mFogFactor + fogY); shadedValue = 0; if (localGrid.mRevealedTiles[x][y] != 0) { shadedValue = localGrid.CalculateFogColorByDistance(x + (fogX * invertedFogFactor), y + (fogY * invertedFogFactor), shadedColor.R, viewer); } else if (shadedColor.R > FogShade) { shadedValue = FogShade; } //shadedColor = Color.FromNonPremultiplied(FogColor.R, FogColor.G, FogColor.B, shadedValue); shadedColor = Color.FromNonPremultiplied(shadedValue, shadedValue, shadedValue, 255); localGrid.mFogImageData.SetPixel(x * mFogFactor + fogX, y * mFogFactor + fogY, shadedColor); } } } } } }