5.6 암호를 입력해 보물상자를 열어요 - 입출력
우리는 지난 장들에서 마우스 입력(drag, click 등)에 대해서는 충분히 사용해 보았다. 이번 장에서는 이 장의 제목답게 처음으로 키보드 입력처리에 대해 살펴볼 것이고, 처음으로 게임의 흥미를 더하기 위해 효과음 파일을 사용해 사운드를 출력하는 방법도 배울 것이다.
여러분들은 앞선 5개의 예제를 해결해봤기 때문에 이제 더이상 파이게임제로의 왕초보라고 말할 순 없겠다. 이제 남은 예제 2개 정도는 코드 하단의 설명을 곧바로 보기보다 먼저 전체코드들을 눈으로 이해할 수 있는 수준까지 최대한 이해해 보도록 노력해보자. 그리고나서 하단의 코드설명을 보는 순서로의 진행을 도전해 보자. 앞으로도 이런 식의 공부가 여러분들의 실력을 키우는 길이다. 여러분들도 경험상 잘 아시겠지만, 빠른 답은 결코 우리의 생각이 자라날 기회는 주지 못하기 때문이다.
🔢 먼저 이번 코드에서 여러차례 사용되었던 Rect라는 것에 대해 알아보자. 대문자로 시작하는 것으로 보아, Rect 는 오브젝트라는 것을 알 수 있다. Rect 는 Rectangle 의 약자로 사각형 모양의 영역을 붙잡고 있는 오브젝트로 게임이란 무대에서 등장하는 대부분은 기본적으로 사각형 모양을 갖는 객체이기 때문에, 이 Rect의 활용이 두들어 진다고 할 수 있다. 만드는 법은 4개(left, top, width, height) 의 인자값으로 사각의 영역을 나타내는데, 앞에 두 값(left, top)은 좌상단 좌표값으로 화면상에 사각영역이 시작하는 시작위치를 나타내는 것이고, 뒤에 두 값(width, height)은 가로길이와 세로길이로 이 값들은 그 영역의 크기를 정하게 된다.
우리는 과거에 이 예제를 이미 엔트리를 통해 만들어 봤기 때문에 이 예제는 사용자와 텍스트적인 인터렉션이 있다는 것을 알 수 있다. 보물상자를 열기 위해 비밀번호를 입력할 것을 안내할 것이고, 입력된 비밀번호가 맞는지의 유무에 따라 최종 보물을 갖게 되었는지/실패했는지를 소리와 함께 텍스트로도 보여주게 된다. 그래서, 우리는 이 예제에 두 개의 Rect 가 필요한데 한 개는 사용자로부터 비밀번호 입력받게 될 사각형의 입력란(input_rect)에서 사용하고, 나머지 하나는 사용자에게 어떤 행동을 지시하거나 결과를 가이드 하는 용도의 텍스트를 출력하는 영역(guide_rect)으로서 사용하게 된다.
🔢 10번 라인의 input_done 변수는 아래의 참고사항에 언급된 플래그 변수이고, 저장되는 값은 참(True)/거짓(Faluse) 둘 중에 하나의 값을 저장한다.
플래그(flag) 변수: 프로그래밍에서 코드간의 상태전달을 알리기 위해 사용하는 참(True)과 거짓(Faluse) 또는 0과 1의 이진값(boolean)을 갖는 변수
사실 플래그 변수는 이번에 처음 등장한 것은 아니고, 이미 5.3 장의 예제에서부터 계속 등장해오고 있다. 주로 마우스, 키보드의 입력처리를 하는 과정에서 사용하는데 입력장치에서 입력이 끝난 시점에 대한 것을 판단하기 위한 목적에서 사용하였다. input_done 이 참(True)값이 되는 시점은 언제인가? 51번 라인에서 참(True)값을 저장하고 있는데, 바로 비밀번호 숫자 입력 후 엔터키를 눌러 비밀번호 입력을 최종 끝낸시점인 것이다. draw 함수에서는 22번 라인에서 이 input_done의 값이 참(True)인 시점을 기준으로 비밀번호를 맞췄는지/틀렸는지에 대한 결과처리를 하고 있는 것이다.
원래 플래그 변수를 많이 사용하는 코딩스타일은 일반적으로 추천되지는 않는다. 플래그 변수를 많이 사용하면 할 수록 코드의 복잡도가 증가하기 때문인데 이는 코드유지보수 측면에서 불리하기 때문이다. 그러나, 파이게임제로 라이브러리 같은 거대게임루프(loop)와 콜백함수를 주로 사용하는 구조에서는 그 사용이 불가피한 면이 있다는 점을 이해하고 있으면 좋을 것 같다.
🔢 24, 26, 31번 라인의 screen.draw.textbox 메소드를 살펴보자. 이전 장에서 살펴 본 screen.draw.text 와 크게 다르지 않다. 메소드 호출에 사용된 인자값들을 비교해 보면 좋을 것 같은데 텍스트 내용이 출력되어야 할 영역을 Rect를 사용해서 제공하고 있다. draw 메소드에서 단지 텍스트 출력위치만 지정한 것과 textbox 메소드에서 출력영역을 지정한 것은 차이가 있다. Rect로 제공하게 되면, 그 영역을 초과하지 않는 범위 내에서 표현할 수 최대크기의 글자크기로 텍스트 내용을 출력하게 된다.
이처럼 출력영역이 고정되는 것은 우리의 목적에 부합하는데 왜냐하면 해당 영역에서 계속 텍스트의 내용이 바뀌기 때문이다. 이 경우, 새로운 텍스트를 쓰기 전에는 이전에 쓴 텍스트를 먼저 지우고나서 그 위에 써야 하는데, 영역이 고정되어 있어야만 기존 텍스트를 완전히 지우기가 편하다. 만약, 텍스트가 씌여지는 영역이 가변적이라면 불편한게 매번 그 가변영역을 기억해두면서 관리해야 하는 부담이 생기기 때문이다. 그밖에 screen.draw.filled_rect 메소드를 사용해 Rect에 배경색을 칠하고 있는데 이는 우리가 화면에 표시할 텍스트가 선명하게 보이도록 하는 효과와 동시에 이전에 씌여진 텍스트를 지우는 효과도 함께 얻을 수 있다.
화면에 표시되어야 할 텍스트는 크게 3가지로 31번 라인의 패스워드 입력 전, 24, 26번 라인의 패스워드 결과에 따른 성공/실패에 대한 내용이며, 패스워드 입력이 일단 완료되면, 28번 라인에서 이전에 사용해 본 메소드인 pygame.display.update()를 통해 성공/실패 유무의 텍스트를 화면에 곧바로 출력하게 만들고, 파이게임 앱을 종료하는 메소드인 game.exit() 라는 메소드를 통해 게임을 종료하게 된다.
추가로 텍스트 출력에 사용할 폰트를 fontname='nanum_square' 이란 인자값으로 지정해 전달했는데 이미 5.1장에서 배운 것처럼 한글 텍스트 출력을 위해 한글폰트를 사용해야 하는 필요인 것이다. 그 밖에도 텍스트를 다양한 형태로 변형하기 위한 여러 옵션 인자값들이 존재하는데 자세한 내용은 이곳 라이브러리 메뉴얼을 참조하도록 하자.
🔢 패스워드 입력이 성공일 경우, 보물상자가 열린 이미지로 대치가 필요한데 이렇게 Actor 객체의 외관 이미지의 변경에 관한 처리와 사운드 효과음을 내는 처리는 update() 콜백함수 내에서 이뤄져야 하는 점을 유의하기 바란다. 이전 장에서 Actor의 외관이 여러 장의 이미지로 구성되어 있을 때, 해당 이미지들의 사이에서 다음 이미지로 이동을 위해 next_image 메소드를 사용해 보았는데, 이번에는 41번 라인에서 특정 이미지로 곧바로 바꾸기 위한 함수인 sel_image 메소드를 사용했다.
게임에서 사운드 효과음을 사용하는 것은 사용자의 흥미를 더하는 게임성(playability)을 높이는데 거의 필수적이라 할 수 있겠다. 사용법 자체는 어렵지 않다. 42, 44번 라인처럼 sounds.사운드파일명.play 라는 메소드로 호출하면 된다. 효과음들은 게임에 사용되는 리소스(이미지, 폰트, 소리 등) 중에 하나로 기존에 리소스 관리와 동일한데 사전에 sounds 라는 폴더 안에 해당 파일이 저장되어 있어야만 한다. 사운드 파일은 모든 파일포맷이 지원되는 것은 아니고, wav와 ogg 포맷만 재생가능하다는 점을 유의하도록 하자. 사운드는 크게 게임 내 특정 사건에서 사용되는 효과음과 게임 내내 재생하는 배경음으로 두 가지로 나눌 수 있는데, 배경음 재생에 관해서는 파이게임제로에서 제공하는 Music 이란 객체를 사용하면 되고, 자세한 사용법은 이곳 라이브러리 메뉴얼을 확인하도록 하자.
🔢 마지막으로 47번 라인의 키보드를 누를 때마다 발생하는 on_key_down 콜백함수에 대해 좀 더 살펴보자. 키보드를 누를 때마다 파마리터인 key, unicode 두 값이 함께 넘어오는데, 이 중 key는 어떤 키가 눌렸는지 용도로 사용하고, unicode는 만약 그 눌린 키가 특수키(ctrl, shift, esc 등)가 아니고 문자/숫자형의 값을 갖을 때는 그 값을 얻는 용도로 사용한다. 그래서, 44번 라인의 input_text += unicode 구문은 키보드에서 누른 값들을 input_text라는 문자열(string)변수에 누적보관하는 용도이다.
만약 사용자가 비밀번호 입력시 숫자를 잘못눌렀을 경우에 뒤로가기(Backspace)키를 눌러 지울 수 있는 기능도 제공하고 있는데, 52-53라인의 구현이 그 내용이다. 53번의 input_text[:-1] 이란 문법표현을 처음 본 사람이 있을 수 있다. 이 문법은 다른 언어에서는 일반적으로 제공되지 않는 파이썬 언어의 매우 편리한 슬라이싱(slicing) 문법표현 중에 하나이다. 간단히 설명하면 -1 이란 의미에서 유추할 수 있듯이 input_text 문자열(string)값 중 맨 마지막 문자값을 뺀 나머지 값들을 돌려주게 된다. 그래서, 맨 마지막 글자가 지워지는 효과를 만들 수 있는 것이다. 슬라이싱 문법은 알아두면 유용한데 설명해야 하는 내용이 적진 않아서 해당 장의 내용이 많이 길어지지 않게 여기서 줄이는 대신에, 해당 문법을 설명한 인터넷 상의 좋은 자료 중 하나를 추천하는 것으로 갈음하도록 하겠다.
여기까지 6번째 예제의 실행결과를 확인하는 것을 끝으로, 이 책의 마지막인 7번째 예제로 넘어가자.
Last updated