adsense



JAVA 2D 슈팅게임 소스 - 요시카 스크램블

요시카 스크램블 소스(이클립스 프로젝트)

재작년에 왔던 각설이..

기존에 배포하던 학습용(?) 공개 슈팅게임 소스를, 최근 질문들어온 내용을 바탕으로 업데이트하였습니다. (사운드 기능은 플랫폼에 좌우되는 부분이 커서 이번에는 넣지 않았습니다)

기본 버전과의 차이는 //2013-10 으로 주석이 붙어있는 문장을 따라가면 됩니다.

주된 변경점은

1. 기존에는 정지상태였던 원경을 느리게 스크롤되도록 변경
2. 점수, 라이프, 레벨 등을 기존의 문자열 대신 이미지로 출력하도록 변경

이상 두 가지입니다.

public void Draw_BG()
public void Draw_UI()
이 두 함수에 집중적으로 변경이 더해졌으며, 숫자를 이미지로 출력하기 위해 public void drawImageNum 함수가 추가되었습니다. 숫자 이미지는 0123456789 순서대로 나열된 것이라면(모든 숫자의 폭은 일정해야) 다른 것으로 바꿔 써도 무방합니다.

그리고 이 처리를 위해 flip된 배경그림과 ui용 이미지가 조금 추가되었습니다. (rsc 폴더)

구체적인 내용은 소스를 확인해보시고, 궁금하신 점은 언제든지 질문해주세요.


덧글

  • 궁금해요 2013/12/01 13:29 # 삭제 답글

    혹시 이것 2인용으로도 할수있나요..?
    아이템을 먹으면 먹은 아이템 갯수가 위에 뜬다던지 그런경우...
    제가2인용으로 만들려고 해봤는데
    스레드 문제인지, 1p가 움직이면 2p가 안움직이고 그러더라구요...
  • 펭귄대왕 2013/12/01 21:41 #

    적 캐릭터 여럿을 처리하듯이 플레이어 캐릭터도 두 개를 처리하도록 하면 됩니다. 총알의 발사나 아이템 취득도 플레이어 캐릭터 수 만큼 반복해주면 되고요.
    단지 컨트롤하기 위해 키입력 설계가 추가로 필요할테죠.
  • 펭귄대왕 2013/12/02 00:26 #

    한쪽 플레이어가 안 움직이는 건 키 버퍼 문제가 아닐까 싶은데요,

    일단 키 버퍼는 한 캐릭터에 대해서만 포커싱되고 있으므로 추가적으로 키버퍼 하나를 더 만들어서 2플레이어는 이 새로운 키버퍼를 참조해서 움직이도록 해줘야 합니다.
    예를 들면
    case KeyEvent.VK_R://2플레이어 FIRE
    keybuff2|=FIRE_PRESSED;
    break;
    case KeyEvent.VK_A://2플레이어 LEFT
    keybuff2|=LEFT_PRESSED;//멀티키의 누르기 처리
    break;
    case KeyEvent.VK_W://2플레이어 UP
    keybuff2|=UP_PRESSED;
    break;
    case KeyEvent.VK_D://2플레이어 RIGHT
    keybuff2|=RIGHT_PRESSED;
    break;
    case KeyEvent.VK_S://2플레이어 DOWN
    keybuff2|=DOWN_PRESSED;
    break;
    이렇게 keybuff2 라는 변수를 하나 더 만들어서 2플레이어용 키 누르기/떼기 처리를 받아들여야죠.

    물론 플레이어의 각종 상태변수나 표시용 변수도 2플레이어용으로 한 조를 더 만들어야 합니다.
    적 캐릭터처럼 클래스를 새로 만들어서 해 주면 더 편할 듯..
  • cchoimin 2014/09/16 19:39 # 삭제 답글

    자바로 돌리니까 에듀케이션용이라는 화면만 뜨는대요?
  • 펭귄대왕 2014/09/17 01:47 #

    이미지 리소스가 없는 경우 나타나는 현상입니다.

    혹시 이클립스에서 새 프로젝트를 생성해 불러들이거나 하셨다면 rsc 폴더를 복사해 넣어주시면 됩니다.
  • 키인식 2014/09/22 22:08 # 삭제 답글

    한번 참고 할려고 실행시켜 봤는데 스페이스바를 눌러도 인식이 안됩니다.
    혹시 이클립스에서 RUN으로 해서 그냥 실행시키면 키보드나 마우스 인식을 못하는 것인가요?
  • 펭귄대왕 2014/09/22 23:17 #

    화면이 나타난 후에 마우스로 게임화면을 클릭하면 키입력을 받지 못합니다. 실행되고 그대로 키를 누르면 조작이 될겁니다
  • 안녕하새요 2014/10/07 18:18 # 삭제 답글

    제가이걸로 수정해서 하려고 해보는대요 음..

    레벨 올라갈떄마다 보스가 나오잔아요

    보스나올때마다 보스 이미지 각각 다른걸로 변경해서 하고싶은대 어덯게 해야하나요.,/?? 바쁘신대

    읽어주셔서 감사합니ㅏ 꼭알려주셧으면 해요..ㅎㅎ

    레벨1에서 보스는 1이미지 레벨2에서는 2이미지 레벨3에서는 3이미지로 각각 다르게 나오게 하고싶어서요..

    부탁드려요 ^^
  • 펭귄대왕 2014/10/07 20:06 #

    http://icegeo.egloos.com/299647
    내용이 좀 길어져서 별도 포스트로 뺐습니다.
  • 2014/10/30 22:12 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 펭귄대왕 2014/10/31 02:49 #

    프로그래밍을 사짜로 배웠다보니 디자인패턴에 대해서는 아는게 없어서 답변드릴수가 없네요..
  • 지스타온 2014/11/19 17:03 # 삭제 답글

    안녕하세요 게임실행하면 스페이스바 누르라고 나오고 시작이 안되는데요

    왜그럴까요 thest1@nate.com 입니다.

    32비트 자바 se 설치햇습니다~
  • 펭귄대왕 2014/11/19 17:44 #

    게임화면을 마우스로 클릭하면 키보드가 안 먹는 버그(?)가 있습니다.
    창을 건드릴 일이 있다면 프레임 부분을 클릭하거나, GameScreen 생성자에
    this.setFocusable(false);
    를 추가해주시면 괜찮습니다.
  • 고등학생 2015/05/07 15:15 # 삭제 답글

    처음 시작화면에 맵이 여러가지가 있고 선택하게 되면 그 맵으로 실행되게 할 수도 있을까요?
    비슷한 게임을 수정중인데 전혀 감이 잡히지 않아서요ㅜㅠ
  • 펭귄대왕 2015/05/07 18:20 #

    맵이 바뀐다면 대개는
    1. 배경이 바뀐다
    2. 적 캐릭터와 공격 패턴이 바뀐다.(보스 포함)
    그런 내용이 될텐데요,

    간단히 배경을 바꾼다고 하면

    현재 맵 번호를 저장하는 int mapIndex; 를 하나 적당한 위치(어디서나 억세스 가능하도록)에 선언해줍니다.

    본 게임을 시작하는 시점에서 mapIndex에 따라 필요한 배경 그림을 로드하고,
    Draw_BG()에서 mapIndex에 따라 배경 그림 그리는 방법을 다르게 해 주면 됩니다.
    이렇게 우선 구현해놓고, 수동으로 mapIndex 값을 바꿔 넣어주며 배경이 다르게 나오는지 확인해 봅니다.
    (맵에 따라 다른 적이 나오게 하는 것도 원리는 동일합니다)

    그 다음은, 맵을 선택하는 UI를 작성해야할텐데..
    간단히 시나리오를 생각해보면
    타이틀 화면 - 맵 선택 화면 - 게임 시작 - 게임 오버 - 타이틀 화면
    이런 구조가 되겠네요.

    그럼 해줄 일은
    1. 타이틀 화면에서 스페이스키를 누르면 맵 선택 화면으로 전환한다 (현재는 메인 게임으로 전환)
    2. 맵 선택 화면에서 어떤 맵이든 선택하면 게임이 시작된다.
    2-1. 맵 선택 화면에 쓰일 그림을 초기화
    2-2. 맵 선택 화면을 그려준다.
    2-3. 맵 선택 화면에서 필요한 키 입력을 받는다.
    2-4. 맵이 선택되면 게임 화면으로 전환한다. (mapIndex에 선택된 맵 번호를 넣어주고, 기존에 타이틀화면에서 스페이스를 누르면 해 주던 처리를 실행)
    이렇게 됩니다.

    현재 이 게임은 마우스처리를 하고 있지 않으므로 맵 선택 UI를 키보드만으로 구현한다면,
    상하좌우 키로 맵 위에 커서를 옮기게 하고
    스페이스로 맵을 결정, 게임을 시작합니다.
    더 단순하게는, 맵이 다섯 개 있다면 1~5번 숫자키를 입력받아 해당 맵으로 스타트하는 방법도 있겠네요.

    앞 단계에서 mapIndex에 따라 원하는 배경이 정확하게 나왔다면 나머지 맵 선택 UI는 화면과 키 입력만 잘 꾸며주면 됩니다.

    이 게임은 구조가 조금 지저분한 편이라서
    http://icegeo.egloos.com/300704
    이쪽을 보시면 구조 해설이 좀 더 깔끔하게 되어 있어 이해하는데 도움이 되지 않을까 합니다.
  • 2015/06/04 11:04 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 펭귄대왕 2015/06/04 17:59 #

    수정할게 아마 상당히 많을겁니다.. 간단하게 설명드리기는 무리겠네요.
  • 2015/06/05 09:15 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 펭귄대왕 2015/06/05 14:42 #

    지금으로선 계획이 없습니다. 딱히 2인용으로 할 이유를 모르겠네요.
  • 2015/10/12 14:45 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 2015/10/12 15:38 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 펭귄대왕 2015/10/13 01:45 #

    그다지 소스가 깔끔하지 못해서 제대로 이해하지 못하면 좀 수정하기 어렵습니다.
    포인트만 몇 개 짚어드리자면

    총알을 수평으로 2발씩 발사하기

    public void process_MY()에서
    shoot=new Bullet를 찾아
    RAND(?,?) -> 270도로 수정하고 두 개만 남겨놓고 하나는 삭제 (세트인 bullets.add(shoot);도 하나는 삭제)
    myy+1500를 하나는 myy+900 하나는 myy+2100 정도로 수정
    그럼 수정 내용이 대충
    shoot=new Bullet(myx+2500, myy+900, 0, 0, 270, 8);
    bullets.add(shoot);
    shoot=new Bullet(myx+2500, myy+2100, 0, 0, 270, 8);
    bullets.add(shoot);
    이렇게 되는데,
    총알의 속도를 바꾸고 싶다면 8을 작은 숫자로 하면 느리게, 더 큰 숫자로 하면 빠르게됩니다.

    총알 발사 딜레이조절하기
    바로 위의
    if(cnt%4==0||myshoot){
    에서 4보다 숫자를 크게 하면 발사 간격이 느리게, 작게 하면 빠르게됩니다.


    아이템 안나오게 하기

    public void process_BULLET()에서
    tem=new Item을 찾아

    tem=new Item 부분과 items.add(tem); 부분을 주석처리(물론 이거랑 전후에 묶여있는 if문도 함께 주석처리합니다)


    보스 안나오게 하기
    public void process_GAMEFLOW()에서

    else {
    // 기존에 레벨만 올려주던 부분에서, 레벨을 올려주면서 보스 캐릭터를 등장시킨다
    .
    .
    .
    }
    부분을 주석처리하고

    else control=1;
    추가

    대충 이정도로 하면 되겠고, 폰에서는 실행할 수 없습니다.
  • 펭귄대왕 2015/10/13 07:18 #

    http://icegeo.egloos.com/275435
    소스가 이해하기 힘든 경우, 게임 형식은 좀 다르지만 위 포스팅으로 시작되는 강좌를 순서대로 따라가 보시면 좀 더 깔끔하게 정리된 내용을 얻을 수 있습니다.

    자바 어플리케이션 버전의 게임을 안드로이드로 포팅하는 방법도
    http://icegeo.egloos.com/279434
    이렇게 소개해 봤습니다만, 솔직히 이쪽은 난이도가 조금 있습니다. 안드로이드에 대한 이해도 필요하고, 그냥 처음부터 안드로이드용으로 만드는게 더 쉬울 수도 있고요..
  • 2015/10/14 08:56 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 펭귄대왕 2015/10/14 10:48 #

    플레이어 캐릭터를 두 개 내보내고 입력을 두 개 받으면 됩니다..만, 이 소스는 2인용으로 개조하기에 적합한 편이 아닙니다.
  • 2015/10/26 10:08 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 펭귄대왕 2015/10/26 10:35 #

    우선 Bullet 생성자를 봅니다.
    Bullet(int x, int y, int img_num, int from, int degree, int speed)
    int x, int y는 각각 총알의 좌표,
    img_num은 그림 번호(Image bullet[]으로 정의된 이미지 객체의 배열 인덱스),
    from은 누가 쏘았는가(0이면 플레이어가 쏜 총알, 1이면 적이 쏜 총알),
    degree는 총알이 날아가는 방향(수직 위를 0으로 반시계 방향으로 0~360도),
    speed는 총알이 날아가는 속도에 해당합니다.

    myx+2500, myy+900은 해당 좌표에 총알이 생성되는 것인데, 실제 좌표계 상에서는 /100 하여 사용합니다.
    그 다음의 0은 이 총알을 그려줄 때 bullet[0] 이미지 객체를 사용하라는 의미,
    다음 0은 플레이어가 쏜 총알이라는 의미,
    270은 오른쪽 앞, 그러니까 3시 방향으로 총알이 날아간다는 것이고, 8은 그 날아가는 속도입니다.
  • 2015/10/28 15:44 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 2015/10/28 16:02 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 펭귄대왕 2015/10/29 01:55 #

    아이템처리를 위해 Item 클래스가 존재합니다.
    적이 격파되었다든가 하는 위치에서
    Item _item = new Item(x, y, 종류);
    items.add(_item);
    식으로 아이템을 생성하게 되어 있습니다.
    아이템을 추가하려면 그 전에 아이템의 그림을 추가하고, 아이템이 등장하는 조건(현재 new Item해 주는 부분을 찾아봅니다)을 만들고, 플레이어가 아이템을 먹었을 때 처리를 각각 코딩해주면 됩니다.

    그림 추가를 위해서는
    Image item[]=new Image[3];
    에서 배열 수를 수정하고
    gamescreen.item[2]=makeImage("./rsc/game/item2.png");//아이템 추가
    부분을 찾아서 이 아래 이미지 선언을 같은 방식으로 추가합니다.

    이후에는 new Item을 해 주고, process_ITEM()에서 아이템 획득 분기(switch(buff.kind) 부분)에서 해당 아이템의 효과를 코딩해주면 됩니다.

    아이템이 화면에 등장하게 하기 위해서는 new Item이 있는 부분을 분석해보면 됩니다.
  • 2015/11/25 17:32 # 답글 비공개

    비공개 덧글입니다.
  • 2015/11/25 18:13 # 비공개

    비공개 답글입니다.
  • 멋부리는 표범해표 2015/12/06 23:23 # 답글

    자바 슈팅게임을 만들고 있는 학생입니다.

    대충 어디서 소스는 주워서 써서 대략 슈팅게임 비슷하게는 만들어놨는데

    2가지에서 막힙니다

    첫번째는 타이틀화면이고 두번째는 hp바 ( 하트 이미지 3개 출력하고 비행기가 적비행기에게 피격시 하트하나가 줄어드는 방식을 구현하고싶습니다) 입니다

    도움을좀 주실수 있을련지요
  • 펭귄대왕 2015/12/07 06:25 #

    타이틀화면은 현재 상태를 나타내는 state값을 갖고(보통 int) 이 값에 따라 화면 그리기/처리를 switch문으로 분기하는 방법이 가장 간단하겠고요,

    int state;//선언
    .
    .
    state = 0;//초기화
    .
    .
    스레드루프{
    switch(state){
    case 0:
    타이틀그리기();
    타이틀처리하기();//여기서 키 입력 등으로 state를 1로 전환
    break;
    case 1:
    게임그리기();
    게임처리하기();//게임이 끝나면 state를 2로 전환
    break;
    case 2:
    게임오버그리기();
    게임오버처리하기();//키 입력 등으로 state를 0으로 전환
    break;
    }
    }

    혹은.. 보통 자바 awt로 게임을 만든다면, 기본적으로 생성한 Frame(또는 JFrame)에 게임 클래스(보통은 Canvas와 Runnable을 상속한)를 add해주는 식으로 만들텐데, 타이틀 화면과 게임 화면을 각각 다른 클래스로 만든 후,

    프로그램이 처음 시작할 때는 타이틀 화면 클래스를 Frame에 add해 주고, 게임으로 전환할 때는 타이틀 화면 클래스를 Frame에서 remove 후 게임 화면 클래스를 add, 반대로 게임에서 타이틀 화면으로 전환할 때도 게임 화면 클래스를 Frame에서 remove 후 타이틀 화면 클래스를 다시 add해 줍니다.

    간단히 처리할 때는 첫 번째 방법을 써도 되고, 화면 상태의 종류가 다양하다면-즉, 게임의 규모가 커진다면- 후자쪽이 화면을 추가, 수정하기 편합니다. 후자는 위치즈 플라이트나 Asteroid Belt 게임에서 쓰는 방법입니다.

    hp를 이미지로 표현한다면 대충

    for(int i = 0; i < hp; i ++)
    draeImage(hpImage, hpX + i * hpImage.getWidth(), hpY);

    같은 식으로 처리하면 됩니다. (실제 코드하고는 조금 다른 부분이 있습니다)
  • 2015/12/08 07:56 # 비공개

    비공개 답글입니다.
  • 펭귄대왕 2015/12/08 09:59 #

    valpa@네이버닷컴 으로 보내주시면 됩니다.
  • 펭귄대왕 2015/12/08 22:59 #

    답장 보내드렸습니다~
  • 멋부리는 표범해표 2015/12/20 21:12 # 답글

    죄송하지만 메일한번 다시 보내도될까요... 이게 파일이 이상해져서요..
  • 펭귄대왕 2015/12/20 21:42 #

    예 보내주세요.

    그런데 압축은 rar나 zip으로 주시면 좋겠습니다..
  • k 2018/06/24 17:40 # 삭제 답글

    펭귄대왕님 xp표시랑 hp 표시 데미지가몇인지 나오게할려면 어캐해야하나요?
    템을먹으면 장비창이 도 표시가되게하고싶은데요. 어캐하나요??
댓글 입력 영역
* 비로그인 덧글의 IP 전체보기를 설정한 이글루입니다.


Books

Geek라이프

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

게임 매니악스 퍼즐 게임 알고리즘
마츠우라 켄이치로,츠카사 유키 공저/김병국 역

만들면서 배우는 유니티 게임 프로그래밍
송용성 저

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

될 수 있어! SE 8
나츠미 코지 저/Ixy 그림/김경훈 역
예스24 | 애드온2