이번 편의 목표: 완성한 게임을 Python이 없는 컴퓨터에서도 돌아가는 실행 파일로 묶고, 홀드 기능을 직접 붙여 봅니다.
실행 파일로 묶기
PyInstaller는 Python 인터프리터, pygame, tetris.py를 한 파일로 묶어 줍니다. tetris.py가 있는 폴더에서 다음 두 명령을 실행합니다.
python3 -m pip install pyinstaller
python3 -m PyInstaller --onefile --windowed tetris.py
dist 폴더에 실행 파일이 생깁니다. Windows에서는 tetris.exe, macOS와 리눅스에서는 tetris입니다. --windowed는 실행할 때 검은 콘솔 창이 같이 뜨지 않게 합니다. 실행 파일은 만든 운영체제에서만 돌아가므로, Windows용은 Windows에서, macOS용은 macOS에서 만들어야 합니다.
08편에서 말한 한글 글꼴 파일을 쓰고 있다면, 그 파일도 같이 넣어야 합니다. 파일 하나로 묶을 때는 --add-data 옵션을 쓰고, 코드에서는 sys._MEIPASS 아래에서 글꼴을 찾아야 합니다. 처음에는 영어 글자로 묶어 보고, 실행 파일이 잘 도는 것을 확인한 뒤 글꼴을 붙이는 순서를 권합니다.
다음 과제: 홀드
홀드는 지금 블록을 옆에 맡겨 두고, 맡겨 둔 블록이 있으면 그것을 꺼내 쓰는 기능입니다. 한 블록이 나올 때마다 한 번만 쓸 수 있어야 무한히 바꿔치기하지 못합니다. C 키로 홀드하도록 만들어 보세요. 막히면 아래 해설을 보세요.
해설
Game.reset에 맡긴 블록의 종류와 홀드 가능 여부를 더합니다.
self.held = None
self.can_hold = TrueGame에 hold 메서드를 더합니다. 맡긴 블록이 없으면 다음 블록을 꺼내 쓰고, 있으면 그 종류로 새 Piece를 만듭니다. 새로 만드는 이유는 맡길 때의 회전과 위치를 버리고 맨 위 가운데에서 다시 시작하기 위해서입니다.
def hold(self):
if not self.can_hold:
return
kind = self.piece.kind
if self.held is None:
self.piece = self.next_piece
self.next_piece = Piece(self.bag.next())
else:
self.piece = Piece(self.held)
self.held = kind
self.can_hold = False
self.drop_timer = 0블록이 굳으면 다시 홀드할 수 있어야 하므로 lock에서 새 블록을 만드는 줄 근처에 self.can_hold = True를 넣습니다. handle_key에는 elif key == pygame.K_c: game.hold()를 더합니다.
화면에는 오른쪽 영역 아래쪽, 예를 들어 y = 340 근처에 HOLD 글자를 쓰고, held가 None이 아니면 SHAPES[game.held]의 좌표로 다음 블록과 같은 방식으로 그립니다. 홀드를 이미 쓴 동안에는 회색으로 그려서 지금은 못 쓴다는 것을 보여 주면 더 친절합니다.
더 해 볼 만한 것
효과음: pygame.mixer.Sound로 줄을 지울 때와 블록이 굳을 때 소리를 냅니다. 최고 점수 저장: 게임 오버 때 점수를 파일에 적고 시작할 때 읽어 옵니다. 잠금 지연: 바닥에 닿은 뒤 0.5초 동안 옆으로 밀 수 있게 합니다. 06편의 해설에서 말한 기능입니다. 공식 회전 규칙: 05편의 간단한 벽 차기 대신 SRS 시도표를 넣어 T-스핀이 되게 합니다.
여기까지 오셨으면 게임 루프, 격자, 충돌 검사, 시간 기반 이동, 상태 초기화를 모두 직접 짜 본 것입니다. 같은 뼈대로 뱀 게임이나 벽돌 깨기도 만들 수 있습니다. 판의 칸에 무엇을 담을지, 한 프레임에 무엇이 바뀌는지부터 정하면 됩니다.
COMMENTS
댓글 0
이 글에 대한 의견이나 질문을 남겨 주세요.
댓글은 구글이나 카카오로 시작한 뒤에 남길 수 있습니다.
등록된 댓글이 없습니다.