Java로 Battle 게임 만들기

니나...·2025년 7월 10일

미니 프로젝트

목록 보기
3/4
post-thumbnail

1. 프로그램 목적과 동작 시나리오

본 프로젝트의 목적은 Java GUI를 활용하여 턴제 기반의 배틀 게임 시스템을 직접 설계하고 구현해보는 것이다. 사용자는 4명의 공주 캐릭터(엘사, 자스민, 뮬란, 라푼젤) 중 하나를 선택하여 전투에 참여하게 되며, 마법사 계열과 전사 계열의 캐릭터 클래스가 분리되어 있고, 각 캐릭터는 고유의 무기(또는 스킬)를 사용하여 상대 캐릭터와 전투를 벌인다.
게임은 단일 전투로 구성되며, 플레이어와 적은 번갈아 가며 공격 또는 회복 액션을 취할 수 있다. 전투 중 캐릭터의 체력이 0이 되면 전투는 종료되며, 전투 상황은 실시간 텍스트 로그와 함께 진행되어 유저가 직관적으로 전황을 파악할 수 있도록 했다.

2. Player와 Weapon의 클래스 다이어그램

Player는 추상 클래스이며, 공통 필드와 메서드(이름, 체력, attack())를 포함한다.
Player를 상속받는 세부 클래스에는 마법사공주, 전사공주가 있으며, 각각 스킬(Skill) 또는 무기(Weapon) 객체를 조합하여 다형성을 구현하였다.
Weapon과 Skill은 각각 공격 수단을 추상화한 클래스이며, Player의 공격 로직에서 위임을 통해 실제 데미지를 출력하거나 효과를 처리한다.

3. 주요 실행화면 (본글에 동영상 별첨)

캐릭터 선택 화면: 콤보박스로 캐릭터를 선택하고 “전투 시작” 버튼을 누르면 게임 화면으로 전환
게임 화면: 플레이어 및 적 캐릭터 이름, HP 바, 공격/회복 버튼, 전투 로그 창으로 구성
전투 진행 중: 로그창에 실시간으로 각 캐릭터의 행동 결과(공격 데미지, 회복량 등)가 출력됨
게임 종료 시: 플레이어 혹은 적이 쓰러졌다는 메시지 출력 후 버튼 비활성화

4. 더 공부한/적용한/찾아본 내용

초기에는 이미지가 로드되지 않는 문제가 발생했는데, 이는 이미지 파일이 src 폴더 바로 아래가 아닌 src/images 폴더에 있었음에도 불구하고, getResource()가 올바른 상대경로를 인식하지 못했기 때문이었다. 문제 해결을 위해 getClass().getResource()로 경로를 절대경로처럼 지정하면서도 classpath 기준의 상대경로로 접근할 수 있도록 수정했다. 또한 .jar 파일로 export한 뒤 외부에서 실행했을 때 이미지가 누락되는 문제도 있었는데, 이는 .jar 패키징 시 이미지 리소스가 포함되지 않아서 발생한 것으로, Eclipse에서 build path에 resource 폴더를 명확히 추가하고, export 설정에서 리소스를 함께 포함시키는 방식으로 해결했다.
전투 흐름 제어를 위해 각 턴마다 공격/회복 버튼을 비활성화하거나 활성화하는 로직을 직접 구현했다. 예를 들어, 플레이어가 공격을 선택하면 버튼은 일시적으로 비활성화되고, 적의 공격이 끝난 후 다시 활성화되도록 구성했다. 이를 통해 이벤트가 중복 처리되는 문제를 방지하고, 사용자의 인터랙션 흐름을 자연스럽게 제어할 수 있었다. setEnabled(false)와 setEnabled(true)를 적절히 사용한 이 방식은 간단하지만 효과적이며, 게임의 직관성과 완성도를 높이는 데 기여했다.
처음에는 Player 클래스의 attack() 메서드를 오버라이딩하여 마법사와 전사의 공격 방식을 각각 다르게 구현했지만, 실제 전투 로그에는 항상 동일하게 "공격했습니다"라는 문장만 출력되는 문제가 있었다. 이는 내부 동작은 다형적으로 구현되어 있었지만, 출력 메시지는 다형성을 활용하지 않아 표현이 단조롭게 고정된 상태였기 때문이다. 이를 해결하기 위해 Player 클래스에 새로운 추상 메서드 getAttackDescription()을 추가하고, 각 하위 클래스에서 스킬명이나 무기명을 포함한 메시지를 다르게 정의함으로써, 공격 방식에 따라 동적으로 다른 전투 로그가 출력되도록 개선하였다.

5. 구현 소감

단순한 GUI 기반 전투 게임이지만, 실제로 구성해보니 클래스 간의 관계 설계, 이벤트 흐름 처리, 상태 제어 등 생각보다 많은 부분에서 객체지향 설계와 GUI 흐름의 연결이 중요함을 느꼈다. 특히 이미지 경로를 설정하는 부분, 다형성 구현을 통해 출력문이 각각 다르게 나오도록 하는 부분에서 애를 먹었다. 그러나 캐릭터별 능력을 분기 처리하는 과정에서 if-else가 아닌 다형성을 통한 확장성 있는 설계를 도입하려 노력했고, 덕분에 새로운 캐릭터를 추가하는 구조도 매우 간결하게 구성할 수 있었다.

0개의 댓글