using UnityEngine; namespace TKS { /// 전장 가장자리 벽 표식. 캐스트 질의에서 벽으로 판정한다. public class BoardWall : MonoBehaviour { } /// 전장(바닥 = 원화 배경 또는 도형·격자 · 테두리 · 4면 벽 콜라이더). 화면보다 넓어 카메라로 스크롤한다. public class Board : MonoBehaviour { public Vector2 Size { get; private set; } /// Resources/Board/<boardArt> 원화 배경을 썼는가(없으면 도형·격자). public bool HasArt { get; private set; } public Rect Rect { get { return new Rect(-Size.x * 0.5f, -Size.y * 0.5f, Size.x, Size.y); } } public void Build(Vector2 size, string boardArt = null) { Size = size; float w = size.x; float h = size.y; Sprite art = string.IsNullOrEmpty(boardArt) ? null : Resources.Load("Board/" + boardArt); HasArt = art != null; if (HasArt) { // 원화 세션 납품 배경(5:8 · 위 = 적 진영) — 전장 크기에 맞춰 늘린다 · 격자·진영 띠는 그리지 않음 var bg = ProceduralSprites.NewSprite(transform, "Background", art, Color.white, 1f, -20); bg.transform.localScale = new Vector3(w / art.bounds.size.x, h / art.bounds.size.y, 1f); } else { var bg = ProceduralSprites.NewSprite(transform, "Background", ProceduralSprites.Square, new Color(0.17f, 0.24f, 0.17f), 1f, -20); bg.transform.localScale = new Vector3(w, h, 1f); // 아군·적군 진영 구분용 옅은 띠 var enemyHalf = ProceduralSprites.NewSprite(transform, "EnemyHalf", ProceduralSprites.Square, new Color(0.45f, 0.2f, 0.2f, 0.18f), 1f, -19); enemyHalf.transform.localScale = new Vector3(w, h * 0.5f, 1f); enemyHalf.transform.localPosition = new Vector3(0f, h * 0.25f, 0f); // 격자(4 단위) — 스크롤 체감용 var gridColor = new Color(1f, 1f, 1f, 0.07f); const float gridStep = 4f; for (float x = -w * 0.5f + gridStep; x < w * 0.5f - 0.01f; x += gridStep) { var g = ProceduralSprites.NewSprite(transform, "GridV", ProceduralSprites.Square, gridColor, 1f, -18); g.transform.localPosition = new Vector3(x, 0f, 0f); g.transform.localScale = new Vector3(0.04f, h, 1f); } for (float y = -h * 0.5f + gridStep; y < h * 0.5f - 0.01f; y += gridStep) { var g = ProceduralSprites.NewSprite(transform, "GridH", ProceduralSprites.Square, gridColor, 1f, -18); g.transform.localPosition = new Vector3(0f, y, 0f); g.transform.localScale = new Vector3(w, 0.04f, 1f); } var mid = ProceduralSprites.NewSprite(transform, "MidLine", ProceduralSprites.Square, new Color(1f, 1f, 1f, 0.14f), 1f, -17); mid.transform.localScale = new Vector3(w, 0.06f, 1f); } // 테두리 var borderColor = new Color(0.85f, 0.75f, 0.45f); const float t = 0.16f; MakeBorder("BorderTop", new Vector2(0f, h * 0.5f + t * 0.5f), new Vector2(w + t * 2f, t), borderColor); MakeBorder("BorderBottom", new Vector2(0f, -h * 0.5f - t * 0.5f), new Vector2(w + t * 2f, t), borderColor); MakeBorder("BorderLeft", new Vector2(-w * 0.5f - t * 0.5f, 0f), new Vector2(t, h), borderColor); MakeBorder("BorderRight", new Vector2(w * 0.5f + t * 0.5f, 0f), new Vector2(t, h), borderColor); // 벽 콜라이더 (바깥쪽 1 단위 두께) const float wallT = 1f; MakeWall("WallTop", new Vector2(0f, h * 0.5f + wallT * 0.5f), new Vector2(w + wallT * 2f, wallT)); MakeWall("WallBottom", new Vector2(0f, -h * 0.5f - wallT * 0.5f), new Vector2(w + wallT * 2f, wallT)); MakeWall("WallLeft", new Vector2(-w * 0.5f - wallT * 0.5f, 0f), new Vector2(wallT, h)); MakeWall("WallRight", new Vector2(w * 0.5f + wallT * 0.5f, 0f), new Vector2(wallT, h)); } void MakeBorder(string name, Vector2 pos, Vector2 size, Color color) { var sr = ProceduralSprites.NewSprite(transform, name, ProceduralSprites.Square, color, 1f, -16); sr.transform.localPosition = pos; sr.transform.localScale = new Vector3(size.x, size.y, 1f); } void MakeWall(string name, Vector2 pos, Vector2 size) { var go = new GameObject(name); go.transform.SetParent(transform, false); go.transform.localPosition = pos; var col = go.AddComponent(); col.size = size; go.AddComponent(); } public Vector2 ClampInside(Vector2 p, float radius) { var r = Rect; float x = Mathf.Clamp(p.x, r.xMin + radius, r.xMax - radius); float y = Mathf.Clamp(p.y, r.yMin + radius, r.yMax - radius); return new Vector2(x, y); } } }