본문 바로가기

Unity/Unity 스파르타

1주차, 카드 게임 기능 구현(2)

728x90
  1. 카드 등장 효과 만들기 구현 + 게임 시작 모든 카드 앞면 보여주기
    1. 카드가 중앙을 향해 나선형으로 등장
    2. 중앙에 도착시 각자 카드의 위치로 이동
    3. 카드가 각자 제자리에 도착했으면 카드를 다 뒤집어 카드의 모든 앞면을 보여준 후 카드를 뒤집고 게임 시작.
  2. 카드 하나를 고르고 일정 시간동안 카드를 고르지 않으면 땡처리 하고 카드 뒤집기

 

1. 카드 등장 효과 만들기 구현 + 게임 시작 모든 카드 앞면 보여주기

 

카드의 나선형 이동 필요 변수

  • 처음 카드의 생성 위치
  • 카드의 회전 속도
  • 나선형으로 돌 최대 반지름
  • 센터를 중심으로 도는 속도
  • 현재 반지름
    public float rotationSpeed = 300f; // 회전 속도
    public float maxRadius; // 주변을 도는 최대 반지름
    public float orbitSpeed = 5f; // 센터를 중심으로 주변을 도는 속도
    private float currentRadius; // 현재 반지름

 

1. 카드가 중앙을 향해 나선형으로 등장

카드가 생성되면 바로 나선형으로 돌게 만들 것 입니다.

    private void Start()
    {
        StartCoroutine(RotationCo());
    }

transform.RotateAround() 함수를 사용해 카드가 중앙을 기준으로 나선형으로 돌게 만들 것 입니다.

transform.RotateAround(기준,도는방향,속도)

현재 반지름이 0 이될때까지 현재 위치를 업데이트 시켜줄 것입니다.

현재 위치의 경우 0 부터 세타값을 증가시킨후 세타값을 이용해 x,y값을 구하고 현재 반지름 값을 곱해준뒤 반환해줍니다.

  Vector2 GetPosition()
    {
        angle += Time.deltaTime * orbitSpeed;
        float x = Mathf.Cos(angle) * currentRadius;
        float y = Mathf.Sin(angle) * currentRadius;
        return new Vector2(x, y);
    }

 

반지름이 0 이하로 줄어들지 않게 클램핑 해줍니다.

    IEnumerator RotationCo()
    {
        while (currentRadius > 0)
        {
            transform.RotateAround(Vector3.zero, Vector3.forward, Time.deltaTime * rotationSpeed);
            transform.position = GetPosition();
            currentRadius -= Time.deltaTime;
            currentRadius = Mathf.Clamp(currentRadius, 0, maxRadius);
            yield return null;
        }
        transform.rotation = Quaternion.Euler(0, 0, 0);

        StartCoroutine(CardOriginalLocationMoveCo());
    }

while문이 끝나면 카드가 중앙에 도착했다는 뜻이기 때문에 이제  카드를 원래 위치로 보내 줍니다. 

 

카드를 생성 할때 생성과 동시에 원래의 위치를 설정해 두었습니다.

모든 카드가 원래의 위치에 도착했을때 모든 카드를 오픈해 이미지를 보여줄 것입니다.

 IEnumerator CardOriginalLocationMoveCo()
    {
        float percent = 0;

        while (percent < 1)
        {
            percent += Time.deltaTime;
            transform.position = Vector3.Lerp(transform.position, new Vector3(x, y, 0), percent);
            yield return null;
        }


        if (GameManager_T4.I.AllCheckCardOriginalPosition())
        {
            GameManager_T4.I.AllOpenCard();
        }

    }

 

모든 카드들을 담은 list를 만들어주고 카드의 현재위치와 카드를 생성할때 설정해 놓은 위치를 확인 합니다.

모든 카드들이 자기 위치를 찾아갔으면 이제 모든 카드를 열어줍니다.

    public bool AllCheckCardOriginalPosition()
    {
        for (int i = 0; i < cardPack.Count; i++)
        {
            float x = cardPack[i].GetComponent<Card>().x;
            float y = cardPack[i].GetComponent<Card>().y;

            if (cardPack[i].transform.position != new Vector3(x, y, 0))
            {
                return false;
            }
        }
        
        return true;

    }

 

카드를 모아놓은 리스트를 사용해 모든 카드들을 오픈해 주고 일정 시간 뒤에 카드를 닫아줍니다.

모든 카드가 다 닫히면 게임모드를 바꿔 게임을 시작합니다.

public void AllOpenCard()
    {
        StartCoroutine(AllCardOpenCo());
    }


    IEnumerator AllCardOpenCo()
    {
        gameState = GameState.Ready;
        for (int i = 0; i < cardPack.Count; i++)
        {
            GameObject front = cardPack[i].transform.Find("Front").gameObject;
            GameObject back = cardPack[i].transform.Find("Back").gameObject;

            cardPack[i].GetComponent<Card>().CardFlip(front, back);
            yield return new WaitForSeconds(0.1f);
        }

        yield return new WaitForSeconds(timeTheCardIsOpen);

        for (int i = 0; i < cardPack.Count; i++)
        {
            GameObject front = cardPack[i].transform.Find("Front").gameObject;
            GameObject back = cardPack[i].transform.Find("Back").gameObject;

            cardPack[i].GetComponent<Card>().CardFlip(back, front);
            yield return new WaitForSeconds(0.1f);
        }

        yield return new WaitForSeconds(1.5f);

        gameState = GameState.Start;

    }

2. 카드 하나를 고르고 일정 시간동안 카드를 고르지 않으면 땡처리 하고 카드 뒤집기

현재 카드게임에는 계속해서 시간이 흘러가는 타이머가 존재 하기 때문에, 이 타이머를 사용해 

카드를 하나 고르고 일정 시간동안 다른 카드를 고르지 않으면 틀린 것으로 간주하고 시간을 감소시키고 땡! 이미지를 나타나게 만든뒤 카드를 다시 뒤집어 줄 것 입니다.

 

 void TimeRun()
    {
        if (gameState == GameState.Start) //게임 상태가 게임 시작일때 타이머 시작
        {
        timeLimit -= Time.deltaTime;
        timeText.text = timeLimit.ToString("N2");
        }

        if(timeLimit < 15 && !timeIsRunning) //15초 부터 타이머를 점멸 시키면서 BGM이 빨리짐
        {
            audioManager.AudioPitchUp();
            timeIsRunning = true;
            timeAnimator.SetBool("TimeIsRunning", true);
        }

        if(timeLimit <= 0) // 게임 오버
        {
            timeText.text = time.ToString("0.00");
            gameState = GameState.GameOver;
            panel.SetActive(true);
            gameOverMessage.GetComponent<Text>().text += "\n" + "Flip Count :" + flipCount.ToString();
            gameOverMessage.SetActive(true);
        }

        if(matchCardList.Count == 1 && !isCardOpen) // 카드를 1개 만 골랐을때 새로운 타이머를 시작
        {
            StartCoroutine(CardOpenTimerCo());
        }

    }

Update() 함수에서 타이머가 작동 중이기 때문에 타이머 작동 조건을 걸어주지 않으면 해당 함수를 한번에 60번 정도 실행하기 때문에 조건을 꼭 걸어줘야 합니다.

 IEnumerator CardOpenTimerCo()
    {
        isCardOpen = true; 카드를 오픈했는가
        float openCardDuration = 3f; 카드 오픈 타임
        while(matchCardList.Count == 1) 고른 카드가 1개일때
        {
            openCardDuration -= Time.deltaTime; 타이머 시작

            if(openCardDuration <= 0) 타이머가 0이 됐을때
            {
                matchCardList[0].GetComponent<Card>().CloseCard(); 카드를 뒤집고
                TimeDeduction(); 시간을 감소시키고
                StartCoroutine(WrongMessageCo()); 떙! 이미지를 나타내고
                matchCardList.Clear(); 고른 카드를 리셋
                isCardOpen = false; 카드를 오픈하지 않음

            }

            yield return null;
        }
    }

 

728x90