250203

Errata·2025년 2월 3일

개발 일지

목록 보기
71/350

✅ 오늘 한 일


  • Project BCA
  • Project MR


🎮 Project BCA


캐슬링

킹을 선택했을 때 PossibleMove()에서

  1. 킹과 룩의 firstmove를 체크한다
  2. 룩까지의 좌표가 비어있는지 확인한다
  3. 게임매니저의 IsCheck(x,y)에서 상대편의 모든 말들의 다음 턴 경로를 확인하고, 캐슬링에 필요한 세 좌표가 공격당할 수 있는 위치인지 확인한다. (확인하려고 할 땐 호출하기 전에 gameManager의 checkFromOther을 true로 설정하고, 확인을 마쳤다면 되돌린다)
  4. 모든 조건이 충족되었다면 조건에 맞추어 게임매니저의 black_kingcastling, black_queencastling, white_kingcastling, white_queencastling을 각각 true로 설정한다.
        // 캐슬링 확인하기 위해 우선 킹이 움직인 적 없는지 확인하고, 다른 편에서 조회하는건지 확인한다
        if (FirstMove && !gameManager.checkFromOther)
        {
            CheckCastling(moves, x, y);
        }

king.cs의 PossibleMove()에서 firstMove랑 checkFromOther 확인 후 캐슬링 체크

    private void CheckCastling(List<(int, int)> moves, int x, int y)
    {
        // 왼쪽에 룩이 있는지 확인한다
        Rook leftRook = null;
        Piece leftRookPositionPiece = gameManager.PieceAt(1, y);
        if (leftRookPositionPiece != null) leftRook = leftRookPositionPiece.GetComponent<Rook>();
        // 룩이 있고, 한 번도 이동하지 않았다면
        if (leftRook != null && leftRook.FirstMove)
        {
            // 킹 자신이 이동한다면 체크메이트 될지 확인할 때 사용하는 플래그 설정 (폰만 사용함)
            gameManager.checkFromOther = true;

            bool canCastle = true;
            // 룩과 킹 사이에 기물이 있는지 확인하고, 체크가 되는지 확인한다
            for (int i = 2; i < x; i++)
            {
                if (gameManager.PieceAt(i, y) != null || gameManager.IsCheck(i, y))
                {
                    canCastle = false;
                    break;
                }
            }
            if (canCastle)
            {
                if (isWhite)
                {
                    gameManager.white_queencastling = true;
                    moves.Add((x - 2, y));
                }
                else
                {
                    gameManager.black_queencastling = true;
                    moves.Add((x - 2, y));
                }
            }

            gameManager.checkFromOther = false;
        }

gameManager.cs의 PieceAt(), IsCheck()로 조건을 체크하고, 캐슬링 변수 설정

    public bool IsCheck(int x, int y)
    {
        for (int i = 1; i <= 8; i++)
        {
            for (int j = 1; j <= 8; j++)
            {
                GameObject piece = pieces[i, j];
                if (piece != null && piece.GetComponent<Piece>().isWhite != whiteTurn)
                {
                    List<(int, int)> moves = piece.GetComponent<Piece>().PossibleMove();
                    if (moves.Contains((x, y)))
                    {
                        return true;
                    }
                }
            }
        }
        return false;
    }

IsCheck()에선 상대편 모든 기물 확인

기물이 이동하려고할 때 MoveTo()에서

  1. 킹인지 확인한다
  2. 캐슬링 변수가 활성화돼있는지 확인한다
  3. 캐슬링 변수가 true이고, 해당하는 좌표로 이동했다면 캐슬링을 실행한다.
    void MoveTo(GameObject piece, Vector2 moveto_position)
    {
        int mx = (int)moveto_position.x;
        int my = (int)moveto_position.y;

        // 기물이 있다면 제거 (같은 편인지는 piece의 스크립트에서 검증되어 들어옴)
        if (pieces[mx, my] != null)
        {
            Destroy(pieces[mx, my]);
            print("Destroyed");
        }
        // 폰이라면 앙파상 설정 혹은 앙파상 행동 여부 검사
        if (piece.GetComponent<Pawn>() != null)
        {
            HandleEnPassant(piece, mx, my);
        }
        // 킹이라면 캐슬링 여부 검사
        if (piece.GetComponent<King>() != null)
        {
            HandleCastling(piece, mx, my);
        }

클릭하여 해당 좌표로 이동할 때 킹인지 확인하고 캐슬링 검사

    private void HandleCastling(GameObject piece, int mx, int my)
    {
        King king = piece.GetComponent<King>();

        if (king.isWhite)
        {
            if (mx == 3 && my == 1 && white_queencastling)
            {
                pieces[1, 1].transform.position = new Vector2(4, 1);
                pieces[4, 1] = pieces[1, 1];
                pieces[1, 1] = null;
                white_queencastling = false;
            }
            else if (mx == 7 && my == 1 && white_kingcastling)
            {
                pieces[8, 1].transform.position = new Vector2(6, 1);
                pieces[6, 1] = pieces[8, 1];
                pieces[8, 1] = null;
                white_kingcastling = false;
            }
        }

이동하려는 좌표를 확인하고, 그에 맞는 캐슬링 변수를 확인.

추가로 필요한 것들

턴이 시작될 때 게임 매니저의 캐슬링 변수들을 false로 초기화한다.

폰은 공격 가능 대상이 있으면 대각선 이동도 가능하므로,
대각선 이동 가능 여부 조건에 checkFromOther = true을 포함시켜야 한다.

향후 체크메이트 로직에서의 중복을 피하기 위해 게임매니저에 IsCheck() 구현
즉, IsCheck()는 두 가지 용도로 사용됨

  • 내가 움직인 기물이 체크메이트를 발생시켰나?
  • 내가 킹을 움직이면 체크메이트를 당하게 되는건가?

실수와 버그

실수

pawn의 이동 로직을 gameManager.whiteTurn으로 구별하고 있었는데,
그게 아니라 Piece 자체의 isWhite로 구별하는게 맞다.
애초에 클릭 로직에서 걸러져서 지금껏 오류가 없었던 것.

버그

  • 캐슬링을 위한 세 좌표가 공격당하고 있는지 확인하기 위해, 상대편 킹의 움직임도 확인해야 함
  • 상대편 킹의 움직임을 확인할 때, 캐슬링 로직 역시 돌아감.
  • 상대편 킹의 캐슬링 로직은 다시 자신의 킹의 캐슬링 로직을 요구함.
  • PossibleMove()가 무한히 호출되어 게임이 터짐.
  • 이를 해결하기 위해 checkFromOther을 이용하여, 상대편의 킹의 움직임을 확인할 땐 캐슬링 로직을 건너뜀.
  • 캐슬링이 된다는 것은 애초에 룩으로 잡을 수 있다는 뜻이기 때문임.

구현 결과



🎮 Project MR


플레이어 공격 애니메이션 제작

profile
Penser, c'est réapprendre à voir

0개의 댓글