우리가 게임을 할 때 캐릭터를 조작한다. 이 때 사용하는 것을 입력장치라고 한다. 키보드나 마우스, 조이스틱으로 조작할 수 있다.

 

도형을 캐릭터라고 하고 키보드로 조종할 수 있으면 어떨까? 최신의 멋진 캐릭터를 조작하는 것은 아니지만 나름 게임의 원리에 접근하는 것 같다.

 

고전게임 갤러그

사실 초기의 게임 캐릭터는 도형이었다. 갤러그는 90년대까지 꽤 오래동안 오락실의 현역이었다. (오락실이란게 아직도 있다) 갤럭그 이전 시초는 스페이스 인베이더이다.

 

스페이스 인베이더

지금 보면 40년전 전자오락은 구석기의 유산처럼 보인다. 그만큼 다른 분야에 비해 전자오락은 엄청난 속도로 발전을 했다.

 

저 시대를 건너뛰고 스마트폰이 이미 보급된 시대에 태어난 아이들에게는 와닿지 않을 수도 있다. 하지만 인류가 사상 최초로 대충 깎아놓은 듯한 도형을 키보드와 조이스틱으로 조작했을 때의 쾌감은 이루 말 할 수 없는 것 이었다. 무언가 상상력만의 세계, 가상의 화면을 보고 반응하면서 인간의 상상력이 다시 한번 시대를 초월했다. 소니나 닌텐도, 그리고 넥슨같은 글로벌 게임회사의 탄생은 정해진 수순이 되버렸다.

 

그것은 한편으로 현재의 게임기술이 우월하다는 인간의 믿음도 미래에는 깨질 것이라는 의미가 될 수 있다. 스페이스 인베이더는 혁명이었는데 UI만큼은 지금도 그때의 입력장치를 메인으로 사용한다. 최근에 밸브의 하프라이프 VR이 출시되면서 조금 가능성을 열어주긴 했다.

 

키보드로 도형을 조작하는 것이 별 의미가 없이 느껴질 수 있기 때문에 서론이 길었다.


키보드로 도형 조작하기

 

키보드 도형 조작

from pygame import *
from pygame.locals import *
import pyc

C1_GREEN = (204, 255, 204)
C1_BLUE = (153, 204, 255)

size = width,height = 700,500
screen = display.set_mode(size)
bgColor = C1_BLUE
screen.fill(bgColor)

pos1 = [0,0,100,70]
draw.rect(screen,pyc.BLUE,pos1)
display.update()

clock = time.Clock()

init()
distance = 10

running = True
while running:
    clock.tick(60)
    for p_event in event.get():
        if p_event.type == QUIT:
            running = False
        if p_event.type == KEYDOWN:
            if p_event.key == K_ESCAPE:
                running = False
    event.pump()
    keys = key.get_pressed()

    if keys[ord('s')]:
        if pos1[1] >= height - pos1[3]:
            pos1[1] = height - pos1[3]
        else:
            pos1[1] += distance

    elif keys[ord('w')]:
        if pos1[1] <= 0:
            pos1[1] = 0
        else:
            pos1[1] -= distance

    elif keys[ord('a')]:
        if pos1[0] <= 0:
            pos1[0] = 0
        else:
            pos1[0] -= distance

    elif keys[ord('d')]:
        if pos1[0] >= width- pos1[2]:
            pos1[0] = width - pos1[2]
        else:
            pos1[0] += distance

    screen.fill(bgColor)
    draw.rect(screen, pyc.BLUE, pos1)
    display.update()

quit()

포스트 4번까지는 event.get() 으로 진행했는데, 이번 포스트에서 바꿨다. event.get() 으로는 키보드를 연속으로 누르는 과정이 번거롭기 때문이다. event.get() 메소드는 키를 누를 때와(KEYDOWN), 키를 떼었을 때(KEYUP) 동작을 분리하기에 좋다. 그러나 뚝뚝 끓기기 때문에 계속 이동하기 위해서는 연타를 쳐야 된다.

 

key.get_pressed() 메소드로 받으면 이 문제가 해결된다. 방향키를 누르고 있으면 도형이 계속 이동한다.

 

from pygame import *
from pygame.locals import *
import pyc

C1_GREEN = (204, 255, 204)
C1_BLUE = (153, 204, 255)

size = width,height = 700,500
screen = display.set_mode(size)
bgColor = C1_BLUE
screen.fill(bgColor)

* 앞부분은 전의 포스트들을 봤다면 이해가 빠를 것이다. pygame과 locals의 변수,상수들을 지금 작업공간에 사용할 수 있도록 모두 가져왔다. pyc 는 사용자 정의 모듈로 기본색상에 관련한 상수를 정의해두었다.

 

size 라인을 보면 저렇게 저장하면 튜플이 된다. 윈도우 창은 한번 설정하면 변하지 않기 때문에 초기에 튜플로 설정한다. 만약 화면크기를 바꾸고 싶다면 여기서 바꿔야 한다.

 

pos1 = [0,0,100,70]
draw.rect(screen,pyc.BLUE,pos1)
display.update()

clock = time.Clock()

init()
distance = 10

*pos 라는 변수로 만들면 보통 position(위치) 의 약자이다. 사실 pos1에 앞부분 두개는 위치(x,y) 이고 뒷부분 두개는 도형의 크기(너비,높이)이다. 리스트로 만들어서 좌표를 이동시킬 것이다.

 

clock 이라는 변수를 선언했다. pygame.time.Clock()은 시간을 컨트롤 하기 위해 사용하는 클래스이다. 이것을 설정하지 않으면 키보드의 반응에 도형은 매우 빠른 속도로 움직인다.

 

사실 그게 진짜 PC의 속도이기도 한데... 그렇게 하면 게임을 진행할 수가 없으니까 인간의 기준에 맞춰주는 기능이 들어있다. 사용법은 while 문안에 나온다. 

 

distance는 키보드 입력 한번에 몇 px 움직일 것인지 설정한다. 이동 관련하는 부분은 여러가지 방법이 있다. 사실 PYGAME에는 도형을 조작하기 위해 최적화된 메소드가 있다. 이 포스트에서는 캐릭터가 이동하는 과정을 하나하나 설명하기 위해서 코드를 다시 구성했다.

 

running = True
while running:
    clock.tick(60)
    for p_event in event.get():
        if p_event.type == QUIT:
            running = False
        if p_event.type == KEYDOWN:
            if p_event.key == K_ESCAPE:
                running = False
    event.pump()
    keys = key.get_pressed()

    if keys[ord('s')]:
        if pos1[1] >= height - pos1[3]:
            pos1[1] = height - pos1[3]
        else:
            pos1[1] += distance

    elif keys[ord('w')]:
        if pos1[1] <= 0:
            pos1[1] = 0
        else:
            pos1[1] -= distance

    elif keys[ord('a')]:
        if pos1[0] <= 0:
            pos1[0] = 0
        else:
            pos1[0] -= distance

    elif keys[ord('d')]:
        if pos1[0] >= width- pos1[2]:
            pos1[0] = width - pos1[2]
        else:
            pos1[0] += distance

    screen.fill(bgColor)
    draw.rect(screen, pyc.BLUE, pos1)
    display.update()

quit()

자 마지막 이동하는 부분이다. while 루프가 왜 돌아가는지 이제 알 것이다. 일단 게임이 시작되고 윈도우창이 열리면 while 루프가 끓임없이 돌면서 사용자의 입력을 기다린다. 게임창을 열어놓으면 우리에게는 그냥 멈춰있는 듯 보이지만 컴퓨터 내부적으로는 끓임없이 루프하면서 사용자의 입력을 기다리고 있는 것이다. 그래서 사용자가 언제라도 다시 키보드를 누르면 즉각적으로 반응할 수 있다.

 

윈도우창의 while loop

우리가 봤을 때는 윈도우창은 쉬고 있었는데 그렇지 않다. 저 정도는 clock 변수로 초당 60회 루프하도록 (60FPS)했을 때의 속도이다. 속도를 컨트롤하지 않았다면 각 피씨의 CPU와 그래픽처리장치의 속도에 따라 다르다. 글쓴이의 PC에서는 초당 약 1,500 회 정도 루프하는 것 같다. 이래서는 도형을 조작할 수 가 없다. 안정된 조작감을 찾아내려면 clock과 distance (보폭)을 활용해서 캐릭터의 속도를 정할 필요가 있다.

 

*key.get_pressed( ) 는 모든 키보드입력의 여부를 불린형 배열로 반환한다. 키보드 s의 아스키코드(유니코드)가 눌렸는지 여부에 따라 elif 문을 실행한다. keys[아스키코드] >> True(1) 인지, False(0) 인지? True면 실행(키보드가 눌렸을때)

 

나머지 코드는 어렵지 않다. 도형이 윈도우창을 빠져나가지 못하게 제어문을 걸어놓은 것이다.

 

파이게임도 클래스와 메소드의 사용법을 파이게임 커뮤니티에 documentation 해놨다. 개발자 Pete 의 말처럼 SDL의 Python을 위한 Wrapper 기 때문에 나중에 SDL을 사용하더라도 적응이 쉬울 것이다. 커뮤니티의 공식문서를 잘 활용하면 좋을 것이다.

 

파이게임 커뮤니티

 

Pygame Front Page — pygame v2.0.0.dev7 documentation

 

www.pygame.org

 

공유하기

facebook twitter kakaoTalk kakaostory naver band