2018. 6. 17. 17:13 IT/Unity 게임개발
[게임 개발] 도시경영 전략 게임 로직 만들기 - 2 (Isometric(마름모 타일) 구현)
앞으로는 단순화해서 포스팅하는 것보다 진행부분 별로 포스팅하도록 바꿀 생각입니다. 파트별로 진행을 해서 포스팅하면서도 좀 정리를 할 겸. 그래서 전략 게임 진행의 첫번째로 Isometric - 마름모 타일 구현하기!
아래 이미지 같은걸 만드는 겁니다. 참고하시길
위와 같은 타일을 isometic 이라고 많이 하더라고요.
솔직히 타일 만드는 것 자체는 쉬운데, 타일 위를 마우스가 지나갈 때 타일별로 하이라이트를 주는 부분에서 생각보다 오래 걸렸네요.
아주 단순하게 생각하면 타일 별로 콜라이더를 적용해서 판별하면 되는데, 이렇게 규칙적으로 생성된 타일은 분명 연산식으로 처리가능 할거고, 앞으로 캐릭터랑 건물들 연산량 쌓일거 생각하면... 반드시 연산식으로 바꿔야 겠다고 생각해서... 고민하느라 오래 걸렸네요.
우선 타일 생성 및 배열 컨트롤을 담당할 TileController
public class TileController : MonoBehaviour { Tile[,] tiles; public Sprite tileImage; // Use this for initialization void Start () { tiles = new Tile[32, 32]; for(int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { // i = y , j = x GameObject tileObj = new GameObject("Tile_" + i + "_" + j); tileObj.transform.position = new Vector3((-1*i) +j, (i*0.5f) + (j*0.5f),0); tileObj.transform.SetParent(transform); tileObj.AddComponent<spriterenderer>().sprite = tileImage; tiles[i, j] = new Tile(i,j,tileObj); } } } }
public class Tile { int posX; int posY; Facility facility; GameObject tileObj; public Tile() { facility = new NullFacility(); } public Tile(int y,int x, GameObject _obj) { posX = x; posY = y; tileObj = _obj; facility = new NullFacility(); } public bool ChangeFacility(Facility _facility) { if (facility.isNull()) { _facility.CreateFacility(tileObj); facility = _facility; return true; } return false; } public void GetInformation() { Debug.Log("posX = " + posX + " posY = " + posY); } }
지금은 그냥 딱 타일 생성만 하는 부분입니다.
로직 관련해서는 너무 단순해서 딱히 설명 할게 없네요.
타일에 관해서는 GameObject가 타일을 컴포넌트로 관리할지, 타일이 GameObject를 가져서 처리를 할지는 좀 더 생각해야겠습니다. (현재는 후자)
InputController - 마우스 컨트롤을 관리하는 클래스
public class InputController : MonoBehaviour { public Sprite mousePointerSprite; GameObject mousePointer; Vector3 lastMousePos; // Use this for initialization void Start () { mousePointer = new GameObject("MousePointer"); mousePointer.AddComponent<spriterenderer>().sprite = mousePointerSprite; } // Update is called once per frame void Update () { if (Input.GetMouseButton(1)) { Vector3 currentPos = currentPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); currentPos.z = 0; Camera.main.transform.Translate(lastMousePos - currentPos); } lastMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); lastMousePos.z = 0; mousePointer.transform.position = getTileCenterPosFromMouse(lastMousePos); } private Vector3 getTileCenterPosFromMouse(Vector3 _mousePos) { _mousePos.y = _mousePos.y * 2; int mPosX = Mathf.FloorToInt(_mousePos.x); int mPosY = Mathf.FloorToInt(_mousePos.y); // 홀짝 구분 / 노출되는 타일들의 중앙점은 합이 짝수다. int checkEven = (mPosX + mPosY) & 1; // 홀수라면 remainX에 곱하여 양수로 바꿔준다. int tempEven = (checkEven * -2) + 1; // 홀수라면 짝수로 기준센터 이동. mPosX += checkEven; float remainX = _mousePos.x - mPosX; float remainY = _mousePos.y - mPosY; // 소수점 이하의 수를 더하여, 1보다 크면 이동. float remainSum = (tempEven *remainX) + remainY; // 더한 값을 내림하여, 1.0 이상이면1로 만들어 최종 계산식에 사용. int floorSum = Mathf.FloorToInt(remainSum); // 더한 값이 1.0 이상이고, checkEven이 짝수라면 x+1,y+1 (floorSum = 1 , tempEven = 1) // 더한 값이 1.0 이상이고, checkEven이 홀수라면 x-1,y+1 (floorSum = 1 , tempEven = -1) // 더한 값이 1.0 이하라면, x,y (floorSum = 0) Vector3 result = new Vector3(mPosX + (floorSum * tempEven),(mPosY + floorSum)*0.5f,-1); //Debug.Log("_mousePos = " +_mousePos + " mPosX = " + mPosX + " mPosY = " + mPosY + " checkEven = " + checkEven + " tempEven = " + tempEven + " remainX = " + remainX + " remainY = " + remainY + " remainSum = " + remainSum +" FloorSum = " + floorSum + " result = " + result); return result; } }
Update에서는 마우스 오른쪽 클릭을 하고, 마우스를 이동시 이전 프레임의 좌표와 현재좌표를 연산하여 카메라를 이동시켜 드래그하여 이동하는 연출을 하고 있습니다.
Update는 나중에 상태 패턴을 이용해 평상시와 건물 설치시로 나눌 예정입니다.
그리고 위에서 말한 타일별 하이라이트를 주는 연산식이 getTileCenterPosFromMouse 입니다.
복잡한 연산할 때는 주석을 미리 써놓고 코딩해서 주석에서 설명을 거의 하고는 있지만, 조금 부연 설명을 하자면... (원래는 각 칸의 높이는 0.5지만, 편의상 1로 하겠습니다.)
목적은 내 하이라이트 타일의 중심점을 각 타일의 중심점에 맞춰주는 것. (절대 (0,1)과 같은 타일의 중간값에 하이라이트가 위치해선 안됨)
사진을 보시면, 모든 마름모 타일의 중앙은 x+y가 짝수이고, 모든 사각형 공간 안의 타일은 그림의 1번과 2번의 두 형태만 존재하는 것에 착안해서 만들었습니다.
그리고 마우스 좌표는 내림을 하면 좌하에 가장 가까운 좌표를 얻을 수 있죠.
- 마우스 좌표를 내림하여 기준 센터를 짝수로 통일
- 마우스 좌표의 내림 합이 짝수면, 2번 영역에 마우스가 있다는 것.
- 마우스 좌표의 내림 합이 홀수면, 1번 영역에 마우스가 있다는 것. (x+1을 하여 짝수로)
- 예를 들면, 내림이 (-1,0)이면 (0,0)을 기준으로 1번 영역에 있는 것이므로 (0,0)으로 기준 변경.
- 각 영역에 맞게 연산하고, 하이라이트 센터 값에 적용.
- 1번은 (0,0)을 기준으로 x,y 소수점 절대값 합이 1.0이상이면 x-1, y+1을 해주고,
- 2번은 (0,0)을 기준으로 x,y 소수점 절대값 합이 1.0이상이면 x+1, y+1을 해줍니다.
- 공통적으로 절대값의 합이 1.0이하면 x,y
isometric 연산식들을 찾아도 봤는데, 위에 말한 단순한 콜라이더 방식도 나오고, 다른 연산은 if-else 문을 이용해서 길게 하는 것도 있더라고요. 마음에 드는 걸 못 찾아서 그냥 만들었습니다. (좀 더 수학공식이나 그래프에 빠삭하면 하는 아쉬움이...) 혹시 비슷한걸 만드시려는 분이시려면 더 좋은 로직을 만드시길... 아마 좀 더 찾으면 대단하신 분들이 간단하게 한게 있을거 같긴한데....
다음에는 건물 설치/ 상태 패턴 적용 을 하겠습니다.
'IT > Unity 게임개발' 카테고리의 다른 글
[게임 개발] 도시경영 전략 게임 로직 만들기 - 4 (건물 기능 / 캐릭터 프로토타입) (0) | 2018.06.23 |
---|---|
[게임 개발] 도시경영 전략 게임 로직 만들기 - 3 (건물 설치) (0) | 2018.06.18 |
[게임 개발]도시경영 전략 게임 로직 만들기 - 1 (0) | 2018.06.15 |
[unity] 구글 플레이 연동 및 파이어 베이스 사용기 (환경 및 오류 위주) (1) | 2018.05.01 |
[unity 게임개발] 테트리스 게임 로직 개발 3 (0) | 2018.04.24 |