public EntityGhost(BoundingBox box, Vector2 position, SurfaceContainer surface) { this.position = position; this.collisionBox = box; this.collisionMask = CollisionLayer.TerrainSolid | CollisionLayer.EntityPhysical; this.surface = surface; }
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> /// Generates the entities to be placed into a chunk /// </summary> /// <param name="chunkX"></param> /// <param name="chunkY"></param> /// <param name="surface"></param> public void GenerateEntities(int chunkX, int chunkY, SurfaceContainer surface) { Vector2 chunkPos = new Vector2(chunkX * Props.chunkSize * Props.tileSize, chunkY * Props.chunkSize * Props.tileSize); for (int i = 0; i < entitiesGenerated.Count; i++) { Vector2[] poissonDiscDistribution = PoissonDiscDistribution.GetDistribution(entitiesGenerated[i].density, (chunkX * (surfaceSize / Props.chunkSize) + chunkY) + seed, 10); for (int j = 0; j < poissonDiscDistribution.Length; j++) { Vector2 curPos = poissonDiscDistribution[j].VAdd(chunkPos); int nx = (int)(curPos.x) / Props.tileSize; int ny = (int)(curPos.y) / Props.tileSize; double elevation = 0.5 * elevationNoise.GetNoise(1 * nx, 1 * ny) + 0.25 * elevationNoise.GetNoise(2 * nx, 2 * ny) + 0.25 * elevationNoise.GetNoise(4 * nx, 4 * ny); double moisture = 0.5 * moistureNoise.GetNoise(1 * nx, 1 * ny) + 0.25 * moistureNoise.GetNoise(2 * nx, 2 * ny) + 0.25 * moistureNoise.GetNoise(4 * nx, 4 * ny); double temperature = 0.5 * temperatureNoise.GetNoise(1 * nx, 1 * ny) + 0.25 * temperatureNoise.GetNoise(2 * nx, 2 * ny) + 0.25 * temperatureNoise.GetNoise(4 * nx, 4 * ny); elevation = 3 * Math.Pow(elevation, elevationFactor); moisture = 3 * Math.Pow(moisture, moistureFactor); temperature = 3 * Math.Pow(temperature, temperatureFactor); float lowestAffinity = 2; int lowestPrototype = 0; for (int k = 0; k < entitiesGenerated[i].prototypeVars.Length; k++) { float entityProb = (float)(Math.Abs(entitiesGenerated[i].elevationAffinities[k] - elevation) + Math.Abs(entitiesGenerated[i].moistureAffinities[k] - moisture) + Math.Abs(entitiesGenerated[i].temperatureAffinities[k] - temperature)); if (entityProb < lowestAffinity) { lowestAffinity = entityProb; lowestPrototype = k; } } float moistureDiff = (float)(Math.Abs(entitiesGenerated[i].moistureAffinities[lowestPrototype] - moisture)); float elevationDiff = (float)(Math.Abs(entitiesGenerated[i].elevationAffinities[lowestPrototype] - elevation)); float temperatureDiff = (float)(Math.Abs(entitiesGenerated[i].temperatureAffinities[lowestPrototype] - temperature)); if (entitiesGenerated[i].moistureRange[lowestPrototype % entitiesGenerated[i].prototypeCount] > elevationDiff && entitiesGenerated[i].temperatureRange[lowestPrototype % entitiesGenerated[i].prototypeCount] > temperatureDiff && entitiesGenerated[i].elevationRange[lowestPrototype % entitiesGenerated[i].prototypeCount] > moistureDiff) { Entity prototype = entityCollection.GetPrototype(entitiesGenerated[i].prototypeVars[lowestPrototype]); if (prototype.tileAligned) { curPos = new Vector2(curPos.x - curPos.x % 32 + 16, curPos.y - curPos.y % 32 + 16); } if (prototype != null && !BoundingBox.CheckForPlacementCollision(prototype.collisionBox, curPos, surface, entitiesGenerated[i].placementMask)) { entityCollection.InstantiatePrototype(prototype.name, curPos, surface); } } } } }
public LightSourceRadial(SurfaceContainer surface, float lightRange, Texture texture, IntRect bounds) { this.texture = texture; this.bounds = bounds; this.surface = surface; lightScale = new Vector2f(lightRange / bounds.Width, lightRange / bounds.Height); origin = new Vector2f(bounds.Width / 2, bounds.Height / 2); }
public LightSourceRadial(SurfaceContainer surface, Vector2f lightScale, Texture texture, IntRect bounds) { this.texture = texture; this.bounds = bounds; this.surface = surface; this.lightScale = lightScale; origin = new Vector2f(bounds.Width / 2, bounds.Height / 2); }
public void Update() { if (focusedEntity != null) { gameView.Center = new Vector2f(focusedEntity.position.x, focusedEntity.position.y); viewedSurface = focusedEntity.surface; Listener.Position = new Vector3f(gameView.Center.X, 0.0f, gameView.Center.Y); } }
public void CheckCullVertexCache(Camera camera, SurfaceContainer surface) { if (cullCounter > cullRate) { CullVertexCache(camera, surface); cullCounter = 0; } modifiedVertexArrays = false; }
public LightSourceDirectional(SurfaceContainer surface, Vector2f lightScale, Texture texture, IntRect bounds) { this.texture = texture; this.bounds = bounds; this.surface = surface; this.rotation = 0.0f; this.lightScale = new Vector2f(lightScale.X, lightScale.Y); this.origin = new Vector2f(bounds.Width / 2, bounds.Height); }
public LightSourceDirectional(SurfaceContainer surface, float lightRange, float lightWidth, Texture texture, IntRect bounds) { this.texture = texture; this.bounds = bounds; this.surface = surface; this.rotation = 0.0f; lightScale = new Vector2f(lightWidth / bounds.Width, lightRange / bounds.Height); origin = new Vector2f(bounds.Width / 2, bounds.Height); }
public override void InitializeEntity(Vector2 position, SurfaceContainer surface) { base.InitializeEntity(position, surface); IntRect bounds; radialLight = new LightSourceRadial(surface, 256.0f, textureAtlases.GetTexture("lightsource", out bounds), bounds); radialLight.on = true; radialLight.attachedEntity = this; directionalLight = new LightSourceDirectional(surface, 2000.0f, 1024, textureAtlases.GetTexture("directionallight", out bounds), bounds); directionalLight.on = true; directionalLight.attachedEntity = this; }
public void FinalizeGame() { //Pop all menus menuContainer.RemoveAllMenus(); player = null; camera.DetachEntity(); camera.viewedSurface = null; surfaceContainer = null; input.ClearGameSubscribers(); renderer.DetachGameWorld(); StaticSoundManager.StopAmbience(); entityUpdateSystem.ResetSystem(); }
/// <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> /// Instantiates an entity and subscribes it to updating /// </summary> /// <param name="name"></param> /// <param name="position"></param> /// <param name="surface"></param> /// <returns></returns> public Entity InstantiatePrototype(string name, Vector2 position, SurfaceContainer surface) { Entity prototype; if (entityPrototypes.TryGetValue(name, out prototype)) { Entity newEntity = prototype.Clone(); //Initialize the Entity newEntity.InitializeEntity(position, surface); //Add to update system entityUpdateSystem.AddEntity(newEntity); return(newEntity); } return(null); }
public void InitializeGame() { //Pop all menus menuContainer.RemoveAllMenus(); //Game systems intialization surfaceContainer = new SurfaceContainer(tileCollection, surfaceGenerator); renderer.InitializeForGame(tileCollection); #region test entities surfaceContainer.GenerateStartingArea(); player = entityCollection.InstantiatePrototype("player", surfaceContainer.spawnPoint, surfaceContainer); IInputSubscriber playerSubscriber = player as IInputSubscriber; if (playerSubscriber != null) { playerSubscriber.SubscribeToInput(input); } #endregion //Attaching the camera to something! camera.SetFocusedEntity(player, menuFactory); this.SubscribeToInput(input); renderer.SubscribeToInput(input); }
/// <summary> /// Generates the bounding box vertex array for a terrain using the map colors of the tile. /// </summary> /// <param name="chunk"></param> /// <param name="chunkIndex"></param> /// <param name="pointsTile"></param> /// <returns></returns> public VertexArray GenerateTerrainBoundingBoxArray(SurfaceContainer surface, Chunk chunk, int chunkIndex, float[] pointsTile) { VertexArray vertexArray = new VertexArray(PrimitiveType.Lines); for (int k = 0; k < Props.chunkSize; k++) { for (int l = 0; l < Props.chunkSize; l++) { Tile tile = GetTerrainTile(chunk.GetTile(k, l)); if ((tile.collisionMask & Base.CollisionLayer.TerrainSolid) != 0) { Vector2 position = surface.WorldToTileVector(chunkIndex, k * Props.chunkSize + l); for (int x = 0; x < pointsTile.Length; x += 2) { vertexArray.Append(new Vertex(new Vector2f(pointsTile[x] + position.x, pointsTile[x + 1] + position.y), tile.mapColor)); vertexArray.Append(new Vertex(new Vector2f(pointsTile[(x + 2) % 8] + position.x, pointsTile[(x + 3) % 8] + position.y), tile.mapColor)); } } } } return(vertexArray); }
/// <summary> /// Gets the tiles the entity could possibly occupy in tile indices /// </summary> /// <param name="self"></param> /// <param name="posSelf"></param> /// <returns></returns> public static int[][] GetTileBounds(BoundingBox self, Vector2 posSelf) { 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 = SurfaceContainer.WorldToTileCoords(xMin, yMin); int[] bot = SurfaceContainer.WorldToTileCoords(xMax, yMax); int yRange = (bot[1] - top[1]) + 1; int xRange = (bot[0] - top[0]) + 1; int[][] ret = new int[xRange * yRange][]; int x = 0; for (int i = top[0]; i <= bot[0]; i++) { for (int j = top[1]; j <= bot[1]; j++) { int tileXmin = i == top[0] ? top[2] : 0; int tileXmax = i == bot[0] ? bot[2] + 1 : Props.chunkSize; int tileYmin = j == top[1] ? top[3] : 0; int tileYmax = j == bot[1] ? bot[3] + 1 : Props.chunkSize; ret[x] = new int[(tileXmax - tileXmin) * (tileYmax - tileYmin)]; int y = 0; for (int k = tileXmin; k < tileXmax; k++) { for (int l = tileYmin; l < tileYmax; l++) { ret[x][y] = k * Props.chunkSize + l; y++; } } x++; } } return(ret); }
public void GenerateEntities(int x, int y, SurfaceGenerator surfaceGenerator, SurfaceContainer surface) { surfaceGenerator.GenerateEntities(x, y, surface); }
public static List <TypeToTest> CheckSelectionOfType <TypeToTest>(Vector2 position, BoundingBox collisionBox, SurfaceContainer surface) where TypeToTest : Entity { //lists to keep track of collided entities List <TypeToTest> list = new List <TypeToTest>(); //list of chunks where collisions may have happened + tiles int[] chunkList = BoundingBox.GetChunkBounds(collisionBox, position, surface); int[][] tileList = BoundingBox.GetTileBounds(collisionBox, position); for (int i = 0; i < chunkList.Length; i++) { Chunk chunk = surface.GetChunk(chunkList[i], false); if (chunk == null) { continue; } //entity collision checks List <Entity> collisionList = chunk.entityCollisionList; for (int j = 0; j < collisionList.Count; j++) { TypeToTest checkEntity = collisionList[j] as TypeToTest; if (checkEntity != null && BoundingBox.CheckCollision(collisionBox, checkEntity.selectionBox, position, collisionList[j].position)) { list.Add(checkEntity); } } } return(list); }
public static bool CheckForPlacementCollision(BoundingBox collisionBox, Vector2 position, SurfaceContainer surface, Base.CollisionLayer collisionMask) { int[] chunkList = BoundingBox.GetChunkBounds(collisionBox, position, surface); int[][] tileList = BoundingBox.GetTileBounds(collisionBox, position); for (int i = 0; i < chunkList.Length; i++) { Chunk chunk = surface.GetChunk(chunkList[i], false); if (chunk == null) { continue; } //entity collision checks List <Entity> collisionList = chunk.entityCollisionList; for (int j = 0; j < collisionList.Count; j++) { if ((collisionList[j].collisionMask & collisionMask) != 0) { if (BoundingBox.CheckCollision(collisionBox, collisionList[j].collisionBox, position, collisionList[j].position)) { return(true); } } } //tile collision checks //Perhaps switch to continually checking whether the player is colliding with a tile at his position until he isnt colliding with a tile? //Would fix the situation where getting stuck in water still allows movement within //TODO: try solution outline above for (int j = 0; j < tileList[i].Length; j++) { Tile tile = surface.tileCollection.GetTerrainTile(chunk.GetTile(tileList[i][j])); if ((collisionMask & tile.collisionMask) != 0) { Vector2 tilePos = surface.WorldToTileVector(chunkList[i], tileList[i][j]); if (BoundingBox.CheckCollision(collisionBox, surface.tileBox, position, tilePos)) { return(true); } } } } return(false); }
/// <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 }
/// <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); } } }
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 }
public VertexArray[] GenerateTerrainVertices(SurfaceContainer surface, int[] pos) { VertexArray[] terrainVertexArray = new VertexArray[terrainTiles.Count]; terrainVertexArray[0] = GenerateCliffVertices(surface, pos); for (int curType = 1; curType < terrainTiles.Count; curType++) { Tile tile = terrainTiles[curType]; terrainVertexArray[curType] = new VertexArray(PrimitiveType.Triangles); int[] cXY = new int[] { pos[0] * Props.chunkSize, pos[1] * Props.chunkSize }; for (int i = 0; i < Props.chunkSize; i++) { for (int j = 0; j < Props.chunkSize; j++) { //the current tile in the loop byte currentTile = surface.GetTileFromWorldInt(pos, i, j); if (currentTile > curType) { continue; } //hash algo int variantX = i * 266489917 + 374761393; variantX = (variantX << 17) | (variantX >> 15); variantX += j * 266489917; variantX *= 668265263; variantX ^= variantX >> 15; variantX *= 246822519; variantX = Math.Abs(variantX); //origin that vertices will be defined relative to int oX = (cXY[0] + i) * Props.tileSize; int oY = (cXY[1] + j) * Props.tileSize; #region Regular tile variant determination if (currentTile == curType) { int variantRegular = variantX % 8; //Append regular tile variation AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 0, variantRegular, tile.shade, tile.textureRect); continue; } #endregion int value = 0; int variant = variantX % 6; //variant is determine by whether the transition is into an impassable tile if (currentTile != 0 && impassableTileTypes.Contains(currentTile)) { variant += 6; } value += (surface.GetTileFromWorldInt(pos, i - 1, j - 1) == curType) ? 1 : 0; //top left value += (surface.GetTileFromWorldInt(pos, i, j - 1) == curType) ? 2 : 0; //top center value += (surface.GetTileFromWorldInt(pos, i + 1, j - 1) == curType) ? 4 : 0; //top right value += (surface.GetTileFromWorldInt(pos, i - 1, j) == curType) ? 8 : 0; //left value += (surface.GetTileFromWorldInt(pos, i + 1, j) == curType) ? 16 : 0; //right value += (surface.GetTileFromWorldInt(pos, i - 1, j + 1) == curType) ? 32 : 0; //bottom left value += (surface.GetTileFromWorldInt(pos, i, j + 1) == curType) ? 64 : 0; //bottom center value += (surface.GetTileFromWorldInt(pos, i + 1, j + 1) == curType) ? 128 : 0; //bottom right if (value == 0) { continue; //no surrounding tiles of tiletype } if (((value & 24) + (value & 2)) == 2) { //top fade AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 2, variant, tile.shade, tile.textureRect); } if (((value & 24) + (value & 64)) == 64) { //bottom fade AppendQuadVertices(terrainVertexArray[curType], oX, oY, 12, 2, variant, tile.shade, tile.textureRect); } if (((value & 66) + (value & 8)) == 8) { //left fade AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 3, variant, tile.shade, tile.textureRect); } if (((value & 66) + (value & 16)) == 16) { //right fade AppendQuadVertices(terrainVertexArray[curType], oX, oY, 12, 3, variant, tile.shade, tile.textureRect); } if ((value & 10) == 10) { //inside corner topleft AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 4, variant, tile.shade, tile.textureRect); } else if (((value & 1) + (value & 10)) == 1) { //outside corner topleft AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 6, variant, tile.shade, tile.textureRect); } if ((value & 18) == 18) { //inside corner topright AppendQuadVertices(terrainVertexArray[curType], oX, oY, 12, 4, variant, tile.shade, tile.textureRect); } else if (((value & 4) + (value & 18)) == 4) { //outside corner topright AppendQuadVertices(terrainVertexArray[curType], oX, oY, 12, 6, variant, tile.shade, tile.textureRect); } if ((value & 72) == 72) { //inside corner bottomleft AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 5, variant, tile.shade, tile.textureRect); } else if (((value & 32) + (value & 72)) == 32) { //outside corner bottomleft AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 7, variant, tile.shade, tile.textureRect); } if ((value & 80) == 80) { //inside corner bottomright AppendQuadVertices(terrainVertexArray[curType], oX, oY, 12, 5, variant, tile.shade, tile.textureRect); } else if (((value & 128) + (value & 80)) == 128) { //outside corner bottomright AppendQuadVertices(terrainVertexArray[curType], oX, oY, 12, 7, variant, tile.shade, tile.textureRect); } } } } return(terrainVertexArray); }
public PathNode GetPath(SurfaceContainer surface, Vector2 start, Vector2 target, int pathTimeout, Base.CollisionLayer unwalkableMask, Base.CollisionLayer collisionMask, float frictionFactor) { this.frictionFactor = frictionFactor; int frictionMask = (int)(collisionMask & Base.CollisionLayer.Terrain); //a nonzero value means the pathcost is higher for lower frictions frictionMask = frictionMask / (1 + frictionMask); //Normalize the frictionmask to 0 or 1 using +1 trick int[] startCoords = surface.WorldToAbsoluteTileCoords(start.x, start.y); int[] endCoords = surface.WorldToAbsoluteTileCoords(target.x, target.y); float heuristic = CalculateHeuristic(startCoords, endCoords); PathNode startNode = new PathNode(null, 0, 0, heuristic, startCoords); List <PathNode> openList = new List <PathNode>(); List <PathNode> closedList = new List <PathNode>(); PathNode endNode = null; openList.Add(startNode); while (openList.Count > 0 && pathTimeout > 0) { pathTimeout--; PathNode curNode = null; int removeIndex = 0; for (int i = 0; i < openList.Count; i++) { if (curNode == null || openList[i].cost < curNode.cost) { removeIndex = i; curNode = openList[i]; } } openList.RemoveAt(removeIndex); closedList.Add(curNode); if (pathTimeout == 0 || (curNode.coords[0] == endCoords[0] && curNode.coords[1] == endCoords[1])) { endNode = curNode; break; } for (int i = curNode.coords[0] - 1; i <= curNode.coords[0] + 1; i++) { for (int j = curNode.coords[1] - 1; j <= curNode.coords[1] + 1; j++) { bool ignore = false; if (i < 0 || j < 0) //Check if coords are outside worldSize { ignore = true; } if (ignore == false) //else check that coords are not already in closedList { for (int k = 0; k < closedList.Count; k++) { if (closedList[k].coords[0] == i && closedList[k].coords[1] == j) { ignore = true; break; } } } if (ignore == false) //else check that coords are not already in openList { for (int k = 0; k < openList.Count; k++) { if (openList[k].coords[0] == i && openList[k].coords[1] == j) { ignore = true; break; } } } if (!ignore) //if neither of the preceding conditiosn set ignore to false, add tile to open list on path search { Tile tile = tileCollection.GetTerrainTile(surface.GetTileFromWorldInt(i, j)); int solidMask = (int)((unwalkableMask & collisionMask) & tile.collisionMask); // a zero value when the tile is walkable if (solidMask == 0) { int[] coords = new int[] { i, j }; PathNode newNode = new PathNode(curNode, frictionMask * (frictionFactor * (1 / tile.frictionModifier)), curNode.begin + 1, CalculateHeuristic(coords, endCoords), coords); openList.Add(newNode); } } } } } return(endNode); }
private VertexArray GenerateCliffVertices(SurfaceContainer surface, int[] pos) { VertexArray vA = new VertexArray(PrimitiveType.Triangles); int[] cXY = new int[] { pos[0] * Props.chunkSize, pos[1] * Props.chunkSize }; for (int i = 0; i < Props.chunkSize; i++) { for (int j = 0; j < Props.chunkSize; j++) { //the current tile in the loop byte currentTile = surface.GetTileFromWorldInt(pos, i, j); #region Skip tile determination if (currentTile != 0) { continue; } #endregion //hash algo int variantX = i * 266489917 + 374761393; variantX = (variantX << 17) | (variantX >> 15); variantX += j * 266489917; variantX *= 668265263; variantX ^= variantX >> 15; variantX *= 246822519; variantX = Math.Abs(variantX); //origin that vertices will be defined relative to int oX = (cXY[0] + i) * Props.tileSize; int oY = (cXY[1] + j) * Props.tileSize; int value = 0; int variant = variantX % 4; //variant is determine by whether the transition is into an impassable tile value += (surface.GetTileFromWorldInt(pos, i - 1, j - 1) != 0) ? 1 : 0; //top left value += (surface.GetTileFromWorldInt(pos, i, j - 1) != 0) ? 2 : 0; //top center value += (surface.GetTileFromWorldInt(pos, i + 1, j - 1) != 0) ? 4 : 0; //top right value += (surface.GetTileFromWorldInt(pos, i - 1, j) != 0) ? 8 : 0; //left value += (surface.GetTileFromWorldInt(pos, i + 1, j) != 0) ? 16 : 0; //right value += (surface.GetTileFromWorldInt(pos, i - 1, j + 1) != 0) ? 32 : 0; //bottom left value += (surface.GetTileFromWorldInt(pos, i, j + 1) != 0) ? 64 : 0; //bottom center value += (surface.GetTileFromWorldInt(pos, i + 1, j + 1) != 0) ? 128 : 0; //bottom right //Virtual mapping of surrounding tiles // 1 2 3 // 4 0 5 // 6 7 8 //bitflag values of surrounding tiles // 1 2 4 // 8 0 16 // 32 64 128 //need specific checks for if left and right exist simultaneously //if top and bottom exist simultaneously //if two corners exist (u shape) in any config //if four corners exist in any config if (value == 0) { continue; //no surrounding tiles of tiletype } if (((value & 24) + (value & 2)) == 2) { //top fade AppendQuadVerticesCliff(vA, oX, oY, 0, 0, variant, cliffShade, cliffBounds); } if (((value & 24) + (value & 64)) == 64) { //bottom fade AppendQuadVerticesCliff(vA, oX, oY, 4, 0, variant, cliffShade, cliffBounds); } if (((value & 66) + (value & 8)) == 8) { //left fade AppendQuadVerticesCliff(vA, oX, oY, 8, 0, variant, cliffShade, cliffBounds); } if (((value & 66) + (value & 16)) == 16) { //right fade AppendQuadVerticesCliff(vA, oX, oY, 12, 0, variant, cliffShade, cliffBounds); } if ((value & 10) == 10) { //inside corner topleft AppendQuadVerticesCliff(vA, oX, oY, 0, 1, variant, cliffShade, cliffBounds); } else if (((value & 1) + (value & 10)) == 1) { //outside corner topleft AppendQuadVerticesCliff(vA, oX, oY, 0, 2, variant, cliffShade, cliffBounds); } if ((value & 18) == 18) { //inside corner topright AppendQuadVerticesCliff(vA, oX, oY, 4, 1, variant, cliffShade, cliffBounds); } else if (((value & 4) + (value & 18)) == 4) { //outside corner topright AppendQuadVerticesCliff(vA, oX, oY, 4, 2, variant, cliffShade, cliffBounds); } if ((value & 72) == 72) { //inside corner bottomleft AppendQuadVerticesCliff(vA, oX, oY, 8, 1, variant, cliffShade, cliffBounds); } else if (((value & 32) + (value & 72)) == 32) { //outside corner bottomleft AppendQuadVerticesCliff(vA, oX, oY, 8, 2, variant, cliffShade, cliffBounds); } if ((value & 80) == 80) { //inside corner bottomright AppendQuadVerticesCliff(vA, oX, oY, 12, 1, variant, cliffShade, cliffBounds); } else if (((value & 128) + (value & 80)) == 128) { //outside corner bottomright AppendQuadVerticesCliff(vA, oX, oY, 12, 2, variant, cliffShade, cliffBounds); } } } return(vA); }
virtual public void InitializeEntity(Vector2 position, SurfaceContainer surface) { this.surface = surface; this.position = position; this.surface.InitiateEntityInChunks(this); }
public override void InitializeEntity(Vector2 position, SurfaceContainer surface) { base.InitializeEntity(position, surface); lightSourceFlicker.on = false; lightSourceFlicker.Initialize(this); }