Compare commits
15 Commits
17e3425de3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d54920df9 | |||
| 03bfb16cf3 | |||
| 65af5ad2eb | |||
| eedbbb2b47 | |||
| 3c6e309886 | |||
| 2bfc2ea9c2 | |||
| 1b8c7f730d | |||
| 8edb5cfbb5 | |||
| f507707251 | |||
| 67df6bf6d6 | |||
| 49c9a7904d | |||
| 34a329ad02 | |||
| d4dc30bd7a | |||
| feed4da28c | |||
| 0704f2e0a0 |
8
Assets/Data.meta
Normal file
8
Assets/Data.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a0d581912a9a00ddd90532c3da3be7fc
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
21
Assets/Data/Level.asset
Normal file
21
Assets/Data/Level.asset
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: d1e67659d937881ee99b3b9e84f91428, type: 3}
|
||||||
|
m_Name: Level
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.LevelDefinition
|
||||||
|
gridSizeX: 40
|
||||||
|
gridSizeY: 40
|
||||||
|
floorHeightDistance: 15
|
||||||
|
floors:
|
||||||
|
- pattern: 0
|
||||||
|
- pattern: 1
|
||||||
|
- pattern: 2
|
||||||
8
Assets/Data/Level.asset.meta
Normal file
8
Assets/Data/Level.asset.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5b72a68ad35f58fc3baa8043b5dfb42c
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because one or more lines are too long
@@ -610,6 +610,7 @@ GameObject:
|
|||||||
- component: {fileID: 453022423}
|
- component: {fileID: 453022423}
|
||||||
- component: {fileID: 453022424}
|
- component: {fileID: 453022424}
|
||||||
- component: {fileID: 453022425}
|
- component: {fileID: 453022425}
|
||||||
|
- component: {fileID: 453022426}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Game
|
m_Name: Game
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -640,11 +641,7 @@ MonoBehaviour:
|
|||||||
npcPrefab: {fileID: 6083523108754401876, guid: 4b3d84858334857368bde30df360ae3e, type: 3}
|
npcPrefab: {fileID: 6083523108754401876, guid: 4b3d84858334857368bde30df360ae3e, type: 3}
|
||||||
hunterNpcPrefab: {fileID: 4496988857626767934, guid: ab4e193839fef9a2189f27360914c044, type: 3}
|
hunterNpcPrefab: {fileID: 4496988857626767934, guid: ab4e193839fef9a2189f27360914c044, type: 3}
|
||||||
floorVisibilityManager: {fileID: 453022425}
|
floorVisibilityManager: {fileID: 453022425}
|
||||||
scoreText: {fileID: 412275999}
|
uiCoordinator: {fileID: 453022426}
|
||||||
highScoreText: {fileID: 1626199842}
|
|
||||||
gameOverUi: {fileID: 87831902}
|
|
||||||
pauseUi: {fileID: 1019087904}
|
|
||||||
startScreenUi: {fileID: 1763855010}
|
|
||||||
restartTime: 3
|
restartTime: 3
|
||||||
powerUpPrefab: {fileID: 7381336953128067686, guid: 8b540be4548e610709c2f7eccf8bf9c6, type: 3}
|
powerUpPrefab: {fileID: 7381336953128067686, guid: 8b540be4548e610709c2f7eccf8bf9c6, type: 3}
|
||||||
--- !u!4 &453022421
|
--- !u!4 &453022421
|
||||||
@@ -678,10 +675,7 @@ MonoBehaviour:
|
|||||||
tileBreakVfxPrefab: {fileID: 0}
|
tileBreakVfxPrefab: {fileID: 0}
|
||||||
jumpPadPrefab: {fileID: 3258547662887829175, guid: e1d1bd44370c9986ebd4bb7730430a12, type: 3}
|
jumpPadPrefab: {fileID: 3258547662887829175, guid: e1d1bd44370c9986ebd4bb7730430a12, type: 3}
|
||||||
teleporterPrefab: {fileID: 4601941687390792571, guid: 53f1de555c523511e9aaa1dee06fdf79, type: 3}
|
teleporterPrefab: {fileID: 4601941687390792571, guid: 53f1de555c523511e9aaa1dee06fdf79, type: 3}
|
||||||
gridSizeX: 25
|
levelDefinition: {fileID: 11400000, guid: 5b72a68ad35f58fc3baa8043b5dfb42c, type: 2}
|
||||||
gridSizeY: 25
|
|
||||||
floorsCount: 3
|
|
||||||
floorHeightDistance: 15
|
|
||||||
decayTime: 0.75
|
decayTime: 0.75
|
||||||
fallingTime: 2
|
fallingTime: 2
|
||||||
minimumDistanceBetweenTeleporters: 10
|
minimumDistanceBetweenTeleporters: 10
|
||||||
@@ -780,6 +774,23 @@ MonoBehaviour:
|
|||||||
fadeSpeed: 5
|
fadeSpeed: 5
|
||||||
hiddenAlpha: 0.1
|
hiddenAlpha: 0.1
|
||||||
visibleAlpha: 1
|
visibleAlpha: 1
|
||||||
|
--- !u!114 &453022426
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 453022419}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: b2d628098b45e36879d59d2c2c2bf061, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.GameUiCoordinator
|
||||||
|
scoreText: {fileID: 412275999}
|
||||||
|
highScoreText: {fileID: 1626199842}
|
||||||
|
gameOverUi: {fileID: 87831902}
|
||||||
|
pauseUi: {fileID: 1019087904}
|
||||||
|
startScreenUi: {fileID: 1763855010}
|
||||||
--- !u!1 &832575517
|
--- !u!1 &832575517
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Core.Ports;
|
using Core.Ports;
|
||||||
using UnityEngine;
|
|
||||||
using Random = System.Random;
|
using Random = System.Random;
|
||||||
|
|
||||||
namespace Core.Domain
|
namespace Core.Domain
|
||||||
@@ -25,7 +25,7 @@ namespace Core.Domain
|
|||||||
public event Action OnSpawnNpc;
|
public event Action OnSpawnNpc;
|
||||||
public event Action<PowerUpType, string> OnSpawnPowerUp;
|
public event Action<PowerUpType, string> OnSpawnPowerUp;
|
||||||
|
|
||||||
private readonly List<Tile> _tiles;
|
private readonly IReadOnlyList<Tile> _tiles;
|
||||||
private readonly IPersistenceService _persistenceService;
|
private readonly IPersistenceService _persistenceService;
|
||||||
private readonly Random _rng = new();
|
private readonly Random _rng = new();
|
||||||
private int _playerFloorIndex = 0;
|
private int _playerFloorIndex = 0;
|
||||||
@@ -40,7 +40,7 @@ namespace Core.Domain
|
|||||||
public int ComboMultiplier { get; private set; } = 1;
|
public int ComboMultiplier { get; private set; } = 1;
|
||||||
public event Action<int> OnComboUpdated;
|
public event Action<int> OnComboUpdated;
|
||||||
|
|
||||||
public GameSession(List<Tile> tiles, IPersistenceService persistenceService)
|
public GameSession(IReadOnlyList<Tile> tiles, IPersistenceService persistenceService)
|
||||||
{
|
{
|
||||||
_tiles = tiles;
|
_tiles = tiles;
|
||||||
_persistenceService = persistenceService;
|
_persistenceService = persistenceService;
|
||||||
@@ -74,7 +74,7 @@ namespace Core.Domain
|
|||||||
{
|
{
|
||||||
_npcTimer = 0f;
|
_npcTimer = 0f;
|
||||||
OnSpawnNpc?.Invoke();
|
OnSpawnNpc?.Invoke();
|
||||||
NpcSpawnTime = Mathf.Max(5f, NpcSpawnTime * 0.95f);
|
NpcSpawnTime = Math.Max(5f, NpcSpawnTime * 0.95f);
|
||||||
}
|
}
|
||||||
|
|
||||||
_powerUpTimer += deltaTime;
|
_powerUpTimer += deltaTime;
|
||||||
@@ -124,15 +124,12 @@ namespace Core.Domain
|
|||||||
|
|
||||||
private void SpawnNextOrb()
|
private void SpawnNextOrb()
|
||||||
{
|
{
|
||||||
var validTiles = _tiles.FindAll(t =>
|
var validTiles = _tiles.Where(t =>
|
||||||
t.CurrentState == TileState.Stable &&
|
t.CurrentState == TileState.Stable &&
|
||||||
t.Floor == _playerFloorIndex
|
t.Floor == _playerFloorIndex).ToList();
|
||||||
);
|
|
||||||
|
|
||||||
if (validTiles.Count == 0)
|
if (validTiles.Count == 0)
|
||||||
{
|
validTiles = _tiles.Where(t => t.CurrentState == TileState.Stable).ToList();
|
||||||
validTiles = _tiles.FindAll(t => t.CurrentState == TileState.Stable);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (validTiles.Count == 0)
|
if (validTiles.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -173,27 +170,24 @@ namespace Core.Domain
|
|||||||
|
|
||||||
private void SpawnRandomPowerUp()
|
private void SpawnRandomPowerUp()
|
||||||
{
|
{
|
||||||
var validTiles = _tiles.FindAll(t =>
|
var validTiles = _tiles.Where(t =>
|
||||||
t.CurrentState == TileState.Stable &&
|
t.CurrentState == TileState.Stable &&
|
||||||
t.Floor == _playerFloorIndex
|
t.Floor == _playerFloorIndex).ToList();
|
||||||
);
|
|
||||||
|
|
||||||
if (validTiles.Count == 0)
|
if (validTiles.Count == 0)
|
||||||
{
|
validTiles = _tiles.Where(t => t.CurrentState == TileState.Stable).ToList();
|
||||||
validTiles = _tiles.FindAll(t => t.CurrentState == TileState.Stable);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (validTiles.Count == 0) return;
|
if (validTiles.Count == 0) return;
|
||||||
|
|
||||||
var tile = validTiles[_rng.Next(validTiles.Count)];
|
var tile = validTiles[_rng.Next(validTiles.Count)];
|
||||||
|
|
||||||
var rand = _rng.Next(0, 4);
|
var rand = _rng.Next(0, 3);
|
||||||
var type = PowerUpType.LightFooted;
|
PowerUpType type;
|
||||||
switch (rand)
|
switch (rand)
|
||||||
{
|
{
|
||||||
case 0: type = PowerUpType.LightFooted; break;
|
case 0: type = PowerUpType.LightFooted; break;
|
||||||
case 1: type = PowerUpType.SpeedBoost; break;
|
case 1: type = PowerUpType.SpeedBoost; break;
|
||||||
case 3: type = PowerUpType.TimeSlow; break;
|
default: type = PowerUpType.TimeSlow; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnSpawnPowerUp?.Invoke(type, tile.Id);
|
OnSpawnPowerUp?.Invoke(type, tile.Id);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace Core.Domain.Status.Effects
|
|||||||
public void ModifyCapabilities(ref PlayerCapabilities caps)
|
public void ModifyCapabilities(ref PlayerCapabilities caps)
|
||||||
{
|
{
|
||||||
caps.CanTriggerDecay = false;
|
caps.CanTriggerDecay = false;
|
||||||
caps.SpeedMultiplier = 1.2f;
|
caps.SpeedMultiplier *= 1.2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnApply()
|
public void OnApply()
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Core.Domain.Status.Effects
|
|||||||
|
|
||||||
public void ModifyCapabilities(ref PlayerCapabilities caps)
|
public void ModifyCapabilities(ref PlayerCapabilities caps)
|
||||||
{
|
{
|
||||||
caps.SpeedMultiplier = _multiplier;
|
caps.SpeedMultiplier *= _multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnApply() { }
|
public void OnApply() { }
|
||||||
|
|||||||
@@ -9,5 +9,6 @@ namespace Core.Ports
|
|||||||
void SetVisualState(TileState state);
|
void SetVisualState(TileState state);
|
||||||
void DropPhysics();
|
void DropPhysics();
|
||||||
void Dispose();
|
void Dispose();
|
||||||
|
void StepOn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Core.Domain;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Infrastructure.Unity
|
namespace Infrastructure.Unity
|
||||||
@@ -10,44 +9,13 @@ namespace Infrastructure.Unity
|
|||||||
[SerializeField] private float fadeSpeed = 5f;
|
[SerializeField] private float fadeSpeed = 5f;
|
||||||
[SerializeField] private float hiddenAlpha = 0.1f;
|
[SerializeField] private float hiddenAlpha = 0.1f;
|
||||||
[SerializeField] private float visibleAlpha = 1.0f;
|
[SerializeField] private float visibleAlpha = 1.0f;
|
||||||
|
|
||||||
private GameSession _gameSession;
|
|
||||||
private List<List<TileViewAdapter>> _floors;
|
private List<List<TileViewAdapter>> _floors;
|
||||||
private int _currentFloorIndex = -1;
|
private int _currentFloorIndex = -1;
|
||||||
|
|
||||||
public void Initialize(GameSession gameSession, List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, int totalFloors)
|
public void Initialize(TileRegistry registry, int totalFloors)
|
||||||
{
|
{
|
||||||
_gameSession = gameSession;
|
_floors = registry.GroupViewsByFloor(totalFloors);
|
||||||
|
|
||||||
_floors = new List<List<TileViewAdapter>>();
|
|
||||||
for (var i = 0; i < totalFloors; i++)
|
|
||||||
{
|
|
||||||
_floors.Add(new List<TileViewAdapter>());
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var tile in allTiles)
|
|
||||||
{
|
|
||||||
if (tileViews.TryGetValue(tile.Id, out var view))
|
|
||||||
{
|
|
||||||
// Safety check for array bounds
|
|
||||||
if (tile.Floor < _floors.Count)
|
|
||||||
{
|
|
||||||
_floors[tile.Floor].Add(view);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
if (_gameSession == null) return;
|
|
||||||
|
|
||||||
// Check if player changed floors
|
|
||||||
// We read the private field _playerFloorIndex via a public getter we need to add,
|
|
||||||
// OR we just track it locally if you updated GameSession to expose it.
|
|
||||||
// Assuming GameSession doesn't expose it publically yet, let's rely on GameBootstrap passing it or just hack it:
|
|
||||||
// Ideally, GameSession should emit an event 'OnFloorChanged'.
|
|
||||||
// For now, let's assume we can get it or we passed the player reference.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call this from GameBootstrap.Update()
|
// Call this from GameBootstrap.Update()
|
||||||
@@ -75,9 +43,9 @@ namespace Infrastructure.Unity
|
|||||||
tile.SetAlpha(targetAlpha);
|
tile.SetAlpha(targetAlpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i % 2 == 0) yield return null;
|
if (i % 2 == 0) yield return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Core.Domain;
|
using Core.Domain;
|
||||||
|
using Core.Domain.Status.Effects;
|
||||||
using Core.Ports;
|
using Core.Ports;
|
||||||
using TMPro;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
@@ -24,11 +23,7 @@ namespace Infrastructure.Unity
|
|||||||
[SerializeField] private FloorVisibilityManager floorVisibilityManager;
|
[SerializeField] private FloorVisibilityManager floorVisibilityManager;
|
||||||
|
|
||||||
[Header("Ui")]
|
[Header("Ui")]
|
||||||
[SerializeField] private TMP_Text scoreText;
|
[SerializeField] private GameUiCoordinator uiCoordinator;
|
||||||
[SerializeField] private TMP_Text highScoreText;
|
|
||||||
[SerializeField] private GameObject gameOverUi;
|
|
||||||
[SerializeField] private GameObject pauseUi;
|
|
||||||
[SerializeField] private GameObject startScreenUi;
|
|
||||||
|
|
||||||
[Header("Settings")]
|
[Header("Settings")]
|
||||||
[SerializeField] private float restartTime = 3f;
|
[SerializeField] private float restartTime = 3f;
|
||||||
@@ -36,8 +31,7 @@ namespace Infrastructure.Unity
|
|||||||
[Header("Power Ups")]
|
[Header("Power Ups")]
|
||||||
[SerializeField] private PowerUpViewAdapter powerUpPrefab;
|
[SerializeField] private PowerUpViewAdapter powerUpPrefab;
|
||||||
|
|
||||||
private readonly List<Tile> _allTiles = new();
|
private readonly TileRegistry _tileRegistry = new();
|
||||||
private readonly Dictionary<string, TileViewAdapter> _tileViews = new();
|
|
||||||
private GameSession _gameSession;
|
private GameSession _gameSession;
|
||||||
private IPersistenceService _persistenceService;
|
private IPersistenceService _persistenceService;
|
||||||
private InputSystem_Actions _actions;
|
private InputSystem_Actions _actions;
|
||||||
@@ -45,11 +39,11 @@ namespace Infrastructure.Unity
|
|||||||
private GameObject _currentOrbInstance;
|
private GameObject _currentOrbInstance;
|
||||||
private bool _isGameRunning;
|
private bool _isGameRunning;
|
||||||
private int _currentPlayerFloorIndex;
|
private int _currentPlayerFloorIndex;
|
||||||
private int _currentDisplayedScore;
|
|
||||||
private float _inputBlockTimer;
|
private float _inputBlockTimer;
|
||||||
private bool _isPaused;
|
private bool _isPaused;
|
||||||
private bool _levelGenerated;
|
private bool _levelGenerated;
|
||||||
|
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
_actions = new InputSystem_Actions();
|
_actions = new InputSystem_Actions();
|
||||||
@@ -67,16 +61,16 @@ namespace Infrastructure.Unity
|
|||||||
{
|
{
|
||||||
_inputBlockTimer = 0.5f;
|
_inputBlockTimer = 0.5f;
|
||||||
_persistenceService = new PlayerPrefsPersistenceAdapter();
|
_persistenceService = new PlayerPrefsPersistenceAdapter();
|
||||||
_gameSession = new GameSession(_allTiles, _persistenceService);
|
_gameSession = new GameSession(_tileRegistry.AllTiles, _persistenceService);
|
||||||
|
|
||||||
// Set Theme based on High Score
|
// Set Theme based on High Score
|
||||||
ThemeManager.CurrentTheme = ThemeManager.GetTheme(_gameSession.HighScore);
|
ThemeManager.CurrentTheme = ThemeManager.GetTheme(_gameSession.HighScore);
|
||||||
|
|
||||||
var floorsCount = levelGenerator ? levelGenerator.FloorsCount : 1;
|
var floorsCount = levelGenerator?.Definition != null ? levelGenerator.Definition.FloorCount : 1;
|
||||||
|
|
||||||
if (levelGenerator)
|
if (levelGenerator)
|
||||||
{
|
{
|
||||||
StartCoroutine(levelGenerator.GenerateAsync(soundManager, _allTiles, _tileViews, cameraController,
|
StartCoroutine(levelGenerator.GenerateAsync(soundManager, _tileRegistry, cameraController,
|
||||||
rumbleManager,
|
rumbleManager,
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
@@ -84,23 +78,21 @@ namespace Infrastructure.Unity
|
|||||||
{
|
{
|
||||||
floorVisibilityManager = gameObject.AddComponent<FloorVisibilityManager>();
|
floorVisibilityManager = gameObject.AddComponent<FloorVisibilityManager>();
|
||||||
}
|
}
|
||||||
floorVisibilityManager.Initialize(_gameSession, _allTiles, _tileViews, floorsCount);
|
floorVisibilityManager.Initialize(_tileRegistry, floorsCount);
|
||||||
|
|
||||||
SpawnDeathPlane();
|
SpawnDeathPlane();
|
||||||
SpawnPlayer();
|
SpawnPlayer();
|
||||||
|
|
||||||
if (gameOverUi) gameOverUi.SetActive(false);
|
uiCoordinator?.ShowStartScreen();
|
||||||
if (startScreenUi) startScreenUi.SetActive(true); // Show start screen NOW
|
uiCoordinator?.UpdateHighScore(_gameSession.HighScore);
|
||||||
|
|
||||||
WireEvents();
|
WireEvents();
|
||||||
UpdateScoreUi(_gameSession.Score);
|
|
||||||
|
|
||||||
_levelGenerated = true;
|
_levelGenerated = true;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameOverUi) gameOverUi.SetActive(false);
|
uiCoordinator?.ShowStartScreen();
|
||||||
if (startScreenUi) startScreenUi.SetActive(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
@@ -134,9 +126,12 @@ namespace Infrastructure.Unity
|
|||||||
// Calculate current floor index based on Y height (inverse logic from Generator)
|
// Calculate current floor index based on Y height (inverse logic from Generator)
|
||||||
// Note: Generator uses negative offsets: 0, -15, -30.
|
// Note: Generator uses negative offsets: 0, -15, -30.
|
||||||
// So Floor 0 is at Y=0. Floor 1 is at Y=-15.
|
// So Floor 0 is at Y=0. Floor 1 is at Y=-15.
|
||||||
|
|
||||||
var heightDist = levelGenerator.FloorHeightDistance;
|
var def = levelGenerator.Definition;
|
||||||
var maxFloors = levelGenerator.FloorsCount;
|
if (def == null) return;
|
||||||
|
|
||||||
|
var heightDist = def.FloorHeightDistance;
|
||||||
|
var maxFloors = def.FloorCount;
|
||||||
|
|
||||||
var rawFloor = Mathf.RoundToInt(-playerY / heightDist);
|
var rawFloor = Mathf.RoundToInt(-playerY / heightDist);
|
||||||
_currentPlayerFloorIndex = Mathf.Clamp(rawFloor, 0, maxFloors - 1);
|
_currentPlayerFloorIndex = Mathf.Clamp(rawFloor, 0, maxFloors - 1);
|
||||||
@@ -155,9 +150,10 @@ namespace Infrastructure.Unity
|
|||||||
// Hard Mode: Decay faster as score increases
|
// Hard Mode: Decay faster as score increases
|
||||||
var decayMultiplier = 1.0f + (_gameSession.Score / 500f);
|
var decayMultiplier = 1.0f + (_gameSession.Score / 500f);
|
||||||
|
|
||||||
for (var i = _allTiles.Count - 1; i >= 0; i--)
|
var allTiles = _tileRegistry.AllTiles;
|
||||||
|
for (var i = allTiles.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
_allTiles[i].Tick(dt * dilation * decayMultiplier);
|
allTiles[i].Tick(dt * dilation * decayMultiplier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,14 +165,14 @@ namespace Infrastructure.Unity
|
|||||||
{
|
{
|
||||||
Time.timeScale = 0f;
|
Time.timeScale = 0f;
|
||||||
if (soundManager) soundManager.SetPaused(true);
|
if (soundManager) soundManager.SetPaused(true);
|
||||||
if (pauseUi) pauseUi.SetActive(true);
|
uiCoordinator?.ShowPauseUi();
|
||||||
if (rumbleManager) rumbleManager.SetPaused(true);
|
if (rumbleManager) rumbleManager.SetPaused(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Time.timeScale = 1f;
|
Time.timeScale = 1f;
|
||||||
if (soundManager) soundManager.SetPaused(false);
|
if (soundManager) soundManager.SetPaused(false);
|
||||||
if (pauseUi) pauseUi.SetActive(false);
|
uiCoordinator?.HidePauseUi();
|
||||||
if (rumbleManager) rumbleManager.SetPaused(false);
|
if (rumbleManager) rumbleManager.SetPaused(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +181,7 @@ namespace Infrastructure.Unity
|
|||||||
{
|
{
|
||||||
if (_currentOrbInstance) Destroy(_currentOrbInstance);
|
if (_currentOrbInstance) Destroy(_currentOrbInstance);
|
||||||
|
|
||||||
if (!_tileViews.TryGetValue(tileId, out var tileView)) return;
|
if (!_tileRegistry.TryGetView(tileId, out var tileView)) return;
|
||||||
if (!tileView) return;
|
if (!tileView) return;
|
||||||
|
|
||||||
var spawnPos = tileView.transform.position + Vector3.up;
|
var spawnPos = tileView.transform.position + Vector3.up;
|
||||||
@@ -204,34 +200,6 @@ namespace Infrastructure.Unity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateScoreUi(int newScore)
|
|
||||||
{
|
|
||||||
if (!scoreText) return;
|
|
||||||
|
|
||||||
LeanTween.cancel(scoreText.gameObject);
|
|
||||||
|
|
||||||
scoreText.rectTransform.localScale = Vector3.one;
|
|
||||||
LeanTween.scale(scoreText.rectTransform, Vector3.one * 1.5f, 0.5f)
|
|
||||||
.setEasePunch();
|
|
||||||
|
|
||||||
LeanTween.value(scoreText.gameObject, (float val) =>
|
|
||||||
{
|
|
||||||
var currentVal = Mathf.RoundToInt(val);
|
|
||||||
|
|
||||||
var combo = _gameSession?.ComboMultiplier ?? 1;
|
|
||||||
var comboText = combo > 1 ? $" <color=yellow>x{combo}</color>" : "";
|
|
||||||
|
|
||||||
scoreText.text = $"{currentVal}{comboText}";
|
|
||||||
}, _currentDisplayedScore, newScore, 0.5f)
|
|
||||||
.setEaseOutExpo();
|
|
||||||
|
|
||||||
_currentDisplayedScore = newScore;
|
|
||||||
|
|
||||||
if (highScoreText && _gameSession != null)
|
|
||||||
highScoreText.text = $"BEST: {_gameSession.HighScore}";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SpawnPlayer()
|
private void SpawnPlayer()
|
||||||
{
|
{
|
||||||
var spawnPos = new Vector3(0f, 5f, 0f);
|
var spawnPos = new Vector3(0f, 5f, 0f);
|
||||||
@@ -251,10 +219,11 @@ namespace Infrastructure.Unity
|
|||||||
{
|
{
|
||||||
if (!levelGenerator) return;
|
if (!levelGenerator) return;
|
||||||
|
|
||||||
var lowestY = -(levelGenerator.FloorsCount * levelGenerator.FloorHeightDistance) - 5f;
|
var def = levelGenerator.Definition;
|
||||||
var pos = new Vector3(levelGenerator.GridSizeX / 2f, lowestY, levelGenerator.GridSizeY / 2f);
|
var lowestY = -(def.FloorCount * def.FloorHeightDistance) - 5f;
|
||||||
|
var pos = new Vector3(def.GridSizeX / 2f, lowestY, def.GridSizeY / 2f);
|
||||||
var plane = Instantiate(deathPlanePrefab, pos, Quaternion.identity);
|
var plane = Instantiate(deathPlanePrefab, pos, Quaternion.identity);
|
||||||
plane.transform.localScale = new Vector3(levelGenerator.GridSizeX * 200f, 1f, levelGenerator.GridSizeY * 200f);
|
plane.transform.localScale = new Vector3(def.GridSizeX * 200f, 1f, def.GridSizeY * 200f);
|
||||||
|
|
||||||
plane.OnPlayerFell += () => _gameSession.EndGame();
|
plane.OnPlayerFell += () => _gameSession.EndGame();
|
||||||
}
|
}
|
||||||
@@ -264,8 +233,6 @@ namespace Infrastructure.Unity
|
|||||||
_isGameRunning = false;
|
_isGameRunning = false;
|
||||||
|
|
||||||
if (beatPulseController) beatPulseController.StopTracking();
|
if (beatPulseController) beatPulseController.StopTracking();
|
||||||
|
|
||||||
if (gameOverUi) gameOverUi.SetActive(true);
|
|
||||||
|
|
||||||
StartCoroutine(RestartRoutine());
|
StartCoroutine(RestartRoutine());
|
||||||
}
|
}
|
||||||
@@ -279,7 +246,7 @@ namespace Infrastructure.Unity
|
|||||||
|
|
||||||
private void WireEvents()
|
private void WireEvents()
|
||||||
{
|
{
|
||||||
_gameSession.OnScoreChanged += UpdateScoreUi;
|
uiCoordinator?.Subscribe(_gameSession);
|
||||||
_gameSession.OnOrbSpawned += SpawnVisualOrb;
|
_gameSession.OnOrbSpawned += SpawnVisualOrb;
|
||||||
_gameSession.OnOrbReset += HandleOrbReset;
|
_gameSession.OnOrbReset += HandleOrbReset;
|
||||||
_gameSession.OnGameOver += HandleGameOver;
|
_gameSession.OnGameOver += HandleGameOver;
|
||||||
@@ -303,18 +270,18 @@ namespace Infrastructure.Unity
|
|||||||
|
|
||||||
private void SpawnNpc()
|
private void SpawnNpc()
|
||||||
{
|
{
|
||||||
var validTiles = _allTiles.FindAll(t => t.Floor == 0 && t.CurrentState == TileState.Stable);
|
var validTiles = _tileRegistry.FindTiles(t => t.Floor == 0 && t.CurrentState == TileState.Stable);
|
||||||
|
|
||||||
if (validTiles.Count == 0)
|
if (validTiles.Count == 0)
|
||||||
{
|
{
|
||||||
validTiles = _allTiles.FindAll(t => t.CurrentState == TileState.Stable);
|
validTiles = _tileRegistry.FindTiles(t => t.CurrentState == TileState.Stable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (validTiles.Count == 0) return;
|
if (validTiles.Count == 0) return;
|
||||||
|
|
||||||
var randomTile = validTiles[Random.Range(0, validTiles.Count)];
|
var randomTile = validTiles[Random.Range(0, validTiles.Count)];
|
||||||
|
|
||||||
if (!_tileViews.TryGetValue(randomTile.Id, out var tileView)) return;
|
if (!_tileRegistry.TryGetView(randomTile.Id, out var tileView)) return;
|
||||||
if (!tileView) return;
|
if (!tileView) return;
|
||||||
|
|
||||||
var spawnPos = tileView.transform.position + Vector3.up * 5f;
|
var spawnPos = tileView.transform.position + Vector3.up * 5f;
|
||||||
@@ -336,9 +303,8 @@ namespace Infrastructure.Unity
|
|||||||
private void StartGameSequence()
|
private void StartGameSequence()
|
||||||
{
|
{
|
||||||
_isGameRunning = true;
|
_isGameRunning = true;
|
||||||
_currentDisplayedScore = 0;
|
|
||||||
|
uiCoordinator?.HideStartScreen();
|
||||||
if (startScreenUi) startScreenUi.SetActive(false);
|
|
||||||
|
|
||||||
if (soundManager)
|
if (soundManager)
|
||||||
{
|
{
|
||||||
@@ -359,7 +325,7 @@ namespace Infrastructure.Unity
|
|||||||
|
|
||||||
private void SpawnPowerUp(PowerUpType type, string tileId)
|
private void SpawnPowerUp(PowerUpType type, string tileId)
|
||||||
{
|
{
|
||||||
if (!_tileViews.TryGetValue(tileId, out var tileView)) return;
|
if (!_tileRegistry.TryGetView(tileId, out var tileView)) return;
|
||||||
if (!tileView) return;
|
if (!tileView) return;
|
||||||
|
|
||||||
var spawnPos = tileView.transform.position + Vector3.up * 0.5f;
|
var spawnPos = tileView.transform.position + Vector3.up * 0.5f;
|
||||||
@@ -367,35 +333,47 @@ namespace Infrastructure.Unity
|
|||||||
|
|
||||||
instance.Configure(type);
|
instance.Configure(type);
|
||||||
|
|
||||||
instance.OnCollected += (t) =>
|
instance.OnCollected += (t, dur) =>
|
||||||
{
|
{
|
||||||
cameraController?.Shake(0.2f, 0.15f);
|
cameraController?.Shake(0.2f, 0.15f);
|
||||||
rumbleManager?.PulseMedium();
|
rumbleManager?.PulseMedium();
|
||||||
|
|
||||||
if (t == PowerUpType.TimeSlow)
|
switch (t)
|
||||||
{
|
{
|
||||||
_gameSession.ActivateTimeSlow(10f);
|
case PowerUpType.TimeSlow:
|
||||||
|
_gameSession.ActivateTimeSlow(dur);
|
||||||
|
break;
|
||||||
|
case PowerUpType.LightFooted:
|
||||||
|
_playerInstance?.Status.AddEffect(new LightFootedEffect(dur));
|
||||||
|
break;
|
||||||
|
case PowerUpType.SpeedBoost:
|
||||||
|
_playerInstance?.Status.AddEffect(new SpeedBoostEffect(dur));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.LogWarning($"GameBootstrap: no effect handler for PowerUpType {t}");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBeatMeasure()
|
private void OnBeatMeasure()
|
||||||
{
|
{
|
||||||
if (_allTiles.Count == 0) return;
|
var allTiles = _tileRegistry.AllTiles;
|
||||||
|
if (allTiles.Count == 0) return;
|
||||||
|
|
||||||
var pulseCount = 25;
|
var pulseCount = 25;
|
||||||
|
|
||||||
for (var i = 0; i < pulseCount; i++)
|
for (var i = 0; i < pulseCount; i++)
|
||||||
{
|
{
|
||||||
var randIndex = Random.Range(0, _allTiles.Count);
|
var randIndex = Random.Range(0, allTiles.Count);
|
||||||
var tile = _allTiles[randIndex];
|
var tile = allTiles[randIndex];
|
||||||
|
|
||||||
if (tile.Floor < _currentPlayerFloorIndex) continue;
|
if (tile.Floor < _currentPlayerFloorIndex) continue;
|
||||||
if (tile.Floor > _currentPlayerFloorIndex + 1) continue;
|
if (tile.Floor > _currentPlayerFloorIndex + 1) continue;
|
||||||
|
|
||||||
if (tile.CurrentState != TileState.Stable) continue;
|
if (tile.CurrentState != TileState.Stable) continue;
|
||||||
|
|
||||||
if (_tileViews.TryGetValue(tile.Id, out var tileView))
|
if (_tileRegistry.TryGetView(tile.Id, out var tileView))
|
||||||
{
|
{
|
||||||
tileView.PulseEmission(Random.Range(1.2f, 2.0f));
|
tileView.PulseEmission(Random.Range(1.2f, 2.0f));
|
||||||
}
|
}
|
||||||
|
|||||||
86
Assets/Scripts/Infrastructure/Unity/GameUiCoordinator.cs
Normal file
86
Assets/Scripts/Infrastructure/Unity/GameUiCoordinator.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
using Core.Domain;
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Infrastructure.Unity
|
||||||
|
{
|
||||||
|
public class GameUiCoordinator : MonoBehaviour
|
||||||
|
{
|
||||||
|
[Header("References")]
|
||||||
|
[SerializeField] private TMP_Text scoreText;
|
||||||
|
[SerializeField] private TMP_Text highScoreText;
|
||||||
|
[SerializeField] private GameObject gameOverUi;
|
||||||
|
[SerializeField] private GameObject pauseUi;
|
||||||
|
[SerializeField] private GameObject startScreenUi;
|
||||||
|
|
||||||
|
private GameSession _session;
|
||||||
|
private int _currentDisplayedScore;
|
||||||
|
|
||||||
|
public void Subscribe(GameSession session)
|
||||||
|
{
|
||||||
|
_session = session;
|
||||||
|
session.OnScoreChanged += UpdateScore;
|
||||||
|
session.OnGameOver += ShowGameOverUi;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
if (_session == null) return;
|
||||||
|
_session.OnScoreChanged -= UpdateScore;
|
||||||
|
_session.OnGameOver -= ShowGameOverUi;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowStartScreen()
|
||||||
|
{
|
||||||
|
if (gameOverUi) gameOverUi.SetActive(false);
|
||||||
|
if (startScreenUi) startScreenUi.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HideStartScreen()
|
||||||
|
{
|
||||||
|
if (startScreenUi) startScreenUi.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowGameOverUi()
|
||||||
|
{
|
||||||
|
if (gameOverUi) gameOverUi.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowPauseUi()
|
||||||
|
{
|
||||||
|
if (pauseUi) pauseUi.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HidePauseUi()
|
||||||
|
{
|
||||||
|
if (pauseUi) pauseUi.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateHighScore(int highScore)
|
||||||
|
{
|
||||||
|
if (highScoreText) highScoreText.text = $"BEST: {highScore}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateScore(int newScore)
|
||||||
|
{
|
||||||
|
if (!scoreText) return;
|
||||||
|
|
||||||
|
LeanTween.cancel(scoreText.gameObject);
|
||||||
|
scoreText.rectTransform.localScale = Vector3.one;
|
||||||
|
LeanTween.scale(scoreText.rectTransform, Vector3.one * 1.5f, 0.5f).setEasePunch();
|
||||||
|
|
||||||
|
LeanTween.value(scoreText.gameObject, (float val) =>
|
||||||
|
{
|
||||||
|
var combo = _session?.ComboMultiplier ?? 1;
|
||||||
|
var comboText = combo > 1 ? $" <color=yellow>x{combo}</color>" : "";
|
||||||
|
scoreText.text = $"{Mathf.RoundToInt(val)}{comboText}";
|
||||||
|
}, _currentDisplayedScore, newScore, 0.5f)
|
||||||
|
.setEaseOutExpo();
|
||||||
|
|
||||||
|
_currentDisplayedScore = newScore;
|
||||||
|
|
||||||
|
if (highScoreText && _session != null)
|
||||||
|
highScoreText.text = $"BEST: {_session.HighScore}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b2d628098b45e36879d59d2c2c2bf061
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Core.Ports;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using KBCore.Refs;
|
using KBCore.Refs;
|
||||||
|
|
||||||
@@ -37,9 +38,9 @@ namespace Infrastructure.Unity
|
|||||||
|
|
||||||
if (Physics.Raycast(transform.position, Vector3.down, out var hit, 2f, tileLayer))
|
if (Physics.Raycast(transform.position, Vector3.down, out var hit, 2f, tileLayer))
|
||||||
{
|
{
|
||||||
if (hit.collider.TryGetComponent<TileViewAdapter>(out var tile))
|
if (hit.collider.TryGetComponent<ITileView>(out var tileView))
|
||||||
{
|
{
|
||||||
tile.OnPlayerStep();
|
tileView.StepOn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
39
Assets/Scripts/Infrastructure/Unity/LevelDefinition.cs
Normal file
39
Assets/Scripts/Infrastructure/Unity/LevelDefinition.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Infrastructure.Unity
|
||||||
|
{
|
||||||
|
[CreateAssetMenu(fileName = "LevelDefinition", menuName = "Decay Grid/Level Definition")]
|
||||||
|
public class LevelDefinition : ScriptableObject
|
||||||
|
{
|
||||||
|
[SerializeField] private int gridSizeX = 10;
|
||||||
|
[SerializeField] private int gridSizeY = 10;
|
||||||
|
[SerializeField] private float floorHeightDistance = 15f;
|
||||||
|
[SerializeField] private FloorConfig[] floors =
|
||||||
|
{
|
||||||
|
new() { pattern = FloorPatternType.Square },
|
||||||
|
new() { pattern = FloorPatternType.Donut },
|
||||||
|
new() { pattern = FloorPatternType.Circle }
|
||||||
|
};
|
||||||
|
|
||||||
|
public int GridSizeX => gridSizeX;
|
||||||
|
public int GridSizeY => gridSizeY;
|
||||||
|
public float FloorHeightDistance => floorHeightDistance;
|
||||||
|
public int FloorCount => floors.Length;
|
||||||
|
public IReadOnlyList<FloorConfig> Floors => floors;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class FloorConfig
|
||||||
|
{
|
||||||
|
public FloorPatternType pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum FloorPatternType
|
||||||
|
{
|
||||||
|
Square,
|
||||||
|
Donut,
|
||||||
|
Circle
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d1e67659d937881ee99b3b9e84f91428
|
||||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Core.Domain;
|
using Core.Domain;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Debug = UnityEngine.Debug;
|
||||||
using Random = UnityEngine.Random;
|
using Random = UnityEngine.Random;
|
||||||
|
|
||||||
namespace Infrastructure.Unity
|
namespace Infrastructure.Unity
|
||||||
@@ -16,50 +17,68 @@ namespace Infrastructure.Unity
|
|||||||
[SerializeField] private JumpPadAdapter jumpPadPrefab;
|
[SerializeField] private JumpPadAdapter jumpPadPrefab;
|
||||||
[SerializeField] private TeleporterAdapter teleporterPrefab;
|
[SerializeField] private TeleporterAdapter teleporterPrefab;
|
||||||
|
|
||||||
|
[Header("Level")]
|
||||||
|
[SerializeField] private LevelDefinition levelDefinition;
|
||||||
|
|
||||||
[Header("Settings")]
|
[Header("Settings")]
|
||||||
[SerializeField] private int gridSizeX = 10;
|
|
||||||
[SerializeField] private int gridSizeY = 10;
|
|
||||||
[SerializeField] private int floorsCount = 3;
|
|
||||||
[SerializeField] private float floorHeightDistance = 15f;
|
|
||||||
[SerializeField] private float decayTime = 0.5f;
|
[SerializeField] private float decayTime = 0.5f;
|
||||||
[SerializeField] private float fallingTime = 2.0f;
|
[SerializeField] private float fallingTime = 2.0f;
|
||||||
[SerializeField] private float minimumDistanceBetweenTeleporters = 3f;
|
[SerializeField] private float minimumDistanceBetweenTeleporters = 3f;
|
||||||
|
|
||||||
public float FloorHeightDistance => floorHeightDistance;
|
public LevelDefinition Definition => levelDefinition;
|
||||||
public int FloorsCount => floorsCount;
|
|
||||||
public int GridSizeX => gridSizeX;
|
|
||||||
public int GridSizeY => gridSizeY;
|
|
||||||
|
|
||||||
private TilePool _tilePool;
|
private TilePool _tilePool;
|
||||||
|
|
||||||
public IEnumerator GenerateAsync(SoundManager soundManager, List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera, RumbleManager rumble, Action onComplete)
|
public IEnumerator GenerateAsync(SoundManager soundManager, TileRegistry registry, CameraController camera, RumbleManager rumble, Action onComplete)
|
||||||
{
|
{
|
||||||
|
if (!levelDefinition)
|
||||||
|
{
|
||||||
|
Debug.LogError("LevelGenerator: levelDefinition is not assigned. Assign a LevelDefinition asset in the Inspector.");
|
||||||
|
onComplete?.Invoke();
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
_tilePool = new TilePool(tilePrefab, transform);
|
_tilePool = new TilePool(tilePrefab, transform);
|
||||||
|
|
||||||
var stopwatch = new Stopwatch();
|
var stopwatch = new Stopwatch();
|
||||||
stopwatch.Start();
|
stopwatch.Start();
|
||||||
|
|
||||||
yield return GenerateFloorAsync(0, MapPatterns.GenerateSquare(gridSizeX, gridSizeY), soundManager, allTiles, tileViews, camera, rumble, stopwatch);
|
for (var i = 0; i < levelDefinition.FloorCount; i++)
|
||||||
yield return GenerateFloorAsync(1, MapPatterns.GenerateDonut(gridSizeX, Mathf.FloorToInt(gridSizeX / 3f)), soundManager, allTiles, tileViews, camera, rumble, stopwatch);
|
{
|
||||||
yield return GenerateFloorAsync(2, MapPatterns.GenerateCircle(gridSizeX), soundManager, allTiles, tileViews, camera, rumble, stopwatch);
|
var coords = GetCoordsForFloor(levelDefinition.Floors[i].pattern);
|
||||||
|
yield return GenerateFloorAsync(i, coords, soundManager, registry, camera, rumble, stopwatch);
|
||||||
stopwatch?.Stop();
|
}
|
||||||
|
|
||||||
|
stopwatch.Stop();
|
||||||
onComplete?.Invoke();
|
onComplete?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator GenerateFloorAsync(int floorIndex, List<Vector2Int> coordinates, SoundManager soundManager,
|
private List<Vector2Int> GetCoordsForFloor(FloorPatternType pattern)
|
||||||
List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera, RumbleManager rumble, Stopwatch stopwatch)
|
|
||||||
{
|
{
|
||||||
var yOffset = -(floorIndex * floorHeightDistance);
|
var sizeX = levelDefinition.GridSizeX;
|
||||||
var xOffset = gridSizeX / 2f;
|
var sizeY = levelDefinition.GridSizeY;
|
||||||
var zOffset = gridSizeY / 2f;
|
return pattern switch
|
||||||
|
{
|
||||||
|
FloorPatternType.Square => MapPatterns.GenerateSquare(sizeX, sizeY),
|
||||||
|
FloorPatternType.Donut => MapPatterns.GenerateDonut(sizeX, Mathf.FloorToInt(sizeX / 3f)),
|
||||||
|
FloorPatternType.Circle => MapPatterns.GenerateCircle(sizeX),
|
||||||
|
_ => MapPatterns.GenerateSquare(sizeX, sizeY)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator GenerateFloorAsync(int floorIndex, List<Vector2Int> coordinates, SoundManager soundManager,
|
||||||
|
TileRegistry registry, CameraController camera, RumbleManager rumble, Stopwatch stopwatch)
|
||||||
|
{
|
||||||
|
var yOffset = -(floorIndex * levelDefinition.FloorHeightDistance);
|
||||||
|
var xOffset = levelDefinition.GridSizeX / 2f;
|
||||||
|
var zOffset = levelDefinition.GridSizeY / 2f;
|
||||||
|
|
||||||
const long frameBudgetMs = 5;
|
const long frameBudgetMs = 5;
|
||||||
|
|
||||||
foreach (var coord in coordinates)
|
foreach (var coord in coordinates)
|
||||||
{
|
{
|
||||||
var pos = new Vector3(coord.x - xOffset, yOffset, coord.y - zOffset);
|
var pos = new Vector3(coord.x - xOffset, yOffset, coord.y - zOffset);
|
||||||
CreateTile(pos, $"{floorIndex}_{coord.x}_{coord.y}", floorIndex, soundManager, allTiles, tileViews, camera, rumble);
|
CreateTile(pos, $"{floorIndex}_{coord.x}_{coord.y}", floorIndex, soundManager, registry, camera, rumble);
|
||||||
|
|
||||||
if (stopwatch.ElapsedMilliseconds > frameBudgetMs)
|
if (stopwatch.ElapsedMilliseconds > frameBudgetMs)
|
||||||
{
|
{
|
||||||
@@ -129,7 +148,7 @@ namespace Infrastructure.Unity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void CreateTile(Vector3 position, string id, int floorIndex, SoundManager soundManager,
|
private void CreateTile(Vector3 position, string id, int floorIndex, SoundManager soundManager,
|
||||||
List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera, RumbleManager rumble)
|
TileRegistry registry, CameraController camera, RumbleManager rumble)
|
||||||
{
|
{
|
||||||
var go = _tilePool.Get();
|
var go = _tilePool.Get();
|
||||||
go.transform.position = position;
|
go.transform.position = position;
|
||||||
@@ -172,8 +191,7 @@ namespace Infrastructure.Unity
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
allTiles.Add(tileLogic);
|
registry.Register(tileLogic, go);
|
||||||
tileViews.Add(id, go);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Core.Ports;
|
||||||
using KBCore.Refs;
|
using KBCore.Refs;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.AI;
|
using UnityEngine.AI;
|
||||||
@@ -49,9 +50,9 @@ namespace Infrastructure.Unity
|
|||||||
|
|
||||||
if (Physics.Raycast(transform.position, Vector3.down, out var hit, 2.0f, tileLayer))
|
if (Physics.Raycast(transform.position, Vector3.down, out var hit, 2.0f, tileLayer))
|
||||||
{
|
{
|
||||||
if (hit.collider.TryGetComponent<TileViewAdapter>(out var tile))
|
if (hit.collider.TryGetComponent<ITileView>(out var tileView))
|
||||||
{
|
{
|
||||||
tile.OnPlayerStep();
|
tileView.StepOn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using Core.Domain.Status;
|
using Core.Domain.Status;
|
||||||
using Core.Domain.Status.Effects;
|
using Core.Domain.Status.Effects;
|
||||||
|
using Core.Ports;
|
||||||
using KBCore.Refs;
|
using KBCore.Refs;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.InputSystem;
|
using UnityEngine.InputSystem;
|
||||||
@@ -244,9 +245,9 @@ namespace Infrastructure.Unity
|
|||||||
{
|
{
|
||||||
if (Physics.SphereCast(transform.position, 0.3f, Vector3.down, out var hit, groundCheckDistance, tileLayer))
|
if (Physics.SphereCast(transform.position, 0.3f, Vector3.down, out var hit, groundCheckDistance, tileLayer))
|
||||||
{
|
{
|
||||||
if (hit.collider.TryGetComponent<TileViewAdapter>(out var tileAdapter))
|
if (hit.collider.TryGetComponent<ITileView>(out var tileView))
|
||||||
{
|
{
|
||||||
tileAdapter.OnPlayerStep();
|
tileView.StepOn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Infrastructure.Unity
|
|||||||
private MaterialPropertyBlock _propBlock;
|
private MaterialPropertyBlock _propBlock;
|
||||||
private static readonly int ColorProperty = Shader.PropertyToID("_BaseColor");
|
private static readonly int ColorProperty = Shader.PropertyToID("_BaseColor");
|
||||||
|
|
||||||
public event Action<PowerUpType> OnCollected;
|
public event Action<PowerUpType, float> OnCollected;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
@@ -45,20 +45,16 @@ namespace Infrastructure.Unity
|
|||||||
|
|
||||||
private void OnTriggerEnter(Collider other)
|
private void OnTriggerEnter(Collider other)
|
||||||
{
|
{
|
||||||
if (other.TryGetComponent<PlayerController>(out var player))
|
if (other.TryGetComponent<PlayerController>(out _))
|
||||||
{
|
{
|
||||||
ApplyEffect(player);
|
OnCollected?.Invoke(type, duration);
|
||||||
OnCollected?.Invoke(type);
|
|
||||||
|
|
||||||
if (pickupVfx)
|
if (pickupVfx)
|
||||||
{
|
{
|
||||||
var vfx = Instantiate(pickupVfx, transform.position, Quaternion.identity);
|
var vfx = Instantiate(pickupVfx, transform.position, Quaternion.identity);
|
||||||
var main = vfx.main;
|
var main = vfx.main;
|
||||||
|
|
||||||
meshRenderer.GetPropertyBlock(_propBlock);
|
meshRenderer.GetPropertyBlock(_propBlock);
|
||||||
var currentColor = _propBlock.GetColor(ColorProperty);
|
main.startColor = _propBlock.GetColor(ColorProperty);
|
||||||
main.startColor = currentColor;
|
|
||||||
|
|
||||||
Destroy(vfx.gameObject, 2f);
|
Destroy(vfx.gameObject, 2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,24 +62,6 @@ namespace Infrastructure.Unity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplyEffect(PlayerController player)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case PowerUpType.LightFooted:
|
|
||||||
player.Status.AddEffect(new LightFootedEffect(duration));
|
|
||||||
break;
|
|
||||||
case PowerUpType.SpeedBoost:
|
|
||||||
player.Status.AddEffect(new SpeedBoostEffect(duration, 1.5f));
|
|
||||||
break;
|
|
||||||
case PowerUpType.TimeSlow:
|
|
||||||
// Handled globally
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Configure(PowerUpType newType)
|
public void Configure(PowerUpType newType)
|
||||||
{
|
{
|
||||||
type = newType;
|
type = newType;
|
||||||
|
|||||||
46
Assets/Scripts/Infrastructure/Unity/TileRegistry.cs
Normal file
46
Assets/Scripts/Infrastructure/Unity/TileRegistry.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Core.Domain;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Infrastructure.Unity
|
||||||
|
{
|
||||||
|
public class TileRegistry
|
||||||
|
{
|
||||||
|
private readonly List<Tile> _tiles = new();
|
||||||
|
private readonly Dictionary<string, TileViewAdapter> _views = new();
|
||||||
|
|
||||||
|
public IReadOnlyList<Tile> AllTiles => _tiles;
|
||||||
|
|
||||||
|
public void Register(Tile tile, TileViewAdapter view = null)
|
||||||
|
{
|
||||||
|
_tiles.Add(tile);
|
||||||
|
if (view != null) _views[tile.Id] = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetView(string tileId, out TileViewAdapter view)
|
||||||
|
=> _views.TryGetValue(tileId, out view);
|
||||||
|
|
||||||
|
public List<Tile> FindTiles(Predicate<Tile> predicate)
|
||||||
|
=> _tiles.FindAll(predicate);
|
||||||
|
|
||||||
|
public List<List<TileViewAdapter>> GroupViewsByFloor(int floorCount)
|
||||||
|
{
|
||||||
|
var floors = new List<List<TileViewAdapter>>(floorCount);
|
||||||
|
for (var i = 0; i < floorCount; i++) floors.Add(new List<TileViewAdapter>());
|
||||||
|
|
||||||
|
foreach (var tile in _tiles)
|
||||||
|
{
|
||||||
|
if (tile.Floor >= floorCount)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"TileRegistry: tile '{tile.Id}' floor {tile.Floor} >= floorCount {floorCount}, skipping");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_views.TryGetValue(tile.Id, out var view))
|
||||||
|
floors[tile.Floor].Add(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
return floors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Scripts/Infrastructure/Unity/TileRegistry.cs.meta
Normal file
2
Assets/Scripts/Infrastructure/Unity/TileRegistry.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b9e18fc22049e4e8c97b14af34cc4747
|
||||||
@@ -106,7 +106,7 @@ namespace Infrastructure.Unity
|
|||||||
StartCoroutine(ShrinkAndDestroy());
|
StartCoroutine(ShrinkAndDestroy());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnPlayerStep()
|
public void StepOn()
|
||||||
{
|
{
|
||||||
_linkedTile?.StepOn();
|
_linkedTile?.StepOn();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ MonoBehaviour:
|
|||||||
m_StripUnusedVariants: 1
|
m_StripUnusedVariants: 1
|
||||||
m_StripScreenCoordOverrideVariants: 1
|
m_StripScreenCoordOverrideVariants: 1
|
||||||
supportRuntimeDebugDisplay: 0
|
supportRuntimeDebugDisplay: 0
|
||||||
|
m_EnableRenderGraph: 0
|
||||||
m_Settings:
|
m_Settings:
|
||||||
m_SettingsList:
|
m_SettingsList:
|
||||||
m_List:
|
m_List:
|
||||||
@@ -68,7 +69,23 @@ MonoBehaviour:
|
|||||||
- rid: 2396665312000868355
|
- rid: 2396665312000868355
|
||||||
- rid: 2396665312000868356
|
- rid: 2396665312000868356
|
||||||
m_RuntimeSettings:
|
m_RuntimeSettings:
|
||||||
m_List: []
|
m_List:
|
||||||
|
- rid: 6852985685364965378
|
||||||
|
- rid: 6852985685364965379
|
||||||
|
- rid: 6852985685364965380
|
||||||
|
- rid: 6852985685364965381
|
||||||
|
- rid: 6852985685364965384
|
||||||
|
- rid: 6852985685364965385
|
||||||
|
- rid: 6852985685364965392
|
||||||
|
- rid: 6852985685364965394
|
||||||
|
- rid: 8712630790384254976
|
||||||
|
- rid: 3311242227245645828
|
||||||
|
- rid: 3311242227245645829
|
||||||
|
- rid: 3311242227245645830
|
||||||
|
- rid: 3311242227245645832
|
||||||
|
- rid: 3311242227245645834
|
||||||
|
- rid: 3311242227245645835
|
||||||
|
- rid: 2396665312000868354
|
||||||
m_AssetVersion: 10
|
m_AssetVersion: 10
|
||||||
m_ObsoleteDefaultVolumeProfile: {fileID: 0}
|
m_ObsoleteDefaultVolumeProfile: {fileID: 0}
|
||||||
m_RenderingLayerNames:
|
m_RenderingLayerNames:
|
||||||
@@ -99,6 +116,8 @@ MonoBehaviour:
|
|||||||
references:
|
references:
|
||||||
version: 2
|
version: 2
|
||||||
RefIds:
|
RefIds:
|
||||||
|
- rid: -2
|
||||||
|
type: {class: , ns: , asm: }
|
||||||
- rid: 2396665312000868354
|
- rid: 2396665312000868354
|
||||||
type: {class: UniversalRenderPipelineRuntimeTerrainShaders, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}
|
type: {class: UniversalRenderPipelineRuntimeTerrainShaders, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}
|
||||||
data:
|
data:
|
||||||
@@ -362,6 +381,7 @@ MonoBehaviour:
|
|||||||
type: {class: RenderGraphSettings, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}
|
type: {class: RenderGraphSettings, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}
|
||||||
data:
|
data:
|
||||||
m_Version: 0
|
m_Version: 0
|
||||||
|
m_EnableRenderCompatibilityMode: 0
|
||||||
- rid: 6852985685364965386
|
- rid: 6852985685364965386
|
||||||
type: {class: GPUResidentDrawerResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.GPUDriven.Runtime}
|
type: {class: GPUResidentDrawerResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.GPUDriven.Runtime}
|
||||||
data:
|
data:
|
||||||
|
|||||||
8
Assets/Tests.meta
Normal file
8
Assets/Tests.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0980498940170826f97da8599b70e474
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Assets/Tests/EditMode.meta
Normal file
8
Assets/Tests/EditMode.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 84756af79e10fce108b1a3dd15cbe7ae
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
44
Assets/Tests/EditMode/StatusManagerTests.cs
Normal file
44
Assets/Tests/EditMode/StatusManagerTests.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using Core.Domain.Status;
|
||||||
|
using Core.Domain.Status.Effects;
|
||||||
|
|
||||||
|
namespace DecayGrid.Tests
|
||||||
|
{
|
||||||
|
public class StatusManagerTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void DefaultCapabilities_HaveExpectedValues()
|
||||||
|
{
|
||||||
|
var sm = new StatusManager();
|
||||||
|
var caps = sm.CurrentCapabilities;
|
||||||
|
Assert.IsTrue(caps.CanTriggerDecay);
|
||||||
|
Assert.AreEqual(1f, caps.SpeedMultiplier, 0.001f);
|
||||||
|
Assert.IsFalse(caps.CanHover);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SpeedBoostAlone_AppliesMultiplier()
|
||||||
|
{
|
||||||
|
var sm = new StatusManager();
|
||||||
|
sm.AddEffect(new SpeedBoostEffect(10f, 1.5f));
|
||||||
|
Assert.AreEqual(1.5f, sm.CurrentCapabilities.SpeedMultiplier, 0.001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void LightFootedAlone_AppliesMultiplier()
|
||||||
|
{
|
||||||
|
var sm = new StatusManager();
|
||||||
|
sm.AddEffect(new LightFootedEffect(10f));
|
||||||
|
Assert.AreEqual(1.2f, sm.CurrentCapabilities.SpeedMultiplier, 0.001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TwoSpeedEffectsStack_Multiplicatively()
|
||||||
|
{
|
||||||
|
var sm = new StatusManager();
|
||||||
|
sm.AddEffect(new LightFootedEffect(10f)); // *1.2
|
||||||
|
sm.AddEffect(new SpeedBoostEffect(10f, 1.5f)); // *1.5
|
||||||
|
Assert.AreEqual(1.8f, sm.CurrentCapabilities.SpeedMultiplier, 0.001f); // 1.0 * 1.2 * 1.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Tests/EditMode/StatusManagerTests.cs.meta
Normal file
2
Assets/Tests/EditMode/StatusManagerTests.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 14aaf27a4073981cea2d26cc74361e3d
|
||||||
69
Assets/Tests/EditMode/TileRegistryTests.cs
Normal file
69
Assets/Tests/EditMode/TileRegistryTests.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using Core.Domain;
|
||||||
|
using Infrastructure.Unity;
|
||||||
|
|
||||||
|
namespace DecayGrid.Tests
|
||||||
|
{
|
||||||
|
public class TileRegistryTests
|
||||||
|
{
|
||||||
|
private TileRegistry _registry;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp() => _registry = new TileRegistry();
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Register_AddsToAllTiles()
|
||||||
|
{
|
||||||
|
var tile = new Tile("0_0_0", 0, 0.5f, 2f);
|
||||||
|
_registry.Register(tile);
|
||||||
|
Assert.AreEqual(1, _registry.AllTiles.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FindTiles_ReturnsMatchingTiles()
|
||||||
|
{
|
||||||
|
var tile = new Tile("0_0_0", 0, 0.5f, 2f);
|
||||||
|
_registry.Register(tile);
|
||||||
|
var result = _registry.FindTiles(t => t.CurrentState == TileState.Stable);
|
||||||
|
Assert.AreEqual(1, result.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FindTiles_ExcludesNonMatchingTiles()
|
||||||
|
{
|
||||||
|
var tile = new Tile("0_0_0", 0, 0.5f, 2f);
|
||||||
|
tile.StepOn(); // Now Warning
|
||||||
|
_registry.Register(tile);
|
||||||
|
var result = _registry.FindTiles(t => t.CurrentState == TileState.Stable);
|
||||||
|
Assert.AreEqual(0, result.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TryGetView_ReturnsFalse_WhenTileHasNoView()
|
||||||
|
{
|
||||||
|
var tile = new Tile("0_0_0", 0, 0.5f, 2f);
|
||||||
|
_registry.Register(tile); // no view
|
||||||
|
Assert.IsFalse(_registry.TryGetView("0_0_0", out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GroupViewsByFloor_PlacesTileOnCorrectFloor()
|
||||||
|
{
|
||||||
|
// Can't create TileViewAdapter in EditMode (MonoBehaviour), so just verify tile with no view doesn't crash
|
||||||
|
var tile = new Tile("1_5_5", 1, 0.5f, 2f);
|
||||||
|
_registry.Register(tile); // no view
|
||||||
|
var floors = _registry.GroupViewsByFloor(3);
|
||||||
|
Assert.AreEqual(3, floors.Count);
|
||||||
|
// Tile has no view registered, so no view should appear in any floor
|
||||||
|
Assert.AreEqual(0, floors[1].Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GroupViewsByFloor_OutOfRangeTile_DoesNotThrow()
|
||||||
|
{
|
||||||
|
var tile = new Tile("5_0_0", 5, 0.5f, 2f); // floor 5, but only 3 floors
|
||||||
|
_registry.Register(tile);
|
||||||
|
Assert.DoesNotThrow(() => _registry.GroupViewsByFloor(3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Tests/EditMode/TileRegistryTests.cs.meta
Normal file
2
Assets/Tests/EditMode/TileRegistryTests.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8d6a64903e18ff18094c2db56bf61f38
|
||||||
@@ -8,8 +8,10 @@
|
|||||||
"com.unity.inputsystem": "1.19.0",
|
"com.unity.inputsystem": "1.19.0",
|
||||||
"com.unity.multiplayer.center": "1.0.1",
|
"com.unity.multiplayer.center": "1.0.1",
|
||||||
"com.unity.render-pipelines.universal": "17.4.0",
|
"com.unity.render-pipelines.universal": "17.4.0",
|
||||||
|
"com.unity.sdk.linux-x86_64": "1.1.0",
|
||||||
"com.unity.test-framework": "1.6.0",
|
"com.unity.test-framework": "1.6.0",
|
||||||
"com.unity.timeline": "1.8.12",
|
"com.unity.timeline": "1.8.12",
|
||||||
|
"com.unity.toolchain.linux-x86_64-linux": "1.1.0",
|
||||||
"com.unity.ugui": "2.0.0",
|
"com.unity.ugui": "2.0.0",
|
||||||
"com.unity.visualscripting": "1.9.11",
|
"com.unity.visualscripting": "1.9.11",
|
||||||
"com.unity.modules.accessibility": "1.0.0",
|
"com.unity.modules.accessibility": "1.0.0",
|
||||||
|
|||||||
@@ -34,16 +34,17 @@
|
|||||||
"url": "https://packages.unity.com"
|
"url": "https://packages.unity.com"
|
||||||
},
|
},
|
||||||
"com.unity.collections": {
|
"com.unity.collections": {
|
||||||
"version": "6.4.0",
|
"version": "2.6.5",
|
||||||
"depth": 2,
|
"depth": 2,
|
||||||
"source": "builtin",
|
"source": "registry",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.burst": "1.8.23",
|
"com.unity.burst": "1.8.27",
|
||||||
"com.unity.mathematics": "1.3.2",
|
"com.unity.mathematics": "1.3.2",
|
||||||
"com.unity.nuget.mono-cecil": "1.11.5",
|
|
||||||
"com.unity.test-framework": "1.4.6",
|
"com.unity.test-framework": "1.4.6",
|
||||||
|
"com.unity.nuget.mono-cecil": "1.11.6",
|
||||||
"com.unity.test-framework.performance": "3.0.3"
|
"com.unity.test-framework.performance": "3.0.3"
|
||||||
}
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
},
|
},
|
||||||
"com.unity.ext.nunit": {
|
"com.unity.ext.nunit": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
@@ -101,7 +102,7 @@
|
|||||||
"url": "https://packages.unity.com"
|
"url": "https://packages.unity.com"
|
||||||
},
|
},
|
||||||
"com.unity.render-pipelines.core": {
|
"com.unity.render-pipelines.core": {
|
||||||
"version": "17.4.0",
|
"version": "17.3.0",
|
||||||
"depth": 1,
|
"depth": 1,
|
||||||
"source": "builtin",
|
"source": "builtin",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -109,28 +110,38 @@
|
|||||||
"com.unity.mathematics": "1.3.2",
|
"com.unity.mathematics": "1.3.2",
|
||||||
"com.unity.ugui": "2.0.0",
|
"com.unity.ugui": "2.0.0",
|
||||||
"com.unity.collections": "2.4.3",
|
"com.unity.collections": "2.4.3",
|
||||||
|
"com.unity.modules.physics": "1.0.0",
|
||||||
"com.unity.modules.terrain": "1.0.0",
|
"com.unity.modules.terrain": "1.0.0",
|
||||||
"com.unity.modules.jsonserialize": "1.0.0"
|
"com.unity.modules.jsonserialize": "1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"com.unity.render-pipelines.universal": {
|
"com.unity.render-pipelines.universal": {
|
||||||
"version": "17.4.0",
|
"version": "17.3.0",
|
||||||
"depth": 0,
|
"depth": 0,
|
||||||
"source": "builtin",
|
"source": "builtin",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.render-pipelines.core": "17.4.0",
|
"com.unity.render-pipelines.core": "17.3.0",
|
||||||
"com.unity.shadergraph": "17.4.0",
|
"com.unity.shadergraph": "17.3.0",
|
||||||
"com.unity.render-pipelines.universal-config": "17.4.0"
|
"com.unity.render-pipelines.universal-config": "17.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"com.unity.render-pipelines.universal-config": {
|
"com.unity.render-pipelines.universal-config": {
|
||||||
"version": "17.4.0",
|
"version": "17.0.3",
|
||||||
"depth": 1,
|
"depth": 1,
|
||||||
"source": "builtin",
|
"source": "builtin",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.render-pipelines.core": "17.4.0"
|
"com.unity.render-pipelines.core": "17.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"com.unity.sdk.linux-x86_64": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.sysroot.base": "1.1.0"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
"com.unity.searcher": {
|
"com.unity.searcher": {
|
||||||
"version": "4.9.4",
|
"version": "4.9.4",
|
||||||
"depth": 2,
|
"depth": 2,
|
||||||
@@ -139,14 +150,21 @@
|
|||||||
"url": "https://packages.unity.com"
|
"url": "https://packages.unity.com"
|
||||||
},
|
},
|
||||||
"com.unity.shadergraph": {
|
"com.unity.shadergraph": {
|
||||||
"version": "17.4.0",
|
"version": "17.3.0",
|
||||||
"depth": 1,
|
"depth": 1,
|
||||||
"source": "builtin",
|
"source": "builtin",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.render-pipelines.core": "17.4.0",
|
"com.unity.render-pipelines.core": "17.3.0",
|
||||||
"com.unity.searcher": "4.9.3"
|
"com.unity.searcher": "4.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"com.unity.sysroot.base": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"depth": 1,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
"com.unity.test-framework": {
|
"com.unity.test-framework": {
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"depth": 0,
|
"depth": 0,
|
||||||
@@ -179,6 +197,15 @@
|
|||||||
},
|
},
|
||||||
"url": "https://packages.unity.com"
|
"url": "https://packages.unity.com"
|
||||||
},
|
},
|
||||||
|
"com.unity.toolchain.linux-x86_64-linux": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.sysroot.base": "1.1.0"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
"com.unity.ugui": {
|
"com.unity.ugui": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"depth": 0,
|
"depth": 0,
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ PlayerSettings:
|
|||||||
xboxEnableGuest: 0
|
xboxEnableGuest: 0
|
||||||
xboxEnablePIXSampling: 0
|
xboxEnablePIXSampling: 0
|
||||||
metalFramebufferOnly: 0
|
metalFramebufferOnly: 0
|
||||||
|
metalUseMetalDisplayLink: 0
|
||||||
xboxOneResolution: 0
|
xboxOneResolution: 0
|
||||||
xboxOneSResolution: 0
|
xboxOneSResolution: 0
|
||||||
xboxOneXResolution: 3
|
xboxOneXResolution: 3
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
m_EditorVersion: 6000.4.3f1
|
m_EditorVersion: 6000.3.15f1
|
||||||
m_EditorVersionWithRevision: 6000.4.3f1 (39d1a88d4dd1)
|
m_EditorVersionWithRevision: 6000.3.15f1 (c1aa84e375f6)
|
||||||
|
|||||||
1327
docs/superpowers/plans/2026-05-14-architecture-refactor.md
Normal file
1327
docs/superpowers/plans/2026-05-14-architecture-refactor.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user