112 lines
4.2 KiB
C#
112 lines
4.2 KiB
C#
using System;
|
|
using System.Collections;
|
|
using UnityEngine;
|
|
|
|
namespace TKS
|
|
{
|
|
/// <summary>간단한 연출(이동 트윈·돌진·화살·피해 숫자). 코루틴 실행자는 BattleManager.</summary>
|
|
public static class Fx
|
|
{
|
|
public static MonoBehaviour Runner;
|
|
|
|
public static Coroutine Run(IEnumerator routine)
|
|
{
|
|
if (Runner == null) return null;
|
|
return Runner.StartCoroutine(routine);
|
|
}
|
|
|
|
public static IEnumerator Wait(float seconds)
|
|
{
|
|
float t = 0f;
|
|
while (t < seconds)
|
|
{
|
|
t += Time.deltaTime;
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>from → to 이동(기본 = 감속 · easeOut false = 등속 → 부딪히는 순간까지 속도를 유지). onDistance 에는 지금까지 지나온 거리를 넘긴다.</summary>
|
|
public static IEnumerator MoveAlong(Transform tr, Vector2 from, Vector2 to, float speed, Action<float> onDistance, bool easeOut = true)
|
|
{
|
|
float total = Vector2.Distance(from, to);
|
|
if (total < 1e-4f) yield break;
|
|
float duration = Mathf.Max(0.12f, total / Mathf.Max(0.1f, speed));
|
|
float el = 0f;
|
|
while (el < duration)
|
|
{
|
|
el += Time.deltaTime;
|
|
float k = Mathf.Clamp01(el / duration);
|
|
float e = easeOut ? 1f - (1f - k) * (1f - k) : k;
|
|
var p = Vector2.Lerp(from, to, e);
|
|
tr.position = new Vector3(p.x, p.y, 0f);
|
|
if (onDistance != null) onDistance(e * total);
|
|
yield return null;
|
|
}
|
|
tr.position = new Vector3(to.x, to.y, 0f);
|
|
if (onDistance != null) onDistance(total);
|
|
}
|
|
|
|
/// <summary>근접 공격 돌진(짧게 찌르고 복귀).</summary>
|
|
public static IEnumerator Lunge(Unit a, Vector2 toward)
|
|
{
|
|
Vector2 start = a.Position;
|
|
Vector2 dir = (toward - start);
|
|
if (dir.sqrMagnitude < 1e-4f) yield break;
|
|
dir.Normalize();
|
|
Vector2 peak = start + dir * 0.3f;
|
|
yield return MoveAlong(a.transform, start, peak, 6f, null);
|
|
yield return MoveAlong(a.transform, peak, start, 4f, null);
|
|
a.Position = start;
|
|
}
|
|
|
|
/// <summary>화살(가늘고 긴 사각형) 날리기.</summary>
|
|
public static IEnumerator Arrow(Vector2 from, Vector2 to)
|
|
{
|
|
var go = new GameObject("Arrow");
|
|
var sr = go.AddComponent<SpriteRenderer>();
|
|
sr.sprite = ProceduralSprites.Square;
|
|
sr.color = new Color(1f, 0.95f, 0.75f);
|
|
sr.sortingOrder = 8;
|
|
Vector2 d = to - from;
|
|
float ang = Mathf.Atan2(d.y, d.x) * Mathf.Rad2Deg;
|
|
go.transform.rotation = Quaternion.Euler(0f, 0f, ang);
|
|
go.transform.localScale = new Vector3(0.5f, 0.06f, 1f);
|
|
float dur = Mathf.Max(0.12f, d.magnitude / 14f);
|
|
float t = 0f;
|
|
while (t < dur)
|
|
{
|
|
t += Time.deltaTime;
|
|
var p = Vector2.Lerp(from, to, Mathf.Clamp01(t / dur));
|
|
go.transform.position = new Vector3(p.x, p.y, 0f);
|
|
yield return null;
|
|
}
|
|
UnityEngine.Object.Destroy(go);
|
|
}
|
|
|
|
public static void Popup(Vector2 pos, string text, Color color)
|
|
{
|
|
Run(PopupRoutine(pos, text, color));
|
|
}
|
|
|
|
static IEnumerator PopupRoutine(Vector2 pos, string text, Color color)
|
|
{
|
|
var tm = TextUtil.CreateWorldText(null, text, 0.42f, color, 20);
|
|
tm.gameObject.name = "Popup";
|
|
var tr = tm.transform;
|
|
float t = 0f;
|
|
const float dur = 0.75f;
|
|
while (t < dur)
|
|
{
|
|
t += Time.deltaTime;
|
|
float k = Mathf.Clamp01(t / dur);
|
|
tr.position = new Vector3(pos.x, pos.y + 0.55f + 0.7f * k, 0f);
|
|
var c = color;
|
|
c.a = 1f - k * k;
|
|
tm.color = c;
|
|
yield return null;
|
|
}
|
|
UnityEngine.Object.Destroy(tm.gameObject);
|
|
}
|
|
}
|
|
}
|