2018. 4. 18. 12:17 IT/Unity 게임개발
[unity 게임개발] 지렁이 키우기 로직 개발 3
지렁이가 지상으로 올라갔다 내려갔다 하다보니까 오브젝트가 겹치는 부분을 좀 더 신경써야하더군요...ㅠ (예를들면 먹이는 지상에있고, 지렁이가 밑을 기어가는 경우)
때문에 기존에 map 배열에 값을 넣는 방식이 아닌 bit 단위로 And와 OR 연산을 하도록 변경되었습니다.
중요 로직은 매 일정시간 단위로 지렁이와 적을 움직이는 함수....정도네요.
1. GameManager (Tick)
public IEnumerator Tick() { bool isGameOver = false; while (snake.Count < 16) { // 현 시점의 지상으로 나왔는지 여부. bool _isOut = isOut; Snake head = snake[0]; isGameOver = false; // 지렁이의 다음 위치 IntVector2 destination = new IntVector2(head.currentPosition.x + checkPosition[direct].x, head.currentPosition.y + checkPosition[direct].y); // 지렁이는 꼬리부터 몸통까지 우선 움직이고, 머리를 움직일 때 먹이와 방해물 판별을 한다. // 꼬리 위치가 다음 이동할 위치라면, 꼬리를 먼저 오므려주어야 꼬리에 닿지 않는다. map[snake[snake.Count - 1].currentPosition.y, snake[snake.Count - 1].currentPosition.x] &= 7; for (int i = snake.Count - 1; i > 0; i--) { snake[i].SetSnakePosition(snake[i - 1].currentPosition, snake[i - 1].isOut); if (snake[i].isOut) { map[snake[i].currentPosition.y, snake[i].currentPosition.x] |= 16; }else { map[snake[i].currentPosition.y, snake[i].currentPosition.x] |= 8; } StartCoroutine( snake[i].MoveSnake()); } // 머리의 다음 위치가 영역을 넘어가면 종료. ( 배열을 2개 더 크게 만들어 테두리에 장애물을 두는 것도 고려) if (destination.x<0 || destination.y<0 || destination.x>=WIDTH || destination.y >= HEIGHT) { isGameOver = true; break; } // 게임 로직 판단. // 밖에 나온 상태에선, 먹이를 먹고, 움직이는 장애물에 부딫힌다. // 0 = 빈공간, 1 = 먹이, 2 = 방해물 , 4 = 움직이는 장애물 , 8 = 지렁이, 16 = 밖에 나와있는 지렁이몸체 if (_isOut) { if (map[destination.y, destination.x] == 1) { // 먹이를 제거하고, 지렁이의 꼬리를 복사해 꼬리 뒤에 붙여 몸체를 늘린다. 그리고 새로운 먹이를 랜덤하게 생성한다. Eat(ref map,destination); } else if ((map[destination.y, destination.x] & 4) == 4) { // 움직이는 장애물에 닿으면 게임종료 // 움직이는 장애물은 지상에 있으므로, 지하에 있는 지렁이 몸체와 겹칠 수 있다. And 연산을 통해 장애물만 확인. isGameOver = true; } } if (map[destination.y, destination.x] == 2) { // 고정 장애물에 닿으면 게임종료 isGameOver = true; } else if (map[destination.y, destination.x] >= 8) { // 자신의 몸체에 닿으면 게임종료 isGameOver = true; } // 머리를 목표로 이동 및 애니메이션. head.SetSnakePosition(destination, _isOut); StartCoroutine(head.MoveSnake()); // 지렁이는 지하에 있을때 지상에 있는 먹이와 움직이는 장애물에 겹칠 수 있다. OR연산으로 지렁이bit만 더해준다. if (head.isOut) { map[head.currentPosition.y, head.currentPosition.x] |= 16; } else { map[head.currentPosition.y, head.currentPosition.x] |= 8; } //지렁이를 움직인 다음에 적을 움직여준다. for (int i = 0; i < enermy.Count; i++) { // 지렁이가 밖에 나오는 상태면 그 공간의 지렁이를 목표물로 삼는다. if (_isOut) { enermy[i].SetDestination(map, destination); } // 너비탐색을 통해 지렁이를 쫒는다. 만약 밖에나온 지렁이 몸체와 닿으면 종료. IntVector2 enermyDest = enermy[i].FindNextTile(map); if (map[enermyDest.y, enermyDest.x] == 16) { isGameOver = true; } // 적이 머물렀던 자리의 bit를 0으로 만들고 이동위치의 bit에 4를 더한다. map[enermy[i].currentPosition.y, enermy[i].currentPosition.x] &= 27; map[enermyDest.y, enermyDest.x] |= 4; enermy[i].SetPosition(enermyDest); yield return StartCoroutine(enermy[i].MoveEnermy()); } if (isGameOver) { break; } yield return null; } if (isGameOver) { GameOver(); } else { Victory(); } }
지렁이의 길이가 16 이상이 될 때까지 매 틱마다 지렁이와 적을 움직입니다.
Map은 bit로 이루어지고, 각 비트는
0000 (0) = 빈공간, 0001(1) = 먹이, 0010 = 움직이는 장애물 , 0100 = 지렁이, 1000 = 밖에 나온 지렁이로 이루어져있습니다.
처음에는 일반 변수로 했었는데 지하에 나오는 지렁이와 지상에 있는 장애물,먹이가 겹칠 경우 지상의 값을 덮어씌우다보니 배열을 나누거나, bit 연산으로 바꿔야 했고, 결국 bit 연산으로 변경해서 만들었습니다.
해당 게임에서는 지렁이의 꼬리를 먼저 오므려서 지렁이가 꼬리를 먹지 못하게끔 했습니다.
지렁이 게임에 괜히 기획 추가해서 좀 꼬였었는데, 이렇게 하는게 재밌긴하네요.. 이전에 만든 게임도 조금씩 변형을 해볼..
* 다른 로직은...포스팅에 추가할만한 건 너비탐색 정도밖에 없는 것 같네요. 너비탐색은 별도로 포스팅하는게 좋을 듯하여 지렁이 관련 로직은 여기서 마무리를 하겠습니다.
* 초록색 - 지렁이, 파란색 - 먹이, 빨간색 - 방해물, 분홍색 - 움직이는 방해물
* 지적은 언제나 환영입니다.
'IT > Unity 게임개발' 카테고리의 다른 글
[unity 게임개발] 테트리스 게임 로직 개발 2 (0) | 2018.04.23 |
---|---|
[unity 게임개발] 테트리스 게임 로직 개발 1 (0) | 2018.04.22 |
[unity 게임개발] 지렁이 키우기 로직 개발 2 (0) | 2018.04.16 |
[unity 게임개발] 지렁이 키우기 로직 개발 1 (0) | 2018.04.16 |
[unity 게임개발] Flood 게임 로직 개발 2 (0) | 2018.04.16 |