목표 |
배운 것을 이용하여 객체를 생성하고 지뢰위치를 찾는 프로그램을 작성해 보자.
실습 |
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
레이캐스트 사용
https://funfunhanblog.tistory.com/24
'응용프로그래밍 > 유니티기초' 카테고리의 다른 글
[유니티2D] 타일맵을 이용하여 배열 맵 구축 (0) | 2022.06.06 |
---|---|
[유니티2D 활용] 테트리스 게임 만들기 (0) | 2022.06.03 |
[유니티기초]2-05. 플레이어 위치를 찾아서 그쪽으로 이동을 해 보자. (0) | 2022.06.01 |
[유니티기초]2-04. 애니메이션 (0) | 2022.06.01 |
[유니티기초] 2-03. 두 객체가 부딪혔을 때 밀림 방지 (0) | 2022.05.31 |