자바 게임 프로그래밍 강좌 5
하이텔 자바 동호회 김명현 (MadOx@hitel.net)님의 글입니다.
이글은 김명현님의 동의없이 함부로 배포하실 수 없습니다.
안녕하세요? 강좌가 좀 늦었습니다. 주말에는 개인적인 일로 무척 바빴습니 다. 그래서 강좌가 늦어진거죠. 이번 강좌는 스프라이트와 키보드 처리에 관련된 내용입니다. 키보드나 마우스 처리는 JDK1.0.x대와 1.1.x대 에서 차 이가 나는 부분이므로, 테스트는 해보지 않았으나, 문제가 발생할 소지가 다분히 있습니다. 될 수 있으면 자료실에 있는 JDK1.0.2 를 사용 하시는 것 이 좋을 것입니다. 만약에 원인모를 이유로 애플릿이 정상 작동 안된다면, 십중 팔구 JDK1.0.x와 JDK1.1.x의 이벤트 처리방식의 차이 때문일 것입니다 * 본 문서는 Java Development Kit 1.0.2 를 기준으로 작성되었습니다. * Java Development Kit 1.1.x 버젼을 사용할 경우 일부 소스가 실행이 되지 않을 수 있습니다. 2.3 스프라이트는 어떻게 처리하나요? 게임에서 스프라이트의 처리는 거의 필수적입니다. (스프라이트라는 것은 배경을 파손하지 않고 이동하는 이미지를 뜻합니다. 게임기나 8Bit MSX등에 서는 스프라이트를 처리하기 위해 VDP 라고 하는 칩들이 있고, 이들이 독립 적으로 스프라이트들을 관리하며 배경 손상없이 이동을 가능하게 해줍니다. 하지만 PC나 SUN Sparc 등의 컴퓨터에서는 VDP가 따로 존재하지 않고, 대부 분의 VGA 나 그래픽 카드들이 스프라이트를 독립적으로 관리해 주지 않으므 로, 일일이 프로그램으로 배경복구를 해줘야 합니다.) Java 는 스프라이트 관련 메소드를 지원하지 않습니다. 그런데 어떻게 스프라이트를 지원하느냐 구요? 그것은 앞서 배운 DoubleBuffering기법을 이용하면 간단히 해결 됩니 다. 배경을 복구하는 작업과 스프라이트를 다른 곳으로 이동시키는 작업을 우리의 눈에 보이지 않는 메모리 버퍼내에서 하게 되므로 게임을 즐기는 플 레이어 입장에서는 하드웨어 스프라이트와 별반 차이를 느끼지 못하게 됩니 다. ● 투명색의 구현 우선 지난 강좌의 [소스4] CutBitmap.java 를 실행하여 보십시오. 잘려진 빨강, 녹색, 파랑 3개의 공이 따로따로 아래에 그려져 있을 것입니다. 그런 데 원래그림의 흰색 배경도 함께 짤려져 공이 아니라 마치 스케치북에 그린 그림조각 같아 보일 것입니다. 실제 게임에서도 캐릭터가 사각형의 배경에 갖혀서 돌아 다니는 것을 여러분은 원하지 않을 것입니다. 그런데 CropIma- geFilter에 의해 짤려지는 그림은 어짜피 사각형이므로 동그랗게 공을 짤라 낼 수는 없습니다. 셀 애니메이션(Cell Animation)에서는 그림을 투명한 셀 로판지위에 그리고, 그것을 배경위에 놓아서 애니메이션을 구현합니다. Ja- va에서도 마찬가지로, 흰색 바탕이 투명한 색이라면 사각형으로 잘려지더라 도 큰 문제는 없을 듯 합니다. (실제 그림은 사각형이지만, 투명한 영역은 뒷부분의 배경이 보이게 되므로, 그림이 폐곡선 형태인것 처럼 보이게 될껍 니다.) Java는 GIF89a형식을 지원합니다. GIF89a는 발전된 GIF로써 투명색이라는 것을 지원하고 있습니다. Java프로그램에서는 투명색을 위해 아무것도 해줄 것이 없습니다. 단순히 이미지 파일내의 바탕색을 투명색으로 지정해 주는 것만으로 투명색 구현을 할 수 있는 것입니다. 앞 절에서 만들었던 CutImage애플릿에 사용되는 이미지는 "Ball.GIF"입니 다. 이 이미지를 GIF89a형식으로 바꾸고, 투명색을 지정해 보겠습니다. ◇ 투명색을 지원하는 유틸리티들 GIF89a형식에서 투명색을 지원하는 유틸리티는 여러가지가 있습니다. 이들 중에서 우리가 사용할 것은 "GIFTRANS.EXE"라고 하는 프로그램 입 니다. 사용방법을 배워 봅시다. (이것 외에도 LViewPro, GifConstruct- on Kit, PhotoShop등 많은 유틸리티가 투명GIF를 지원합니다.) ① 투명색으로 선정할 색깔의 번호를 알아낸다 먼저 "GIFTRANS.EXE" 를 이용해 투명색으로 만들 색깔의 번호를 알아 내야 합니다. "Ball.GIF"에서 투명색은 완전한 흰색으로 (RGB농도가 각 각 255, 255, 255)입니다. "GIFTRANS.EXE"에서 색상리스트를 보는 옵션 은 '-l'입니다. <실행의 예> C:\JavaGame>GIFTRANS.EXE -l BALL.GIF Global Color Table: Color 0: Red 255, Green 255, Blue 255, #ffffff Color 1: Red 199, Green 43, Blue 43, #c72b2b Color 2: Red 199, Green 43, Blue 87, #c72b57 Color 3: Red 199, Green 43, Blue 131, #c72b83 Color 4: Red 199, Green 43, Blue 175, #c72baf Color 5: Red 179, Green 43, Blue 199, #b32bc7 . . . Color 250: Red 170, Green 0, Blue 170, #aa00aa Color 251: Red 170, Green 0, Blue 0, #aa0000 Color 252: Red 0, Green 170, Blue 170, #00aaaa Color 253: Red 0, Green 170, Blue 0, #00aa00 Color 254: Red 0, Green 0, Blue 170, #0000aa Color 255: Red 0, Green 0, Blue 0, #000000 실행 결과로 색번호와 RGB농도가 출력됩니다. 그런데 너무 빨리 지나 가서 제대로 알아 볼 수가 없을 것입니다. "GIFTRANS.EXE" 는 Color T- able List를 표준에러 스트림으로 출력합니다. 이것을 파일로 저장하는 방법은 "-e 출력파일명"옵션을 주면 됩니다. 위의 컬러 테이블에서 0번 색깔의 RGB 농도가 255, 255, 255로 "Ball.GIF"의 배경색임을 알 수 있 습니다. ② 투명색 처리를 한다 이제 투명색으로 만들 색번호를 알아냈으니 투명색 처리를 하도록 하 겠습니다. "GIFTRANS.EXE"는 원본 이미지를 GIF89a로 바꾼 내용을 표준 출력 스트림으로 출력합니다. (MS-DOS에서 표준 출력은 화면이므로, 화 면에 변환된 내용들이 주욱 나올것입니다.) "-o 출력파일명" 옵션으로 표준 출력을 파일로 보낼 수 있습니다. <실행의 예> C:\JavaGame>GIFTRANS.EXE -t 0 -o Ball2.GIF Ball.GIF -t 0 : 0번색을 투명색으로 지정한다 -o Ball2.GIF : 표준출력(GIF89a로 변환된 내용)을 Ball2.GIF로 출력 Ball.GIF : 원본 이미지의 파일명 변환이 끝났습니다. 디렉토리의 내용을 살펴보면 "Ball2.GIF"가 생성 되어 있을것입니다. 이 이미지의 이름을 "Ball.GIF" 로 바꾸고 바로 앞 절에서 만든 [소스4] CutBitmap.java 를 실행해 보십시오. 그림의 바깥 쪽 흰색 테두리가 없어진 것을 확인하실수 있을 것입니다. 시간이 된다 면 Tag에 배경그림을 다른것으로 줘서 실제 뒷 배경을 파손하지 않는지 테스트 해보셔도 좋을것입니다. 3. 그림을 마음대로 움직여 볼까요? 이번 절에서는 지금까지 배워온 기법들에 덧붙여 화면상의 그림을 마음대 로 움직일 수 있는 기법을 배우게될 것입니다. Java에서 사용가능한 입력장 치는 키보드, 마우스 두가지 입니다. 불행이도 게임패드, 죠이스틱은 아직 지원하지를 않습니다. 3.1 애플릿에서 키보드는 어떻게 처리합니까? GUI 환경의 운영체제에서 사용자가 할 수 있는 일은 무척 많습니다. 윈도 우상에 존재하는 각종 버튼을 누를수도 있을 것이고, 키보드를 직접 누를수 도 있을 것이고, 아예 윈도우를 닫아버릴수도 있을 것입니다. 이런 사용자 의 행동을 응용프로그램이 직접 체크를 한다면 응용프로그램을 만드는 일이 무척 고역일 것입니다. 어떤 사람이 어떤 행동을 취할지 일일히 경우의 수 를 따져 프로그램하기란 여간 힘든일이 아닐테니까요. MS-Windows를 비롯한 대부분의 GUI 운영체제들은 사용자들의 행동을 감시 하고, 친절하게 이들의 행동을 응용 프로그램에게 통보해 줍니다. 덕분에 응용프로그램들은 일일이 사용자들의 행동을 체크할 필요가 없습니다. 이때 운영체제로 부터 응용프로그램으로 통보되는 내용을 메시지(Message) 또는 이벤트(event)라고 부릅니다. 응용 프로그램에서는 각각의 이벤트에 대한 핸들러(Handler : 해당 이벤트를 처리하기 위한 메소드)를 만들어 줌으로써 사용자의 요구를 수용할 수 있게 되는 것입니다. 예를 들어 사용자가 윈도 우를 Minimize 시킨후 다시 이를 원래 크기로 환원시켰다면, OS 는 응용 프 로그램에게 '윈도우의 내용을 다시 그리시오' 라고 'repaint' 이벤트를 발 생시키고 통보를 할 것입니다. 응용 프로그램은 repaint이벤트에 대한 핸들 러로 paint메소드를 가지고 있으므로 paint 메소드를 실행해 윈도우의 내용 을 다시 그리게 되고 우리는 정상적인 화면을 볼 수 있게 되는 것입니다. 'repaint'이벤트와 마찬가지로 사용자가 키보드를 눌렀을때에도 이벤트가 발생되고, 해당 응용 프로그램으로 OS가 통보합니다. 3.1.1 키보드에서 발생할 수 있는 이벤트의 종류는? 키보드에서 발생할 수 있는 이벤트는 두 가지 입니다. 우리가 키를 누를 때 KeyDown 이벤트가 발생되고 눌렀던 키를 놓을 때 KeyUp 이벤트가 발생되 어 현재 포커스(focus)를 가지고 있는 Component(거의 모든 AWT요소들의 최 상위 클래스입니다)에게 통보됩니다. 각각의 이벤트에 대해서 Component 는 해당 이벤트를 처리하기 위한 메소 드를 제공 하는데, KeyDown 이벤트에는 keyDown 메소드, KeyUp 이벤트에는 keyUp메소드가 불려지게 됩니다. 이 두 개의 메소드는 Component 클래스에 다음과 같이 정의되어 있습니다. public boolean keyDown(Event evt, int key); public boolean keyUp(Event evt, int key); [표1] 키보드 이벤트 처리 핸들러 기본적으로 위의 두 메소드는 별다른 일을 하지 않도록 정의 되어 있으므 로, 우리는 paint 메소드들 다시 정의한 것처럼 이 메소드들을 다시 정의함 으로써 원하는 일을 할 수 있을 것입니다. 3.1.2 키코드를 출력해주는 프로그램을 만들어 봅시다. 키보드 처리를 하는 방법을 연습하기 위해 간단히 키를 누르면 해당 키의 코드 값을 출력해주는 애플릿을 만들어 보도록 합시다. 게임에서 사용되는 각종 키들의 코드 값을 알아내는데 사용할 것이므로 꼭 필요한 유틸리티 입 니다. 01: import java.awt.*; 02: import java.applet.*; 03: 04: public class ReadKeyCode extends Applet 05: { 06: private String strMsg; // 출력할 메시지를 담을 변수 07: 08: public void start() 09: { 10: // 처음에는 아무것도 안눌려졌음 11: strMsg = "No key pressed"; 12: } 13: 14: public void paint(Graphics g) 15: { 16: // 화면에 메시지 출력 17: g.drawString(strMsg, 10, 45); 18: } 19: 20: public boolean keyDown(Event e, int key) 21: { 22: // 눌려진 키값을 출력하기 위해 문자열을 만들고 23: strMsg = "Key code is (" + key + ")"; 24: // 화면 갱신 25: repaint(); 26: return true; // 처리 완료! 27: } 28: 29: public boolean keyUp(Event e, int key) 30: { 31: // 키보드에서 손을 뗏으므로 아무것도 안눌려졌음 32: strMsg = "No key pressed"; 33: // 화면 갱신 34: repaint(); 35: return true; // 처리 완료! 36: } 37: } [소스1] ReadKeyCode.java ReadKeyCode 애플릿을 실행해 봅시다. 화면 중앙에 "No key pressed"라는 메시지가 나와 있을 것입니다. 그런데 키보드를 누르면 키 값이 화면에 "K- ey code is (xxx)" 식으로 출력 되어야 될것인데 이상하게도 아무런 반응이 없습니다. 이유는 Web Browser나 AppletViewer가 Focus를 가지고 있기 때문 입니다. 다른 이벤트와는 달리 키보드 이벤트는 Focus를 가지고 있는 윈도 우에게만 전달 됩니다. 때문에 우리가 누른 키보드에 대한 이벤트는 ReadK- eyCode 애플릿이 가져간 것이 아니라 Web Browser나 AppletViewer가 가져간 것이므로, 애플릿은 아무 반응이 없는 것입니다. 마우스커서를 애플릿 영역 으로 옮긴후 한 번 클릭을 해줘서 애플릿이 Focus를 가지게 한 후 키보드를 눌러봅시다. 제대로 하셨다면 우리가 누른 키보드에 대한 코드가 디스플레 이 될 것입니다. 그렇다면 키보드 입력을 받는 모든 애플릿에서 매번 마우 스로 한 번 클릭을 한 후 사용해야 할까요? 그렇지는 않습니다. Component 객체의 메소드중 requestFocus() 라고 하는 메소드가 있는데, 이 메소드를 start()메소드 등에서 한 번 실행해 주면 현재 Focus가 Web Browser나 App- letViewer에서 애플릿으로 넘어가게 됩니다.
'자바 > 자바게임' 카테고리의 다른 글
자바프로그래밍#6 (0) | 2010.10.28 |
---|---|
자바게임프로그래밍#4 (0) | 2010.10.28 |
자바게임프로그래밍#3 (0) | 2010.10.28 |
자바게임프로그래밍#2 (1) | 2010.10.28 |
자바게임프로그래밍#1 (1) | 2010.10.28 |