convert game playing..
This commit is contained in:
@@ -53,13 +53,17 @@ namespace BumpCombat.UI
|
||||
private Button[] debugSpawnButtons = System.Array.Empty<Button>();
|
||||
private GameObject minimapPanel;
|
||||
private RectTransform minimapMapRect;
|
||||
private RectTransform minimapTerrainRoot;
|
||||
private RectTransform minimapMarkerRoot;
|
||||
private RectTransform minimapViewportRoot;
|
||||
private Image minimapPlayerMarker;
|
||||
private Image[] minimapViewportEdges = System.Array.Empty<Image>();
|
||||
private readonly List<Image> minimapEnemyMarkers = new();
|
||||
private readonly Dictionary<Vector2Int, Image> minimapTerrainCells = new();
|
||||
private EnemyController[] minimapEnemies = System.Array.Empty<EnemyController>();
|
||||
private float minimapEnemyRefreshElapsed;
|
||||
private Stage.ZoneInstance minimapTerrainZone;
|
||||
private int minimapTerrainVisibilityRevision = -1;
|
||||
private ArenaBounds arenaBounds;
|
||||
// The panel sprite has transparent source padding. At multiplier 1,
|
||||
// 6px of canvas space keeps the map inside the visible frame.
|
||||
@@ -68,22 +72,9 @@ namespace BumpCombat.UI
|
||||
private Image[] artifactSlotIcons = System.Array.Empty<Image>();
|
||||
private readonly Stack<Text> damagePopupPool = new();
|
||||
private readonly HashSet<Text> activeDamagePopups = new();
|
||||
private static readonly RunTimedEvent[] NextBossEvents =
|
||||
{
|
||||
RunTimedEvent.MidBoss,
|
||||
RunTimedEvent.FinalBoss,
|
||||
};
|
||||
private static readonly string[] NextBossLabels =
|
||||
{
|
||||
"다음 중간보스",
|
||||
"다음 보스",
|
||||
};
|
||||
private int activeDamagePopupCount;
|
||||
private int damagePopupLifecycleVersion;
|
||||
private float compactHudFadeElapsed;
|
||||
private int lastNextEventSecond = -1;
|
||||
private bool lastNextEventUsesDebugTimes;
|
||||
private bool lastNextEventIsProductionRun;
|
||||
private static readonly Color PlayerDamagePopupColor =
|
||||
new(244f / 255f, 117f / 255f, 112f / 255f, 1f);
|
||||
private static readonly Color GuardReadyColor = new Color32(255, 205, 92, 255);
|
||||
@@ -741,61 +732,25 @@ namespace BumpCombat.UI
|
||||
new Vector2(0f, -100f),
|
||||
new Vector2(420f, 28f));
|
||||
ConfigureCompactHudText(eventText, 14, 18);
|
||||
eventText.gameObject.SetActive(true);
|
||||
eventText.gameObject.SetActive(false);
|
||||
UpdateNextEventHud();
|
||||
}
|
||||
|
||||
private void UpdateNextEventHud()
|
||||
{
|
||||
if (eventText == null || runManager == null || showingTimedEventMessage)
|
||||
if (eventText == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int elapsedSecond = Mathf.FloorToInt(runManager.ElapsedTime);
|
||||
if (elapsedSecond == lastNextEventSecond
|
||||
&& runManager.UseDebugEventTimes == lastNextEventUsesDebugTimes
|
||||
&& runManager.IsProductionRun == lastNextEventIsProductionRun)
|
||||
if (!showingTimedEventMessage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lastNextEventSecond = elapsedSecond;
|
||||
lastNextEventUsesDebugTimes = runManager.UseDebugEventTimes;
|
||||
lastNextEventIsProductionRun = runManager.IsProductionRun;
|
||||
float nextTime = float.PositiveInfinity;
|
||||
string nextLabel = "다음 이벤트 없음";
|
||||
for (int i = 0; i < runManager.CurrentEliteEventCount; i++)
|
||||
{
|
||||
float eliteTime = runManager.GetEliteEventTimeForCurrentRun(i);
|
||||
if (eliteTime > runManager.ElapsedTime)
|
||||
if (eventText.gameObject.activeSelf)
|
||||
{
|
||||
nextTime = eliteTime;
|
||||
nextLabel = "다음 엘리트";
|
||||
break;
|
||||
eventText.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < NextBossEvents.Length; i++)
|
||||
{
|
||||
float eventTime = runManager.GetEventTimeForCurrentRun(
|
||||
NextBossEvents[i]);
|
||||
if (eventTime > runManager.ElapsedTime && eventTime < nextTime)
|
||||
{
|
||||
nextTime = eventTime;
|
||||
nextLabel = NextBossLabels[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (float.IsPositiveInfinity(nextTime))
|
||||
{
|
||||
eventText.text = nextLabel;
|
||||
return;
|
||||
}
|
||||
|
||||
int seconds = Mathf.FloorToInt(nextTime);
|
||||
eventText.text =
|
||||
$"{nextLabel} {seconds / 60:00}:{seconds % 60:00}";
|
||||
}
|
||||
|
||||
private void LayoutDebugText()
|
||||
@@ -844,6 +799,20 @@ namespace BumpCombat.UI
|
||||
{
|
||||
popupText = $"LAUNCH {popupText}";
|
||||
}
|
||||
|
||||
EnemyController popupEnemy = result.Target != null
|
||||
? result.Target.GetComponentInParent<EnemyController>()
|
||||
: null;
|
||||
Stage.ZoneInstance popupZone = Stage.StageManager.Instance != null
|
||||
? Stage.StageManager.Instance.CurrentZone
|
||||
: null;
|
||||
if (popupEnemy != null
|
||||
&& popupZone != null
|
||||
&& !popupZone.IsWorldPositionVisible(popupEnemy.GroundAnchorPosition))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Color popupColor;
|
||||
if (!TryGetArtifactPopupColor(result, out popupColor))
|
||||
{
|
||||
@@ -1271,7 +1240,7 @@ namespace BumpCombat.UI
|
||||
RunTimedEvent.MidBoss,
|
||||
RunTimedEvent.FinalBoss,
|
||||
};
|
||||
string[] labels = { "엘리트 출현", "중간보스 출현", "보스 출현" };
|
||||
string[] labels = { "엘리트 출현", "중간보스 출현", "보스방 이동" };
|
||||
debugSpawnButtons = new Button[events.Length];
|
||||
for (int i = 0; i < events.Length; i++)
|
||||
{
|
||||
@@ -1296,16 +1265,30 @@ namespace BumpCombat.UI
|
||||
Button button = buttonObject.GetComponent<Button>();
|
||||
button.targetGraphic = image;
|
||||
PresentationUiStyle.ApplyButton(button);
|
||||
RunTimedEvent requestedEvent = events[i];
|
||||
button.onClick.AddListener(() =>
|
||||
if (i == 2)
|
||||
{
|
||||
if (spawnDirector != null
|
||||
&& spawnDirector.TryDebugSpawnEventEnemy(requestedEvent))
|
||||
button.onClick.AddListener(() =>
|
||||
{
|
||||
HandleTimedEvent(requestedEvent);
|
||||
}
|
||||
UpdateDebugSpawnHud();
|
||||
});
|
||||
if (Stage.StageManager.Instance != null)
|
||||
{
|
||||
Stage.StageManager.Instance.CheatTeleportToBossRoom();
|
||||
}
|
||||
UpdateDebugSpawnHud();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
RunTimedEvent requestedEvent = events[i];
|
||||
button.onClick.AddListener(() =>
|
||||
{
|
||||
if (spawnDirector != null
|
||||
&& spawnDirector.TryDebugSpawnEventEnemy(requestedEvent))
|
||||
{
|
||||
HandleTimedEvent(requestedEvent);
|
||||
}
|
||||
UpdateDebugSpawnHud();
|
||||
});
|
||||
}
|
||||
CreateRuntimeText(
|
||||
buttonObject.transform,
|
||||
"Label",
|
||||
@@ -1327,7 +1310,7 @@ namespace BumpCombat.UI
|
||||
|
||||
bool visible = runManager != null && runManager.UseDebugArtifactSelection;
|
||||
debugSpawnPanel.SetActive(visible);
|
||||
if (!visible || spawnDirector == null)
|
||||
if (!visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1338,10 +1321,19 @@ namespace BumpCombat.UI
|
||||
RunTimedEvent.MidBoss,
|
||||
RunTimedEvent.FinalBoss,
|
||||
};
|
||||
bool inputEnabled = RunManager.GameplayInputEnabled;
|
||||
for (int i = 0; i < debugSpawnButtons.Length; i++)
|
||||
{
|
||||
debugSpawnButtons[i].interactable =
|
||||
spawnDirector.CanDebugSpawnEventEnemy(events[i]);
|
||||
if (i == 2)
|
||||
{
|
||||
debugSpawnButtons[i].interactable =
|
||||
inputEnabled && Stage.StageManager.Instance != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
debugSpawnButtons[i].interactable =
|
||||
spawnDirector != null && spawnDirector.CanDebugSpawnEventEnemy(events[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1370,7 +1362,7 @@ namespace BumpCombat.UI
|
||||
new Vector2(panelWidth, panelHeight));
|
||||
Image minimapFrame = minimapPanel.GetComponent<Image>();
|
||||
PresentationUiStyle.ApplyPanel(minimapFrame);
|
||||
minimapFrame.pixelsPerUnitMultiplier = 1f;
|
||||
minimapFrame.pixelsPerUnitMultiplier = PresentationUiStyle.ThreePixelBorderMultiplier;
|
||||
minimapFrame.fillCenter = false;
|
||||
|
||||
GameObject map = CreateRuntimePanel(
|
||||
@@ -1384,6 +1376,7 @@ namespace BumpCombat.UI
|
||||
map.GetComponent<Image>().color = new Color(0.035f, 0.06f, 0.08f, 0.28f);
|
||||
map.AddComponent<RectMask2D>();
|
||||
|
||||
minimapTerrainRoot = CreateMinimapLayer(map.transform, "Minimap Terrain");
|
||||
minimapMarkerRoot = CreateMinimapLayer(map.transform, "Markers");
|
||||
minimapViewportRoot = CreateMinimapLayer(map.transform, "Minimap Camera Viewport");
|
||||
minimapMarkerRoot.SetAsLastSibling();
|
||||
@@ -1453,6 +1446,8 @@ namespace BumpCombat.UI
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateMinimapTerrain();
|
||||
|
||||
SetMinimapMarkerPosition(
|
||||
minimapPlayerMarker,
|
||||
playerHealth != null ? playerHealth.transform.position : Vector3.zero,
|
||||
@@ -1469,6 +1464,9 @@ namespace BumpCombat.UI
|
||||
}
|
||||
|
||||
int markerIndex = 0;
|
||||
Stage.ZoneInstance visibilityZone = Stage.StageManager.Instance != null
|
||||
? Stage.StageManager.Instance.CurrentZone
|
||||
: null;
|
||||
for (int i = 0; i < minimapEnemies.Length; i++)
|
||||
{
|
||||
EnemyController enemy = minimapEnemies[i];
|
||||
@@ -1476,6 +1474,16 @@ namespace BumpCombat.UI
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (worldCamera == null
|
||||
|| !arenaBounds.IsInsideCameraVisible(worldCamera, enemy.GroundAnchorPosition))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (visibilityZone != null
|
||||
&& !visibilityZone.IsWorldPositionVisible(enemy.GroundAnchorPosition))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Image marker = GetMinimapEnemyMarker(markerIndex++);
|
||||
marker.gameObject.SetActive(true);
|
||||
@@ -1499,6 +1507,132 @@ namespace BumpCombat.UI
|
||||
UpdateMinimapViewport(extents);
|
||||
}
|
||||
|
||||
private void UpdateMinimapTerrain()
|
||||
{
|
||||
Stage.ZoneInstance currentZone = Stage.StageManager.Instance != null
|
||||
? Stage.StageManager.Instance.CurrentZone
|
||||
: null;
|
||||
if (currentZone == minimapTerrainZone)
|
||||
{
|
||||
if (currentZone != null
|
||||
&& currentZone.VisibilityRevision != minimapTerrainVisibilityRevision)
|
||||
{
|
||||
UpdateMinimapTerrainVisibility(currentZone);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
minimapTerrainZone = currentZone;
|
||||
minimapTerrainVisibilityRevision = -1;
|
||||
minimapTerrainCells.Clear();
|
||||
if (minimapTerrainRoot == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = minimapTerrainRoot.childCount - 1; i >= 0; i--)
|
||||
{
|
||||
Destroy(minimapTerrainRoot.GetChild(i).gameObject);
|
||||
}
|
||||
|
||||
Stage.RoomPreset preset = currentZone != null ? currentZone.Preset : null;
|
||||
if (preset == null || !currentZone.HasRuntimeGrid ||
|
||||
preset.GridWidth <= 0 || preset.GridHeight <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 mapSize = minimapMapRect.rect.size;
|
||||
float cellWidth = mapSize.x / preset.GridWidth;
|
||||
float cellHeight = mapSize.y / preset.GridHeight;
|
||||
float left = -mapSize.x * 0.5f;
|
||||
float top = mapSize.y * 0.5f;
|
||||
|
||||
for (int y = 0; y < preset.GridHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < preset.GridWidth; x++)
|
||||
{
|
||||
Stage.PresetCellType cellType = currentZone.GetRuntimeCell(x, y);
|
||||
if (cellType == Stage.PresetCellType.Empty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Image cell = CreateRuntimeImage(
|
||||
minimapTerrainRoot,
|
||||
$"Terrain {x},{y}",
|
||||
Vector2.zero,
|
||||
new Vector2(cellWidth + 0.2f, cellHeight + 0.2f));
|
||||
cell.raycastTarget = false;
|
||||
minimapTerrainCells[new Vector2Int(x, y)] = cell;
|
||||
SetRectTransform(
|
||||
cell.rectTransform,
|
||||
new Vector2(0.5f, 0.5f),
|
||||
new Vector2(0.5f, 0.5f),
|
||||
new Vector2(
|
||||
left + (x + 0.5f) * cellWidth,
|
||||
top - (y + 0.5f) * cellHeight),
|
||||
cell.rectTransform.sizeDelta);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateMinimapTerrainVisibility(currentZone);
|
||||
}
|
||||
|
||||
private void UpdateMinimapTerrainVisibility(Stage.ZoneInstance zone)
|
||||
{
|
||||
if (zone == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<Vector2Int, Image> entry in minimapTerrainCells)
|
||||
{
|
||||
Vector2Int cell = entry.Key;
|
||||
if (entry.Value == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
entry.Value.color = GetMinimapTerrainColor(
|
||||
zone.GetRuntimeCell(cell.x, cell.y),
|
||||
zone.IsCellVisible(cell.x, cell.y),
|
||||
zone.IsCellExplored(cell.x, cell.y));
|
||||
}
|
||||
|
||||
minimapTerrainVisibilityRevision = zone.VisibilityRevision;
|
||||
}
|
||||
|
||||
private static Color GetMinimapTerrainColor(
|
||||
Stage.PresetCellType cellType,
|
||||
bool visible,
|
||||
bool explored)
|
||||
{
|
||||
Color baseColor = cellType switch
|
||||
{
|
||||
Stage.PresetCellType.Obstacle => new Color32(12, 18, 22, 240),
|
||||
Stage.PresetCellType.Socket => new Color32(54, 103, 112, 230),
|
||||
Stage.PresetCellType.RewardAnchor => new Color32(73, 88, 70, 205),
|
||||
_ => new Color32(41, 57, 62, 190),
|
||||
};
|
||||
|
||||
if (visible)
|
||||
{
|
||||
return baseColor;
|
||||
}
|
||||
|
||||
if (explored)
|
||||
{
|
||||
return new Color(
|
||||
baseColor.r * 0.35f,
|
||||
baseColor.g * 0.35f,
|
||||
baseColor.b * 0.35f,
|
||||
1f);
|
||||
}
|
||||
|
||||
return new Color32(2, 4, 5, 255);
|
||||
}
|
||||
|
||||
private Image GetMinimapEnemyMarker(int index)
|
||||
{
|
||||
while (minimapEnemyMarkers.Count <= index)
|
||||
@@ -1544,9 +1678,11 @@ namespace BumpCombat.UI
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 center = arenaBounds != null ? arenaBounds.ZoneCenter : Vector2.zero;
|
||||
Vector2 localPos = worldPosition - center;
|
||||
Vector2 normalized = new(
|
||||
Mathf.Clamp01((worldPosition.x + extents.x) / (extents.x * 2f)),
|
||||
Mathf.Clamp01((worldPosition.y + extents.y) / (extents.y * 2f)));
|
||||
Mathf.Clamp01((localPos.x + extents.x) / (extents.x * 2f)),
|
||||
Mathf.Clamp01((localPos.y + extents.y) / (extents.y * 2f)));
|
||||
Vector2 halfMarker = marker.rectTransform.rect.size * 0.5f;
|
||||
float halfMapWidth = mapSize.x * 0.5f;
|
||||
float halfMapHeight = mapSize.y * 0.5f;
|
||||
@@ -1575,8 +1711,9 @@ namespace BumpCombat.UI
|
||||
|
||||
Vector2 mapSize = minimapMapRect.rect.size;
|
||||
Bounds visible = arenaBounds.GetCameraVisibleBounds(worldCamera);
|
||||
Vector2 min = WorldToMinimapPosition(visible.min, extents, mapSize);
|
||||
Vector2 max = WorldToMinimapPosition(visible.max, extents, mapSize);
|
||||
Vector2 zoneCenter = arenaBounds != null ? arenaBounds.ZoneCenter : Vector2.zero;
|
||||
Vector2 min = WorldToMinimapPosition(visible.min, extents, mapSize, zoneCenter);
|
||||
Vector2 max = WorldToMinimapPosition(visible.max, extents, mapSize, zoneCenter);
|
||||
float width = Mathf.Max(2f, max.x - min.x);
|
||||
float height = Mathf.Max(2f, max.y - min.y);
|
||||
Vector2 center = (min + max) * 0.5f;
|
||||
@@ -1617,11 +1754,13 @@ namespace BumpCombat.UI
|
||||
private static Vector2 WorldToMinimapPosition(
|
||||
Vector2 worldPosition,
|
||||
Vector2 extents,
|
||||
Vector2 mapSize)
|
||||
Vector2 mapSize,
|
||||
Vector2 center = default)
|
||||
{
|
||||
Vector2 localPos = worldPosition - center;
|
||||
Vector2 normalized = new(
|
||||
Mathf.Clamp01((worldPosition.x + extents.x) / (extents.x * 2f)),
|
||||
Mathf.Clamp01((worldPosition.y + extents.y) / (extents.y * 2f)));
|
||||
Mathf.Clamp01((localPos.x + extents.x) / (extents.x * 2f)),
|
||||
Mathf.Clamp01((localPos.y + extents.y) / (extents.y * 2f)));
|
||||
return new Vector2(
|
||||
(normalized.x - 0.5f) * mapSize.x,
|
||||
(normalized.y - 0.5f) * mapSize.y);
|
||||
@@ -1705,12 +1844,10 @@ namespace BumpCombat.UI
|
||||
private IEnumerator ShowEventMessage(string message)
|
||||
{
|
||||
showingTimedEventMessage = true;
|
||||
lastNextEventSecond = -1;
|
||||
eventText.text = message;
|
||||
eventText.gameObject.SetActive(true);
|
||||
yield return new WaitForSecondsRealtime(3f);
|
||||
showingTimedEventMessage = false;
|
||||
lastNextEventSecond = -1;
|
||||
UpdateNextEventHud();
|
||||
}
|
||||
|
||||
@@ -1760,7 +1897,7 @@ namespace BumpCombat.UI
|
||||
"Presentation/Fonts/NanumGothic-Regular";
|
||||
private const string NeoFontResource = "Presentation/Fonts/neodgm";
|
||||
private const string GalmuriFontResource = "Presentation/Fonts/Galmuri9";
|
||||
private const float ThreePixelBorderMultiplier = 1f / 3f;
|
||||
internal const float ThreePixelBorderMultiplier = 1f / 3f;
|
||||
|
||||
private static readonly Color PanelFallback =
|
||||
new(24f / 255f, 27f / 255f, 39f / 255f, 0.94f);
|
||||
|
||||
Reference in New Issue
Block a user