Add Hunter NPC and Teleporter features with associated prefabs and effects

This commit is contained in:
2025-12-13 00:01:29 +01:00
parent c0fb207768
commit d8b0583fac
32 changed files with 823 additions and 217 deletions

View File

@@ -10,6 +10,7 @@ namespace Infrastructure.Unity
[SerializeField] private TileViewAdapter tilePrefab;
[SerializeField] private ParticleSystem tileBreakVfxPrefab;
[SerializeField] private JumpPadAdapter jumpPadPrefab;
[SerializeField] private TeleporterAdapter teleporterPrefab;
[Header("Settings")]
[SerializeField] private int gridSizeX = 10;
@@ -18,23 +19,27 @@ namespace Infrastructure.Unity
[SerializeField] private float floorHeightDistance = 15f;
[SerializeField] private float decayTime = 0.5f;
[SerializeField] private float fallingTime = 2.0f;
public float FloorHeightDistance => floorHeightDistance;
public int FloorsCount => floorsCount;
public int GridSizeX => gridSizeX;
public int GridSizeY => gridSizeY;
public void Generate(SoundManager soundManager, List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews)
private TilePool _tilePool;
public void Generate(SoundManager soundManager, List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera)
{
GenerateFloor(0, MapPatterns.GenerateSquare(gridSizeX, gridSizeY), soundManager, allTiles, tileViews);
GenerateFloor(1, MapPatterns.GenerateDonut(gridSizeX, Mathf.FloorToInt(gridSizeX / 3f)), soundManager, allTiles, tileViews);
GenerateFloor(2, MapPatterns.GenerateCircle(gridSizeX), soundManager, allTiles, tileViews);
_tilePool = new TilePool(tilePrefab, transform);
GenerateFloor(0, MapPatterns.GenerateSquare(gridSizeX, gridSizeY), soundManager, allTiles, tileViews, camera);
GenerateFloor(1, MapPatterns.GenerateDonut(gridSizeX, Mathf.FloorToInt(gridSizeX / 3f)), soundManager, allTiles, tileViews, camera);
GenerateFloor(2, MapPatterns.GenerateCircle(gridSizeX), soundManager, allTiles, tileViews, camera);
}
private void GenerateFloor(int floorIndex, List<Vector2Int> coordinates, SoundManager soundManager,
List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews)
private void GenerateFloor(int floorIndex, List<Vector2Int> coordinates, SoundManager soundManager,
List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera)
{
var yOffset = -(floorIndex * floorHeightDistance);
var xOffset = gridSizeX / 2f;
@@ -43,46 +48,77 @@ namespace Infrastructure.Unity
foreach (var coord in coordinates)
{
var pos = new Vector3(coord.x - xOffset, yOffset, coord.y - zOffset);
CreateTile(pos, $"{floorIndex}_{coord.x}_{coord.y}", floorIndex, soundManager, allTiles, tileViews);
CreateTile(pos, $"{floorIndex}_{coord.x}_{coord.y}", floorIndex, soundManager, allTiles, tileViews, camera);
}
if (floorIndex > 0 && jumpPadPrefab)
{
var validSpot = coordinates[Random.Range(0, coordinates.Count)];
var padPos = new Vector3(validSpot.x - xOffset, yOffset + 0.6f, validSpot.y - zOffset);
Instantiate(jumpPadPrefab, padPos, Quaternion.identity, transform);
}
if (floorIndex > 0 && teleporterPrefab && coordinates.Count > 5)
{
// Spawn a pair of teleporters
var indexA = Random.Range(0, coordinates.Count);
int indexB;
do
{
indexB = Random.Range(0, coordinates.Count);
} while (indexB == indexA);
var spotA = coordinates[indexA];
var spotB = coordinates[indexB];
var posA = new Vector3(spotA.x - xOffset, yOffset + 0.6f, spotA.y - zOffset);
var posB = new Vector3(spotB.x - xOffset, yOffset + 0.6f, spotB.y - zOffset);
var telA = Instantiate(teleporterPrefab, posA, Quaternion.identity, transform);
var telB = Instantiate(teleporterPrefab, posB, Quaternion.identity, transform);
telA.Initialize(telB.transform);
telB.Initialize(telA.transform);
}
}
private void CreateTile(Vector3 position, string id, int floorIndex, SoundManager soundManager,
List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews)
private void CreateTile(Vector3 position, string id, int floorIndex, SoundManager soundManager,
List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera)
{
var go = Instantiate(tilePrefab, position, Quaternion.identity, transform);
var go = _tilePool.Get();
go.transform.position = position;
go.transform.rotation = Quaternion.identity;
go.transform.localScale = Vector3.one * 0.95f;
var tileLogic = new Tile(id, floorIndex, decayTime, fallingTime);
go.Initialize(tileLogic);
if (soundManager)
// 15% chance to be Fragile
var isFragile = Random.value < 0.15f;
var type = isFragile ? TileType.Fragile : TileType.Normal;
var tileLogic = new Tile(id, floorIndex, decayTime, fallingTime, type);
go.Initialize(tileLogic, (t) => _tilePool.Return(t));
tileLogic.OnStateChanged += (t) =>
{
tileLogic.OnStateChanged += (t) =>
if (t.CurrentState == TileState.Warning)
{
if (t.CurrentState == TileState.Warning)
soundManager?.PlayTileWarning(position);
}
else if (t.CurrentState == TileState.Falling)
{
soundManager?.PlayTileBreak(position);
if (t.Type == TileType.Fragile)
{
soundManager.PlayTileWarning(position);
camera?.Shake(0.1f, 0.05f);
}
else if (t.CurrentState == TileState.Falling)
if (tileBreakVfxPrefab)
{
soundManager.PlayTileBreak(position);
if (tileBreakVfxPrefab)
{
Instantiate(tileBreakVfxPrefab, position, Quaternion.identity);
}
Instantiate(tileBreakVfxPrefab, position, Quaternion.identity);
}
};
}
}
};
allTiles.Add(tileLogic);
tileViews.Add(id, go);