Search
Duplicate

[파이썬 활용] PyGame으로 공룡게임을 만들어보자안녕하세요? 초코쌤입니다.

Created
2024/10/05 11:19
Tags
#초코쌤
#파이썬
#게임개발
파이썬을 활용하여 재밌는 게임을 만들 수 있다는 사실을 아시나요?
이번 글에서는 Pygame 이라는 라이브러리를 활용하여 간단한 게임을 만들어보려고 합니다~!
먼저, 이번 글에서는 클래스를 활용해서 게임을 만들어보려고 하는데요 ㅎㅎ
왜 클래스를 활용하냐?
위 그림은 2022 개정 교육과정의 고등학교 정보 내용체계 중 ‘알고리즘과 프로그래밍’ 부분입니다. 잘 보시면 과정, 기능 내용요소 가장 아래에 ‘클래스를 정의하고 인스턴스를 생성하여 문제 해결에 적합한 객체를 구현하기’ 라고 적혀있습니다.
⇒ 즉, 2022 개정 교육과정에서는 클래스라는 개념을 학생들한테 가르쳐야 합니다! 새로운 것을 배울 때에는 재밌는 것으로 배우는 것만큼 좋은게 없습니다 ㅎㅎ
따라서, 저와 함께 따라하면서 게임이 이렇게 만들어지는구나~! 라고 생각하시면 새로운 것을 아이들한테 가르쳐줄 준비도 되어있고, 게임을 만들어보려고하는 동아리 학생들에게도 재밌게 가르쳐주실 수 있을 것 같습니다.
저희는 수업 전문가이니깐요
자, 그럼 저와 함께 게임을 만들어볼까요?

1. Python 설치

선생님들이 Google Colab을 많이 사용하실텐데, 여기서 사용하기에는 절차가 복잡해지기 때문에 Python IDLE을 설치하도록 하겠습니다.
먼저, 위 링크에 들어가서 ‘Download’를 눌러서 설치합니다.
다운로드된 파일을 클릭하고 나서, 바로 Install Now 클릭하지 않고 아래 체크표시를 해주신 후에 설치를 진행해주세요~ 나머지는 그냥 넘어가면서 설치해주시면 됩니다 ㅎㅎ
검색창에 cmd라고 치고 켜시면 위와 같은 명령프롬프트 창이 나올텐데요
‘pip install pygame’ 이라고 텍스트를 치고 엔터를 눌러서 위와 같이 설치를 완료해주세요.
설치가 완료되면 창을 닫으셔도 됩니다^^
이제 파이썬을 실행해볼까요? 검색창에 ‘IDLE’라고 눌러서 왼쪽과 같은 Shell창을띄워주시고요.
오른쪽과 같이 Shell창에 [File] - [New File]을 눌러서 새로운 Edit창을 띄워주세요.

2. dino 게임 소개

선생님들 혹시, 공룡 게임(dino)라고 아시나요?
구글 주소창에 chrome://dino/ 라고 검색해보면 위와 같은 게임이 나옵니다.
공룡은 단순하게 오른쪽으로 뛰면서 장애물이 나타나면 점프로 피하는 게임입니다.
인터넷 없이도 가능해서, 인문계 고등학교에 있을 때 아이들이 하던걸 많이 봤었는데요 ㅎㅎ
오늘은 이 게임을 클래스를 활용하여 가볍게 한번 만들어보려고 합니다.
⇒ 한번 글을 읽으시면서 따라 쳐보시는 것을 꼭 추천드립니다

3. 코드 설명

1) 초기 세팅

1-1) 라이브러리 불러오기
import pygame # Pygame 라이브러리 부르기
Python
복사
⇒ 이렇게 에디터창(위 그림)에서 코드를 작성하고 F5(실행)를 누르면, 쉘창(아래 그림)과 같이 결과가 나옵니다. 앞으로는 코드 설명과 결과창만 공유하겠습니다.
글을 읽으시기 전에 에 대한 답을 같이 생각하시면서 하면 좋을 것 같습니다. 이대로 학생들에게 발문해도 좋습니다 ㅎㅎ
1-2)Pygame 초기화
게임을 만들려면 무엇이 필요할까요?
많은 것들이 필요하겠지만, 저희 눈 앞에 그림을 그려줄 무언가가 필요합니다. 그 중 저희는 pygame이라는 python의 라이브러리를 활용하겠습니다.
import pygame # Pygame 라이브러리 부르기 pygame.init()
Python
복사
pygame.init(): Pygame의 모든 모듈을 초기화합니다. 게임을 시작하기 전에 호출해야 합니다.
⇒ 마치 도서관에서 책의 내용을 읽기 위해 책을 펼친다고 생각하시면 이해하기 쉬울 것입니다.
1-3)화면 띄우기
화면을 띄우려면 어떤 정보가 필요할까요?
화면의 크기를 알아야 합니다.
# 화면 크기 설정 (가로, 세로) WIDTH, HEIGHT = 800, 400 screen = pygame.display.set_mode((WIDTH, HEIGHT))
Python
복사
WIDTH, HEIGHT = 800, 400: 너비와 높이의 값을 WIDTH, HEIGHT 변수에 저장합니다.
pygame.display.set_mode(): () 안에 값을 넣어서 지정된 크기로 게임 화면을 만들어 줍니다.
F5를 눌러서 실행하면 이러한 화면이 나타날 것입니다.
화면을 종료하고 싶다면 Shell창에서 X버튼을 마우스로 클릭하면 됩니다.
import pygame # Pygame 라이브러리 부르기 pygame.init() # 화면 크기 설정 (가로, 세로) WIDTH, HEIGHT = 800, 400 screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("JY Dino Game")
Python
복사
pygame.display.set_caption(): () 안에 문자열 값을 넣어서 제목을 변경합니다.
다시 F5를 눌러서 제목이 바뀌는지 확인합니다.
1-4)사용할 색상 정의
import pygame # Pygame 라이브러리 부르기 pygame.init() # 화면 크기 설정 (가로, 세로) WIDTH, HEIGHT = 800, 400 screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("JY Dino Game") # 색상 WHITE = (255, 255, 255) GREEN = (0, 255, 0) RED = (255, 0, 0)
Python
복사
사용할 색상을 정의합니다. (R, G, B) 순서대로 값이며 빨간색을 사용하고 싶다면 (255, 0, 0) 값을 활용하면 됩니다.
한글이나 그림판에서 이렇게 R, G, B 값을 활용하여 색상을 지정하는 이 스펙트럼을 생각하시면 좋을 것 같습니다.
⇒ 지금 내가 이 게임에서 무슨 색상들을 사용할지 정의하는 작업입니다. 저희는 흰색 배경에, 초록색 공룡, 빨간색 장애물을 만들 예정입니다.

2) 클래스 정의

객체지향 프로그래밍의 핵심은 객체입니다. 게임에서 객체로 움직일 것을 정의해보겠습니다.
공룡 게임에서는 공룡과 적이 반드시 필요합니다. 이들을 객체로 만들어보면서 게임을 만들어보겠습니다.
2-1) 공룡 정의
일단, 달리는 공룡이 있겠습니다.
공룡이 알고 있어야 하는 정보와 공룡이 할 수 있는 행동은 무엇이 있을까요?
공룡은 자신의 크기와 위치를 알고 있어야 하며, 자신이 점프 중인지 아닌지 알고 있어야 합니다.
또한, 공룡은 점프를 할 수 있어야 하고 중력을 받습니다.
import pygame # Pygame 라이브러리 부르기 pygame.init() # 화면 크기 설정 (가로, 세로) WIDTH, HEIGHT = 800, 400 screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("JY Dino Game") # 색상 WHITE = (255, 255, 255) GREEN = (0, 255, 0) RED = (255, 0, 0) # 공룡 클래스 class Dino: def __init__(self): # 생성자 self.rect = pygame.Rect(50, 300, 40, 40) # 크기를 크게 설정 self.jumping = False self.velocity_y = 0 def jump(self): # 점프 함수 if not self.jumping: self.jumping = True self.velocity_y = -10 # 점프 높이 조절 def update(self): #업데이트 함수 self.rect.y += self.velocity_y self.velocity_y += 0.5 # 중력 if self.rect.y > 300: # 바닥에 닿으면 self.rect.y = 300 self.jumping = False self.velocity_y = 0 # 속도 초기화
Python
복사
Dino 클래스)
def __init__(self): 클래스의 생성자로, 객체가 생성될 때 실행됩니다.
self.rect = pygame.Rect(50, 300, 40, 40): (왼쪽, 위쪽, 너비, 높이) 의 값을 넣어 공룡의 위치와 크기를 설정하는 사각형을 만듭니다.
self.jumping = False: 공룡이 점프 중인지 여부를 저장하는 변수입니다. 처음에는 점프하지 않습니다.
self.velocity_y = 0: 공룡의 초기 수직 속도는 0으로 초기화 합니다.
jump 함수)
if not self.jumping: 공룡은 점프 중이 아닐 때만 점프해야 합니다. 여기를 조절한다면, 더블 점프를 구현할 수도 있습니다.
self.jumping = True: 점프 함수는 자신의 점프 상태를 True로 변경합니다.
self.velocity_y = -10: 점프를 한다면 위로 이동하도록 속도를 조절합니다. 음수인 이유는 좌표계가 위 그림과 같기 때문입니다.
update 함수)
여기서 잠깐!
⇒ 게임이라는 것은 매 프레임마다 값(데이터)이 변경되고 이를 그려주는 작업입니다.
그 중에 값이 변경될 함수가 update 함수입니다. 즉, 이 함수는 매 프레임마다 계속 호출될 함수라고 생각하시면 됩니다.
self.rect.y += self.velocity_y: 매 프레임마다 공룡의 y위치를 더해서 위로 올립니다.
self.velocity_y += 0.5: 중력 효과를 주기 위해 속도를 증가시킵니다.
⇒ 즉, 점프를 누르면 -10이라는 값을 누적시켜서 점점 위로 올라가지만 velocity라는 속도라는 값에 0.5를 더해져 나가면서 다시 땅으로 내려오게 됩니다. 이게 점프입니다.
if self.rect.y > 300: 공룡이 바닥에 닿으면.
self.rect.y = 300: 바닥에 고정시키고.
self.jumping = False: 점프 상태를 False로 변경합니다.
self.velocity_y = 0: 속도 초기화
⇒ 계속해서 중력이 더해지는데 바닥에 닿았으면 0.5씩 누적된 속도 값을 0으로 초기화합니다.
2-2) 메인 함수 정의
클래스를 활용하여 객체를 만들어내고 그려내기 위한 메인 함수를 정의하겠습니다.
# 메인 루프 def main(): clock = pygame.time.Clock() dino = Dino() isrunning = True while isrunning: screen.fill(WHITE) # 이벤트 처리 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: dino.jump() # 공룡 업데이트 dino.update() # 그리기 pygame.draw.rect(screen, GREEN, dino.rect) pygame.display.flip() clock.tick(60) pygame.quit() #if __name__ == "__main__": # main() main()
Python
복사
clock = pygame.time.Clock(): 게임의 속도를 조절하기 위한 Clock 객체를 생성합니다.
dino = Dino(): 앞서 class Dino로 설계한 공룡 객체를 생성합니다.
⇒ 저희가 만든 붕어빵 틀로 붕어빵을 찍어낸 것입니다.
isrunning = True: 게임이 계속 실행되도록 설정합니다. 장애물과 부딪혀서 게임이 종료될 때 이 변수 값을 False로 설정할 것입니다.
while isrunning : isrunning이 True인 동안 게임이 계속 실행됩니다.
screen.fill(WHITE): 기본 화면이 검정색이었기 때문에 흰색으로 채웁니다.
for event in pygame.event.get(): #pygame 내 발생한 이벤트를 처리합니다. if event.type == pygame.QUIT: #창을 닫는 이벤트 즉, 오른쪽 상단에 있는 X버튼이 눌렸다면 isrunning = False #게임을 종료시키고 if event.type == pygame.KEYDOWN: # 키 누름 이벤트가 발생했는데 if event.key == pygame.K_SPACE: # 그게 키보드의 스페이스바라면 dino.jump() # 공룡의 점프 함수를 호출합니다.
dino.update(): 공룡은 매 프레임 업데이트로 값이 변경됩니다.
pygame.draw.rect(screen, GREEN, dino.rect): (그릴 화면, 색상, 사각형) 값을 넣어 공룡을 화면에 그립니다.
pygame.display.flip() : 화면을 업데이트하여 변경 사항을 화면에 반영합니다.
clock.tick(60) : 게임의 프레임 속도를 초당 60으로 설정합니다.
pygame.quit(): while문이 종료되면 pygame을 종료합니다.
main(): 메인 함수를 호출합니다.
Tip) if __name__ == "__main__": main() ⇒ 파이썬에서는 스크립트 파일이 실행될 때 __name__ 이라는 특별한 변수를 설정하는데, 이 값이 main이라면 실행하라는 의미입니다. 하지만 이 파일을 다른 파일에서 import 하면 __name__의 값이 해당 파일의 이름이 됩니다., 이 조건문을 통해 이 파일이 메인 프로그램으로 실행 될때만 실행하라는 의도입니다. 이 실습에서는 간단하게 main()으로만 사용하겠습니다.
Python
복사
위 2-1의 공룡 정의와 2-2 메인 함수 정의를 합치고 F5를 눌러서 실행하게 되면 위와 같은 화면이 나타날 것입니다. 스페이스바를 눌러보시면 점프를 할 것입니다. 벌써 저희는 점프라는 것을 구현했습니다!!
2-3) 장애물 정의
장애물이 알고 있어야 하는 정보와 장애물이 할 수 있는 행동은 무엇이 있을까요?
장애물은 딱히 무언가를 하지는 않고, 자신의 크기와 위치로 왼쪽으로 이동합니다.
⇒ 아래 코드에서 진하게 표시한 부분은 추가한 부분입니다.
import random # 난수를 생성하기 위 한 random 모듈 부르기 # 장애물 클래스 class Obstacle: def __init__(self): self.rect = pygame.Rect(WIDTH, 300, 40, 40) def update(self): self.rect.x -= 5 # 메인 루프 def main(): clock = pygame.time.Clock() dino = Dino() isrunning= True obstacles = [] while isrunning: screen.fill(WHITE) # 이벤트 처리 for event in pygame.event.get(): if event.type == pygame.QUIT: isrunning= False if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: dino.jump() # 장애물 생성 if random.randint(1, 100) <= 3: obstacles.append(Obstacle()) # 장애물 업데이트 for obs in obstacles[:]: obs.update() if obs.rect.x < 0: obstacles.remove(obs) # 충돌 감지 if dino.rect.colliderect(obs): isrunning= False # 공룡 업데이트 dino.update() # 그리기 pygame.draw.rect(screen, GREEN, dino.rect) # 장애물 그리기 for obs in obstacles: pygame.draw.rect(screen, RED, obs.rect) pygame.display.flip() clock.tick(60) pygame.quit()
Python
복사
장애물 생성)
공룡은 저희가 처음에 생성했습니다. 그렇다면 장애물은 언제 생성되어야 할까요?
장애물은 화면 오른쪽에서 랜덤으로 생성되어야 재밌습니다. 게임에서 장애물이 언제 나오는지 알 수 있다면 게임의 재미는 반감될 것입니다.
import random: 이를 위해 random 모듈을 불러오겠습니다.
if random.randint(1, 100) <= 3: obstacles.append(Obstacle())
⇒ 1부터 100 사이의 난수를 생성하고 이 숫자가 3이하일 경우에만 장애물이 생성됩니다. 3%의 확률입니다.
⇒ 확률에 들었을 때마다 장애물 리스트에 장애물 객체를 생성하여 append함수로 추가합니다.
장애물 업데이트)
for obs in obstacles[:]: obs.update() if obs.rect.x < 0: obstacles.remove(obstacle)
⇒ 장애물을 모두 가져와서 각 장애물을 업데이트 시키고 x의 위치가 0이하가 되어 화면 밖으로 넘어가면 그 장애물을 리스트에서 제거합니다.
충돌 감지)
if dino.rect.colliderect(obs): isrunning= False
⇒ pygame.rect.colliderect() 함수를 통해서 충돌 감지를 합니다. 이 함수는 두 사각형이 겹쳤는지를 체크합니다. 충돌이 났다면 미리 만들어둔 isrunning이라는 변수를 False로 설정하여 게임을 종료합니다.
장애물 그리기)
for obs in obstacles: pygame.draw.rect(screen, RED, obs.rect)
⇒ 장애물을 가져와서 공룡을 그린 함수처럼 모두 그려줍니다.

전체 코드

import pygame # Pygame 라이브러리 부르기 import random # 난수를 생성하기 위 한 random 모듈 부르기 pygame.init() # 화면 크기 설정 (가로, 세로) WIDTH, HEIGHT = 800, 400 screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("JY Dino Game") # 색상 WHITE = (255, 255, 255) GREEN = (0, 255, 0) RED = (255, 0, 0) # 공룡 클래스 class Dino: def __init__(self): self.rect = pygame.Rect(50, 300, 40, 40) # 크기를 크게 설정 self.jumping = False self.velocity_y = 0 def jump(self): if not self.jumping: self.jumping = True self.velocity_y = -10 # 점프 높이 조절 def update(self): self.rect.y += self.velocity_y self.velocity_y += 0.5 # 중력 if self.rect.y > 300: # 바닥에 닿으면 self.rect.y = 300 self.jumping = False self.velocity_y = 0 # 속도 초기화 # 장애물 클래스 class Obstacle: def __init__(self): self.rect = pygame.Rect(WIDTH, 300, 40, 40) def update(self): self.rect.x -= 5 # 메인 루프 def main(): clock = pygame.time.Clock() dino = Dino() isrunning = True obstacles = [] while isrunning: screen.fill(WHITE) # 이벤트 처리 for event in pygame.event.get(): if event.type == pygame.QUIT: isrunning = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: dino.jump() # 장애물 생성 if random.randint(1, 100) <= 3: obstacles.append(Obstacle()) # 장애물 업데이트 for obs in obstacles[:]: obs.update() if obs.rect.x < 0: obstacles.remove(obs) # 충돌 감지 if dino.rect.colliderect(obs): isrunning = False # 공룡 업데이트 dino.update() # 그리기 pygame.draw.rect(screen, GREEN, dino.rect) # 장애물 그리기 for obstacle in obstacles: pygame.draw.rect(screen, RED, obstacle.rect) pygame.display.flip() clock.tick(60) pygame.quit() #if __name__ == "__main__": # main() main()
Python
복사
그러면 결과 화면이 위와 같이 나옵니다.
장애물을 점프(Space바)로 피해보세요 ㅎㅎ
⇒ 현재 게임은 장애물이 겹치게 나와 무조건 밟을수밖에 없는 상황도 나오고, 처음에 보신 것처럼 공룡이 존재하지도 않고, 도형으로만 그려져있죠. 점수도 없구요. 지루한 점프의 연속일겁니다. 앞으로 해야할 작업들이긴 합니다.
저희 혹은 학생들이 생각하는 그런 이미지의 게임을 만든다는 것은 작업할 양이 많다는 것을 알 수 있습니다. 실제 게임 개발자들의 그런 세심한 노력으로 재밌는 게임들이 탄생하는 것이죠 ㅎㅎ

4. 글을 마치며..

게임 만들어보시니까 어떠신가요? 어렵지는 않으셨나요? 아마 처음에는 어려우실 수도 있습니다. 저도 그랬거든요 ㅠㅠ 게임을 만든다는 것은 이런 흐름이다, 생각보다 어렵지 않다. 라는 것을 전달드리고 싶었습니다.
제가 인문계 고등학교에 있을 때 학생들에게 Python을 가르쳐주면 이걸로 게임을 만들 수 있냐는 친구들이 많았거든요. 그런 학생들과 함께 해보거나, Python이라는 텍스트 코딩에 흥미를 못 느끼는 학생들과 함께 해보면 어떨까요?
결국, 저희가 학생들에게 가르치는 추상화- 알고리즘 - 프로그래밍이 모두 들어간 작품이 게임이기도 하거든요 ^^
↓ Pygame에 관심이 생기신 선생님들은 아래 문서를 활용하셔도 좋을 것 같습니다 ^^
긴 글 읽어주셔서 감사합니다.