adsense



[java] Slick2D로 게임 만들기 -시작-

그럼 이번 포스팅부터, Slick2D를 사용해 실제 게임을 만드는 과정을 진행해 보겠습니다.

여기서 소개하는 내용은 https://github.com/ChangseOh/LetsStudySlick2D 이곳에서 프로젝트를 다운받으실 수 있습니다.

우선 앞선 포스팅을 참조해, 이클립스에서 신규 자바 프로젝트를 생성하고 유저 라이브러리로 Slick2D를 추가해줍니다.

프로젝트를 생성했으면 src 아래 패키지를 새로 만들어줍니다.
차례대로
Main
forSlick2D
Scenes
prefab
을 생성했는데,
왜 이렇게 하느냐.. 정해진 것은 아니고, 앞으로의 작업의 편의를 위해 제가 임의로 만든 것입니다.

앞으로 여기 생성될 클래스의 종류는
forSlick2D : Slick2D 엔진 사용을 보조할 자작 함수/클래스를 담을 예정입니다.
Main : 최초 실행될 때 호출될 main 함수를 가진 클래스가 위치합니다.
prefab : 게임에서 사용될 오브젝트들을 클래스로 만들어 위치시킬 것입니다. 요시카 스크램블로 따지면 Enemy나 Bullet, Item 같은 클래스입니다.
Scenes : 타이틀, 메뉴, 메인게임, 게임결과 같이 화면 단위를 클래스로 만들어 여기에 둡니다. 화면 단위라는 것은 위치즈 플라이트의 scene과 비슷합니다.

※prefab이라고 하면 뭔가 익숙한 분도 있을텐데, unity3D에서 말하는 그 프리팹 맞습니다. 물론 유니티3D와 같은 것은 아니고 비슷한 개념인데, 굳이 말하자면 유니티의 프리팹이 이런 oop언어의 객체 개념을 구상화한 것이랄까요..

프리팹 식으로 만드는 이유에 관해서는 차차로..



앞에서의 샘플 프로젝트는 단일화면만 사용했습니다.
이번부터의 프로젝트는 여러개의 화면을 이동해 가면서 진행됩니다.

그러기 위해서 main함수를 포함하는 메인 클래스는, BasicGame이 아닌 StateBasedGame을 상속해서 구성됩니다.


StateBasedGame
public static void main(String[] args)을 갖고 있는 클래스입니다.
main함수 내에서 게임이 실행될 윈도우에 관련된 설정을 하며
반드시 오버라이드해야 하는 initStatesList에서, 사용할 state(각 화면의 단위)를 지정합니다.

그럼 일단 StateBasedGame를 상속한 메인 함수를 만들어봅니다.
프로젝트의 src->Main->new->Class



① 메인 클래스 이름을 적습니다. 적당히 좋은 것으로.
② 상속할 super 클래스를 지정합니다. Browse 버튼을 눌러 StateBasedGame을 입력/선택합니다. (나중에 extends로 추가해도 됩니다)
③ main 함수, 생성자, 추상함수 옵션을 모두 켭니다.

이렇게 하고 Finish 하면 다음과 같이 생성이 완료됩니다.




main 함수 내에는 게임 윈도우 설정에 관한 항목을 추가합니다.
해상도와 게임 제목 정도를 제외하면 이 부분의 내용은 항상 동일합니다.




기본적으로 오버라이드된 initStatesList 함수 안에서 이제 사용할 화면(state) 클래스들을 등록해줘야 합니다. (하나만 등록할 수도 있습니다)
addState로 등록하는데, 등록되는 클래스는 BasicGameState를 상속합니다.

그러니 우선 BasicGameState를 상속한 클래스를 Scenes 패키지에 추가해봅니다. 아직 내용은 써넣지 않아도 되니까.
프로젝트의 src->Scenes->new->Class
이름은 TitleScene으로 정했습니다.
superclass를 BasicGameState로 지정하고, main 생성 옵션은 끕니다.



아직 새로 생성한 State의 내용은 신경쓰지 말고, 메인 함수의 initStatesList 안에서 addState로 추가합니다.



구글에서 Slick2D 관련 강좌를 찾아보신 분은 여기서 뭔가 이상한 점을 느꼈을텐데, 대개 예제로 나오는 스테이트 추가에서는 스테이트 생성자에 스테이트 ID를 지정하도록 되어 있습니다.
예를 들면

addState(new TitleScene(0));

이런 식으로요. (0이 스테이트ID)


그런데 사실은 스테이트ID를 기본 지정하는 과정이 현재 배포중인 Slick2D에는 없습니다. (최소한 제가 Slick2D 홈에서 다운 받은 것은 그러한데, 이게 제대로 구현된 버전이 있을지는 모르겠습니다..)

화면 전환에는 스테이트ID를 사용하므로 이게 꼭 필요한 내용인 것은 맞습니다.
그럼 스테이트ID는 어떻게 부여하느냐..

BasicGameState

아까 생성한 TitleScene.java를 열어봅니다. 생성자와 필수 오버라이드함수를 함께 생성하도록 했으니 아래 내용으로 되어 있을겁니다.


여기서 맨 아래 getID라는 함수가 있고, return 0; 을 하고 있는데, 이 0값이 스테이트ID입니다.
다른 스테이트를 추가했다면 이곳의 리턴값을 일일이 바꿔줘야 하는 것입니다.

이쯤되면 'ID를 인수로 받는 생성자를 만들고, 해당 아이디를 getID에서 리턴해주면 되지 않는가?'가 당연히 떠오릅니다.
그렇게 해서 수정해 본 것이 아래 내용이고 (붉은 사각형 안이 추가 또는 수정한 것)



하는 김에 스테이트를 하나 추가하고, (GameScene이란 이름으로 TitleScene과 같은 방법으로 생성하고, 내용을 수정)
메인클래스에서도 보기 좋게 상수값을 사용해서 아래와 같이 수정합니다.




그럼 이번 TitleScene과 GameScene을 전환해보겠습니다.
아래 그림과 같이 TitleScene에 추가 코딩을 해 줍니다.



스테이트를 전환하는 것은 keyReleased 함수의 game.enterState(ProjectMain.STATE_GAME); 부분입니다.

GameScene 쪽도 TitleScene을 참조해서 비슷하게 코딩해 줍니다.
그쪽에서는 반대로
game.enterState(ProjectMain.STATE_TITLE);
로 해줍니다.
구분하기 좋게 문자 색을 하얀색 이외의 다른걸로 해도 좋겠네요.

실행하기 전에
프로젝트 -> Run As -> Run Configurations에서 실행 정보를 만들어줍니다.
Java Application에서 오른클릭->New 하고 프로젝트와 메인클래스를 입력, 그리고 Arguments 부분에서도 앞선 포스팅을 참조해 Slick2D 엔진이 있는 폴더를 지정합니다.




그렇게하고 실행하면 아래와 같은 결과를 볼 수 있습니다.




스테이트를 사용할 때 몇 가지 미리 알아둘 사항.

1. init는 스테이트 클래스를 처음 new 할 때, 그러니까 보통은 addState 하는 시점에서 실행됩니다.
2. 가장 처음에 addState한 스테이트 클래스가 최초로 실행되는 스테이트입니다.
3. 필수가 아닌 선택 가능한 오버라이드 함수중에 enter와 leave가 있습니다. 이름 그대로 enter는 이 스테이트에 들어올 때, leave는 다른 스테이트로 전환하기 직전에 각각 호출됩니다.
4. 이미지 리소스를 init에서 불러둬도 되지만 가급적 enter와 leave에서 부르고 해제하는 것이 좋겠습니다.


대충 Slick2D로 게임을 만들기 위한 기본 사항이 모두 끝났습니다.
앞으로 이 내용을 바탕으로 게임을 만들어볼려는데.. 어떤 게임이 좋을까요. 구경오시는 분도 슬슬 슈팅게임은 좀 질리지 않으셨을지..

뭘 만들지는 생각 좀 해보겠습니다.. 리소스 많이 안쓰는 게임이니까 러닝류 게임으로 할까 아니면 이전의 레가시 애니메이션을 응용해볼지.. 반영된다는 보장은 어렵지만 이런 게임 해보면 좋겠다는 말씀도 환영합니다. ^^



덧글

  • 밤콩 2015/12/12 17:53 # 삭제 답글

    안녕하세요 펭귄대왕님 덕분에 프로젝트 잘마무리하였고 덕분에 많은걸배웠습니다 인사말 남기러왔습니다.
    정말 감사합니다
  • 펭귄대왕 2015/12/12 18:25 #

    별로 도움드린 것도 없는 것 같습니다만, 잘 마무리하셨다니 다행입니다.
    감사합니다.
  • ㅇㅇ 2015/12/17 23:46 # 삭제 답글

    자바 게임엔진 완전끌리는데...
    어떤가요?쓸만한가요? 물론 공부나 연습목적이요
  • 펭귄대왕 2015/12/18 05:47 #

    기능은 많이 부족해서 속도의 잇점 정도를 제외하면 awt나 swing으로 짜는 것과 비슷합니다.
    그런 점에서는 공부용도에는 괜찮을듯 하네요.
  • ㅇㅇ 2015/12/17 23:46 # 삭제 답글

    자바 게임엔진 완전끌리는데...
    어떤가요?쓸만한가요? 물론 공부나 연습목적이요
  • 자바초보 2017/03/04 04:22 # 삭제 답글

    안녕하세요. 글 잘보고 갑니다. 여쭤보고싶은게 있는데 중간에 KeyReleased 메소드는 어떻게 생겨난건가요?? KeyListener를 구현한건가요??? 초보라서 잘 모르겠습니다..
  • 펭귄대왕 2017/03/04 18:07 #

    저도 지금 가물가물해서 일단 생각나는대로 적고 내일중에 정확히 확인해서 틀린게 있으면 정정해두겠습니다.

    일단 KeyReleased는 BasicGame에 구현되어 있는 오버라이드 함수인데,

    StateBasedGame이 BasicGame을 상속하기 때문에
    StateBasedGame을 상속한 클래스에서도 KeyReleased를 오버라이드해서 쓸 수 있습니다.
  • 자바초보 2017/03/04 04:30 # 삭제 답글

    그리고 init에서 퍼리미터로 GameContainer와 StatebasedGame을 받아서 변수 gc 와 game에 넣어주는데 이것들은 ProjectMain 클래스에서 TitleScene 인스턴스를 생성할 때 TitleScene(int id, StateBasedGame game, GameContainer gc)라는 생성자를 만들어두고 new TitleScene(0, this, appgc) 이런식으로 퍼리미터를 넣어줘야하는거아닌가요?

    game.enterState() 메소드로 씬이 변경되는건 알겠는데, 제(초보자)가 볼땐 game에 아직 인스턴스가 할당되지 않은거처럼보여서 너무 혼란스럽네요...
  • 펭귄대왕 2017/03/05 10:37 #

    BasicGameState를 상속한 클래스(예:TitleScene)에서, init는 생성할 때 바로 불리지는 않고
    StateBasedGame을 상속한 클래스(=ProjectMain 클래스)에서 initStatesList이 끝나고 나면
    add된 스테이트들의 init를 한꺼번에(보통 add한 차례대로) 부릅니다.

    addState를 갖고 있는 initStatesList는 AppGameContainer 인스턴스를 start한 직후에 불리게 됩니다.

    이때문에 addState를 실행하는 단계까지 오면 이미 GameContainer와 StateBasedGame 인스탄스는 메모리에 존재하고 있는 것이죠.

    ※확인해서 수정했습니다. 이런 순서는 라이브러리 내부에서 정해져 있는데, 소스까지 열어보지 않더라도 브레이크 포인트를 지정하고 디버그 모드로 순서대로 따라가보면서 확인할 수도 있습니다.
  • 자바초보 2017/03/05 05:30 # 삭제 답글

    감사합니다. 비전공자라서 자바를 책과 함께 독학하는데 책에있는 기본적인 내용들은 숙달이 되어가는데 그것 이상으로 가르쳐주는 곳이 별로 없더라고요. 이 블로그를 통해서 slick2d라는 엔진이 있는걸 알게되었고 자바를 공부하는데 또다른 목표(기존에는 책 한권 숙지하기)가 생겼습니다. 앞으로도 유용한 글 많이 부탁드리겠습니다~~
  • 펭귄대왕 2017/03/05 10:38 #

    어제 적었던 답글을 일부 수정했습니다.

    잘 봐주셔서 감사드리고, 요즘은 일때문에 업데이트가 뜸합니다만, 공부하시는데 작은 도움이 되었으면 좋겠습니다.
  • 자바2 2020/06/17 00:21 # 삭제 답글

    ailed to initialize device Synaptics HID-Compliant Touch pad Device because of: java.io.IOException: Failed to acquire device (8007001e)
    라고 콘솔에 뜨고 1을 눌러도 노란색으로 안바뀌네요.. 무슨 에러일까요?
  • 펭귄대왕 2020/06/17 04:35 #

    어느 단계에서 문제가 생기시는건가요?
    본문은 라이브러리와 무관하게 자바 클래스를 생성하는 자바 공통적인 내용이고, 적어주신 에러 메시지는 아마 노트북용 터치패드 드라이버 에러 같은데 본편과 연관이 있을지는 모르겠습니다.
댓글 입력 영역


Books

Geek라이프

메가 드라이브 퍼펙트 카탈로그
마에다 히로유키 저/조기현 역

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

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

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