public Cell[][] ComputeMap(Cell[][] baseMap, Enemy[] enemies, List <List <Vector2> > cellsByEnemy) { Cell[][] im = new Cell[cellsX][]; for (int x = 0; x < cellsX; x++) { im [x] = new Cell[cellsZ]; for (int y = 0; y < cellsZ; y++) { im [x] [y] = baseMap [x] [y].Copy(); } } for (int i = 0; i < enemies.Length; i++) { Enemy enemy = enemies [i]; // For every enemy, get their direction and current world position and scale into IM scale Vector2 dir = new Vector2(enemy.GetSimulatedForward().x, enemy.GetSimulatedForward().z); // Convert enemy position into Grid Coordinates Vector2 pos = new Vector2((enemy.GetSimulationPosition().x - minX) / tileSizeX, (enemy.GetSimulationPosition().z - minZ) / tileSizeZ); Vector2 p = new Vector2(); for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { // Check map boundaries if (Mathf.FloorToInt(pos.x + x) >= 0 && Mathf.FloorToInt(pos.x + x) < cellsX && Mathf.FloorToInt(pos.y + y) >= 0 && Mathf.FloorToInt(pos.y + y) < cellsZ) { // (everything here is in world coord, so we must transform back from grid coord to world coord) // If the distance from the position of the guy to the middle of the 4 cells around him is leseer than the radius, we paint those cells if (Vector2.Distance(new Vector2(enemy.GetSimulationPosition().x, enemy.GetSimulationPosition().z), new Vector2((Mathf.Floor(pos.x + x) + tileSizeX) * tileSizeX + minX, (Mathf.Floor(pos.y + y) + tileSizeZ) * tileSizeZ + minZ)) < enemy.radius) { im [Mathf.FloorToInt(pos.x + x)] [Mathf.FloorToInt(pos.y + y)].seen = true; cellsByEnemy [i].Add(new Vector2(pos.x + x, pos.y + y)); } } } } // if tileSizeX != tileSizeZ we can be in big trouble! float dist = enemy.fovDistance / ((tileSizeX + tileSizeZ) / 2); DDA dda = new DDA(tileSizeX, tileSizeZ, cellsX, cellsZ); for (int x = 0; x < cellsX; x++) { for (int y = 0; y < cellsZ; y++) { // Skip cells that are staticly blocked or seen by other enemies // Don't skip cells seen by other enemies or we won't have the correct seenCells computed if (im [x] [y].blocked || im [x] [y].safe) { continue; } // This enemy haven't seen it yet bool seen = false; for (int px = 0; px <= 1; px++) { for (int py = 0; py <= 1; py++) { // Destination of the ray p.Set(x + px, y + py); // Direction of the ray Vector2 res = (p - pos).normalized; // Is the target within our FoV? if (Vector2.Distance(p, pos) < dist && Vector2.Angle(res, dir) < enemy.fovAngle) { // Check if target is seen by this enemy seen = seen || dda.HasLOS(im, p, pos, res, x, y); } } } // If this enemy has seen it if (seen) { cellsByEnemy [i].Add(new Vector2(x, y)); } // Now take into account other enemies before modifying the cells value im [x] [y].seen = im [x] [y].seen || seen; } } } return(im); }