캐릭터의 이동

턴제제작 2018. 9. 4. 22:58

 

 일단 적 캐릭터를 이동을 시켜야 한다. 아직 장애물이나 그런 게 많지가 않아서 굳이 은패를 더 선호하게 이동을 시킬 필요는 없는 듯싶다. 전투 시스템도 아직 제대로 짠 것도 아니고 말이다. 선행해서 만들어야 할 것들이 좀 있기 때문에 우선은 옆으로 두 칸씩 이동하는 걸 만들고 그다음에 랜덤 하게 이동을 하는 걸 만들어야 할 듯싶다. 행동력을 다 소비할 때까지 말이다. 행동력을 고려해서 이동하는 것은 전투와 관련이 있는 요소라 우선은 랜덤 하게 이동을 하고 플레이어에게 턴을 넘기는 걸로 넘어가야 될 듯싶다.

 전번에 에너미 무브 클래스를 만들어 놓으니까 그거 테스트를 해봐야 할 듯싶다. 일단 에너미 턴이 되면 앞으로 2칸씩 움직이는 거를 만들어야겠다. 아 그리고 동시에 움직이는 게 아니라 순차적으로 움직이도록 해야 한다. 일단은 동시에 움직이는 것부터 구현하고 그다음으로 순차적으로 움직이는 걸 만들어야 할 듯싶다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyAI : MonoBehaviour {

    public GameManager gameManager;

    // enemyList and PlayerList are in the GameMander

    void Awake()
    {
        gameManager = FindObjectOfType<GameManager>();
    }

    public void StartAI()
    {
        print ("Enemy AI is ready");
        gameManager.enemyList.ForEach (i => i.TestMove());
    }

 

    public void TestMove ()
    {
        var testTile = new List<TileNode>();

        enemyMove.IndicateUnit (testTile);
    }

 

  우선 테스트 무브를 만든다. 아직은 리스트 안에 아무것도 들어가 있지가 않기 때문에 오류가 뜬다. 이동할 타일을 검색해서 타일 리스트에 넣어주어야 한다.

    public void TestMove ()
    {
        var testTileList = new List<TileNode>();
        var enemyPos = GameUtility.Coordinate (this.transform.position);

        var testTile1 = board.transform.Find ("TileNode (" + (enemyPos.x +4) + ", " + (enemyPos.y) + ")").GetComponent<TileNode>();
        var testTile2 = board.transform.Find ("TileNode (" + (enemyPos.x +2) + ", " + (enemyPos.y) + ")").GetComponent<TileNode>();

        testTileList.Add (testTile1);
        testTileList.Add (testTile2);
        enemyMove.IndicateUnit (testTileList);
    }


 

 이렇게 만들면 되는데. 다만 플레이어 캐릭터 이동이 끝나기도 전에 턴이 넘어가기 때문에 플레이어와 에너미가 동시에 움직인다는 문제가 있다. 코 루틴을 써야 할 듯싶다. 어디에서 써야 하는지 고민이 된다. 이동을 마친 다음에 행동력이 줄어들게 해야 하느지도 고민이 된다.

 근데 보니까 게임 매니저에서 이미 해당 기능을 만들어 놓았다. 거기서 만들어야 할 듯싶다.


    void OnMouseDown()
    {
        // print (this.name);
        // print (this.tileStyle);

        // enable moving
        if (gameManager.currentPlayer != null)
        {
            if ((tileStyle == TileStyle.OneVigor || tileStyle == TileStyle.TwoVigor )
            && gameManager.currentPlayer.playerTurnState == PlayerTurnState.Active && gameManager.currentPlayer.currentVigor > 0)
            {
                if (gameManager.currentPlayer.playerActiveState == PlayerActiveState.NotAnything)
                {
                    Moving();
                    gameManager.SpendSkill (Skill.Moving, this);
                }
            }
        }
    }

 


IEnumerator Indicator (List<Vector3> way)
{
        // start
var destinationFlag = Instantiate (destinationPoint, way[way.Count -1], Quaternion.identity);
enemy.GetComponent<CapsuleCollider>().enabled = false;
board.ResetBoard();
enemy.enemyActiveState = EnemyActiveState.Moving;

yield return null;

if (way == null)
{
print ("No Way");
DestroyImmediate (destinationFlag);
enemy.GetComponent<CapsuleCollider>().enabled = true;
board.ResetBoard();
enemy.enemyActiveState = EnemyActiveState.Ready;
}

        // do
foreach (var destination in way)
{
MoveUnit (destination);
while (enemy.enemyActiveState == EnemyActiveState.Moving)
{
yield return null;
}
}

yield return null;

        // end
DestroyImmediate (destinationFlag);
enemy.GetComponent<CapsuleCollider>().enabled = true;
board.ResetBoard();
// player.activeOff.Invoke();
enemy.enemyActiveState = EnemyActiveState.Ready;
}

 

 코루틴을 쓰지 않고 그 해당 부분을 빌고 스킬을 사용 시 행동력을 깎는 것과 턴이 끝났을 때 행동력을 체크하는 부분을 분리하였다.

    void CheckPlayerTurn (List<Player> waitingPlayerList)
    {   
        if (waitingPlayerList.Count != 0)
            {
                currentPlayer = waitingPlayerList[0];
                SelectPlayer (currentPlayer);
                return;
            }
            else
            {
                currentPlayer = null;
                turnState = Turn.EnemyTurn;
                print("EnemyTurn");
                // TestEnemyAI();
                enemyAI.StartAI();
                return;
            }
    }

 

    public void SpendSkill (Skill skillName, TileNode clickedTile = null)
    {

        if (skillName == Skill.Moving && clickedTile != null)
        {
            // print (clickedTile.tileStyle);

            if (clickedTile.tileStyle == TileStyle.OneVigor)
            {
                currentPlayer.currentVigor = currentPlayer.currentVigor -1;
            }
            else if (clickedTile.tileStyle == TileStyle.TwoVigor)
            {
                currentPlayer.currentVigor = currentPlayer.currentVigor -2;
            }
            else
            {
                currentPlayer.currentVigor = currentPlayer.currentVigor -1;
            }
        }
        else if (skillName == Skill.Attack)
        {
            currentPlayer.currentVigor = currentPlayer.currentVigor -2;
        }
        
        board.ResetBoard();
        
    }

 

    void CheckPlayerTurn (List<Player> waitingPlayerList)
    {   
        if (waitingPlayerList.Count != 0)
            {
                currentPlayer = waitingPlayerList[0];
                SelectPlayer (currentPlayer);
                return;
            }
            else
            {
                currentPlayer = null;
                turnState = Turn.EnemyTurn;
                print("EnemyTurn");
                // TestEnemyAI();
                enemyAI.StartAI();
                return;
            }
    }

 

 이 문제를 해결했다. 그러나 단거리 이동에도 행동력을 2를 쓰는 버그가 아직 있다.

    public void SpendSkill (Skill skillName, TileNode clickedTile = null)
    {

        if (skillName == Skill.Moving && clickedTile != null)
        {
            // print (clickedTile.tileStyle);

            if (clickedTile.tileStyle == TileStyle.OneVigor)
            {
                print ("One Vigor");
                currentPlayer.currentVigor = currentPlayer.currentVigor -1;
            }
            else if (clickedTile.tileStyle == TileStyle.TwoVigor)
            {
                print ("Two Viger");
                currentPlayer.currentVigor = currentPlayer.currentVigor -2;
            }
        }
        else if (skillName == Skill.Attack)
        {
            currentPlayer.currentVigor = currentPlayer.currentVigor -2;
        }
        
        board.ResetBoard();
        
    }

 

 해당 문제도 해결했다. 

 그러나 여전히 문제가 있다. 한 칸을 움직인 다음에는 이동 가능 범위를 한 칸 범위로 줄여야 한다. 행동력이 -1이 가능하기 때문에 1 행동력 범위를 이동하고 2 행동력 범위로 움직이게 할 수 있는 문제가 있다.

 보드 클래스에 이 부분을 좀 수정하면 될 듯싶지 않나 싶다. 지금은 행동력이 몇이든 일괄적으로 키고 있으니 말이다. 

void MoveAreaOn()
{
if (gameManager.currentPlayer != null)
{
if (gameManager.currentPlayer.currentVigor == 2)
{
gameManager.currentPlayer.moveMaxArea.SetActive (true);
gameManager.currentPlayer.moveBaseArea.SetActive (true);
}
else if (gameManager.currentPlayer.currentVigor == 1)
{
gameManager.currentPlayer.moveMaxArea.SetActive (false);
gameManager.currentPlayer.moveBaseArea.SetActive (true);
}
else if (gameManager.currentPlayer.currentVigor <= 0)
{
gameManager.currentPlayer.moveMaxArea.SetActive (false);
gameManager.currentPlayer.moveBaseArea.SetActive (false);
}
}
}

 

 이런 식으로 바꾸었더니 해당 문제가 해결이 되었다.

 여전히 독특한 버그가 있다. 이동이 끝나기 전에 다른 캐릭터를 이동할 수 있도록 편의를 제공했더니 커런트 플레이어가 바뀌는 통에 플레이어의 턴 종료가 인지가 안 되는 문제가 있다. 좀 고차원 적인 버그라고 해야 하나. 

    public void CheckPlayerTurn ()
    {
        if (currentPlayer.currentVigor <= 0)
        {
            var waitingPlayerList = new List<Player>();

            foreach (var player in playerList)
            {

                if (player.playerTurnState == PlayerTurnState.Waiting)
                {
                    waitingPlayerList.Add (player); 
                }
            }

            if (waitingPlayerList.Count != 0)
            {
                currentPlayer = waitingPlayerList[0];
                SelectPlayer (currentPlayer);
                return;
            }
            else
            {
                currentPlayer = null;
                turnState = Turn.EnemyTurn;
                print("EnemyTurn");
                // TestEnemyAI();
                enemyAI.StartAI();
                return;
            }
        }
    }
}

 

    public void CheckVigor()
    {
        // print ("Check Vigor");
        if (currentPlayer.currentVigor <= 0)
        {
            currentPlayer.playerTurnState = PlayerTurnState.Ending;
            print (currentPlayer.name + " is end");
            currentPlayer.activeOff.Invoke();
        }
    }

 

IEnumerator Indicator (List<Vector3> way)
{
        // start
player.playerActiveState = PlayerActiveState.Moving;
var destinationFlag = Instantiate (destinationPoint, way[way.Count -1], Quaternion.identity);
player.GetComponent<CapsuleCollider>().enabled = false;
board.ResetBoard();

yield return null;

if (way == null)
{
print ("No Way");
DestroyImmediate (destinationFlag);
player.GetComponent<CapsuleCollider>().enabled = true;
board.ResetBoard();
player.playerActiveState = PlayerActiveState.NotAnything;
}

        // do
foreach (var destination in way)
{
MoveUnit (destination);
while (player.playerActiveState == PlayerActiveState.Moving)
{
yield return null;
}
}

yield return null;

        // end
DestroyImmediate (destinationFlag);
player.GetComponent<CapsuleCollider>().enabled = true;
board.ResetBoard();
// player.activeOff.Invoke();
player.playerActiveState = PlayerActiveState.NotAnything;
 
gameManager.CheckPlayerTurn();
}

 

    void OnMouseDown()
    {
        // print (this.name);
        // print (this.tileStyle);

        // enable moving
        if (gameManager.currentPlayer != null)
        {
            if ((tileStyle == TileStyle.OneVigor || tileStyle == TileStyle.TwoVigor )
            && gameManager.currentPlayer.playerTurnState == PlayerTurnState.Active && gameManager.currentPlayer.currentVigor > 0)
            {
                if (gameManager.currentPlayer.playerActiveState == PlayerActiveState.NotAnything)
                {
                    Moving();
                }
            }
        }
    }

 

    public void SpendSkill (Skill skillName, TileNode clickedTile = null)
    {

        if (skillName == Skill.Moving && clickedTile != null)
        {
            // print (clickedTile.tileStyle);

            if (clickedTile.tileStyle == TileStyle.OneVigor)
            {
                print ("One Vigor");
                currentPlayer.currentVigor = currentPlayer.currentVigor -1;
            }
            else if (clickedTile.tileStyle == TileStyle.TwoVigor)
            {
                print ("Two Viger");
                currentPlayer.currentVigor = currentPlayer.currentVigor -2;
            }
        }
        else if (skillName == Skill.Attack)
        {
            currentPlayer.currentVigor = currentPlayer.currentVigor -2;
        }
        
        board.ResetBoard();
        CheckVigor();
    }


    public void CheckVigor()
    {
        // print ("Check Vigor");
        if (currentPlayer.currentVigor <= 0)
        {
            currentPlayer.playerTurnState = PlayerTurnState.Ending;
            print (currentPlayer.name + " is end");
            currentPlayer.activeOff.Invoke();
        }
    }

 

 생각보다 많은 부분을 고쳤다. 문제는 다시 이동이 끝나지 않았다. 에너미 턴이 시작되는 문제가 제발 한다는 거다.

    public void CheckPlayerTurn ()
    {
        if (currentPlayer == null) {

            return;
        }
        
        if (currentPlayer.currentVigor > 0)
        {
            return;
        }

        var waitingPlayerList = new List<Player>();

        foreach (var player in playerList)
        {

            if (player.playerTurnState == PlayerTurnState.Waiting)
            {
                waitingPlayerList.Add (player); 
            }
        }


        if (waitingPlayerList.Count != 0)
            {
                currentPlayer = waitingPlayerList[0];
                SelectPlayer (currentPlayer);
                return;
            }
            else
            {
                currentPlayer = null;
                turnState = Turn.EnemyTurn;
                print("EnemyTurn");
                // TestEnemyAI();
                enemyAI.StartAI();
                return;
            }
    }

 

 이런 식으로 바꿔주면 문제가 해결된다가 아니라. 이게 중간쯤 해서 문직이기 시작한다. 완전히 도착하고 움직여야 할 텐데 말이다. 한 행동력만 쓸 때는 문제가 없다. 두 행 동력을 이동할 때 한 행 동력 이동 한 다음 중간쯤에 서 턴이 넘어가 버린다. 

 이게 아마 1번 캐릭터의 동작이 끝난 시점에서 2번 캐릭터는 이동을 하고 있지만 1번 캐릭터에서 턴 체크를 했을 때 이미 행동력을 써버린 상황이어서 그런 듯싶다.

    public void CheckPlayerTurn ()
    {
        if (currentPlayer == null) {

            return;
        }
        
        if (currentPlayer.currentVigor > 0)
        {
            return;
        }

        foreach (var player in playerList)
        {
            if (player.playerActiveState == PlayerActiveState.Moving)
            {
                return;
            }
        }

        var waitingPlayerList = new List<Player>();

        foreach (var player in playerList)
        {

            if (player.playerTurnState == PlayerTurnState.Waiting)
            {
                waitingPlayerList.Add (player); 
            }
        }


        if (waitingPlayerList.Count != 0)
        {
            currentPlayer = waitingPlayerList[0];
            SelectPlayer (currentPlayer);
            return;
        }
        else
        {
            currentPlayer = null;
            turnState = Turn.EnemyTurn;
            print("EnemyTurn");
            // TestEnemyAI();
            enemyAI.StartAI();
            return;
        }
    }
}


 

 이걸 이렇게 해주면 된다. 허허허... 이제 더는 버그가 없어야 할 텐데...

 

 

'턴제제작' 카테고리의 다른 글

엄패  (0) 2018.09.23
씬시티 느낌  (0) 2018.09.07
턴제 인디게임 개발  (0) 2018.08.28
다시 코딩  (0) 2018.08.25
프로토 타입  (1) 2018.07.24

WRITTEN BY
아이고이아

,