2025년, 코딩은 선택이 아닌 필수!

2025년 모든 학교에서 코딩이 시작 됩니다. 먼저 준비하는 사람만이 기술을 선도해 갑니다~

응용프로그래밍/유니티기초

[유니티2D활용]지뢰찾기 게임 만들기

파아란기쁨1 2022. 6. 1. 20:26
반응형
목표

배운 것을 이용하여 객체를 생성하고 지뢰위치를 찾는 프로그램을 작성해 보자.

 

 

실습

1. Square 를 추가하여 프리팹으로 만들어 놓는다. size를 0.9,0.9 크기로 만든다.

2. 블럭을 동적으로 할당 할 것이므로 스크립트를 실행할 GameObject를 생성하여 다음 스크립트 추가

동적객체생성( https://thinkmath2020.tistory.com/3506?category=1019149 ) 참고.

 

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

public class Block : MonoBehaviour
{
    public int height=10,width=10; //기본으로 10 x 10
    public GameObject square;
    private GameObject[,] blockMap;

    // Start is called before the first frame update
    void Start()
    {
        blockMap = new GameObject[width,height]; //block를 담아 놓을 Map를 생성하자
        IniatializeBlock(); //Block initialization     
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    void IniatializeBlock(){
        //Block initialization

        int startX = -width /2;//중간 위치는 0,0 을 기준으로 상하 좌우로 생성하자
        int startY = -height /2;

        for(int i=0;i<height;i++){
            for(int j=0;j<width;j++){

                Vector3 pos = new Vector3(startX + j, startY + i,0);
                GameObject tmp = Instantiate<GameObject>(square,pos,Quaternion.identity); //square 생성하자
				tmp.name = (i*100+j).ToString(); //컴포넌트에 이름을 할당하자.
                
                blockMap[j,i]=tmp;
            }
        }
    }
}

위와 같이 작성해서 실행해 보면 다음과 같이 실행 되는 것을 확인 할 수 있다.

.

3. 클릭 했을 때 어느 위치인지 확인해 보자.

        if(Input.GetMouseButtonUp(0)){//좌클릭
            Debug.Log(gameObject.name);
        }

이렇게 했을때 0,0 부터 9,9 까지 모든 프리팹 이름이 출력 되는 것을 확인 할 수 있다.

따라서 해당 클릭한 위치의 객체 이름을 가져 오기 위해서는 생성할 프리팹에 collider 를 추가 한 후에 다음과 같이 마우스 클릭 위치에 collider 가 존재 하는지 체크 하고 존재 한다고 하면 그 곳  위치의 객체명을 가져 올 수 있다.

 

        if(Input.GetMouseButtonUp(0)){//좌클릭
            RaycastHit2D hit;
            Vector2 pos = mainCam.ScreenToWorldPoint(Input.mousePosition);
            hit = Physics2D.Raycast(pos,Vector2.zero,0f);
      
            if(hit.collider != null){
                currentTouch = hit.transform.gameObject;
                Debug.Log(currentTouch.name.ToString());
            }
        
        }

이렇게 해서 실행을 해보면 클릭한 객체의 이름이 잘 표시 되는 것을 확인 할 수  있다.

 

4. 지뢰 위치를 생성하자.

private void MineCreate(){
        int y,x;

        for(int i=0;i<mineCnt;i++){
            y = Random.Range(0, height);
            x = Random.Range(0, width);
            if(mine[x,y]){
                i--;
            }
            else{
                mine[x,y]=true;
            }
        }  

    }

5. 클릭 했을때 주변으로 Open 하면서 이미지를 변경하자.

이미지셋을 만들어 놓은 후 다음과 같이 이미지를 매칭하자.

public Sprite[] imgset= new Sprite[13];

0번 위치는 0의 이미지, 1번부터 9번까지는 각각의 숫자 매칭 후,10번에 깃발,11번에 지뢰,12번에 원본 위치를 매칭한후 다음과 같이 코딩하자.

 

이 때 이미지 변경시에 이미지 크기대로 나오는 부분을 수정하기 위해 프리팹의 속성을 다음과 같이 변경하자.

클릭했을 때 오픈하는 코드를 다음과 같이 추가 하자.

//클릭을 하면 주변의 지뢰수 만큼 표시
    private void Click(int x,int y){
        Debug.Log("Left Click" + x.ToString() + " " + y.ToString());
        if(x<0||x>=width) return;
        if(y<0||y>=height) return;
        Debug.Log("1Level Click");
        if(visited[x,y]) return; //이미 클릭했으면 진행 하지 말자.
        visited[x,y]=true;
        if(mine[x,y])
        {
            Debug.Log("Mine Click");
            //지뢰를 클릭하면 게임 종료
            blockMap[x,y].GetComponent<SpriteRenderer>().sprite=imgset[11]; //지뢰모양으로 표시
            return;
        }
        int cnt=0;
        for(int i=x-1;i<=x+1;i++){
            if(i<0||i>=width) continue; //범위를 넘어 가는 경우 세지 말자.
            for(int j=y-1;j<=y+1;j++){
                if(j<0||j>=height) continue; //범위를 넘어 가는 경우 세지 말자.
                if(mine[i,j]) cnt++;
            }
        }
        Debug.Log(x.ToString() + "," + y.ToString() + ":" + cnt.ToString());
        blockMap[x,y].GetComponent<SpriteRenderer>().sprite=imgset[cnt]; //갯수의 이미지를 표시하자.
        if(cnt==0){//지뢰 갯수가 0 개이면 주변으로 번지자.
            for(int i=x-1;i<=x+1;i++){
                if(i<0||i>=width) continue; //범위를 넘어 가는 경우 세지 말자.
                for(int j=y-1;j<=y+1;j++){
                    if(j<0||j>=height) continue; //범위를 넘어 가는 경우 세지 말자.
                    Click(i,j);
                }
            }
        }
        
    }

 

완성 소스코드  - http://h.wondangcom.com/download/unity/minesweeper.zip 

연습문제

위의 지뢰 찾기를 마무리 우클릭시 깃발 표시 하고 UI를 만들어서 클릭할 때마다 오픈 된 갯수와 지뢰 남은 갯수를 표시하자.

깃발을 세우면 지뢰 남은 갯수를 하나씩 줄이면서 지뢰 갯수가 0 개 일때 아직 깃발을 세우지 않았고 클릭하지 않은 모든 곳을 open 하면서 open 한 곳에 지뢰가 있다면 게임 오버를 띄운다.

 

 

 

 

 

 

 

 

 

 

참고

https://202psj.tistory.com/1284

 

[Unity] 유니티 오브젝트 선택, 클릭, 터치, 접근, 상호작용 이벤트 관련

================================= ================================= ================================= 출처: https://mentum.tistory.com/192 Unity/프로그래밍 Touch로 3d오브젝트 선택하기  void Updat..

202psj.tistory.com

레이캐스트 사용

https://funfunhanblog.tistory.com/24

 

유니티) ScreenPointToRay 카메라로 부터의 스크린의 점

Camera.ScreenPointToRay 카메라로 부터의 스크린의 점을 통해 레이를 반환합니다. 스크린공간은 픽셀로 정의되며. 픽셀단위 1번 : 왼쪽 하단의 화면이 (0,0) 2번: 오른쪽 상단이 (pixelWidth,pixelHeight) if (In..

funfunhanblog.tistory.com

 

반응형