public void GeneratePollutionVertexArray(SurfaceContainer surface, Vector2 position, int xRange, int yRange, VertexArray vA) { int[] chunkIndices = SurfaceContainer.WorldToChunkCoords(position); vA.Clear(); for (int i = chunkIndices[0] - xRange; i <= chunkIndices[0] + xRange; i++) { for (int j = chunkIndices[1] - yRange; j <= chunkIndices[1] + yRange; j++) { byte val = Convert.ToByte(surface.GetInterpolatedPollution(i, j) * 255 / Props.maxPollution); Color topLeft = new Color(val, 0, 0, (byte)(val / 2)); val = Convert.ToByte(surface.GetInterpolatedPollution(i + 1, j) * 255 / Props.maxPollution); Color topRight = new Color(val, 0, 0, (byte)(val / 2)); val = Convert.ToByte(surface.GetInterpolatedPollution(i, j + 1) * 255 / Props.maxPollution); Color botLeft = new Color(val, 0, 0, (byte)(val / 2)); val = Convert.ToByte(surface.GetInterpolatedPollution(i + 1, j + 1) * 255 / Props.maxPollution); Color botRight = new Color(val, 0, 0, (byte)(val / 2)); int oX = i * Props.chunkSize; int oY = j * Props.chunkSize; vA.Append(new Vertex(new Vector2f(oX, oY), topLeft)); vA.Append(new Vertex(new Vector2f(oX + Props.chunkSize, oY), topRight)); vA.Append(new Vertex(new Vector2f(oX, oY + Props.chunkSize), botLeft)); vA.Append(new Vertex(new Vector2f(oX + Props.chunkSize, oY), topRight)); vA.Append(new Vertex(new Vector2f(oX + Props.chunkSize, oY + Props.chunkSize), botRight)); vA.Append(new Vertex(new Vector2f(oX, oY + Props.chunkSize), botLeft)); } } }
/// <summary> /// Gets minimap textures for a specified surface. The position is the centered location. The range is the number of chunks x/y away from center to get. /// </summary> /// <param name="surface"></param> /// <param name="position"></param> /// <param name="ranges"></param> public void GenerateMinimapTextures(SurfaceContainer surface, Vector2 position, int xRange, int yRange, List <VertexArray> vertexArrays) { int[] chunkIndices = SurfaceContainer.WorldToChunkCoords(position); vertexArrays.Clear(); for (int i = chunkIndices[0] - xRange; i <= chunkIndices[0] + xRange; i++) { for (int j = chunkIndices[1] - yRange; j <= chunkIndices[1] + yRange; j++) { Chunk chunk = surface.GetChunk((i * surface.worldSize) + j, false); if (chunk != null) { VertexArray vA; if (!minimapVertexArrays.TryGetValue(i * surface.worldSize + j, out vA)) { vA = tileCollection.GenerateTerrainMinimap(chunk, (i * surface.worldSize) + j, surface.worldSize); minimapVertexArrays.Add(i * surface.worldSize + j, vA); } vertexArrays.Add(vA); //next get entities //This is very dynamic so there is no point caching it List <Entity> entityList = chunk.entityList; VertexArray entityArray = new VertexArray(PrimitiveType.Triangles); int oX = i * Props.chunkSize; int oY = j * Props.chunkSize; for (int l = 0; l < entityList.Count; l++) { EntityPhysical e = entityList[l] as EntityPhysical; if (e == null) { continue; } int[] pos = surface.WorldToAbsoluteTileCoords(e.position.x, e.position.y); float halfWidth = e.tileWidth; float halfHeight = e.tileHeight; entityArray.Append(new Vertex(new Vector2f(pos[0] - halfWidth, pos[1] - halfHeight), e.mapColor)); entityArray.Append(new Vertex(new Vector2f(pos[0] + halfWidth, pos[1] - halfHeight), e.mapColor)); entityArray.Append(new Vertex(new Vector2f(pos[0] - halfWidth, pos[1] + halfHeight), e.mapColor)); entityArray.Append(new Vertex(new Vector2f(pos[0] + halfWidth, pos[1] - halfHeight), e.mapColor)); entityArray.Append(new Vertex(new Vector2f(pos[0] + halfWidth, pos[1] + halfHeight), e.mapColor)); entityArray.Append(new Vertex(new Vector2f(pos[0] - halfWidth, pos[1] + halfHeight), e.mapColor)); } if (entityArray.VertexCount > 0) { vertexArrays.Add(entityArray); } } } } }
/// <summary> /// Gets the chunks the entity is possibly present in chunk indices /// </summary> /// <param name="self"></param> /// <param name="selfPos"></param> /// <returns></returns> public static int[] GetChunkBounds(BoundingBox self, Vector2 posSelf, SurfaceContainer surface) { float xMin = posSelf.x - self.radiusApproximation - Props.tileCollisionFactor * Props.tileSize; float xMax = posSelf.x + self.radiusApproximation + Props.tileCollisionFactor * Props.tileSize; float yMin = posSelf.y - self.radiusApproximation - Props.tileCollisionFactor * Props.tileSize; float yMax = posSelf.y + self.radiusApproximation + Props.tileCollisionFactor * Props.tileSize; int[] top = surface.WorldToChunkCoords(xMin, yMin); int[] bot = surface.WorldToChunkCoords(xMax, yMax); int yRange = (bot[1] - top[1]) + 1; int xRange = (bot[0] - top[0]) + 1; int[] ret = new int[xRange * yRange]; int k = 0; for (int i = top[0]; i <= bot[0]; i++) { for (int j = top[1]; j <= bot[1]; j++) { ret[k] = i * surface.worldSize + j; k++; } } return(ret); #region more complex chunk bound code /*if(self.rotation == 0) * { * int[] top = SurfaceContainer.WorldToChunkCoords(selfPos.x + self.topLeftR.x, selfPos.y + self.topLeftR.y); * int[] bot = SurfaceContainer.WorldToChunkCoords(selfPos.x + self.botLeftR.y, selfPos.y + self.botLeftR.y); * int yRange = (bot[1] - top[1]); * int xRange = (bot[0] - top[0]); * int[] ret = new int[xRange * yRange]; * int k = 0; * for(int i = top[0]; i <= bot[0]; i++) * { * for(int j = top[1]; j <= bot[1]; j++) * { * ret[k] = i * Props.worldSize + j; * k++; * } * } * return ret; * } * int[][] coords = new int[4][]; * coords[0] = SurfaceContainer.WorldToChunkCoords(selfPos.VAdd(self.topLeftR)); * coords[1] = SurfaceContainer.WorldToChunkCoords(selfPos.VAdd(self.topRightR)); * coords[2] = SurfaceContainer.WorldToChunkCoords(selfPos.VAdd(self.botLeftR)); * coords[3] = SurfaceContainer.WorldToChunkCoords(selfPos.VAdd(self.botRightR)); * int[] min = new int[] { coords[0][0], coords[0][1] }; * int[] max = new int[] { coords[3][0], coords[3][1] }; * for (int i = 0; i < 4; i++) * { * if(coords[i][0] <= min[0]) * { * min[0] = coords[i][0]; * } * if(coords[i][0] >= max[0]) * { * max[0] = coords[i][0]; * } * if(coords[i][1] <= min[1]) * { * min[1] = coords[i][1]; * } * if(coords[i][1] >= max[1]) * { * max[1] = coords[i][1]; * } * }*/ #endregion more complex chunk bound code }
public void RenderWorld(RenderWindow window, Camera camera, SurfaceContainer surface) { window.SetView(camera.GetGameView()); //Set view Vector2f origin = window.MapPixelToCoords(new Vector2i(0, 0), camera.GetGameView()); Vector2f extent = window.MapPixelToCoords(new Vector2i((int)window.Size.X, (int)window.Size.Y), camera.GetGameView()); int[] begPos = surface.WorldToChunkCoords(origin.X, origin.Y); int[] endPos = surface.WorldToChunkCoords(extent.X, extent.Y); windowBox = new BoundingBox(0, 0, extent.X - origin.X, extent.Y - origin.Y); #region terrain drawing for (int i = begPos[0]; i <= endPos[0]; i++) { for (int j = begPos[1]; j <= endPos[1]; j++) { int key = (i) * surface.worldSize + j; if (terrainVertexArrays.TryGetValue(key, out _) == false) { terrainVertexArrays.Add(key, tileCollection.GenerateTerrainVertices(surface, new int[] { i, j })); } VertexArray[] vArr; if (terrainVertexArrays.TryGetValue(key, out vArr)) { for (int k = 0; k < vArr.Length; k++) { window.Draw(vArr[k], terrainRenderStates[k]); } } } } #endregion terrain drawing #region entity drawing renderedEntityCount = 0; renderedSpriteCount = 0; for (int i = begPos[0]; i <= endPos[0] + 1; i++) { for (int j = begPos[1]; j <= endPos[1] + 1; j++) { Chunk chunk = surface.GetChunk(i, j); if (chunk == null) { continue; } List <Entity> entityList = chunk.entityList; for (int k = 0; k < entityList.Count; k++) { if (entityList[k].drawArray != null && BoundingBox.CheckCollision(windowBox, entityList[k].drawingBox, new Vector2(origin), entityList[k].position)) { drawList.Add(entityList[k]); } } } } drawList.Sort(delegate(Entity a, Entity b) { int ydiff = a.position.y.CompareTo(b.position.y); if (ydiff != 0) { return(ydiff); } else { return(a.position.x.CompareTo(b.position.x)); } }); for (int i = 0; i < entityBatch.Length; i++) { entityBatch[i].Initialize(camera.GetGameView(), Color.Transparent); } foreach (Entity e in drawList) { renderedEntityCount++; for (int i = 0; i < e.drawArray.Length; i++) { if (e.drawArray[i].drawLayer != Drawable.DrawLayer.None) { e.drawArray[i].Draw(entityBatch[(int)e.drawArray[i].drawLayer - 1], e.position.internalVector); renderedSpriteCount++; } } } window.SetView(camera.GetGUIView()); for (int i = 0; i < entityBatch.Length; i++) { Sprite sprite = entityBatch[i].Finalize(); window.Draw(sprite); } window.SetView(camera.GetGameView()); drawList.Clear(); #endregion entity drawing #region lighting drawing lightingBatch.Initialize(camera.GetGameView(), new Color(0, 0, 0, surface.GetDarkness())); for (int i = begPos[0]; i <= endPos[0]; i++) { for (int j = begPos[1]; j <= endPos[1]; j++) { Chunk chunk = surface.GetChunk(i, j); List <LightSource> lightSources = chunk.lightSources; for (int k = 0; k < lightSources.Count; k++) { if (lightSources[k].on == true) { lightSources[k].Draw(lightingBatch); } } } } Sprite lightingSprite = lightingBatch.Finalize(); window.SetView(camera.GetGUIView()); window.Draw(lightingSprite); window.SetView(camera.GetGameView()); #endregion #region bounding box drawing if (drawBoundingBoxes == true) { for (int i = begPos[0]; i <= endPos[0]; i++) { for (int j = begPos[1]; j <= endPos[1]; j++) { Chunk chunk = surface.GetChunk(i, j); #region Tile bounding box drawing int chunkIndex = i * surface.worldSize + j; float[] pointsTile = surface.tileBox.GetPoints(); VertexArray vA; if (!tileBoundingBoxVertexArray.TryGetValue(chunkIndex, out vA)) { vA = tileCollection.GenerateTerrainBoundingBoxArray(surface, chunk, chunkIndex, pointsTile); tileBoundingBoxVertexArray.Add(chunkIndex, vA); } window.Draw(vA); #endregion Tile bounding box drawing #region Entity bounding box drawing List <Entity> entityList = chunk.entityList; for (int k = 0; k < entityList.Count; k++) { float[] pointsEntity = entityList[k].collisionBox.GetPoints(); float[] drawingPointsEntity = entityList[k].drawingBox.GetPoints(); Vector2 position = entityList[k].position; for (int l = 0; l < pointsEntity.Length; l += 2) { entityBoundingBoxArray.Append(new Vertex(new Vector2f(pointsEntity[l] + position.x, pointsEntity[l + 1] + position.y), Color.Red)); entityBoundingBoxArray.Append(new Vertex(new Vector2f(pointsEntity[(l + 2) % 8] + position.x, pointsEntity[(l + 3) % 8] + position.y), Color.Red)); } for (int l = 0; l < drawingPointsEntity.Length; l += 2) { drawingBoundingBoxArray.Append(new Vertex(new Vector2f(drawingPointsEntity[l] + position.x, drawingPointsEntity[l + 1] + position.y), Color.Blue)); drawingBoundingBoxArray.Append(new Vertex(new Vector2f(drawingPointsEntity[(l + 2) % 8] + position.x, drawingPointsEntity[(l + 3) % 8] + position.y), Color.Blue)); } } #endregion Entity bounding box drawing } } window.Draw(entityBoundingBoxArray); window.Draw(drawingBoundingBoxArray); entityBoundingBoxArray.Clear(); drawingBoundingBoxArray.Clear(); VertexArray windowBoxArray = new VertexArray(PrimitiveType.Lines); float[] pointsWindow = windowBox.GetPoints(); for (int l = 0; l < pointsWindow.Length; l += 2) { windowBoxArray.Append(new Vertex(new Vector2f(pointsWindow[l] + origin.X, pointsWindow[l + 1] + origin.Y), Color.Magenta)); windowBoxArray.Append(new Vertex(new Vector2f(pointsWindow[(l + 2) % 8] + origin.X, pointsWindow[(l + 3) % 8] + origin.Y), Color.Magenta)); } window.Draw(windowBoxArray); windowBoxArray.Clear(); } #endregion bounding box drawing }
/// <summary> /// Culls vertex arrays that are too far away based on camera variables. /// </summary> public void CullVertexCache(Camera camera, SurfaceContainer surface) { int[] cameraChunkCoords = surface.WorldToChunkCoords(camera.GetGameView().Center.X, camera.GetGameView().Center.Y); List <int> keysToRemove = new List <int>(); foreach (int key in terrainVertexArrays.Keys) { int[] chunkIndices = surface.ChunkIndexToChunkCoords(key); if (Math.Abs(chunkIndices[0] - cameraChunkCoords[0]) > Props.vertexArrayCullingDistance || Math.Abs(chunkIndices[1] - cameraChunkCoords[1]) > Props.vertexArrayCullingDistance) { keysToRemove.Add(key); } } foreach (int key in keysToRemove) { VertexArray[] vA; if (terrainVertexArrays.TryGetValue(key, out vA)) { foreach (VertexArray v in vA) { v.Dispose(); } } terrainVertexArrays.Remove(key); } keysToRemove.Clear(); foreach (int key in tileBoundingBoxVertexArray.Keys) { int[] chunkIndices = surface.ChunkIndexToChunkCoords(key); if (Math.Abs(chunkIndices[0] - cameraChunkCoords[0]) > Props.vertexArrayCullingDistance || Math.Abs(chunkIndices[1] - cameraChunkCoords[1]) > Props.vertexArrayCullingDistance) { keysToRemove.Add(key); } } foreach (int key in keysToRemove) { VertexArray vA; if (tileBoundingBoxVertexArray.TryGetValue(key, out vA)) { vA.Dispose(); } tileBoundingBoxVertexArray.Remove(key); } keysToRemove.Clear(); if (cullMinimap) { foreach (int key in minimapVertexArrays.Keys) { int[] chunkIndices = surface.ChunkIndexToChunkCoords(key); if (Math.Abs(chunkIndices[0] - cameraChunkCoords[0]) > Props.vertexArrayCullingDistance || Math.Abs(chunkIndices[1] - cameraChunkCoords[1]) > Props.vertexArrayCullingDistance) { keysToRemove.Add(key); } } foreach (int key in keysToRemove) { VertexArray vA; if (minimapVertexArrays.TryGetValue(key, out vA)) { vA.Dispose(); } minimapVertexArrays.Remove(key); } } }