본문 바로가기

Development/Tetris

Python - 테트리스(Tetris) 만들기 (3) - Pygame Library

Library 설치

우선 python을 화면에 띄우기 위해서는, library가 있어야 합니다. GUI모듈을 만드는 것은 매우 어려운 일이기 때문에...누군가 잘 만든 Tool, Library, Framework가 있다면 사용해야죠. 빌딩을 크레인 없이 삽질로만 만들 수는 없지 않겠습니까?

 

저는 GUI Tool로 Pygame을 선택했습니다. Library를 설치해 봅시다.

pip install pygame

 

그러면 설치가 완료됩니다.

 

가상환경을 활성화 하고 설치해야 합니다.

 

Library 사용법 확인

pygame까지 설치한 것은 좋았는데, 이제 어떻게 할까요? 새로운 library를 봤으면 유튜브나, 구글 문서를 확인해 보는 것도 좋지만, 공식 Site에서 보여주는 Tutorial을 참조하는 것도 좋은 습관입니다.

 

Pygame의 공식홈페이지. Tutorials를 통해 Library 사용법을 익힐 수 있다.

 

 

여기서 Tutorials에 들어가면 다양한 Tutorial이 나옵니다.

 

PyGame에 대한 다양한 Tutorial들, 어떤 것을 선택해야 할까?

 

2번째의 PyGame object oriented tutorials를 들어가도록 합니다.

접속해 보니 Python2.7과 pygame1.9.1을 기준으로 작성되었다고 합니다. 필자는 python3.x를 사용하고 있으니 주의하겠습니다. 

여기도 PyGame 튜토리얼이다...사용할 예제코드를 확인하기 까지 거의 다 왔다.

 

Library 예제 정리

글 하단부에 Creating Simple Window 예제코드를 발견했습니다.

import pygame
from pygame.locals import *
 
class App:
    def __init__(self):
        self._running = True
        self._display_surf = None
        self.size = self.width, self.height = 640, 400
 
    def on_init(self):
        pygame.init()
        self._display_surf = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)
        self._running = True
 
    def on_event(self, event):
        if event.type == pygame.QUIT:
            self._running = False
    def on_loop(self):
        pass
    def on_render(self):
        pass
    def on_cleanup(self):
        pygame.quit()
 
    def on_execute(self):
        if self.on_init() == False:
            self._running = False
 
        while( self._running ):
            for event in pygame.event.get():
                self.on_event(event)
            self.on_loop()
            self.on_render()
        self.on_cleanup()
 
if __name__ == "__main__" :
    theApp = App()
    theApp.on_execute()

 

저는 이 코드를 읽어보고, 이해가 안 되거나, 필요 없어 보이는 부분을 주석처리해 보았습니다.

import pygame
# from pygame.locals import *   ## 아직 모르는 library니까 이런 문구는 없이 진행
 
 
class Tetris:
    def __init__(self):
        self._running = False       ## False로 init하고록 변경
        self._display_surf = None
        self.size = self.width, self.height = 640, 400
        
    def on_init(self):
        pygame.init()
        ## pygame.HWSURFACE와 pygame.DOUBLEBUF의 의미를 아직 모른다.
        self._display_surf = pygame.display.set_mode(self.size) #, pygame.HWSURFACE | pygame.DOUBLEBUF)
        self._running = True
 
    def on_event(self, event):  ## pygame.QUIT의 용도를 아직 모른다.
        pass
        # if event.type == pygame.QUIT:
        #     self._running = False

    # def on_loop(self):    ## 현재 사용하지 않음
    #     pass

    # def on_render(self):  ## 현재 사용하지 않음
    #     pass

    def on_cleanup(self):
        pygame.quit()
 
    def on_execute(self):
        # if self.on_init() == False:   ## on_init()이 return이 없으니 무조건 실행으로 변경
        #     self._running = False
        self.on_init()

        while self._running:
            for event in pygame.event.get():
                self.on_event(event)
            # self.on_loop()        ## 현재 사용하지 않음
            # self.on_render()      ## 현재 사용하지 않음
        self.on_cleanup()
 
 
def main():
    tetris = Tetris() 		## 이름 바꾸기
    tetris.on_execute()		## 이름 바꾸기


if __name__ == "__main__" :
    main()

 

실행하면 검은 창이 뜨는 것을 확인할 수 있습니다. 그런데 뭔가 이상합니다.

근데...X를 눌러도 꺼지지 않는다??

 

실행창을 끌 수 없습니다. vscode에서 파이썬 실행 자체를 종료하지 않는 한, 이 pygame window는 죽지 않습니다.

이제야 pygame.QUIT가 application 상단 X버튼 클릭을 의미했습니다. 아래와 같이 수정합니다.

    def on_event(self, event):
    	## pygame.QUIT은 윈도우 상단 오른쪽 X 버튼 클릭을 의미
        if event.type == pygame.QUIT:
            self._running = False

 

이제는 X버튼을 누르면 정상 종료가 됩니다.

그리고 아직 모르는 부분이 하나 더 있습니다. pygame.display.set_mode입니다.

    def on_init(self):
        pygame.init()
        ## pygame.HWSURFACE와 pygame.DOUBLEBUF의 의미를 아직 모른다.
        self._display_surf = pygame.display.set_mode(self.size) #, pygame.HWSURFACE | pygame.DOUBLEBUF)
        self._running = True

 

size는 application의 해상도를 의미하는 것 같지만, HWSURFACE와 DOUBLEBUF는 어떤 역할을 하는 것일까요?

공식 문서에서 검색하면 다음과 같이 확인해 볼 수 있습니다.

pygame2부터는 사용되지 않는다고 합니다. Double buf는 openGL에서 사용된다고 합니다.

 

openGL을 사용할 만큼 고사양 게임은 아닙니다. 둘 다 필요 없는 키워드인 것을 확인했습니다. 이제 코드를 정리합시다.

import pygame as pg

 
class Tetris:
    def __init__(self, width: int, height: int):
        self._size = self.width, self.height = width, height
        self._display_surf = None
        self._running = False

    def _init(self):
        pg.init()
        self._display_surf = pg.display.set_mode(self._size)
        self._running = True
 
    def _event(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:   ## Window 상단 X버튼
                self._running = False

    def _quit(self):
        pg.quit()
 
    def execute(self):
        self._init()

        while self._running:
            self._event()
        self._quit()
 
def main():
    tetris = Tetris(640, 400)
    tetris.execute()

if __name__ == "__main__" :
    main()

 

내부적으로 쓰일 것들을 underscore 처리했고, 필요 없어 보이는 부분을 삭제했습니다. 

 

다음에는 검은 화면에 물체를 띄워보도록 하겠습니다.

 


* reference

https://www.pygame.org/

http://pygametutorials.wikidot.com/

https://www.pygame.org/docs/tut/newbieguide.html?highlight=hwsurface