56 lines
2.1 KiB
C#
56 lines
2.1 KiB
C#
|
|
using System.Collections.Generic;
|
||
|
|
using UnityEngine;
|
||
|
|
|
||
|
|
namespace TKS
|
||
|
|
{
|
||
|
|
/// <summary>적군 슬링샷 결정: 가장 가까운 아군을 향해 당기고, 정확도에 따라 흔들린다.</summary>
|
||
|
|
public static class EnemyAI
|
||
|
|
{
|
||
|
|
public static Vector2 Decide(Unit e, IReadOnlyList<Unit> targets, float accuracy, System.Random rng, Board board)
|
||
|
|
{
|
||
|
|
Unit nearest = null;
|
||
|
|
float best = float.MaxValue;
|
||
|
|
for (int i = 0; i < targets.Count; i++)
|
||
|
|
{
|
||
|
|
var t = targets[i];
|
||
|
|
if (!t.IsAlive) continue;
|
||
|
|
float d = Vector2.Distance(e.Position, t.Position);
|
||
|
|
if (d < best)
|
||
|
|
{
|
||
|
|
best = d;
|
||
|
|
nearest = t;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (nearest == null) return e.Position;
|
||
|
|
|
||
|
|
Vector2 toT = nearest.Position - e.Position;
|
||
|
|
float dist = toT.magnitude;
|
||
|
|
Vector2 dir = dist > 0.001f ? toT / dist : Vector2.up;
|
||
|
|
|
||
|
|
Vector2 target;
|
||
|
|
if (dist <= e.SlingMaxDistance)
|
||
|
|
{
|
||
|
|
target = nearest.Position; // 최종 목표점 명중 시도
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
target = e.Position + dir * e.SlingMaxDistance; // 접근(궁병은 사거리 안이면 이동 후 사격)
|
||
|
|
}
|
||
|
|
|
||
|
|
if (rng.NextDouble() > accuracy)
|
||
|
|
{
|
||
|
|
float ang = ((float)rng.NextDouble() * 2f - 1f) * 22f * Mathf.Deg2Rad;
|
||
|
|
float cs = Mathf.Cos(ang);
|
||
|
|
float sn = Mathf.Sin(ang);
|
||
|
|
Vector2 rd = new Vector2(dir.x * cs - dir.y * sn, dir.x * sn + dir.y * cs);
|
||
|
|
float len = (target - e.Position).magnitude * (0.75f + 0.5f * (float)rng.NextDouble());
|
||
|
|
target = e.Position + rd * Mathf.Min(len, e.SlingMaxDistance);
|
||
|
|
}
|
||
|
|
|
||
|
|
Vector2 v = target - e.Position;
|
||
|
|
if (v.magnitude > e.SlingMaxDistance) v = v.normalized * e.SlingMaxDistance;
|
||
|
|
return board.ClampInside(e.Position + v, e.Radius);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|