반응형

카드 판정에 따른 게임의 상태를 표시하고 카드가 모두 열리면 다음 스테이지로 이동하는 프로그램을 만들어 보겠습니다

먼제 GameManager 스크립트를 열고 수정합니다

 

GameManager 스크립트 수정

게임의 상태를 설정할 수 있는 enum 열거형의 자료를 설정하고 Star() 함수에 모바일 기기를 위한 설정을 추가합니다

초기의 스테이지 만드는 문장도 삭제합니다

그리고 Update() 함수에 state 값을 바꾸어서 반복 호출하지 않도록 MakeStage() 함수에 처음 state = STATE.WAIT을 추가하고 마지막에 state = STATE.IDLE을 추가합니다.

 

또한 카드 판정할 수 있는 CheckCard() 함수를 추가하여  카드를 판정하고 카드가 서로 다르면 CloseTwoCards() 함수를 추가하여 카드를 닫습니다

그래서 스테이지 카드가 모두 열리면 StageClear() 함수를 추가하여 스테이지를 클리어하고 다음 스테이지로 넘어가는 함수를 만듭니다

 

 

 

GameManager 스크립트 수정

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

public class GameManager : MonoBehaviour
{
    //클릭한 카드 번호
    static public int cardNum;

    //직전의 카드 번호
    int lastNum = 0;

    //스테이지의 전체 카드수
    int cardCnt;

    //카드 클릭 횟수
    int hitCnt = 0;

    //스테이지 번호
    static public int stageNum = 1;

    //스테이지 수
    int stageCnt = 6;

    //카드 배열 카드 섞기용
    int[] arCards = new int[50];

    //게임 시작 시간
    float startTime;

    // 스테이지 경과 시간
    float stageTime;

    //열거형 의 자료를 설정하는 정의문 나열의 자료는 0,1,2....의 값이 할당된다
    public enum STATE
    {
        START, HIT, WAIT, IDLE, CLEAR
    };

    static public STATE state = STATE.START;

    // Start is called before the first frame update
    void Start()
    {

        
        Screen.orientation = ScreenOrientation.LandscapeRight;
        Screen.sleepTimeout = SleepTimeout.NeverSleep;

        startTime = stageTime = Time.time;

        //시간초기화
        startTime = stageTime = Time.time;
        //스테이지 만들기
        // StartCoroutine(MakeStage());
    }

    void Update()
    {
        switch (state)
        {
            //스테이지 만들기
            case STATE.START:
                StartCoroutine(MakeStage());
                break;

                // 같은 그림인지 판정
            case STATE.HIT:

                CheckCard();
                break;

                //스테이지를 클리어 하고 다음 스테이지를 만듬
            case STATE.CLEAR:
                StartCoroutine(StageClear());
                break;

        }

        //게임중지
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            Application.Quit();
        }

    }

    void CheckCard()
    {
        state = STATE.WAIT;

        //첫 번째 카드
        if (lastNum == 0)
        {
            //현재 카드 보존
            lastNum = cardNum;
            state = STATE.IDLE;
            return;
        }

        //이미지 찾기
        int img1 = (cardNum + 1) / 2;
        int img2 = (lastNum + 1) / 2;

        //다른 카드 이면  카드를 닫게한다
        if (img1 != img2)
        {
            StartCoroutine(CloseTwoCards());

            lastNum = 0;
            state = STATE.IDLE;
            return;
        }


        //같은 카드면 
        hitCnt += 2;

        //카드가 모두 열리면 스테이지를 클리어 한다
        if (hitCnt == cardCnt)
        {
            state = STATE.CLEAR;
            return;
        }

        //카드가 남아있으면 다른 카드를 조사한다
        lastNum = 0;
        state = STATE.IDLE;
    }

    //카드 닫기
    IEnumerator CloseTwoCards()
    {
        //테그로 카드 찾기
        GameObject card1 = GameObject.FindWithTag("card" + lastNum);
        GameObject card2 = GameObject.FindWithTag("card" + cardNum);


        //카드 닫기
        yield return new WaitForSeconds(0.2f);
        card1.SendMessage("CloseCard", SendMessageOptions.DontRequireReceiver);
        card2.SendMessage("CloseCard", SendMessageOptions.DontRequireReceiver);

    }

    //스테이지를 클리어 한다
    IEnumerator StageClear()
    {
        state = STATE.WAIT;

        yield return new WaitForSeconds(2);


        //스테이지 카드 제거
        for (int i = 1; i <= cardCnt; i++)
        {
            GameObject card = GameObject.FindWithTag("card" + i);
            Destroy(card);
        }

        //다음 스테이지 번호
        ++stageNum;
        if (stageNum > stageCnt)
        {
            //Application.LoadLevel("GameStart");
            //return;
        }

        //스테이지 초기화
        stageTime = Time.time;
        lastNum = 0;
        hitCnt = 0;

        state = STATE.START;
    }
    IEnumerator MakeStage()
    {
        //현재 작업중으로 설정
        state = STATE.WAIT;

        //시작카드의 x좌표
        float sx = 0;

        //시작카드의 z좌표
        float sz = 0;

        
        SetCardPos(out sx, out sz);

        //카드섞기
        ShuffleCard();


        //시작카드의 번호
        int n = 1;

        //카드배열 읽기 배열의 1행을 읽고 변수 t에 할당한다
        string[] str = StageSet.stage[stageNum - 1];

        //배열의 행의 수만큼 반복
        foreach (string t in str)
        {
            // 각행의 문자열을 단일 문자 배열로 변환(문자열 좌우의 공백 제거) , 변수t의 자우 공백을 제거(Trim)하고 단일 문자배열로 변환
            char[] ch = t.Trim().ToCharArray();

            //카드의 x축 좌표
            float x = sx;

            //1행의 문자열 길이만큼 반복
            //배열의 ch의 한문자를 읽고 변수 c에 할당한다
            foreach (char c in ch)
            {
                switch (c)
                {

                    //맵의 내용이 * 이면 그위치에 카드 만들어서 배치
                    case '*':
                        //카드 만들기
                        GameObject card = Instantiate(Resources.Load("Prefab/Card")) as GameObject;

                        //카드 좌표설정
                        card.transform.position = new Vector3(x, 0, sz);

                        //태그 달기
                        //card.tag = "card" + n++;

                        
                        //섞인카드
                        card.tag = "card" + arCards[n++];
                        x++;
                        break;

                        //빈칸 처리
                    case '.':
                        x++;
                        break;


                        //반 칸 공백처리
                    case '>':
                        x += 0.5f;
                        break;


                        //반 줄 행간 처리
                    case '^':
                        sz += 0.5f;
                        break;


                }

                //카드를 표시한 후에는 지연 시간을 두어 카드가 배치되는 과정이 보이도록함
                if (c == '*')
                {
                    yield return new WaitForSeconds(0.03f);

                }
            }

            //한줄 아래로 이동
            sz--;
        }
        //입력 대기중으로 설정
        state = STATE.IDLE;
    }

    //카드의 시작 위치 계산
    void SetCardPos(out float sx, out float sz)
    {
        //가로 카드수 반 칸 공백 포함
        float x = 0;

        //세로 행수 반줄 행간 포함
        float z = 0;

        //가로 카드 최대수
        float maxX = 0;

        //스테이지 전체 카드수
        cardCnt = 0;

        //카드 배열 조사 맵 배열 을 읽음
        string[] str = StageSet.stage[stageNum - 1];

        //행의 수만큼 반복
        for (int i = 0; i < str.Length; i++)
        {
            //1행읽기
            string t = str[i].Trim();

            //각행의 카드수
            x = 0;

            //각행의 글자 수만큼 반복
            for (int j = 0; j < t.Length; j++)
            {
                //문자열(string)은 단일 문자(char)의 배열로 취급할수 있음
                switch (t[j])
                {
                    case '.':
                    case '*':

                        //카드배치에 필요한 공간
                        x++;
                        if (t[j] == '*')
                        {
                            //전체 카드수
                            cardCnt++;
                        }
                        break;
                    case '>':
                        x += 0.5f;
                        break;
                    case '^':
                        z -= 0.5f;
                        break;

                }
            }

            //각 행의 최대 카드수 계산
            if (x > maxX)
            {
                maxX = x;
            }
            //전체 행의 수
            z++;
        }
        //카드 가로 시작 위치
        sx = -maxX / 2;
        sz = (z - 1) / 2;

        //  StartCoroutine(CardOpen(cardCnt));
    }

    void ShuffleCard()
    {
        for (int i = 1; i <= cardCnt; i++)
        {
            arCards[i] = i;
        }
        //return;

        //카드섞기 15회정도 반복
        for (int i = 1; i <= 15; i++)
        {
            //임의의 난수를 두개 만든다
            int n1 = Random.Range(1, cardCnt + 1);
            int n2 = Random.Range(1, cardCnt + 1);

            //교환
            int t = arCards[n1];//배열의 값을 바꾼다
            arCards[n1] = arCards[n2];
            arCards[n2] = t;

            //StartCoroutine(CardOpen(arCards[n1]));
        }
    }
}

 

 

 

카드와 게임 메니져 GameManager 스크립트와 통신하기 위해서 CardCtrl 스크립트를 수정합니다

 

CardCtrl 스크립트 수정

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

public class CardCtrl : MonoBehaviour
{
    //이미지 번호
    int imgNum = 1;

    //카드 뒷면 이미지 번호
    int backNum = 1;

    // 오픈된 카드의 판별여부 
    bool isOpen = false;

    Animator anim;


    // Start is called before the first frame update
    void Start()
    {
        anim = GetComponent<Animator>();
    }

    void Update()
    {
        //왼쪽 마우스버튼 클릭 모바일에선 터치 
        if (Input.GetButtonDown("Fire1") && GameManager.state == GameManager.STATE.IDLE)
        {
            CheckCard();
        }
    }

    //카드체크
    void CheckCard()
    {
        RaycastHit hit;
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        //터치한 카드 식별
        if (Physics.Raycast(ray, out hit, Mathf.Infinity))
        {
            string tag = hit.transform.tag;
            if (tag.Substring(0, 4) == "card")
            {
                //터치한 카드의 OpenCard()함수 실행
                hit.transform.SendMessage("OpenCard", SendMessageOptions.DontRequireReceiver);
            }
        }
    }
    void OpenCard()
    {
        //열린 카드는 처리 없음
        if (isOpen) return;

        //열린 카드 참거짓 판정
        isOpen = true;

        // 카드 번호 Substring() 문자열의 일부분을 추출하는 함수 , 카드 번호(tag)는 card0~card32 있으므로 문자4번째부터(card~) 끝까지 추출한다
        int cardNum = int.Parse(transform.tag.Substring(4));

        //이미지 번호 카드 두장에 하나씩 같은 이미지를 할당하므로 이미지 번호는 (카드번호 +1)/2 로 구한다 정수 /정수 = 정수 이므로 소수 이하는 자동으로 잘림
        imgNum = (cardNum + 1) / 2;
        //카드 애니메이션 실행
        anim.Play("aniOpen");

        GameManager.cardNum = cardNum;
        GameManager.state = GameManager.STATE.HIT;

    }
    void CloseCard()
    {
        anim.Play("aniClose");
        isOpen = false;
    }
    //카드 앞면을 이미지을 가지고 온다
    void ShowImage()
    {
        transform.GetComponent<Renderer>().material.mainTexture = Resources.Load("card" + imgNum) as Texture2D;
    }


    //카드 뒷면 이미지을 가지고 온다
    void HideImage()
    {
        transform.GetComponent<Renderer>().material.mainTexture = Resources.Load("back" + backNum) as Texture2D;
    }
}

 

 

 

 

임포트 받았더 back5 를 back1으로 수정합니다 

 

게임을 실행시켜서 두 개의 그림이 맞으면 서로 열리고 안 맞으면 서로 닫힙니다 

그리고 그림이 모두 열리면 다음 스테이지로 넘어갑니다 

아래 동영상과 같이 게임이 실행되면 성공입니다

 

 

반응형

+ Recent posts