adsense



[JAVA] 2D 슈팅게임 개발강좌- 위치즈 플라이트 5부 (끝) PC/Mobile/Developer

마지막 챕터입니다.

이번에 다룰 내용은

- 타이틀 화면의 대대적인 수정 (꾸미기)
- 총알의 레벨 업 & 구매 적용
- 팝업 메시지에서 타이머 응용
- 파괴 불가 적 캐릭터 등장

입니다.



GameShop.zip (이클립스용 프로젝트 파일 다운받기)


타이틀 화면은 보시다시피, 드○○○○○트처럼

- 뒤에 배경이 천천히 흘러가고
- 앞에 플레이어 캐릭터 일러스트가 큼직하게 나와 있으며
- 타이틀 로고가 떠 있는 것

이고, 기본 정보인 최고점수, 현재 소지 골드는 위치만 변경되었고 이전과 동일합니다.

이쪽은 일부 cnt값에 연동하는 부분이 있긴 해도 그저 출력하기만 하고 복잡한 내용은 없으므로 자세한 설명은 생략하겠습니다. dblpaint의 내용을 봐 주세요. 전체이용가 마크는 그냥 개드립..

그 대신, 새롭게 총알 레벨업을 위한 안내문이 생겼습니다.

총알 레벨 업을 위해 구현해야 할 내용은

- 게임 세이브 파일의 로드/세이브에 현재 총알의 레벨을 적용합니다.- 타이틀 화면에서 해당 버튼을 누르면 골드를 감소시키고 총알의 레벨을 올려줍니다.
연속으로 버튼이 눌리는 걸 방지할 필요가 있습니다.
- 골드가 부족하거나 레벨업이 한계 상태라면 레벨업 불가 메시지(팝업)을 띄웁니다.- 게임 중 발사하는 총알의 그림과 파워를 레벨에 맞춰 바꿔줍니다.



파괴 불가 오브젝트를 위해 구현할 내용은

사실은 내구력을 1천만쯤 할당하면 그게 파괴불가 오브젝트입니다.. 하지만 그것만 하자는 건 아니죠.

- 출현 전에 어느 위치에 출현하는지 경고를 표시해줍니다.
- 통상의 네우로이와 그림이 다릅니다.
- 통상의 네우로이보다 속도가 빠릅니다.



그럼 순서대로 구현해 보겠습니다.

GameManager에
public int powlevel = 0;//플레이어 총알 단계
를 우선 추가해주고,

public boolean LoadGame(String fname)에서

powlevel = Integer.parseInt(gamedata[2]);
를 추가해 줍니다. 물론 gamedata 배열은 3개로 늘려둡니다.

기존 세이브 파일에서 세 번째 값이 없기 때문에 어떤 문제가 생길지 모르므로 try_catch로 감싸줍니다.

이어서
public boolean SaveGame(String fname)에서

bw.write(String.valueOf(powlevel)+"\n");
를 flush 전에 추가해 줍니다.



GameScene.java 수정

파워 레벨을 게임에서 반영시켜주는 부분부터입니다.


총알 그림을 레벨에 따라 30개로 준비해 놨습니다. (크기만 조절한건데 하다가 지루해져서 몇 개는 똑같은 그림입니다..) 프로젝트의 rsc/game에서 bullet_01.png~bullet_30.png를 참고해 주세요.

이걸 파워(powLevel)에 맞춰 읽어들이기 위해

bullet = manager.makeImage("rsc/game/mybullet"+String.format("%02d", manager.powlevel+1)+ ".png");

총알 그림을 받아오는 부분을 위와 같이 수정합니다.

String.format은 C언어의 printf와 비슷합니다. %02d는 정수값을 반영하는데, 정수가 2자리수가 아니면 자동으로 앞에 0을 삽입해 줍니다. 그러므로 01, 02, ... 09, 10, ... 이렇게 들어갑니다.

오소독스한 슈팅게임은 대개 게임 중에 파워업을 하는데, 이 게임은 트윈샷 외에는 게임 중 파워업이 없어 총알 그림은 한 종류만 읽어두면 됩니다.

그럼 총알을 발사(생성)하는 처리가 있는 myProcess 쪽을 봅니다.

기존 총알 클래스 생성자에 파워를 받는 부분이 있었으므로 이 파워에 powLevel 값을 넣어줍니다. 단, 최초의 레벨값이 0이므로 +1해서 넣어주지 않으면 아무리 쏴도 가장 약한 적도 파괴되지 않습니다.

그리고, 파워에 따라서 총알 크기가 달라지므로 충돌 사각형의 범위도 파워가 올라갈 수록 조금씩 크게 적용해 줍니다.
powRange라는 변수가 사용된 부분을 참고해 주세요.
int powRange = manager.powlevel/6;
.
.
.
~ new Rectangle(5-powRange, 1, 10+powRange*2, 33) ~
에 해당합니다.

이것으로 메인 게임에서 파워 적용을 마쳤습니다.


파워 업은 타이틀 화면에서 구매합니다.
별도의 샵이 없고 타이틀 화면이 샵의 역할을 대신하는 셈인데요,

앞서 보여드렸던 새로운 타이틀 화면을 다시 한 번 봐 주세요.


원래는 좌하단의 Pow 아이콘을 마우스로 클릭. 하면 골드를 소비해서 파워 업 한다는 구상이었습니다만..

유감스럽게도, java awt에서 canvas로 화면 전환을 시도하는 구조에서는, 화면을 마우스로 클릭하면 포커스가 프레임이 아닌 캔버스로 옮겨가 버리는 현상이 있습니다.

반대로 키/마우스 리스너를 캔버스에 얹어주면, 일단 화면을 한 번 클릭해야 키 이벤트가 받아들여지게 되고요.

이 부분은 해결책을 찾지 못해서, 부득이하게 파워업도 키보드로만 처리하게 되었습니다.


'P' 키를 누르면, 파워 업을 하도록 하였습니다.


P 키가 눌리면
- powLevel을 1 증가하고
- gold를 감소시키고
- 이 상태를 세이브


하는 처리로 파워업 구매는 간단하게 끝납니다.

buyPower 함수가 그 역할을 하고 있습니다. (※여기서 사용하는 popupOn은 별도로 해설하겠습니다)


파워에 따라 필요한 골드량을 어떻게 할 것인지와,
시각적 효과를 위해 구매 직후 골드가 감소하는 모습을 리얼타임으로 보여주는 내용 정도가 추가되겠네요.

골드 양은 테이블을 만들어도 되고, 적절한 공식을 만들어도 됩니다.
실제 플레이하면서 적당하겠다 생각되는 값을 적용하면 됩니다.

nextPowGold = (manager.powlevel/4)*500+(manager.powlevel+1)*100;

이번에는 이런 공식을 썼습니다.
기본적으로 1레벨 올리기 위해 레벨*100 골드를 요구하면서, 거기에 더해 4레벨 마다 500골드씩 할증이 붙는 방식입니다.최고 레벨(powLevel 값이 29)인 상태에서는, 더 이상 레벨업 할 필요가 없으므로 요구 골드를 0으로 바꿔주고 있습니다.

구매하면 골드가 감소하는 처리입니다.
우리는 현재 골드값으로 manager.gold를 갖고 있는데, 화면에 표시중인 골드 값을 별도로 설정합니다.
이것을 int viewGold 라고 합니다.

buyPower 함수가 호출되면, manager.gold에서 nextPowGold 값을 빼 줍니다.

이러면 자연스럽게 viewGold 값과 manager.gold 값이 달라지게 되고,

viewGold값이 manager.gold값과 차이가 나면, 이 차이가 없어질 때 까지 매 프레임마다 viewGold 값을 증감시켜주면 됩니다.

이때 증감시켜주는 폭을 비교적 일정하게 하기 위해서
minusGold = Math.abs(manager.gold-viewGold)/20;
와 같은 값을 준비합니다. 이것으로 최대 20프레임동안 viewGold 값을 변경시켜주면 viewGold 값과 manager.gold 값이 다시 일치하게 됩니다.

viewGold 값은 다른 용도로도 응용할 수 있는데, 이 값이 manager.gold 값과 다른 동안에는 키 이벤트를 무시하도록 만들면 P 키가 연타되는 일을 막을 수 있습니다.


일정 시간이 지나면 자동으로 사라지는 팝업

buyPower 함수에서는 골드가 부족하거나, 더 이상 파워업 할 필요가 없으면 안내 메시지를 보여주는 팝업을 띄웁니다.
void popupOn(String message){

isPopup = true;
popupMessage = message;
_timer.schedule(new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
popupOff();
}
}, 3000);
}

이것이 팝업을 여는 부분입니다.단순히 메시지를 세트하고, 팝업 플래그를 true로 바꿔주는 것입니다.

그러면 dblpaint에서, 새로 만들어놓은 drawPopup을 호출하고 팝업 플래그가 세워져 있으면 팝업을 그려주면 됩니다.

여기서 중요한 것은 타이머 스케줄 부분입니다.
Timer _timer;
.
.
.
_timer.schedule(new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
popupOff();
}
}, 3000);


위 내용은 3000밀리초.. 그러니까 3초가 지나면 지정된 타이머태스크를 수행합니다.
여기서는 popupOff란 함수를 호출하도록 했습니다.
void popupOff(){

isPopup = false;
_timer.cancel();
}


팝업 플래그를 해제해주고, 타이머 스케줄링도 취소합니다.
이것으로 돈이 없을 때 P키를 누르면, "골드가 부족합니다."(인앱상점으로 안내할까요?)란 메시지를 띄우는 팝업이 3초동안 나타났다 사라지는 것을 볼 수 있습니다.




파괴 불능 오브젝트

- 출현 전에 어느 위치에 출현하는지 경고를 표시해줍니다.
- 통상의 네우로이와 그림이 다릅니다.- 통상의 네우로이보다 속도가 빠릅니다.


그림이 다르고 속도가 빠르다는 것은, 간단하게 구현이 됩니다.그렇다면
- 출현 전에 어느 위치에 출현하는지 경고를 표시해줍니다.
요게 조금 어려워 보이죠.

실은 대단히 간단합니다.

이 경고 자체가 적 캐릭터의 일부인 것입니다.

캐릭터 생성시에 두 장의 그림을 전달합니다.하나는 적 캐릭터 본체, 다른 하나는 경고 사인.

캐릭터가 생성되었을 때, 처음 한동안은 경고 사인을 보여주다가, 시간이 좀 지나면 본체가 등장하도록 하는 겁니다.
경고 사인이 보이는 동안은 충돌판정이나 이동처리를 하지 않는거죠.


일단 이 파괴불능 오브젝트- 드○○플○○○로 치면 운석입니다만.

뭘로 해야 이 게임에 어울리는 파괴불능물이 될까 고민하다 살짝 장난끼를 발휘해 봤습니다.이 파괴불능 오브젝트를 네우로이보다 훨씬 크게 만들어버리는 거였습니다.

그래서 생각해낸 V2로켓형 네우로이.


기존의 네우로이와 달리 경고 사인에 해당하는 그림을 한 장 더 받아와야 하므로 생성자가 달라집니다.
public Enemy(Image pic, Image pic2, Rectangle rect, int x, int y, int hp, int speed, int kind)

kind와 pic2가 Enemy class에 새로 추가되었습니다. 그리고 시간 관리용으로 cnt가 추가되었습니다.

기존의 네우로이는 kind=0, V2네우로이는 kind=1 입니다. 이게 선언되면 hp를 1천만으로 할당합니다.

그럼 Enemy class의 draw와 process도 각각 수정합니다.

draw에서 V2 네우로이를 그리는 부분만 보겠습니다.
if(cnt<150 && cnt%4<2)
gContext.drawImage(pic2, x+19, 32, _ob);//초반에는 경고만 나온다
else
gContext.drawImage(pic, x, y, _ob);//그리고 본체가 나온다


cnt가 150 미만이면 경고 사인을 보여줍니다. (cnt%4<2 조건은 깜박거리게 하기 위한 것입니다)

process에서 V2 네우로이의 처리는
if(kind==1){
if(cnt>=150)//자체 카운트가 150에 도달하기 전까지는 경고만 나오므로 이동이 없다
y+=(speed*15/10);//1/.5배 빠르다
else
return NO_PROCESS;//경고만 보여지고 있는 동안에는 충돌 체크가 없다
}

cnt가 150 이상일 경우 좌표를 이동시켜주고 아래로 내려갑니다. 아래에는 기존의 충돌 체크 부분이 있습니다.
그렇지 않다면 (150 미만) 좌표 변경 없이 그냥 리턴해서 충돌 체크도 생략합니다.

이렇게 해서 cnt가 150이 될 때 까지는 경고사인이 깜빡이고, cnt가 150을 넘으면 시커먼 네오암스트롱사이클론제트암스트롱포V2로켓이 빠르게 내려옵니다.

그리고 V2네우로이를 생성하기 위한 조건은
if(cnt > 200 && manager.RAND(0,1000) < 5*_level){//어느 정도는 레벨이 높아질수록 나오기 쉬워지는 편
이와 같은데, 생각보다 잘 나오는 편입니다.

검고 커다란 것이 서너발 씩 내려오고 있는데다 계속 경고 사인이 깜박이고 있으면 압박감이 대단합니다.




이것으로 약 40일간 진행한 위치즈 플라이트 개발 강좌를 모두 마치겠습니다.

중반에 일정이 많이 늘어지기도 했고, 부족한 점 역시 많았지만 너그러이 끝까지 봐주셔서 감사합니다.


다음에는 이것을 그대로 SurfaceView 를 사용해 안드로이드 버전을 포팅하는 것,
그리고 AndEngine이나 cocos2d-x를 사용해 포팅하는 것,

정도를 목표로 잡고 있습니다..만, SurfaceView 버전 까지는 몰라도 엔진 버전은 강좌로서 진행하기엔 엔진에 대한 제 이해도가 많이 낮은 편이라 강좌라고 할 수 있는게 나와줄지, 조금 의문의문 합니다.

그럼, 계속해서 잘 부탁드리겠습니다.




※ ANC_LEFT, CENTER, RIGHT의 의미

덧글

  • 하얀삼치 2013/12/12 17:54 # 답글

    와! 완결이군요! 정말 잘 봤습니다. ^^ 고생하셨어요!
  • 펭귄대왕 2013/12/13 05:22 #

    감사합니다. 보아주신 분들께 조금이라도 도움이 되었다면 기쁘겠습니다.
  • 군중속1인 2013/12/13 16:19 # 답글

    오오 저도 참고하면서 공부중입니다 :)
  • 펭귄대왕 2013/12/14 05:42 #

    개발을 야매로 배운지라 기초가 부족함을 항상 한탄합니다. 열심히 공부하시길..! ^_^
  • 슈크렐 2013/12/20 07:22 # 답글

    잘 봤습니다, 이제서야 봤네요 (...)
    으으 공부해야 하는데
  • 펭귄대왕 2013/12/20 09:09 #

    저도 어떻게든 없는 틈이라도 만들어서 책 한줄이라도 더 봐야 할텐데 쉽지가 않네요 ^_^;
  • 백수 2013/12/22 11:10 # 삭제 답글

    혹시 이 프로그램 안드로이드로 바꾸는 방법 혹시 아시나여?
  • 펭귄대왕 2013/12/22 14:22 #

    차후에 별도 포스팅으로 정리할 예정이지만
    http://icegeo.egloos.com/277711

    이 포스팅에 첨부된 프로젝트를 참조해 보시기 바랍니다.
    어플리케이션 버전과 가급적 같은 구조를 유지하면서 안드로이드용 SurfaceView로 구현하고 있습니다.

    중간단계에서 포팅한거라 모든 내용이 옮겨져 있지는 않습니다.
  • RedPumpkin 2014/05/06 20:53 # 삭제 답글

    setFocusable( false );
    이걸 게임캔버스의 생성자에 넣어주면 캔버스가 포커스를 받지 않아요.
  • 펭귄대왕 2014/05/06 23:29 #

    테스트해보고 소스/본문에 반영하도록 하겠습니다. 도움말씀 감사합니다.
  • 님프 2014/09/18 21:54 # 삭제 답글

    펭귄대왕님 질문있습니다.
    1. ANC_RIGHT가 지금 어떻게 동작하는지 모르겠습니다. 결과씬에서 변수들이 전부 RIGHT로 되어 있는데, LEFT로 바꾸면 전부 오른쪽으로 붙어버리고.. 게임씬에서도 스코어 점수도 RIGHT로 되어있는데 LEFT로 바꾸면 또 오른쪽으로 붙더라구요. 제가 생각하는 LEFT와 RIGHT의 개념이 아니라서 지금 헷갈립니다..ㅠ

    2. 게임씬에서 리네짱을 출력할 때도 LEFT로 하셨는데 RIGHT로 바꾸면 또 따로 노네요.. 원래 LEFT로 하면 계살될 때 빼주는 값이 0이라서 그대로 하신 것 같은데 ,, LEFT와 RIGHT를 모르겠어요.. 이게 무슨 의미인지 모르겠습니다.

    3. 드로우넘 함수가 이해가 안갑니다.. substring이 쓰이는데 .. 이게 어떻게 이렇게 이렇게 되는지 잘 이해가 안갑니다. ㅠ.ㅠ

    4. 아 그리고 게임씬에서 process로 충돌 범위 Rectangle 지정해주는데,, 그 숫자들 넣어도 범위를 확인할 수 없는데.. 어떻게 하신거죠..?.. 픽셀로 따신건가요..?

    부탁드려요.. 펭귄님!!!
  • 펭귄대왕 2014/09/18 22:19 #

    이 포스팅 맨 마지막에 추가한 이미지를 봐 주세요.
    ANC란 anchor.. 이미지의 축을 설정해 주는 것입니다.
    지정한 좌표에 이미지를 출력할 때, 이미지의 어느 부분이 해당 좌표의 위치가 되는가? 하는 것인데요,
    ANC_LEFT, CENTER, RIGHT는 각각 위 이미지처럼 왼쪽, 가운데, 오른쪽을 축으로 하게 됩니다.

    그때문에 ANC_LEFT를 지정하면 지정 좌표보다 그림이 오른쪽으로 쏠려서 보이게 됩니다.

    "0000000000".substring(0, digit-valueStr.length()) + valueStr
    이것은 숫자의 자리수가 지정한 자리수(digit)보다 짧으면 숫자 앞쪽에 0을 붙여주기 위한 것입니다.
    예를 들어 점수를 여덟자리로 표시하려고 하는데 받은 숫자가 12345라면, 00012345 이런 식으로 되도록.

    digit가 지정한 자리수이고 (예를 들면 8)
    valueStr은 받은 값(value)을 문자열로 바꾼 것이죠, 이 예에서는 "12345"가 되겠네요.
    그럼 "0000000000".substring(0, 8-"12345".length())
    이렇게 되는데, "12345".length()는 5니까 8-5=3
    문자열 "0000000000"을 맨 앞(0)에서 세 글자 자르라는 것이 됩니다.
    이 결과는 "000"이 되고 여기 다시 "12345"를 붙여주니까 "00012345"가 됩니다.

    Rectangle 지정 값은, 해당 이미지 안에서의 픽셀 좌표와 사각형의 크기-픽셀 단위-를 지정하고 있는 것입니다.
    Rectangle(39,49, 44,258) 라고 하면, 이미지의 왼쪽 위를 0,0이라고 봤을 때, 39, 49 위치에서 가로로 44픽셀, 세로로 258픽셀의 영역입니다.

    Enemy class의 draw 함수 안에

    gContext.setColor(Color.RED);
    gContext.drawRect(x+rect.x, y+rect.y, rect.width, rect.height);

    위 두 줄을 넣어주면, 적 캐릭터의 충돌 범위에 해당하는 사각형이 표시됩니다. 다른 클래스의 draw에 넣어봐도 됩니다.
  • 님프 2014/09/18 22:40 # 삭제 답글

    감사합니다~! 전부 이해갔는데요.
    anchor가 굳이 필요한가라는 생각이 들어요. 어차피 좌표 설정으로 해줄꺼면 어떻게든 해도 되는게 아닌가 싶어서...
    게임씬 score 부분에서도 좌표를 2, 39로 놓고 엥크_LEFT로 놓아도 ... 똑같은게 아닌가 해서 ...
  • 펭귄대왕 2014/09/19 04:51 #

    여기서는 그렇게 큰 의미가 없지만 화면 디자인 할 때의 편의라던가-문자열을 정렬하기 위한 좌표를 뽑을 때 등-에 도움이 됩니다.

    예를 들어 게임의 그래픽 영역이 480*800일 때, 점수를 화면 중앙에 정렬해서 뿌려줄 생각인데 이때 앵커를 중앙 맞춤으로 적용하면 점수의 출력 가로 좌표가 240(가로 영역의 정확히 반)이라고 하면 쉽게 나오는데, 앵커가 없거나 앵커가 왼맞춤이면 숫자 1글자 폭의 반 만큼 240보다 왼쪽으로 이동시켜서 출력해 줘야죠.

    이 게임에서는 쓰이지 않지만, 이번같은 상자충돌이 아닌 원 충돌을 적용하거나, 이미지의 회전을 지원하는 환경에서도 앵커가 중요하게 쓰입니다.
  • 님프 2014/09/23 20:06 # 삭제 답글

    펭귄님 안녕하세요. 질문이 있습니다!

    요시카 스크램블처럼 몬스터에도 움짐임을 주고 총알을 주고 싶은데
    음.. 이게 base가 다르다고 해야하나...? 좀 그렇네요.. ㅠㅠ
    막 섞어서 하려는데 생각보다 잘 안됩니다.. ㅠ
    어떤식으로 해야할까요;.. 리네짱한테도 life를 줘야겠는데..이ㅠ
  • 펭귄대왕 2014/09/24 04:28 #

    어떻게 움직일지 구체적으로 생각하고,
    그 움직임을 논리구조를 가진 문장으로 바꾼 다음에,
    이걸 Enemy 클래스의 process 내에 코드로 만들어 넣으면 됩니다.

    이건 기술적인게 아니고 게임 내용을 구체적인 문장과 논리로 설계할 수 있느냐의 문제니까 그쪽으로 생각해야 됩니다.
  • 님프 2014/09/24 16:50 # 삭제 답글

    감사합니다~!
    Enemy 클래스에 process로 넣으면 할 수 있을 것 같아요! 논리 설계만 잘 하면 될듯합니다 ㅎ~!
  • 노래 2014/10/03 17:06 # 삭제 답글

    질문이요! 만약 게임에 배경음을 넣을려면 어떤 명령어를 추가해야 하죠?
  • 펭귄대왕 2014/10/03 18:22 #

    http://icegeo.egloos.com/274353

    자바 awt에서 사운드 추가는 난관이 많습니다. mp3 등을 재생하려면 javax.swing을 사용하거나, 이걸 사용한 외부 라이브러리를 추가해야 하기 때문에 거기까지는 다루지 않았습니다.
  • 프레스코 2017/10/14 13:27 # 삭제 답글

    안녕하세요 자바 공부하고있는학생입니다. 이번에 비행기 게임을 만들려고하는데 제가 추가하고싶은 아이디어가 몇가지있습니다. 아이템 기능을 추가하고싶은데...
    예를들어 기름통이나 탄창 등을 먹어야지만 공격이 가능하게끔 만들고싶은데 어떤 명령어를 써야할지 모르겠는데 알려주실수있나요?
  • 펭귄대왕 2017/10/14 13:55 #

    특정한 명령어가 있는 건 아니고, 기본적인 연산과 제어문들을 조합하면 만들 수 있습니다.
    구체적인 설계의 예를 들어보겠습니다.

    (1)총알(BULLET)이 없으면 총을 쏠 수 없다.
    (2)총알은 최초에 100을 갖고 시작한다.
    (3)총알 아이템을 먹으면 총알(BULLET) 50을 얻을 수 있다.
    (4)총을 한 번 쏠 때마다 BULLET은 1씩 줄어든다.

    이정도가 기본적인 시나리오가 되겠네요. 그럼 각각을 구현해 보면

    적절한 위치에
    int _bullet = 100;
    을 선언해주고,

    총을 쏘는 부분에서 if(_bullet > 0) 으로 제어를 추가하고,

    new Bullet으로 총알을 생성한 후 _bullet--; 로 총알을 차감합니다.

    아이템을 생성하는 부분에서, 아이템의 속성(itemkind)에 총알을 추가하고 (itemkind = 4;)
    아이템 취득을 판정하는 부분에서 itemkind가 4이면 총알 아이템으로 판정, _bullet += 50; 해 줍니다.

    이렇게 하고, 총알 아이템의 그림과, 남은 총알 수를 표시해주는 UI를 추가해주면 되겠네요.

    단, 총알이 없으면 적을 공격할 수 없고, 적을 격파하지 못하면 아이템도 나오지 않으니 그 부분은 게임 규칙의 측면에서 조금 생각해보면 되겠습니다.
  • 프레스코 2017/10/15 14:45 # 삭제 답글

    감사합니다. 친절하게 잘 알려주시네요^^ 덕분에 많이 공부하게 되었습니다.!!
  • 펭귄대왕 2017/10/16 12:01 #

    또 물어보실것이 있다면 주저말고 적어주세요. 변변찮은 실력이지만 도움이 되면 좋겠습니다.
  • 프레스코 2017/10/18 00:06 # 삭제 답글

    안녕하세요!! 갑자기 궁금한점이 생겨서 질문드립니다!!
    지금 게임플레이 시점이 위에서 아래로 보는 2d형식의 시점인데
    시점을 1인칭시점으로 바라보는건 자바에서 구현이 안되는걸까요??
    조종석에서 유리창을 바라보는시점같이 구현해보고싶은데요.
    이미지로만은 구현이 힘들겠죠?
  • 펭귄대왕 2017/10/18 08:24 #

    java 3D도 있긴 하지만 거기까지는 제가 다루지는 못하고요,

    고전 게임처럼 일반 그림의 확대축소를 이용해서 유사 3D형태로 만드는 방법 정도는 가능할듯 합니다.
    https://www.youtube.com/watch?v=n9dPtH75BAI
    https://www.youtube.com/watch?v=Ssr-6GLKtOo
    아마 이런 느낌 비슷한 게임들을 만들 수 있겠네요.

    자바에서 그림의 확대 축소는
    http://icegeo.egloos.com/300628
    이쪽을 참고해주세요
  • 프레스코 2017/10/19 23:20 # 삭제 답글

    초보자라 그런지 저부분까지는 너무 어렵네요..ㅎㅎ
댓글 입력 영역
* 비로그인 덧글의 IP 전체보기를 설정한 이글루입니다.