생각해보면, 우리는 무언가를 출력하는 방법을 먼저 배우고(“Hello World”를 생각해봐라) 무언가를 입력하는 방법은 나중에 배운다. 왜 그런가? 왜냐면 입력은 몇몇 프로그램에선 필수조건이 아니지만, 출력은 모든 프로그램에선 항상 필수조건이기 때문이다. (프로그램의 정의: 0개 이상의 입력, 1개 이상의 출력) 그러나, 모든 게임은 입력이 필요하다. 그것이 우리는 “나는 게임을 Play한다”라고 말하는 이유이다. Play라는 단어는 몸의 일부분(아마도 손가락)을 움직인다는 뜻이다. 어쨌든, 이 프로젝트가 진짜 게임이 되기 위해 입력 로직을 추가해보자.

../../../../_images/Bagic-INPUT-sourcecode.png
 1import sys, pygame
 2pygame.init()
 3
 4size = width, height = 220, 140
 5speed = [2, 2]
 6black = 0, 0, 0
 7
 8screen = pygame.display.set_mode(size)
 9
10ball = pygame.image.load("Bagic-INPUT-sourcecode.png")
11ballrect = ball.get_rect()
12
13while True:
14    for event in pygame.event.get():
15        if event.type == pygame.QUIT: sys.exit()
16
17    ballrect = ballrect.move(speed)
18    if ballrect.left < 0 or ballrect.right > width:
19        speed[0] = -speed[0]
20    if ballrect.top < 0 or ballrect.bottom > height:
21        speed[1] = -speed[1]
22
23    screen.fill(black)
24    screen.blit(ball, ballrect)
25    pygame.display.flip()
../../../../_images/Bagic-INPUT-resultscreen.png
 1import sys, pygame
 2pygame.init()
 3
 4size = width, height = 220, 140
 5speed = [2, 2]
 6black = 0, 0, 0
 7
 8screen = pygame.display.set_mode(size)
 9
10ball = pygame.image.load("Bagic-INPUT-resultscreen.png")
11ballrect = ball.get_rect()
12
13while True:
14    for event in pygame.event.get():
15        if event.type == pygame.QUIT: sys.exit()
16
17    ballrect = ballrect.move(speed)
18    if ballrect.left < 0 or ballrect.right > width:
19        speed[0] = -speed[0]
20    if ballrect.top < 0 or ballrect.bottom > height:
21        speed[1] = -speed[1]
22
23    screen.fill(black)
24    screen.blit(ball, ballrect)
25    pygame.display.flip()

(Controlling World 프로젝트의 소스 코드 일부 와 실행 결과)

(Controlling World가 키보드 방향키를 누르면 해당 방향으로 움직인다.)

이전 프로젝트와 비교하여 2개의 큰 차이점이 생겼다. 첫째는 #5에 KEYDOWN 이벤트가 트리거 되었는지 아닌지를 판단하는 것이다. 다른 줄들은 이전의 알고리즘의 약간 다르게 동작하도록 바꾼 것에 불과하다. 똑같은 명령어가 Event문 앞에 있느냐 뒤에 있느냐 결과는 완전히 달라질 수 있음을 우리는 알고 있다. 좌표를 업데이트하는 경우, Event문이 종료되고 이루어짐에 주목해라. (세팅 된 후 업데이트된다. 그것이 두번째 차이점이다.) 객체 event.key는 키보드에 마지막으로 눌린 키를 의미한다. 구체적인 키의 이름을 보아라. K_UP, K_LEFT, K_DOWN, K_RIGHT. 매우 직관적인 K_시리즈이다. (Header의 pygame.locals로부터 이용할 수 있다.) 다른 키의 이름으로는 K_8, K_a, K_L, K_LCTRL, K_DELETE, L_F4등이 있다. 이런 키들도 추가적인 도움 없이 직관적으로 이해할 수 있다. 모든 키 이름 목록은 https://pyga.me/docs/ref/key.html#pygame.key.name 에서 확인할 수 있다.

KEYDOWN은 “이 키는 이전에는 눌리지 않았지만, 지금은 눌렸다.”를 의미하고, “이전부터 지금까지 계속 눌린 채로 있다.”를 의미하지는 않는다. 눌려있는 경우를 다루기 위해서는, KEYUP이라는 이벤트를 추가적으로 확인해야 한다. (변수와 알고리즘이 더 추가된다) 이는 심화 부분에서 다루겠다.

입력을 추가하는 것은 단순히 이벤트 인자를 추가하는 것이기 때문에 쉽다. 이제 게임 프로젝트는 완성되었다. 왜냐하면 프로젝트가 출력, 처리, 입력을 가지고 있기 때문이다. 맞는가? 아니다. 이 프로젝트는 게임 오브젝트간 상호작용이 전혀 없고, 플레이 규칙(제약조건(HP, 시간 등)도 없고 점수도 없다)이 없고, 즐길 것(동기부여 요소, 입력 출력의 다양성, 컨텐츠)이 없기 때문에 게임이라고 불릴 수 없다. 우선, 게임의 인터페이스/시스템을 풍성하게 하기 위해 우리는 심화된 입력(마우스 상태 반영), 처리(적절한 함수화), 출력(이미지, 소리 및 내부 데이터 시각화 방법)을 알아야 한다. 물론, 기초 단계에서의 경험이 반드시 도움이 된다. 심화 단계로 가보자!

<참고 코드>

import pygame, sys
from pygame.locals import*

white = (255,255,255)
red = (255,0,0)
green = (0,255,0)
pygame.init()
pygame.display.set_caption("Controlling World Project")
myScreen = pygame.display.set_mode((640, 480))
myTextFont = pygame.font.Font("HoonWhitecatR.ttf", 32)
myText = myTextFont.render("Controlling World!", True, red, green)
myTextArea = myText.get_rect()
myTextArea.center = (320, 240)
fpsClock = pygame.time.Clock()
x = 0
y = 0
moveRight = 0 #1
moveDown = 0 #2

while True:
    moveRight = 0 #3
    moveDown = 0 #4
    myTextArea.center = (320 + x, 240 + y)
    myScreen.fill(white)
    myScreen.blit(myText, myTextArea)

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == KEYDOWN: #5
            if event.key == K_UP:
                moveDown = -1
                moveRight = 0
            elif event.key == K_LEFT:
                moveDown = 0
                moveRight = -1
            elif event.key == K_DOWN:
                moveDown = 1
                moveRight = 0
            elif event.key == K_RIGHT:
                moveDown = 0
                moveRight = 1

    if(moveRight == 1): #6
        x = x + 10
    elif(moveRight == -1): #7
        x = x - 10
    if(moveDown == 1): #8
        y = y + 10
    elif(moveDown == -1): #9
        y = y - 10

    pygame.display.update()



Edit on GitHub