lab6 dop
This commit is contained in:
1 parent
bca661e132
commit
ed0437638b
9 files changed
+3442
-17
No files matched your search
@@ -20,6 +20,11 @@ namespace Code.Lab6
|
||||
private int _numRows;
|
||||
private GameObject[] _vertexObj;
|
||||
private bool[,] _mapVertices;
|
||||
|
||||
public bool useWeightedMap = true;
|
||||
public Texture2D weightMapTexture;
|
||||
public float minWeight = 0.5f;
|
||||
public float maxWeight = 5f;
|
||||
|
||||
private Dictionary<int, int> _gridIdToVertexIndex;
|
||||
|
||||
@@ -32,6 +37,309 @@ namespace Code.Lab6
|
||||
{
|
||||
return new Vector2Int(id % _numCols, id / _numCols);
|
||||
}
|
||||
|
||||
private void LoadMapWithWeights(string filename)
|
||||
{
|
||||
var path = Application.dataPath + "/" + MapsDir + "/" + filename;
|
||||
|
||||
try
|
||||
{
|
||||
var strmRdr = new StreamReader(path);
|
||||
using (strmRdr)
|
||||
{
|
||||
strmRdr.ReadLine();
|
||||
|
||||
var line = strmRdr.ReadLine();
|
||||
if (line != null && line.StartsWith("height"))
|
||||
_numRows = int.Parse(line.Split(' ')[1]);
|
||||
|
||||
line = strmRdr.ReadLine();
|
||||
if (line != null && line.StartsWith("width"))
|
||||
_numCols = int.Parse(line.Split(' ')[1]);
|
||||
|
||||
strmRdr.ReadLine();
|
||||
|
||||
Vertices = new List<Vertex>();
|
||||
Neighbours = new List<List<Vertex>>();
|
||||
Costs = new List<List<float>>();
|
||||
_vertexObj = new GameObject[_numRows * _numCols];
|
||||
_mapVertices = new bool[_numRows, _numCols];
|
||||
_gridIdToVertexIndex = new Dictionary<int, int>();
|
||||
|
||||
Debug.Log($"Loading weighted map {_numRows}x{_numCols}");
|
||||
|
||||
for (var row = 0; row < _numRows; row++)
|
||||
{
|
||||
line = strmRdr.ReadLine();
|
||||
if (string.IsNullOrEmpty(line)) continue;
|
||||
|
||||
for (var col = 0; col < _numCols && col < line.Length; col++)
|
||||
{
|
||||
var cellChar = line[col];
|
||||
var isGround = cellChar != '#';
|
||||
|
||||
_mapVertices[row, col] = isGround;
|
||||
|
||||
var position = new Vector3(col * cellSize, 0f, row * cellSize);
|
||||
var gridId = GridToId(col, row);
|
||||
|
||||
GameObject obj;
|
||||
|
||||
if (isGround && vertexPrefab != null)
|
||||
{
|
||||
obj = Instantiate(vertexPrefab, position, Quaternion.identity);
|
||||
}
|
||||
else if (!isGround && obstaclePrefab != null)
|
||||
{
|
||||
obj = Instantiate(obstaclePrefab, position, Quaternion.identity);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
obj.transform.position = position;
|
||||
}
|
||||
|
||||
if (obj == null) continue;
|
||||
|
||||
obj.name = $"{cellChar}_{gridId}";
|
||||
obj.transform.parent = transform;
|
||||
|
||||
var scale = obj.transform.localScale;
|
||||
scale.x = cellSize;
|
||||
scale.z = cellSize;
|
||||
scale.y = isGround ? 0.1f : 1f;
|
||||
obj.transform.localScale = scale;
|
||||
|
||||
_vertexObj[gridId] = obj;
|
||||
|
||||
if (!isGround) continue;
|
||||
|
||||
var v = obj.GetComponent<Vertex>();
|
||||
if (v == null)
|
||||
v = obj.AddComponent<Vertex>();
|
||||
|
||||
v.id = gridId;
|
||||
v.neighbours = new List<Edge>();
|
||||
|
||||
v.weight = GetWeightFromChar(cellChar);
|
||||
|
||||
var renderer1 = obj.GetComponent<Renderer>();
|
||||
if (renderer1 != null)
|
||||
{
|
||||
renderer1.material.color = cellChar switch
|
||||
{
|
||||
'r' => new Color(0.8f, 0.2f, 0.2f),
|
||||
'm' => new Color(0.6f, 0.4f, 0.2f),
|
||||
'h' => new Color(0.2f, 0.8f, 0.2f),
|
||||
_ => new Color(0.8f, 0.8f, 0.8f)
|
||||
};
|
||||
}
|
||||
|
||||
var vertexIndex = Vertices.Count;
|
||||
Vertices.Add(v);
|
||||
Neighbours.Add(new List<Vertex>());
|
||||
Costs.Add(new List<float>());
|
||||
|
||||
_gridIdToVertexIndex[gridId] = vertexIndex;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var kvp in _gridIdToVertexIndex)
|
||||
{
|
||||
var gridId = kvp.Key;
|
||||
var vertexIndex = kvp.Value;
|
||||
var gridPos = IdToGrid(gridId);
|
||||
SetNeighboursWithWeights(gridPos.x, gridPos.y, vertexIndex);
|
||||
}
|
||||
|
||||
Debug.Log($"Weighted map loaded. {Vertices.Count} walkable vertices");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Failed to load weighted map: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private float GetWeightFromChar(char c)
|
||||
{
|
||||
return c switch
|
||||
{
|
||||
'h' => 0.5f,
|
||||
'.' => 1f,
|
||||
'm' => 3f,
|
||||
'r' => 5f,
|
||||
'#' => float.MaxValue,
|
||||
_ => 1f
|
||||
};
|
||||
}
|
||||
|
||||
private float CalculateVertexWeight(int row, int col, Texture2D weightTexture)
|
||||
{
|
||||
if (weightTexture != null)
|
||||
{
|
||||
var texX = Mathf.FloorToInt((float)col / _numCols * weightTexture.width);
|
||||
var texY = Mathf.FloorToInt((float)row / _numRows * weightTexture.height);
|
||||
|
||||
var pixel = weightTexture.GetPixel(texX, texY);
|
||||
var gray = pixel.grayscale;
|
||||
|
||||
return Mathf.Lerp(minWeight, maxWeight, gray);
|
||||
}
|
||||
|
||||
var centerX = _numCols / 2f;
|
||||
var centerY = _numRows / 2f;
|
||||
var distFromCenter = Vector2.Distance(new Vector2(col, row), new Vector2(centerX, centerY));
|
||||
var maxDist = Mathf.Max(_numCols, _numRows) / 2f;
|
||||
var centerWeight = Mathf.Lerp(minWeight, maxWeight, distFromCenter / maxDist);
|
||||
|
||||
var noise = Mathf.PerlinNoise(col * 0.1f, row * 0.1f);
|
||||
var noiseWeight = Mathf.Lerp(minWeight, maxWeight, noise);
|
||||
|
||||
var riverX = _numCols * 0.3f + Mathf.Sin(row * 0.3f) * 5f;
|
||||
var distToRiver = Mathf.Abs(col - riverX);
|
||||
var riverWeight = distToRiver < 3f ? maxWeight : minWeight;
|
||||
|
||||
var finalWeight = (centerWeight * 0.3f + noiseWeight * 0.3f + riverWeight * 0.4f);
|
||||
|
||||
return Mathf.Clamp(finalWeight, minWeight, maxWeight);
|
||||
}
|
||||
|
||||
protected void SetNeighboursWithWeights(int x, int y, int vertexIndex)
|
||||
{
|
||||
var currentVertex = Vertices[vertexIndex];
|
||||
|
||||
Neighbours[vertexIndex].Clear();
|
||||
Costs[vertexIndex].Clear();
|
||||
currentVertex.neighbours.Clear();
|
||||
|
||||
Vector2Int[] directions;
|
||||
|
||||
if (get8Vicinity)
|
||||
{
|
||||
directions = new[]
|
||||
{
|
||||
new Vector2Int(x, y - 1), new Vector2Int(x + 1, y - 1),
|
||||
new Vector2Int(x + 1, y), new Vector2Int(x + 1, y + 1),
|
||||
new Vector2Int(x, y + 1), new Vector2Int(x - 1, y + 1),
|
||||
new Vector2Int(x - 1, y), new Vector2Int(x - 1, y - 1)
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
directions = new[]
|
||||
{
|
||||
new Vector2Int(x, y - 1), new Vector2Int(x + 1, y),
|
||||
new Vector2Int(x, y + 1), new Vector2Int(x - 1, y)
|
||||
};
|
||||
}
|
||||
|
||||
const float diagonalMultiplier = 1.4f;
|
||||
|
||||
foreach (var dir in directions)
|
||||
{
|
||||
if (dir.x < 0 || dir.x >= _numCols || dir.y < 0 || dir.y >= _numRows)
|
||||
continue;
|
||||
|
||||
if (!_mapVertices[dir.y, dir.x])
|
||||
continue;
|
||||
|
||||
var neighbourGridId = GridToId(dir.x, dir.y);
|
||||
|
||||
if (!_gridIdToVertexIndex.TryGetValue(neighbourGridId, out var neighbourIndex))
|
||||
continue;
|
||||
|
||||
var neighbourVertex = Vertices[neighbourIndex];
|
||||
|
||||
var baseCost = (currentVertex.weight + neighbourVertex.weight) / 2f;
|
||||
|
||||
if (dir.x != x && dir.y != y)
|
||||
{
|
||||
baseCost *= diagonalMultiplier;
|
||||
}
|
||||
|
||||
Neighbours[vertexIndex].Add(neighbourVertex);
|
||||
Costs[vertexIndex].Add(baseCost);
|
||||
currentVertex.neighbours.Add(new Edge(neighbourVertex, baseCost));
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateLargeWeightedMap(int width, int height)
|
||||
{
|
||||
_numCols = width;
|
||||
_numRows = height;
|
||||
|
||||
Vertices = new List<Vertex>();
|
||||
Neighbours = new List<List<Vertex>>();
|
||||
Costs = new List<List<float>>();
|
||||
_vertexObj = new GameObject[width * height];
|
||||
_mapVertices = new bool[height, width];
|
||||
_gridIdToVertexIndex = new Dictionary<int, int>();
|
||||
|
||||
for (var y = 0; y < height; y++)
|
||||
{
|
||||
for (var x = 0; x < width; x++)
|
||||
{
|
||||
_mapVertices[y, x] = true;
|
||||
|
||||
var position = new Vector3(x * cellSize, 0f, y * cellSize);
|
||||
var gridId = GridToId(x, y);
|
||||
|
||||
var obj = Instantiate(vertexPrefab, position, Quaternion.identity);
|
||||
obj.name = $"Vertex_{gridId}";
|
||||
obj.transform.parent = transform;
|
||||
|
||||
var v = obj.GetComponent<Vertex>();
|
||||
if (v == null)
|
||||
v = obj.AddComponent<Vertex>();
|
||||
|
||||
v.id = gridId;
|
||||
v.neighbours = new List<Edge>();
|
||||
|
||||
v.weight = CalculateVertexWeight(y, x, null);
|
||||
|
||||
var renderer1 = obj.GetComponent<Renderer>();
|
||||
if (renderer1 != null)
|
||||
{
|
||||
var t = Mathf.InverseLerp(minWeight, maxWeight, v.weight);
|
||||
renderer1.material.color = Color.Lerp(Color.white, Color.black, t);
|
||||
}
|
||||
|
||||
var vertexIndex = Vertices.Count;
|
||||
Vertices.Add(v);
|
||||
Neighbours.Add(new List<Vertex>());
|
||||
Costs.Add(new List<float>());
|
||||
|
||||
_gridIdToVertexIndex[gridId] = vertexIndex;
|
||||
}
|
||||
}
|
||||
|
||||
for (var y = 0; y < height; y++)
|
||||
{
|
||||
for (var x = 0; x < width; x++)
|
||||
{
|
||||
var gridId = GridToId(x, y);
|
||||
if (_gridIdToVertexIndex.TryGetValue(gridId, out var vertexIndex))
|
||||
{
|
||||
SetNeighboursWithWeights(x, y, vertexIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"Generated large weighted map: {width}x{height} ({Vertices.Count} vertices)");
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
if (useWeightedMap)
|
||||
{
|
||||
LoadMapWithWeights(mapName);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadMap(mapName);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadMap(string filename)
|
||||
{
|
||||
@@ -226,11 +534,6 @@ namespace Code.Lab6
|
||||
}
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
LoadMap(mapName);
|
||||
}
|
||||
|
||||
public override Vertex GetNearestVertex(Vector3 position)
|
||||
{
|
||||
var col = Mathf.RoundToInt(position.x / cellSize);
|
||||
|
||||
Reference in new issue
Block a user