adsense



JAVA/slick2d] 2D 슈팅게임 위치즈 스크램블 제작강좌 -step 15- (끝)

step 15. 최종적으로 완성된 게임의 형태입니다.


마지막으로
- 순서와 위치를 지정해서 적이 나오게 하는 Scenario2 구현
- 추가 적 캐릭터와 추가 보스 캐릭터 지정
- 사운드 지정

이상을 구현하겠습니다.

우선 사운드 지정입니다.

그 전에
- 블로그에 올린 압축파일에는 (저작권문제 상)음악이 들어있지 않습니다. 별도로 준비해주세요.


- slick2d에서 사운드는 ogg, xm/mod 파일만 지원됩니다. 평범하게 생각하면 보통 ogg를 쓰는게 무난할 듯 합니다.
- slick2d의 바탕이 되는 LWJGL의 문제로 스테레오 포맷일 경우 오류를 일으키는 수가 있으니 모노 채널로 컨버트해서 사용해야 합니다. (GoldWave 등을 사용)


사운드/음악을 연주할 때마다 파일을 읽으면 부하가 커지니 일단 미리 읽어둡니다.

GameScene에 사운드 관련 변수를 선언합니다.


enter에서 사용할 사운드를 -용량이 크지 않다면- 모두 불러둡니다.


사운드 파일을 재생할 함수를 만듭니다. 이제 사운드 재생이 필요하다면 이 함수에 사운드 번호를 인수로 주고 호출하면 됩니다.



※어떤 경우에 사운드를 호출하는가도 살짝 고민해 볼 부분입니다.

예를 들어 적 캐릭터는 한 순간에 일제히 수십발의 총알을 발사하는데, 총알의 생성자에 사운드를 처리해주면 순식간에 수십회의 사운드 호출이 이루어지고 일시적으로 상당한 부하가 걸립니다. 그때문에 이런 경우에는 Enemy 클래스에서 총알을 발사하기로 결정한 지점에서 사운드를 1회만 호출해주는게 좋습니다.

연발로 발사하는 경우, 사운드를 연달아서 호출해주는 수도 있지만 '연발 발사음'을 따로 만들고 이 발사음 1회만 호출하는 트릭도 있습니다.


배경 음악도 기본적으로는 효과음과 크게 다르진 않지만, 여기서는 게임의 전개와 음악을 연동하기위해-보스가 등장하면 보스 음악으로 전환- 시나리오 클래스에 음악을 넣기로 했습니다. 그럼 새로 추가하는 시나리오를 보겠습니다.


새로운 게임 전개 시나리오로 Scenario2를 준비해 뒀습니다.
Scenario2는 랜덤에 기대지 않고 순서와 위치를 지정해서 적이 나오게 할 것입니다.
초반엔 쉽게, 갈수록 어렵게 전개되는 패턴으로.

GameScene의 enter에서 사용하는 시나리오를 이것으로 대치해서, 시나리오의 개념에 대해서 알아볼 수 있습니다.
만약에 타이틀 화면과 게임 화면 사이에 미션 선택 화면을 두고,
어떤 미션을 선택했느냐에 따라서 GameScene에서 선택되는 시나리오를 다르게 할 수도 있습니다.
스테이지식 게임 전개를 만든다면 그런식으로 처리하게 되겠죠.


시나리오 전개는 주로 update에 집중되어 있습니다. 구현 자체는 cnt값을 보고 순서대로 나와야 할 적을 호출하는 패턴입니다.


update에서 눈여겨볼 것은 음악 처리 방식입니다.
음악을 시작하거나 일시정지/리쥼해야 하는 경우의 처리.
그리고 보스가 나타났을 때 보스 음악으로 전환하는 처리.

음악 전환은, 두 개의 음악을 미리 읽어둠으로서 전환할 때 렉이 없게 하는 것입니다. (사양이 안 좋은 컴퓨터라면 음악을 전환할 때 new Music으로 불러들이려고 하면 렉이 발생합니다) 보스까지 오면 일반 진행 음악은 나올 일이 없다는 판단도 있고요.


시나리오 2와 연결해서 추가로 등장하는 적 캐릭터는 네우코(위치 네우로이)와 보스입니다.

후반부에 단 하나 등장하는 네우코는 도움을 주는 존재인 동시에 미끼입니다.
네우코는 무조건 실드 아이템을 드롭하는데,
동시에, 다른 적들이 치열하게 공격하고 있기 때문에 실드 아이템을 먹으려다 오히려 죽을 수도 있는 상황을 유도합니다.
화면에 등장해서 지정된 위치까지 이동하고 나면 아무것도 하지 않고, 파괴되었을 때 실드 아이템을 드롭합니다.

※최초에는 파괴되는 것으로 하였는데, 네우코의 캐릭터를 생각하면 파괴되는 건 미묘한 느낌이라 실드 아이템을 드롭하고 돌아가는 것으로 수정하였습니다.


마지막에는 보스가 나옵니다.


보스의 패턴은,
- 화면 중단 오른쪽에서 등장 후,
- 플레이어를 쫓아 상하로 움직이며 수평탄을 연사하고,
- 2회 연사 후, 왼쪽으로 돌진.
- 돌진했다 물러가며 원형으로 탄막을 칩니다.

이것을 반복하다 격파되지 않고 1분이 지나면 퇴각합니다.

각 행동의 사이에 약간씩의 딜레이가 존재하는 것도 프로그램적으로는 별개의 패턴에 해당합니다. 정리하면 보스의 패턴은

등장 - 딜레이 - 상하 이동 - 연사 공격 - 딜레이 - 상하 이동 - 연사 공격 - 딜레이 - 돌격 - 후퇴 & 난사 - 딜레이 - 상하 이동 - ...(반복)

이렇게 됩니다.

패턴 구성과, 격파/도주 후 클리어 처리되는 것을 제외하면 기존 적 캐릭터와 구현 상 크게 다른 점은 없기 때문에 소스 해설은 생략하겠습니다.


보스를 격파하거나 보스가 퇴각하면 스테이지는 클리어.
현재는 클리어 후 타이틀 화면으로 되돌아가게 됩니다.

여기서 한 가지 문제가..
1플레이어가 게임오버 되어 화면에 게임오버 메시지가 떠 있고, 2플레이어 입력을 기다리는 동안의 경우입니다.
여기서 2플레이어를 난입하지 않고 가만히 있으면 보스까지 가고, 보스에서도 더 기다리면 자연히 클리어하게 됩니다.

앞에서 플레이어가 게임오버 될 때까지 무한루프로 돌아가는 게임이라면 생기지 않을 문제인데, 시나리오 2는 보스를 격파/보스가 도주하면 스테이지가 끝나기 때문에 불거진 문제이죠.

현시점에서는 이에 대한 확실한 대책은 세우지 않았습니다. 보통이라면 시나리오 전개를 멈추고-음악을 멈춘 것 처럼- 타이틀로 돌아가거나 2플레이어가 난입하기를 기다리게 되겠네요.



※이외에 몇몇가지 비효율적인 함수를 수정했습니다. (해설은 생략했는데, 일부는 step 14에서도 대응하고 있습니다)






마치며

Slick2D를 바탕으로, 게임을 Scene과 Object로 구성하는 방법으로 프로젝트를 진행해 봤습니다.
이번 프로젝트는 슈팅게임이었습니다만, 이 구조는 2D로 표현되는 게임이라면 거의 대부분 대응할 수 있습니다.

이렇게 하는 경우의 장점

- 단위 Scene이나 오브젝트의 추가, 제거가 용이해 게임의 규모가 커지더라도 감당할 수 있고,
- Scene의 구조는 대단히 간단해지며-GameScene에서 제일 지저분한 부분이 사실상 키/게임패드 입력 담당 부분..-
- 각 Scene이나 하위 오브젝트 클래스의 규칙을 공유하기만 하면, 복수의 개발자가 여러 Scene/오브젝트를 나누어 개발하기 좋고,
- 버그가 발생하더라도, 거의 확실히(완전히는 아니고) 버그가 발생한 오브젝트 전용 클래스 내부만의 문제이므로 수정하거나, 최악의 경우 그것만 제거하면 되므로 버그 대처도 쉬워집니다.


간단히 말하면 '대형 프로젝트에 대응하는 효과적인 방법이며, 버그 대책에도 강하다' 정도 되겠습니다.

반대로 규모가 작더라도 빠르고 깔끔하게 개발할 수 있다. 는 장점도 있겠네요.
이 게임의 경우, 리소스를 제외한, 사실상 백지 상태에서 꽉 채워서 8일 걸렸습니다.
그래픽 디자인 지원을 받고 넉넉하게 한 달 정도 추가작업하면 8스테이지 정도의, 메가드라이브용 하프프라이스 슈팅게임 퀄리티 정도는 나올만한 페이스..?

엔진과 언어는, 프로젝트를 배포하기 편하게 java를 사용하고, 그래픽과 사운드를 위해 Slick2D를 사용했습니다만,
Scene과 Object로 다루는 것 자체는 언어나 엔진과 상관없이 (언어가 클래스 개념을 지원하는 이상은) 어떤 환경에서도 응용 가능합니다.
(애시당초 이렇게 다루려는 개념 자체가 cocos2d-x(c++)나 유니티3D(c#)에서 참고해 온 것이라..)

이상을 이해하고 나면, 아마 유니티3D 같은, 얼핏 보기에는 전혀 다른 개념을 바탕으로 한 것 같은 개발툴에 대해서도 그 동작 원리를 어렴풋이나마 짐작할 수 있지 않을까 합니다.


얼마 전 포스팅에서도 언급한 것처럼, 다음엔 타워 디펜스 게임을 준비하고 있습니다.
슈팅게임을 벗어난 새로운 형식의 게임을 다뤄보는 것이 목적으로,
별도의 엔진을 사용하지 않고 java awt-swing으로 만들어집니다.

coco2d-x나 유니티도 다뤄보면 좋겠지만 그쪽은 남한테 설명할만한 실력이 아직 부족한 것 같습니다.



핑백

덧글

  • 2016/05/31 17:54 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 펭귄대왕 2016/06/01 11:27 #

    솔직히 데스크탑용 java 게임 엔진에 대해서는 그다지 아는게 없습니다. slick2d도 비교적 최근에 알게 된 것이고..

    그 외에 사용해 본 거라면 libgdx정도인데, 초기 적용하기가 힘들었고-공식 위키에 있는대로 따라하면 되긴 하는데, 이걸 다시 다른 사람에게 설명할 자신이 없습니다 ^^;-, 배포시 유료 규정이 있어서 강좌용으로 쓰기에는 좋지 않다고 생각했습니다.

    강좌의 모토는 엔진의 사용법 보다는 기본 API 중심으로 구현, 원리를 중심으로 설명해서 플랫폼이나 엔진, 언어에 대한 의존성을 줄이는 것입니다.
    자바 뿐 아니라 c++이나 c# 등으로도 응용할 수 있는 것을 목적으로..

    정리하자면, slick2d는 라이브러리를 포함하는게 쉬웠고,
    엔진이라고 해도 기본 API로 구현하는 것과 크게 다르지 않은 형태라 이런 목적에 알맞았고,
    기본 API보다 처리속도나 사운드 효과에 장점이 있어 사용해보았습니다.
  • 답글감사합니다 2016/06/04 16:08 # 삭제 답글

    답글 정말 감사합니다!

    주인장님 그런데 "slick2d는 라이브러리를 포함하는게 쉬웠고" 라는 게 무슨 말씀인지 자세히 설명 부탁드려도 될까요??

    자기만의 라이브러리를 엔진에 넣기 편하다는 뜻인가요?
  • 펭귄대왕 2016/06/04 17:13 #

    프로젝트에 'slick2d 라이브러리'를 추가하는게 쉽다는 의미였습니다.
  • 감사합니다. 2016/06/06 10:01 # 삭제 답글

    그렇군요. 친절한 답변 감사합니다!
  • gkci2201 2016/10/03 17:06 # 삭제 답글

    컴공과 학생이라서 많은걸 알아가요!!
    2d 슈팅게임 위치즈제작과정을 보고 직접 이클립스를 이용해서 실행해보기위해서 다운로드하고 java용 2d 게임엔진에 관련된 글을 참고해서 적용시켜서 실행해보았지만 main을 찾을수 없다고만 계속 뜨는데 어떻게 해야될지 알 수 있을까요??ㅠㅠ
  • 펭귄대왕 2016/10/03 21:09 #

    main을 찾을 수 없다고 나오면 Run -> Run Configurations로 들어갑니다.

    Main 탭을 선택해서 프로젝트명에 현재 실행하려는 프로젝트 이름을 Browse버튼을 눌러 찾아 지정해주고,
    Main class 옆의 Search 버튼을 누르면 main 함수를 포함한 클래스를 찾아줍니다. 복수의 main이 있으면 여러개가 뜨지만 보통 하나만 나옵니다.
    (만일 여기서 클래스 목록이 뜨지 않으면 뭔가 다른 오류가 있는 것입니다)

    여기서 main이 포함된 함수를 지정해준 후 Apply -> Run 해 주면 됩니다.
  • gkci2201 2016/10/05 13:57 # 삭제

    여러개가 뜨는거 보니까 다른 오류가 있는거 같은데 모든 클래스자체에 오류는 없는데 찾을 수 있는 방법이 업을까요??ㅜㅜ
  • 펭귄대왕 2016/10/06 00:37 #

    지금 작업하시는게 YSslick2d_160123.zip 이것 전체를 불러들이셨다면,
    기본적으로는 src/Main 폴더에 있는 ProjectMain.java를 지정하면 됩니다.

    각 단계별 소스를 보실 때는 최초의 src 폴더를 src_step15로 리네임해주고, 확인하려는 단계의 소스 폴더를 src로 리네임해서 사용하면 됩니다.

    이렇게 해도 안된다면 이클립스의 Package Explorer 부분과 Run Configurations의 Main탭 부분을 캡처해서 valpa@naver.com 으로 보내주시면 검토해보도록 하겠습니다.
댓글 입력 영역


Books

Geek라이프

게임 매니악스 슈팅 게임 알고리즘
마츠우라 켄이치로,츠카사 유키 공저/손정도 역/박민근,Pope Kim 감수

미소녀 일러스트 테크닉
B-은하, pen스케, 카와이 저/정유진 역

핵심강좌! Cocos2d-x
이재환 저

피규어의 교과서 레진 키트 & 도색 입문 편
후지타 시게토시 저/김정규 역
예스24 | 애드온2