바이브코딩으로 게임 만들기 #7 — 발사체 베이스 클래스 설계

아처 유닛을 만들면서 화살 발사체를 어떻게 구현할지 고민했다. 일단 화살 하나만 필요했지만, 나중에 마법 투사체나 다른 발사체가 생길 수도 있었다. 그래서 Projectile 베이스 클래스를 만들고 Arrow가 상속받는 구조로 갔다.

베이스 클래스에는 공통 로직만

Projectile은 발사체가 공통으로 가져야 할 것들만 담았다. 이동, 팀 정보, 공격력, 목표 설정, 충돌 처리가 그것이다. 충돌이 일어나면 상대방 CombatComponent를 찾아서 데미지를 넣고, 피격 처리 후 발사체를 제거한다.

이동 방식이나 애니메이션은 자식 클래스에서 구현하도록 _move() 같은 가상 함수를 열어뒀다. Arrow에서 이걸 오버라이드해서 포물선 이동을 구현했다.

포물선 이동

화살이 직선으로 날아가면 심심하다. 포물선을 주고 싶었다. 구현은 생각보다 단순하다. 발사 시점과 목표 지점을 기준으로 진행 비율(t)을 0에서 1로 올리면서, Y축에 포물선 오프셋을 더해준다.

오프셋은 sin(t * PI) * arc_height로 계산했다. t가 0이면 0, 0.5면 최대 높이, 1이면 다시 0이 된다. arc_height를 CSV에서 받아오니까 화살마다 다른 궤도를 줄 수 있었다.

관통 처리

화살에 pierce_count를 추가했다. 충돌할 때마다 1씩 줄이고, 0이 되면 제거한다. 기본값은 1이고, 특수 화살은 2나 3으로 설정하면 여러 유닛을 관통한다.

이 기능을 베이스 클래스에서 처리해뒀으니까 Arrow뿐 아니라 다른 발사체를 추가해도 관통 로직을 다시 짤 필요가 없다.

스폰은 팩토리에서

화살을 발사할 때마다 인스턴스를 생성하면 성능 문제가 생길 수 있다. CharacterFactory Autoload에서 발사체 풀을 관리하게 했다. 사용하지 않는 발사체를 재사용하는 방식이다.

정리하자면

발사체 베이스 클래스 하나를 제대로 잡아두니까 나중에 새 발사체를 추가할 때 공통 로직을 다시 짜지 않아도 됐다. 상속 구조가 항상 좋은 건 아니지만, 발사체처럼 공통점이 많은 경우엔 효과적이었다.