adsense



[JAVA] 2D 슈팅게임 개발강좌 - 위치즈 플라이트 1부

(※ 본 포스트에서 제공하는 압축파일은 게임 프로그래밍 기초를 돕기 위한 예제 프로젝트입니다. 별도의 게임 파일은 배포하지 않습니다)



이번에 새로 시작하는 프로젝트는

1. 다양한 화면을 쉽게 관리하기 위한 메인 프레임 워크 개선
2. 상자형 충돌 체크

두 가지를 메인으로, 스크린 샷에서 보시는 그대로, 드○○플○○트 카피캣 게임을 하나 만들어 보겠습니다.

아직 소스와 강좌를 다듬고 있습니다만, 실행 가능한 풀버전 프로젝트를 미리 공개합니다. (아직은 소스가 좀 지저분합니다..)

요시카 스크램블 소스를 분석해 보셨다면 이번에도 역시 주석을 참조하면 소스의 내용을 이해하실 수 있으리라 생각됩니다.

편의기능이나 샵/골드 이외의 추가 아이템 등은 구현되어있지 않고 타이틀-게임-결과화면을 구현하고, 각 화면을 전환하는 것을 메인으로 하고 있습니다.


※ JAVA SE 1.7 로 개발되어 있습니다.

게임 메인 프레임 이클립스용 프로젝트 소스 다운받기 GameMainFrame.zip

위치즈 플라이트 이클립스용 프로젝트 소스 다운받기 WFlight20131203.zip(2013년 12월 03일 수정)


-------------------------------------------------------------------------------------------
1부. 메인 프레임 워크 소개


게임용 프레임워크의 가장 기본적인 구조는 이전 요시카 스크램블에서도 보았듯이

1. 플랫폼에서 어플리케이션 구동의 가장 기본 바탕(윈도우라면 창) 생성
2. 캔버스를 상속한 클래스 생성 (게임캔버스)
3. 게임캔버스에서 스레드 순환
4. 스레드 내에서 화면 묘화, 마우스(터치)/키 입력 처리, 기타 연산 처리를 수행

이 내용을 갖고 있으면 일단 기본적인 리얼타임 게임을 구현할 수 있습니다.

하지만, 게임이 좀 더 심화/복잡하게 되면

- 리소스(주로 이미지)의 불러오기/해제
- 화면 전환과 화면 단위 관리

의 문제가 생기게 됩니다.

여기서 화면이라 함은, 기존 프로젝트를 예로 들자면 타이틀 화면, 게임 화면과 같이 크게 나누어져 입출력이 독립적으로 처리되는 각각의 단위입니다.

요시카 스크램블에서는 상태변수를 주고 이 상태변수값에 따라 타이틀이라던가 게임화면에 관련된 처리로 분기했는데, 화면의 종류가 보다 다양해지면-상용 게임의 예를 든다면 도움말, 아이템샵, 결과화면, 랭킹화면 등등- 이 방식으로는 화면 관리가 어려워지는 것이죠.

화면마다 별개의 클래스로 만들어 관리하게 되면, 리소스 관리와 화면, 입력, 처리를 해당 클래스 내에서만 다루면 되므로 화면 단위 관리가 쉬워지고, 화면의 추가, 삭제가 쉬워집니다.


그러기위한 것이 이 GameMainFrame 입니다.

메인프레임을 구성하는 핵심적인 부분은 GameManager와 GameCanvas 클래스입니다. 그럼 순서대로 해설해 보겠습니다.

GameManager.java
: 윈도우를 열기 위한 프레임과, 키 입력 처리를 위한 키리스너를 받습니다.

소스를 위에서부터 훑어보겠습니다.

35~55 라인 : 생성자에서 기본 윈도우를 설정합니다. 이전과는 조금 다르게, 항상 화면 중앙에 윈도우가 나타나도록 했습니다.

57 라인, 61~68 라인 : firstScene()에서 최초 화면을 불러들입니다. 나중에 이 함수의 sampleCanvas는 적절하게 자신이 작성한 최초의 화면으로 교체하면 됩니다. 예를 들면 회사 로고라던가, 게임 타이틀이라던가가 있겠죠.

70~76라인 : sceneChange(....)은 현재 화면을 다른 화면으로 교체합니다.

79~136 라인 : 앞으로 자주 쓰게 될 공용 함수들입니다.

RAND : 난수를 생성합니다.
makeImage : 이미지파일을 불러들여 Image 객체로 만듭니다.
drawImageRect : Image 객체의 일부분만 선택해 화면에 그립니다.

138~200 라인 : 키/마우스 이벤트 관련 오버라이드 함수입니다.
여기에 처리를 구현해도 되고, 각 화면에서 추가로 오버라이드하여 이벤트를 전달받아 처리해도 됩니다.


일단 샘플 소스에서는, firstScene에서 SampleCanvas란 화면을 생성하여 첫 화면으로 쓰고 있습니다.

SampleCanvas는 GameCanvas를 상속한 클래스로 이루어집니다. 이번 편의 가장 핵심적인 부분입니다.


GameCanvas.java

사용자는 GameCanvas를 직접 수정하지 않고, 이것을 상속한 별도의 클래스를 만들어 사용하게 됩니다.
GameCanvas는 화면을 그리기 위한 Canvas를 상속하고, 스레드 처리를 위해 Runnable 인터페이스를 포함합니다.

GameCanvas 클래스는 추상클래스지만 스레드 구현을 위한 run() 함수, 화면 갱신을 위한 paint(Graphics g) 함수는 함수 본체를 갖고 있습니다.

run 함수에서는 update()라는 추상 함수를, paint 함수에서는 dblpaint(Graphics gContext)라는 추상 함수를 각각 호출합니다.
추상 함수이기 때문에 반드시 오버라이딩해야 합니다.

update에서는 입력 처리와 각종 연산을, dblpaint에서는 화면 갱신을 구현해주면 됩니다.

이외에 키 입력 이벤트와 마우스 조작 이벤트를 받아들이기 위한 함수가 있는데, 오버라이딩해서 쓸지는 자유입니다.

참고로, Destroy는 이 씬을 중지할 때 불러주기 위한 함수인데, 추가적인 처리가 필요하므로 자동으로 부르지는 않고 수동으로 불러줘야 합니다. 필요한 처리는 아래의 SamleCanvas 클래스 소개에서 알아보겠습니다.



SampleCanvas.java

GameCanvas를 상속해 실제 화면을 구현하는 클래스입니다. 이것이 한 단위의 '화면(Scene)'에 해당합니다,
initImage에 이 화면에서 사용할 리소스들을 로드하고, 추상함수인 update와 dblpaint를 필요한 내용으로 구현해주면 됩니다.

다른 화면으로 전환할 때는

1. Destroy 함수를 호출합니다.
2. manager.sceneChange((GameCanvas)new 전환할화면(manager));
위 코드를 실행합니다.
이 순서로 다른 화면으로 전환할 수 있습니다. 예제 소스의 keyReleased를 참조합니다.

이를 위해서 사전에 Destroy() 함수를 작성해 둬야 합니다만, 예제 소스에 작성된 세 줄을 그대로 유지해도 됩니다.
수정해서 사용할 경우
super.Destroy();
manager.remove(this);
이 두 줄은 반드시 첫머리에 들어가야 합니다.

releaseImage() 함수에서는 이 화면에서 사용한 이미지들을 해제하도록 합니다. 예제를 참조해 주세요.


그럼 이클립스에서 샘플 프로젝트를 실행해 봅니다.
아무 키나 누르면 순서대로 화면이 번갈아 보여지게 됩니다.


설명이 좀 길어졌습니다만, 소스와 함께 보신다면 어려운 내용은 아닐 것이라 생각됩니다.

그럼 다음에는 각 화면 별로 서로 다른 이미지와 처리를 통해 게임의 기본 골격을 짜도록 하겠습니다.



덧글

  • 감사 2013/11/23 16:52 # 삭제 답글

    2학년인데.... 많이 배우고 갑니다 ^^
    아직 초보라 프로그램 구조를 이런식으로 만들기는 힘드네요 ㅜㅠ

    키입력이나 쓰래드 충돌체크 부분 도움이 많이 됬어요. 감사합니다.
  • 펭귄대왕 2013/11/24 16:10 #

    봐주셔서 감사합니다. ^_^
  • 질문입니다. 2014/02/02 11:14 # 삭제 답글

    게임 상에서 사용할 이미지가 모두 원형이라 원을 그리는 것으로 바꾸고 싶습니다.

    충돌할 때에도 원의 중심으로 부터의 거리를 기준으로 충돌 여부를 판단하기 위해

    그림의 x, y 는 원의 중심 좌표를 가리키고, r이라는 변수를 사용해 반지름을 넣어주려구요.

    아래 코드를 변형해야 하는 것 같은데 아래 코드가 잘 이해가 가지 않아서요.

    1.anc가 뜻하는 것은 무엇인가요?
    2.gc.drawimage()안에서 x-sx 이런식으로 해주시는데, 제가 원하는대로 원을 그리고자 한다면 x, y 그냥 이렇게 하면 되는건가요?
    (원래 중심좌표를 넣는 것인지 궁금합니다)
    3.gc.clip은 무슨 일을 하는 것인가요?

    public void drawImageRect(Graphics gc, Image img, int x, int y, int sx,
    int sy, int wd, int ht, int anc) {// sx,sy부터 wd,ht만큼 클리핑해서 그린다.
    if (x < 0) {
    wd += x;
    sx -= x;
    x = 0;
    }
    if (y < 0) {
    ht += y;
    sy -= y;
    y = 0;
    }
    if (wd < 0 || ht < 0)
    return;
    x = x - (anc % 3) * (wd / 2);
    y = y - (anc / 3) * (ht / 2);
    gc.setClip(x, y, wd, ht);
    gc.drawImage(img, x - sx, y - sy, this);
    gc.setClip(0, 0, SCREEN_WIDTH + 10, SCREEN_HEIGHT + 30);
    }
  • 펭귄대왕 2014/02/02 13:28 #

    원의 공식을 이용하는 경우는
    http://icegeo.egloos.com/275023
    이쪽 소스를 참고하시면 됩니다.

    위 게임프로젝트에서는 각 오브젝트를 원형으로 파악해 원과 원 중심점 사이의 거리를 구해 충돌 여부를 체크하거나, 특정 원에서 또 다른 원을 겨냥할 때 각도를 산출하는 공식, 360도 자유로운 방향으로 총알을 발사하는 방법 등이 쓰여지고 있습니다.

    질문에 적어주신 소스는 이미지의 일부분을 rectangle-사각형으로 잘라 부분만 보여주는 것입니다. 클리핑이라고도 합니다.
    anc는 좌표가 왼쪽/가운데/오른쪽, 위/중간/바닥을 기준으로 표시하는가 여부입니다.
    sx, sy는 큰 이미지 안에서 보여주고자 하는 사각형의 왼쪽 위 꼭지점,
    그리고 wd, ht로 보여주고자 하는 사각형의 너비와 높이를 지정해서

    소스가 되는 큰 이미지(img)의 sx, sy위치에서부터 wd*ht 픽셀만큼만 화면에 그려주도록 하는 것입니다.
  • 감사합니다. 2014/02/03 14:29 # 삭제 답글

    감사합니다. 많은 도움 되었습니다.
  • class 2014/02/03 14:35 # 삭제 답글

    class 파일로 되어 있는데 java 파일도 올려 주실 수 있을까요?
  • 펭귄대왕 2014/02/03 15:25 #

    W_Shooting.java 라는 파일이 압축에 포함되어 있습니다.

    이클립스에서 연 경우는 Package Explorer에서 (default package) 아래에 위치하고 있습니다.
  • sexyback 2014/07/01 15:40 # 삭제 답글

    감사합니다 .
    이런 자료 찾고있었는대 정말 많은 도움이 되었습니다 !
  • 펭귄대왕 2014/07/02 08:21 #

    도움이 되었다니 기쁩니다. 보시다가 혹시 도움이 필요한 부분이 있으면 언제든 말씀해 주세요.
  • 송파로봇 2014/10/03 09:24 # 삭제 답글

    아직 자바에 익숙하지 않아 아무키나 누르면 화면전환 되는 부분이 이해가 잘 안됩니다.

    화면전환의 시발점은 키가 눌린 후니까 다음 코드가 실행된 후 부터 일 것 같습니다
    @Override
    public void keyReleased(KeyEvent e) {
    // TODO Auto-generated method stub

    nowCanvas.keyReleased(e);
    }

    그런데. 위 코드가 실행되면 다음 코드가 어디부터 시작하게 되는지 그리고 그 이유가 뭔지 잘 모르겠습니다. 도움주시면 감사하겠습니다. ^^
  • 송파로봇 2014/10/03 09:52 # 삭제

    조금 더 살펴보니 아래 코드에서 화면 전환시키는 것을 발견했습니다.
    @Override
    public void keyReleased(KeyEvent e) {
    // TODO Auto-generated method stub

    Destroy();

    //다른 씬으로 전환한다. manager.sceneChange((GameCanvas)new 전환할화면(manager));
    manager.sceneChange((GameCanvas)new SampleCanvas2(manager));
    }

    그리고 위의 설명글에서 "2. manager.sceneChange((GameCanvas)new 전환할화면(manager));"이라고 설명을 해 주셨는데 manager.sceneChange의 파라메터부분을 어떻게 해독할 지 이해가 안되네요.

    최근에 독학으로 자바책 두 권을 몇 번 읽고 관련강의도 4개정도 들어 봤는데 모두 기본적인 문법사항들과 기본예제들 뿐이라 위의 2번 내용과 같이 ((GameCanvas)new 전환할화면(manager)) 형식으로 사용하는 것이 이해가 안됩니다.

    1. 구체적으로 클래서명을 괄호로 묻은 것이 캐스팅을 하는 것 같은데 데이터형들의 형변환시에 하는 것은 이해가 되는 데 클래스명에 형변환을 시키는 것이 무슨 뜻인지요?

    2. 그리고, 객체를 만들때는"클래스명 객체명 = new 클래스생성자명()"의 방식으로 하는 것으로 알게됬는데, 님의 소스중에
    //게임 공용 기본함수/변수
    public GameCanvas nowCanvas;//현재 화면에 보여지고 있는 캔버스
    와 같이 nowCanvas 변수를 선언한 후 nowCanvas = new GameCanvas()의 형태로 객체화 시키지 않고 nowCanvas를 manager.nowCanvas =(GameCanvas)this;
    와 같이 사용하시던데, 이것은 무슨 의미인지요? 제가 분석하기로는 참조형 변수로 주소값을 가지고 있는 것 같던데, new를 이용하여 객체로 만들어도 주소값을 가지게 할 수 있는데 그렇게 사용하지 않는지 궁금합니다.

    지식이 부족해 기초적인 부분에서 헤매고 있습니다. 도움주시면 감사하겠습니다.^^
  • 펭귄대왕 2014/10/03 14:12 #

    1. 클래스 객체도 형변환이 가능합니다.

    예를 들어 아래와 같은 코드를 보면..
    manager.sceneChange((GameCanvas)new GameScene(manager));
    new GameScene이 리턴하는 객체는 아시다시피 GameScene class의 객체가 됩니다.

    sceneChange는 GameCanvas객체를 인수로 받으므로 GameScene객체를 인수로 주기 위해 (GameCanvas)를 붙여 GameCanvas 객체로 캐스팅하게 됩니다.

    자바에서는 상속관계에 있는 클래스 객체끼리 형 변환 시, 상위(여기서는 GameCanvas)객체에 하위객체(여기서는 GameScene)를 대입하면 내부적으로 형변환이 자동으로 발생하기 때문에 (GameCanvas)new GameScene(manager)에서 (GameCanvas)캐스팅은 사실 해 주지 않아도 됩니다만, 의식적으로 캐스팅하는 습관을 들여두는 쪽이 좋다고 개인적으로는 생각합니다.

    2. manager.nowCanvas = (GameCanvas)this;
    nowCanvas의 목적은, 현재 프레임에 바운딩된 GameCanvas 객체와 통신하기 위한 것입니다.

    this는 자기 자신, 즉 이미 생성된 TitleScene 객체입니다. 이 객체의 생성은 GameManager의 firstScene 함수에서 new를 통해 이미 해 놓았고, 현재 이 TitleScene 객체가 바운딩되어있는 상태입니다.

    그런데,
    manager.nowCanvas = new TitleScene();
    과 같이 해 주면 nowCanvas에 대입되는 것은 완전히 새로 생성되는 별개의 객체가 됩니다.

    만일 새 객체를 생성해서 nowCanvas에 넣어주면, GameManager가 통신하는 대상은 '현재 바운딩 된 TitleScene 객체'가 아니라, 새로 생성된 TitleScene 객체가 되기 때문에 nowCanvas를 통해 TitleScene 객체에서 발생하는 변화는 현재 바운딩 된 객체-프레임에 붙어서 화면에 보여지고 있는 객체-에는 반영되지 않습니다.

    this를 타 클래스에 인자로 넘기는 방식은 클래스 객체 간 통신(값을 주고받거나 함수를 호출하거나)에 자주 쓰이는 형태입니다.
  • 송파로봇 2014/10/03 15:24 # 삭제

    답변 감사합니다.

    이해가 안되는 부분 때문에 속이 답답하였는데, 빨리 답글 달아주셔서 감사합니다. 내용을 읽어보니 아직 알송당송하네요. 찬찬히 읽어보고 좀더 클래스 케스팅에 대해 알아보고 연구해 보겠습니다.

    팽귄대왕님의 소스를 보며 게임제작의 전체적인 윤곽을 이해하고 리소스와 클래스별 팩키지로 분류하는 폴더 운영방법에 대해 알게되어 전체적인 윤곽을 이해 할 수 있게 됬습니다. 좋은 내용 감사합니다.
  • lafra 2014/10/14 18:47 # 삭제 답글

    코드들이 어떤 기능, 상호작용, 흐름을 갖고 실행되는지 제 머릿속에서 시뮬레이션이 쉽지 않네요.
    공부가 부족한가 봅니다.
  • 펭귄대왕 2014/10/15 02:20 #

    그럴땐 직접 프로젝트를 생성해서 샘플코드를 한 줄 씩 베껴서 직접 적어 넣어보거나, 샘플코드를 수행되는 순서대로 -main이 있는 클래스가 제일 먼저 실행되니 거기서부터 추적해 갑니다- 단계별로 남겨놓고 뒤의 것은 주석처리 해 가면서 이 단계까지 하면 뭐가 되는구나 그리고 단계별로 주석을 풀어가면서 어떻게 실행이 바뀌어가는가 짚어가면 이해하시는데 도움이 되지 않을까 합니다.
    브레이크 라인을 설정하고 한 줄씩 수행 순서를 따라가보는 것도 좋습니다.
  • lafra 2014/10/16 22:03 # 삭제

    조금씩 배우는 기분이지만 아무래도 긴 고통의 시간이 필요한거 같습니다.
    코칭 감사합니다~
  • 님프 2014/10/29 00:45 # 삭제 답글

    대왕님 질문입니다.
    1. drawImageRect 함수에서 에서
    if (x < 0) {
    wd += x;
    sx -= x;
    x = 0;
    }
    if (y < 0) {
    ht += y;
    sy -= y;
    y = 0;
    }

    이 부분이 이해가 안갑니다.

    2. 오버라이딩 하는 함수들 중에
    Scene에서는 super를 써주셨는데 키버튼이나 마우스 버튼에서는 super를 지우셨는데
    super의 의미와 사용법이 햇갈립니다.. super 지워도 잘돌아 가더라구요 ..

    3. makeImage(String furl) 함수
    내용에 보면 Toolkit 이랑 Mediatracker 가 나오는데
    이 함수 내용에 대해서 주석이라던지 설명 부탁드립니다.. waitforID 라던지.. 무슨 의미인지 잘 모르겠습니다.


    부탁드려요 대왕님..>_<!!
  • 펭귄대왕 2014/10/29 03:07 #

    1. 화면 밖으로 나간 부분을 그려줄 필요가 없으므로 그 부분만큼 그릴 범위와 그릴 위치를 조정하는 것입니다.
    노트에 사각형과 화면 경계를 그려보면 쉽게 이해할 수 있습니다.

    2. super는 오버라이딩하는 함수의 super 클래스-그러니까 이 경우에는 GameCanvas 클래스가 되겠지요-의 함수를 호출하는 것입니다.
    이클립스에서 Source->Override implement method를 선택해서 오버라이딩 함수를 불러오면 super는 대개 자동으로 붙습니다.

    물론 오버라이딩 함수의 안쪽이 비어있는 경우도 있고, 혹은 쓰여져있는 경우도 있습니다. 비어있거나 특별한 동작을 하지 않는다면 super는 의미가 없지요.
    또 동작이 완전히 대체되어 super를 호출할 필요가 없거나, 호출하면 안되는 경우도 있습니다. (예:update(Graphic g))

    그런데, 종종 super를 통해 상위함수를 반드시 호출해야 하는 경우도 있습니다.

    어떤 경우에 호출해야 하고 호출하지 않아도 되는가 혹은 호출하면 안되는가 그건 해당 클래스/함수의 구성에 따라 그때그때 다르기 때문에 예제 등을 통해 정해진 방법대로 쓰면서, super 클래스의 해당 함수를 확인/분석하여 판단하면 됩니다.
  • 펭귄대왕 2014/10/29 07:28 #

    3. 자바에서 A라는 클래스를 사용하면, 어떤 플랫폼 위에서도 동일한 동작을 해야하는 것이 자바의 조건..이랄까요. (실제론 제약이 있지만)
    그런데 플랫폼-OS나 하드웨어-이 다르면 눈에 보이는 결과는 같더라도 실제 동작은 각 플랫폼에 맞춰진 별도의 구현을 따르게 됩니다.
    즉 겉으로 보이는 클래스는 A이지만, 실제로 동작하는 건 windows용 A, 리눅스용 A, osx용 A.. 예를 들자면 그런 식으로요.
    우리가 A만 사용하면 되도록 해 주는게 Toolkit 클래스입니다.
    이게 없다면 현재 어떤 플랫폼인지 알아내서 해당 플랫폼에서 동작하는 클래스를 호출해야 하겠죠.

    미디어 트랙커는 해당 미디어(이미지, 사운드 등)의 상태를 추적하는 기능을 갖고 있습니다.

    getImage 메소드는, 실제로는 이미지를 곧바로 메모리에 적재하지 않고 일단은 주소값만 갖고 있습니다.
    그리고 이 Image 객체가 화면에 그려져야 할 때가 되면 그때 메모리에 이미지를 불러들이는데, 이렇게 하면 상황에 따라서 메모리에 이미지가 미처 로드되지 못했는데 그리기를 수행하게 되는 수가 있습니다.
    그때문에 미디어 트랙커를 사용해 이 이미지가 메모리에 로드되었는가를 확인해서 확실하게 로드시키는 것입니다.

    addImage는 getImage로 불러들이려고 한 이미지를 미디어 트랙커에 등록하고, 추적용 ID(0)를 부여합니다.
    그리고 waitForID는 해당 아이디의 이미지가 로드될때까지 기다리고, 로드되지 않았다면 로드하는 기능을 합니다.

    이것에 의해 이미지 로드가 끝난 후에 return img;가 호출되므로 이미지는 안전하게 메모리에 로드되어 사용할 수 있는 상태가 된 후에 함수를 종료하게 됩니다.

    사실 awt에서 미디어트랙커 쓸 일이 이미지 불러오기 정도밖에 없는지라, 그냥 이미지 로드하는 함수라고 (관용구?) 외우다시피하고 가도 괜찮지 않나 싶습니다..
  • 님프 2014/10/29 11:06 # 삭제 답글

    감사합니다. 다 이해 했네요. 다행히 .

    몇개 질문 더 드려봅니다.

    1. 드로우 렉트 이미지 부분인데요.
    y = y-(anc/3)*(ht/2); // 이 부분에서 y축으로도 기준선을 잡는 것으로 알고있는데
    anc%3으로 해야하지 않나요 .. ?
    왼쪽 오른쪽 중앙 전부 /3하면 0인데 이거 왜 이렇게 되는지 모르겠습니다.

    2. 아래쪽의 gc.drawImage(img, x-sx, y-sy, this); 질문입니다.
    여기서 this가 gc의 이미지 오브젝트 맞나요?
  • 펭귄대왕 2014/10/29 12:31 #

    anc값은 0~8로 들어옵니다.
    가로축에 대해서는 %3으로
    세로축에 대해서는 /3으로 함으로서 가로 앵커와 세로 앵커를 숫자 하나로 각각 따로따로 줄 수 있습니다.
    예를 들어 앵커를 정중앙으로 하려고 한다면 anc를 4로 주면 4%3 = 1, 4/3 = 1 하는 식이죠. anc/3이 0인 것은 가로 앵커와 상관없이 세로앵커는 윗줄 기준으로 정렬하는 겁니다.

    this는 ImageObserver입니다. (이클립스에서 drawImage 함수 위에 커서를 놓고 F3을 눌러서 쫓아가보면 됩니다)
    GameScene의 상속 단계를 거슬러 올라가면 GameCanvas->Canvas->Component->... 순인데, Component가 ImageObserver를 implements하고 있으므로 게임 캔버스의 상속 객체를 인수로 넣어줘도 됩니다.(자동으로 클래스 형변환이 됩니다)

    이미지를 다루는 작업은 실행속도가 천차만별일 수 있기 때문에 이 이미지에 대한 작업이 어떻게 되고 있는가 모니터링하는 관찰자가 필요해서 사용하는 것이 ImageObserver인데, 우리가 직접 다루는 것은 아니므로 세세하게 이해하지는 않아도 됩니다. 간혹 이미지옵저버를 할당할 자리에 null을 넣어서 아예 무시하기도 합니다.
  • 님프 2014/10/29 16:52 # 삭제 답글

    아 이해했습니다 감사합니다~!
  • 빡빡이 2015/10/14 09:13 # 삭제 답글

    2인용으로도 만들 수있을까요??
  • 펭귄대왕 2015/10/14 10:50 #

    수평 좌우로만 움직이는 게임을 둘이서 어떻게 하나요..
  • 2015/11/30 21:38 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 펭귄대왕 2015/11/30 22:55 #

    시작화면이라면 게임 전의 타이틀이나 캐릭터 선택같은 UI인가요 아니면 본게임 시작할 때의 도입 연출 같은 것인가요?
    전자라면 게임 시스템에 관련된 설계가 필요하겠고, 후자라면 연출이 잘된 고전 슈팅게임같은걸 참조해서 흉내내보면 좋을듯요.

    http://icegeo.egloos.com/183632
    위 링크에 있는 요시카 스크램블이란 게임은 게임 본편을 최초 시작(캐릭터가 왼쪽에서 등장하며 SCRAMBLE! 이란 글자가 점멸)하는 상태, 게임이 진행중인 상태, 게임오버된 상태 등으로 나눠서 사용하고 있습니다. 이런 식으로 '시작하는 상태'에서 캐릭터의 움직임이나 애니메이션 등을 해 주면 됩니다.
  • 후니 2016/05/20 11:44 # 삭제 답글

    반갑습니다 ^^ 자바를 배운지 3달쯤 되었는데 혼자서 닷지게임을 만들다 보니 어려움에 부딪혀서
    검색에 검색을 거듭하다 펭귄대왕님의 블로그를 찾게 되었습니다 ^^

    제가 하던 것은 잠시 멈춰두고 이 강좌를 꼼꼼하게 읽어보려고 합니다.
    스레드를 다루는 게 너무나 어려웠는데 1부만 보아도 펭귄대왕님의 내공이 느껴지네요
    혼자 머리 싸매고 궁금했던 점이 벌써 몇개 해결되었습니다.
    앞으로 잘 부탁드리겠습니다 ㅎㅎ
  • 펭귄대왕 2016/05/20 14:10 #

    찾아주셔서 감사합니다.
    대단치 않은 내용들이지만 공부하시는데 도움이 되었으면 좋겠습니다.
    잘 부탁드립니다 ^^
  • k 2018/06/24 17:41 # 삭제 답글

    xp와hp표시와 템을먹으면장비템과 데미지표시 하고싶은데요 어캐표시하나요?
  • 펭귄대왕 2018/06/25 11:33 #

    hp나 경험치를 숫자가 아닌 그래프로 표시하고 싶다면, 본게임중에 듀얼샷같은 아이템을 먹었을 때 그래프 그려주는 방법을 참조하면 됩니다.
    데미지 같은 정보는, 게임 중에 총알 타격이나 폭발 같이 이펙트를 그려주는 코드를 사용,그림 대신 텍스트나 그림문자를 보여주면 됩니다.
    장비 구현은 답플로 설명드리기엔 좀 긴 내용이 되겠네요. 이건 시간이 좀 나면 따로 정리해 보겠습니다.
  • 1pick 2019/12/02 19:44 # 삭제 답글

    2019년에도 보고있습니다. 개인프로젝트로 꼭 해보고 싶었는데 펭귄대왕님 덕분에 시작할 수 있었습니다. 감사합니다~
  • 펭귄대왕 2019/12/10 02:49 #

    도움이 되었다면 저도 기쁘고 감사합니다. 좋은 결과 얻으시기를..!
댓글 입력 영역


Books

Geek라이프

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

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

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

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