18 January 2024

Avoid Game 게임 구조 설계

by 꽈배기

문득 이런 생각이 들었다.

뱀서라이크에 닷지 게임을 합치면 어떨까? 쉴세 없이 몰려드는 공격들, 뱀서라이크 특유의 스킬 빌딩을 살린 로그라이크 형식의 피하기 게임 말이다.


이제부터 나는 피하기 게임을 만들것이다. 그럼 이제 게임의 방향성을 고려해봐야 할 차례다. 뱀서라이크 게임을 분석해보자.

image

직접 구매해서 플레이해봤다.

  1. 뱀서 게임을 본다면 적을 제거하거나 일정 조건을 도달할 때, 선택지를 통해 플레이어를 키운다.
  2. 로그라이크 형식을 지니기에 매 시도마다 랜덤 결과를 출력해 새로운 플레이 경험을 유도한다.
  3. 일정 스테이지마다 특수 웨이브 또는 보스 난이도가 존재한다.
  4. 무한 난이도
  5. 플레이어 업그레이드 (영구적) 시스템이 존재한다.

흠… 대략 매번 새로운 카드를 골라 생존하는 게임을 만들면 될 것 같다. 다만 뱀서라이크와 똑같이 만들 순 없을것 같다.

만약 스테이지마다 무한으로 버티기 라던지… 공격 개체들이 아주 많아질 경우 버티는게 무슨 의미가 있어질까 싶다.



본격적인 개발을 시작하기 전에 중요한것이 있다. 나는 감히 구조를 짜는것부터 시작이라 말하고 싶다.

몇 번의 경험을 통해 구조의 소중함을 깨달았기 때문이기도 하지만 추후에 수정해야 할 코드 늪에서 허우적거리거나 전체적으로 갈아엎고 싶지 않기 때문에 처음부터 구조를 꽤나 고려하면서 작업하기로 하였다.

아래 기록된 내용들은 현재 (2024.01.21) 기준으로 완성된 구조이며 초기 구조부터 복기하며 어떻게 바뀌었고 왜 바뀌었는지에 중점으로 기술할것이다.

전체 구조 미리보기


image

우선 큰 구조부터 고려해보자.

크게 4가지로 나눌 수 있을 것 같다.

물론 구조는 언제든 바뀔 수 있다지만, 왠만하면 메인 시스템은 고정으로 가져가고 싶다. 특히 연관관계에 자유롭게 언제든 접근할 수 있도록 메인 시스템을 싱글톤으로 처리한다.

마찬가지로 적 버프 생성 및 관리 시스템을 따로 두어 메인 시스템을 거친 뒤 플레이어에게 적용되도록 한다. 만약 카드마다, 적 마다 플레이어에게 직접 접근하거나 참조하게 된다면 추후 제어에 문제가 생기거나 연관관계가 꼬여 돌이킬 수 없을지도 모르기에 최대한 클래스간 모듈화를 유지하도록 하자.

Player & BuffManager 플레이어 적용


image

Player Stat, Player는 동일한 오브젝트에 부착된다.

PlayerStat, BuffManager는 메인 시스템에 직접적인 참조를 할 수 있다. PlayerStat은 메인 시스템으로 부터 플레이어의 상태를 제어하게 된다.

플레이어의 실질적인 연산 부분과 행동 부분을 구분하기위해 분리하였다. 단순히 Buff 카드가 능력치 상승이 아닌 특수효과를 포함하게 된다면 이를 분리하는게 훨씬 유리하기 때문이며, 이동만 관리하는 Player 스크립트를 다른 개체들이 굳이 참조 할 필요도 없으니 말이다.


Attack 카드 생성


image

공격용 카드에 포함될 기능들이 존재할 것이다. 그 중 공격 개체에 새로운 유형이 추가되거나 다양한 기능을 제공하기위해 상속을 통해 유사한 부분을 묶고 사용할 데이터를 일괄적으로 관리하도록 했다.

마찬가지로 상속으로 구현할 수 없는 부분은 인터페이스를 활용한다. 이렇듯 Attack 카드 구조는 다형성과 상속을 이용한 재사용을 고려하였다.

Buff 카드 생성


image 다음은 플레이어와 상호작용 할 카드들이다. 각 카드들은 Status Effect를 상속받아 버프종류 카드의 기본 자원과 기능을 상속 받는다.

플레이어에게 적용될 버프와 디버프로 구분되며 이를 통합 관리하기위해 하나의 부모로 상속 받게하였다. 카드 UI는 언터페이스를 구현받아 AttacCard, BuffCard 서로 다르게 구현하기로 하였다.


전체 시스템 구조


image

마지막 메인 시스템은 제너릭 싱글톤으로 이루어져있다.

둘을 구분지어 놓은 이유는 Events는 각 상황에 일어날 일들을 action 타입으로 묶어 처리하기 위해, Manager는 게임의 메인 시스템 및 초기화 정보를 담당하는 말 그대로 매니저의 기능을 가지고 있다.


Manager & Events 클래스


image

이렇게 대략적으로 구조를 그려보았다. 다음은 코드를 작성해보자.