[유니티][isometric 타일맵 좌표 이동 part.3] 캐릭터 이동

bamtoridotori·2021년 8월 29일
0

unity

목록 보기
3/5

타일맵에서 클릭 좌표로 캐릭터 이동

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
 
public class TestIsometric_MoveCharacter : MonoBehaviour
{
    public Button btn;
    public int colCount, rowCount;
    public Vector2 startPos;
 
    private GameObject mapTile;
    private Coroutine routine;
    private int tileWidth = 64;
    private int tileHeight = 32;
    private int col = 0; //행
    private int row = 0; //열
    
    private GameObject my;
    private GameObject motherNode;
    private GameObject targetNode;
    private GameObject selectedTile;
 
    private Dictionary<Vector2, GameObject> dicFIndTile = new Dictionary<Vector2, GameObject>();
    private List<GameObject> closeList = new List<GameObject>();
    private List<GameObject> movePositionList = new List<GameObject>();
 
    void Start()
    {
        this.CreateMap();
        this.CreateTile();
        this.TileCheck();
 
        this.btn.onClick.AddListener(() =>
        {
            this.FIndNextPos();
        });
    }
 
    void TileCheck()
    {
        if (this.routine != null)
        {
            StopCoroutine(this.routine);
        }
        this.routine = StartCoroutine(this.TileCheckImpl());
    }
 
    IEnumerator TileCheckImpl()
    {
        while (true)
        {
            if (Input.GetMouseButtonDown(0))
            {
                Vector2 worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
 
                RaycastHit2D hit = Physics2D.Raycast(worldPos, Vector2.zero);
 
                if (hit.collider != null)
                {
                    this.ClearMap();
                    this.targetNode = hit.collider.gameObject;
                    hit.collider.GetComponent<SpriteRenderer>().color = Color.cyan;
                }
            }
            yield return null;
        }
    }
 
    private void FIndNextPos()
    {
        if (this.routine != null)
        {
            StopCoroutine(this.routine);
        }
        this.routine = StartCoroutine(this.FindNextPosImpl());
    }
 
    private IEnumerator FindNextPosImpl()
    {
        while (true)
        {
            var dir = (this.motherNode.transform.position - this.my.transform.position).normalized;
            var nextNode = Vector2.Distance(this.my.transform.position, this.motherNode.transform.position);
            var distance = Vector2.Distance(this.my.transform.position, this.targetNode.transform.position);
 
            this.my.transform.position += dir * 2f * Time.deltaTime;
 
            
            if (nextNode <= 0.05f)
            {
                if (distance <= 0.05f)
                {
                    Debug.Log("도착");
                    this.TileCheck();
                    break;
                }
                this.FindNode();
                Debug.Log("다음");
            }
            
            yield return null;
        }
        
    }
 
 
    private void FindNode()
    {
        var mother = this.motherNode.GetComponent<TestTile>().vec2;
 
        var motherX = mother.x - 1;
        var motherY = mother.y - 1;
        var maxX = mother.x + 1;
        var maxY = mother.y + 1;
 
        if (motherX < 0)
        {
            motherX = 0;
        }
        if (motherY < 0)
        {
            motherY = 0;
        }
 
        for (int x = (int)motherX; x <= maxX; x++)
        {
            for (int y = (int)motherY; y <= maxY; y++)
            {
                if (x < this.colCount && y < this.rowCount)
                {
                    var data = new Vector2(x, y);
 
                    var tile = this.dicFIndTile[data];
 
                    if (tile.GetComponent<TestTile>().isBlock != true && !this.closeList.Contains(tile))
                    {
 
                        if(data.x == motherX && data.y == mother.y || data.y == mother.y)
                        {
                            this.movePositionList.Add(tile);
                        }
                        if (data.y == motherY && data.x == mother.x || data.x == mother.x)
                        {
                            this.movePositionList.Add(tile);
                        }
                        
                        this.movePositionList.Remove(motherNode);
 
                        this.closeList.Add(motherNode);
                        if (!this.closeList.Contains(tile))
                        {
                            tile.GetComponent<SpriteRenderer>().color = Color.grey;
                            this.SetFGH();
                        }
                    }
                }
            }
        }
        
        this.NextNode();
    }
    
    private void NextNode()
    {
        IEnumerable<GameObject> sortNode = this.movePositionList.OrderBy(x => x.GetComponent<TestTile>().f);
        this.selectedTile = sortNode.FirstOrDefault<GameObject>();
        this.motherNode = this.selectedTile;
        this.motherNode.GetComponent<SpriteRenderer>().color = Color.blue;
    }
 
    private void ClearMap()
    {
        Debug.Log("타일초기화");
 
        for (int i = 0; i < colCount; i++)
        {
            for (int j = 0; j < rowCount; j++)
            {
                var tiles = new Vector2(j, i);
 
                var tile = dicFIndTile[tiles];
                
                tile.GetComponent<SpriteRenderer>().color = Color.white;
            }
        }
        this.closeList.Clear();
        this.targetNode = null;
        this.selectedTile = null;
 
        this.movePositionList.Clear();
    }
 
 
    #region FGH 활성화 비활성화
    private void SetActiveFGH(GameObject tile)
    {
        if (!this.movePositionList.Contains(tile))
        {
            tile.GetComponent<TestTile>().G.gameObject.SetActive(false);
            tile.GetComponent<TestTile>().F.gameObject.SetActive(false);
            tile.GetComponent<TestTile>().H.gameObject.SetActive(false);
        }
        else
        {
            tile.GetComponent<TestTile>().G.gameObject.SetActive(true);
            tile.GetComponent<TestTile>().F.gameObject.SetActive(true);
            tile.GetComponent<TestTile>().H.gameObject.SetActive(true);
        }
    }
    #endregion
    
    private void SetFGH()
    {
        foreach (var tile in this.movePositionList)
        {
            var getG = tile.GetComponent<TestTile>().g;
            var getH = tile.GetComponent<TestTile>().h;
            getG = Mathf.Round(Vector2.Distance(tile.GetComponent<TestTile>().vec2, this.motherNode.GetComponent<TestTile>().vec2) * 10);
            var dx = Mathf.Abs(tile.GetComponent<TestTile>().vec2.x - this.targetNode.GetComponent<TestTile>().vec2.x);
            var dy = Mathf.Abs(tile.GetComponent<TestTile>().vec2.y - this.targetNode.GetComponent<TestTile>().vec2.y);
 
            getH = (dx + dy) * 10;
 
            tile.GetComponent<TestTile>().f = getG + getH;
        }
    }
 
    #region 맵, 타일 생성
    private void CreateTile()
    {
        if (this.my == null)
        {
            this.my = Instantiate(Resources.Load<GameObject>("hero"));
 
            this.CreatedTileMap(my, this.startPos.x, this.startPos.y);
        }
    }
 
    private void CreateMap()
    {
        while (true)
        {
            this.mapTile = Instantiate(Resources.Load<GameObject>("tile"));
 
            this.mapTile.tag = "Tile";
 
            this.mapTile.transform.SetParent(this.transform);
 
            this.CreatedTileMap(this.mapTile, this.col, row);
            this.dicFIndTile.Add(new Vector2(col, row), mapTile);
            this.col++;
 
            if (this.col >= this.colCount)
            {
                this.col = 0;
                this.row++;
            }
            if (this.row >= this.rowCount)
            {
                row = 0;
                break;
            }
        }
    }
 
    private void CreatedTileMap(GameObject tileMap, float x, float y)
    {
        var vec2 = new Vector2(x, y);
 
        if (tileMap.GetComponentInChildren<TextMesh>())
        {
            tileMap.GetComponentInChildren<TextMesh>().text = string.Format("({0},{1})", x, y);
            this.SetActiveFGH(tileMap);
        }
 
        if (tileMap == this.my)
        {
            this.motherNode = tileMap;
        }
 
        tileMap.AddComponent<TestTile>();
        tileMap.GetComponent<TestTile>().vec2 = vec2;
 
        var screen = this.MapToScreen(vec2);
 
        var screenPos = Camera.main.ScreenToWorldPoint(new Vector2(screen.x + 512, screen.y + 384 + 100));
 
        tileMap.transform.position = new Vector3(screenPos.x, screenPos.y, 0);
    }
 
    public Vector2 MapToScreen(Vector2 mapPos)
    {
        var screenX = mapPos.x * this.tileWidth - (mapPos.y * this.tileWidth);
        var screenY = mapPos.y * -tileHeight - (mapPos.x * tileHeight);
 
        return new Vector2(screenX, screenY);
    }
    #endregion
}
profile
편하게 끄적이는 벨로그이자 개인적인 메모 공간

0개의 댓글