TIL - 23.12.21

Amberjack·2023년 12월 21일
0

TIL

목록 보기
1/83

오늘은 게임 부트 캠프의 사전 캠프 4주차에 진행한 프로젝트를 다시 한번 복습했다.

카드 두 장을 뒤집어 같은 카드를 찾는 카드 맞추기 게임.

👏 프로젝트 진행 절차

  1. MainScene 생성 및 타이머 만들기
  2. 카드 만들기
    👉 카드를 16개 만들어서 4 * 4로 정렬하기
    👉 카드 애니메이션 만들기
  3. 카드끼리 서로 비교해서 같으면 사라지고 다르면 다시 뒤집기
  4. 카드 다 뒤집으면 게임 종료
  5. 끝! 버튼 누르면 게임 재시작

🃏 카드 만들기

▪️ 카드를 뒤집는 방법?

  1. card 밑에 front와 back을 만들어 앞 뒷면을 만들어 준다.
  2. 카드가 클릭되면 back은 SetActive를 false로, front는 true로 변경해준다.
    transform.Find("front").SetActive(true);
    transform.Find("back").SetActive(false);

▪️ 카드 만들기

게임이 실행되자마자 카드가 생성되어야 하므로 Start()에 코드를 작성한다.
카드에 임의의 이미지 넣기???

  1. 사용할 이미지 수 만큼 반복되는 for문을 사용하자.

  2. 이미지들의 이름을 나타낼 배열을 만들어두자.

    in[] rtans = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7};
  3. 만든 배열을 무작위로 섞기!!!

  4. rtans 리스트를 랜덤하게 무작위로 선정해준다.

    rtans = rtans.OrderBy(item => Random.Range.ToString();
  5. Resource의 이미지 적용시키기

🃏 카드 뒤집기

▪️ 카드를 뒤집기 위해선?

  1. 카드가 눌리면 뒤집어진다 → 카드에 Button 컴포넌트를 추가한다.
  2. card.cs에 openCard()를 만들어 카드를 뒤집었을 때 카드 비교하기.
  3. gameManager.cs에서 isMatched()를 생성, 두 카드의 이미지 명이 동일한 지 여부를 확인!!!

👏 카드가 모든 짝을 찾으면 게임 종료 시키기

🤔 모든 짝을 찾았는 지 어떻게 확인?
✨ cards 밑에 card가 몇 개나 남았는 지 확인!!!

📌 기억해둘 기능들!

▪️ gameManager의 싱글톤화

public static gameManager I;

void Awake()
{
	I = this;
}

▪️ 배열 랜덤으로 정렬하기

int[] rtans = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
// rtans 리스트를 랜덤하게 정렬하기
rtans = rtans.OrderBy(item => Random.Range(-1.0f, 1.0f)).ToArray();

OrderBy를 통해 배열을 오름차순 혹은 내림차순으로 정렬할 수 있다.

▪️ 스프라이트 교체하기

▪️ 스프라이트 이름 가져오기

▪️ Animation Transition의 조건 변경하기!

public Animator anim;

anim.SetBool("조건", true 혹은 false);

✨ 오늘을 마치며...

오늘은 게임 개발 부트캠프가 본격적으로 시작하는 날이었다. 설렘인지 긴장인지 모르겠지만 잠을 못 잤다. 때문에 TIL을 쓰면서 비몽사몽 해서 정말 힘들었다...
미니 프로젝트 팀원들을 만나 함께 얘기 해보고 팀 노션도 꾸며보았는데, 주도적이신 두 분이 계셔서 든든했다. 옆에서 뭔가를 말할 틈도 없이 일이 척척 진행되는 것을 보고 적극적인 소통이 정말 중요하다 느꼈다. 나도 더욱 적극적으로 참여할 수 있도록 해야겠다.

🤔 과제 :

▪️ 미니 프로젝트에서 내게 맡겨진 과제는 "결과에 카드 매칭 시도 횟수 표시하기"이다.

  1. 카드 매칭 횟수를 카운팅하기 위한 변수 counter가 필요할 것이다.
  2. counter를 증가시킬 타이밍? → 두 개의 카드를 뒤집고 서로 비교를 하기 위해 isMatched() 함수가 호출될 때 counter를 증가시키면 될 것이다.
  3. 결과창??? 결과창을 새로 만들어야 하는 걸까? 내일 팀원들과 회의할 때 물어봐야 함!!!

일단 완료!

public class gameManager : MonoBehaviour
{
    public static gameManager I;

    public GameObject card;
    public GameObject firstCard;
    public GameObject secondCard;
    public GameObject endPanel;

    public Text timeTxt;
    public Text count;

    public float time = 60.0f;
    public int counter = 0;

    // gameManager 싱글톤
    private void Awake()
    {
        I = this;
    }

    // Start is called before the first frame update
    void Start()
    {
        Time.timeScale= 1.0f;

        int[] rtans = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
        // rtans 리스트를 랜덤하게 정렬하기
        rtans = rtans.OrderBy(item => Random.Range(-1.0f, 1.0f)).ToArray();

        for(int i = 0; i < 16; i++)
        {
            // card를 cards의 자식으로 넣기
            GameObject newCard = Instantiate(card);
            newCard.transform.parent = GameObject.Find("cards").transform;

            // 카드 X, Y좌표 배치하기
            float x = (i % 4) * 1.4f - 2.1f;
            float y = (i / 4) * 1.4f - 3.0f;

            newCard.transform.position = new Vector3(x, y, 0);

            // 카드 이미지 넣기
            string rtanName = "rtan" + rtans[i].ToString();
            newCard.transform.Find("front").GetComponent<SpriteRenderer>().sprite = Resources.Load<Sprite>(rtanName);
        }
    }

    // Update is called once per frame
    void Update()
    {
        // 시간 흐르게 하기
        time -= Time.deltaTime;

        // 30초 되면 게임 멈추기
        if(time <= 0.0f)
        {
            time = 0.0f;    // 시간 감소로 0보다 작아지는 것을 방지!
          
            //////////////////////////////////////////////////////////////////
            // 결과창 띄우기
            endPanel.gameObject.SetActive(true);
            count.text = counter.ToString();
            Time.timeScale = 0.0f;
        }

        timeTxt.text = time.ToString("N2");
    }

    public void isMatched()
    {
        counter++;      // 시도 횟수 증가

        // 첫 번째, 두 번째 카드의 이미지 이름을 가져와 비교하기
        string firstCardImage = firstCard.transform.Find("front").GetComponent<SpriteRenderer>().sprite.name;
        string secondCardImage = secondCard.transform.Find("front").GetComponent<SpriteRenderer>().sprite.name;

        if (firstCardImage == secondCardImage)
        {
            // 두 카드의 이미지 이름이 같을 경우 destroy
            firstCard.GetComponent<card>().destroyCard();
            secondCard.GetComponent<card>().destroyCard();

            // 카드 다 맞추면 게임 멈추기
            int cardsLeft = GameObject.Find("cards").transform.childCount;
            if(cardsLeft == 2)
            {
                // 결과창 띄우기
                endPanel.gameObject.SetActive(true);
                count.text = counter.ToString();
                Time.timeScale = 0.0f;
            }
        }
        else
        {
            // 카드 다시 뒤집기
            firstCard.GetComponent<card>().closeCard();
            secondCard.GetComponent<card>().closeCard();

            // 실패할 때마다 시간 감소!
            time -= 3.0f;
        }

        // 다시 null로 초기화 시켜서 카드 두 장을 선택할 수 있도록 만들어 주기
        firstCard = null;
        secondCard = null;
    }
}

😱 미니 프로젝트의 Challenge 문제

▪️ 게임 난이도 설정하기(2분 / 1분 30초 / 1분)

시간제한을 두는 것은 어렵지 않다. Game Mode 1, 2, 3을 두어 관리하면 될 것 같다.
난이도를 해금하는 방식? : 쉬운 난이도를 깨면 새로운 난이도가 열리도록 만들기?
👉 Scene을 여러 개 만들면 어떨까?

▪️ 카드 맞추기 실패할 때마다 시간 감소 효과 넣어보기 - 완료!

isMatched() 함수에서 else 부분의 카드 다시 뒤집기에서 변수 time을 줄이면 됨.

▪️ firstCard 고르고 5초간 카운트 다운 - 안 고르면 다시 뒤집기

해내긴 했는데 내가 봐도 너무 별로인 코드... 알고리즘 및 클린 코드 공부를 필수적으로 해야겠다...

// card.cs
void Update()
{
	// gameManager.I.time은 실시간으로 줄어들고 있는 게임 내 시간이다.
	// 때문에 timeSpan에 저장했을 때보다 time이 5초만큼 더 작아지면 firstCard 다시 뒤집기
	if(timeSpan - gameManager.I.time >= 5.0f)
	{
		timeSpan = 0.0f;
		gameManager.I.firstCard.GetComponent<card>().closeCard();
       
		gameManager.I.firstCard = null;
	}
}

// 카드 뒤집기
public void openCard()
{
	// 카드 뒤집는 애니메이션 활성화
	anim.SetBool("isOpen", true);

	// 카드 뒤집기
	transform.Find("front").gameObject.SetActive(true);
	transform.Find("back").gameObject.SetActive(false);

	if(gameManager.I.firstCard == null)
	{
		// firstCard가 null이면 firstCard로 넣어버리기
		gameManager.I.firstCard = gameObject;

		// firstCard가 뒤집힌 시간을 timeSpan에 저장하기
		timeSpan = gameManager.I.time;

	}
	else
	{
		timeSpan = 0.0f;
		gameManager.I.secondCard= gameObject;
		gameManager.I.isMatched();
	}
}

실행 화면 ▼

0개의 댓글