adsense



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

4. 게임 결과 화면 ResultScene.java


게임이 끝났으니 자신이 플레이한 결과를 정리해서 보여주는 화면을 출력합니다.


득점, 비행 거리, 득점+비행거리를 합산한 총점, 이번 게임차에 획득한 골드를 보여줍니다.
그리고, 총점이 기존의 최고 기록을 넘어섰다면 '참 잘했어요' 도장을 찍어줍니다.





GameResult.zip 이클립스 프로젝트 다운받기



그냥 이것만 보여주면 재미없으니 약간 동적으로 만들어보겠습니다.


득점->거리->총점->골드 순으로 숫자가 도르륵 올라가서 보여주고,
최고기록을 달성했다면 총점 자리에 스탬프 그림이 생깁니다.


이후에 키가 입력되면 타이틀 화면으로 바뀝니다.

(이런 동선 설계도 게임 시나리오의 일종입니다)


- scenes에 ResultScene.java를 추가합니다.
- 다른 화면과 마찬가지로 GameCanvas를 상속하고, 기초 함수를 오버라이드합니다.
- initImage와 releaseImage에 rsc/result 폴더의 그림 두 장을 초기화/해제하도록 합니다.


- 기존 GameScene에서, 게임 오버되면 타이틀화면으로 돌아가던 부분을 ResultScene으로 변경합니다.


그럼 이제 점수들을 표시해줘야 하는데..


기존에 GameScene에서 처리하던게 GameScene의 클래스 변수죠.
그래서는 이 값을 ResultScene에 전달할 수 없으니, 기존 점수 관련 변수를 GameManager 하에 위치하도록 수정합니다.
_score, _gold, _range가 되겠네요.


그런데 이미 기존에 만들어 놓은 것에서, manager._score 이런 식으로 수정해주자니 귀찮습니다.


그래서 GameManager에 따로 선언하고,
//결과화면에서 보여주기 위한 공용값
public int _getScore;
public int _getRange;
public int _getGold;


ResultScene으로 전환하기 전에
manager._score = _score;
식으로 전달해줍니다.


변수를 적게 쓰는게 좋지 않는가. 하는 점에서는 약간의 수고를 감수하는 것도 좋겠지만요.



올라가는 숫자를 보여주기


가장 일반적인 것은, 일정 값만큼 더해서 획득한 값까지 보여주는 방법인데, 점수가 너무 작거나 너무 크면 시간 차이가 커집니다.


그때문에 여기서는 루프 횟수를 사전에 전해서, 단위 값 만큼 보여주는 방법을 씁니다.
각 숫자를 20으로 나눠서 20프레임동안 보여줄 것입니다.


이 값을 화면 생성 초기-SceneStart에서 작성해 줍니다.


viewScore[0] = (float)manager._getScore/20.0f;
viewScore[1] = (float)manager._getRange/20.0f;
viewScore[2] = (float)totalScore/20.0f;
viewScore[3] = (float)manager._getGold/20.0f;


그리고 해당 프레임 간격이 되면 이 숫자들을 보여줍니다.
점수 보여주기 부분의 예입니다. 다른 숫자들도 처리 방식은 대동소이합니다.


//점수 보여주기 (20~40 프레임)
if(cnt>=40)//40 프레임 이상이 되면 최종값만 지속적으로 보여준다
 manager.drawnum(gContext, numpic, 328, 257, manager._getScore, 8, manager.ANC_RIGHT);
else if(20<=cnt&&cnt<40)//20~40 프레임 사이에는 변동값만 보여준다
 manager.drawnum(gContext, numpic, 328, 257, (int)((cnt-20) * viewScore[0]), 8, manager.ANC_RIGHT);
else//자기 차례가 아니라면 0만 보여준다
 manager.drawnum(gContext, numpic, 328, 257, 0, 8, manager.ANC_RIGHT);


최종값만 보여주는 부분 때문에, 중간값과 관계없이 최종값은 정상적인 값이 보여줍니다. 중간값은 어디까지나 일종의 눈속임.


그리고 모든 단계가 끝나고(cnt>=110), 최고기록 갱신 플래그가 켜져있으면 스탬프를 찍어줍니다.
뭔가 효과음으로 '퉁!' 소리가 나야 할 것 같은 느낌. 음악과 효과음은, 안드로이드 버전으로 예약해두겠습니다.


참고로, 이 시퀀스가 끝날 때까지 키 입력 처리를 막고 있는 부분도 참조해 주세요.
키를 막고 있는 동안 키를 연타해도 키 버퍼가 쌓이지 않도록 하는 방법이 나와 있습니다. 



마지막으로, 지금까지 획득한 점수를 저장하겠습니다.
GameManager에 LoadGame, SaveGame 함수를 만들었습니다.



흔히 보는 파일 입출력입니다.
SaveGame ~ 쓰기에서는 BufferedWriter와 write를 사용해 "wflight"란 파일에 값을 저장하고
LoadGame ~ 읽기에서는 BufferedReader와 readLine을 사용해 값을 불러옵니다.


LoadGame은 프로그램 시작 초반에, SaveGame은 결과 화면의 초반에 각각 호출합니다.
LoadGame을 부르는 부분은 GameManager에 있고, SaveGame을 부르는 부분은 ResultScene에 있습니다.



작동은 잘 됩니다만.. 뭔가 켕깁니다.



예, 세이브 파일을 열어보면 데이터가 그냥 훤히 보입니다.


이건 샘플게임이니까 괜찮습니다만, 일반에 공개하거나 리더보드 기능을 탑재하는 게임이라면? 당연 이렇게 간단히 데이터가 노출/조작 가능해서는 안됩니다.

인앱도 없고 이벤트거는 것도 없다고 방심했더니 런칭 첫날 곧바로 조작데이터부터 날라들어오기에 부랴부랴 패치한 케이스.
게임 이렇게 해야겠습니까..


그렇기 때문에 상용 게임에서는 세이브/로드 파일을 바이너리 파일로 만들고, 여기 암호화된 정보를 격납합니다.
간이 db를 쓰는 경우도 있는데, 속도와 플랫폼 문제로 개인적으로는 권하지 않는 방법입니다. (근데 의외로 많이들 쓰시는 듯..)


스탠드 얼론 게임의 게임 데이터 보안에 관해서는 다음 기회에 다루도록 하고, 이번에는 여기서 마치겠습니다.

 


아아, 원래 계획은 여기서 피날레였습니다만,


이만큼 했으니까 뭔가 마지막으로 해 보고 싶은게 있지 않겠습니까?


다음 강좌로 위치즈 플라이트 드디어 마지막.


타이틀 화면의 개선, 그리고 기왕 모은 골드, 씁니다! 총알의 파워 업!

그리고, 파괴 불능 오브젝트. 드○○○라○트의 운석같은 존재를 구현하겠습니다.


(※단, 다음 파트는 조금 늦어질지도 모르겠습니다..)




덧글

  • 안녕하세요 2015/10/15 22:15 # 삭제 답글

    결과창이미지에서 캐릭터만 지우고 사용해도될까요?
  • 펭귄대왕 2015/10/16 02:06 #

    상관없습니다. 단순한 이미지니까 그냥 하나 그리는게 더 빠르지 않을까 싶긴 하지만요.
댓글 입력 영역


Books

Geek라이프

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

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

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

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