Search
Duplicate

PyGame으로 스베랑카 게임 만들기2

생성일
2025/11/21 07:39
태그
초코쌤
파이썬
파이게임
게임개발
안녕하세요? 초코쌤입니다.
10월호에 저와 함께 같이 Pygame으로 스베랑카 게임을 만들었었는데(링크), 오늘 조금 업그레이드 해보려고합니다!
10월호에서는
큰 틀 잡기 → 플레이어를 움직일 수 있게 하기 →떨어지는 도형 만들기 → 부딪히면 게임 종료
이렇게까지 했었는데요.
이번호에서는 아래 4단계를 하려고 합니다.
떨어지는 오브젝트 화면 밖으로 나가면 삭제하기
떨어지는 오브젝트 속도 다르게 하기
점수 추가
이미지 추가
먼저, 지난시간에 했던 스베랑카 게임을 키면 위와 같이 화면이 나올 것입니다. 이 게임을 오른쪽으로 변화시키는 것이 목표입니다!
import pygame #Pygame 기능 쓰기 위함 import sys #sys.exit()를 사용하기 위함 import random WIDTH, HEIGHT = 400, 600 # 창 크기 FPS = 60 # 초당 60프레임 WHITE = (255, 255, 255) BLACK = (0,0,0) BROWN = (150, 75, 0) OBJECT_SIZE = 30 class Player: def __init__(self, x, y, w, h, speed, color): self.rect = pygame.Rect(x, y, w, h) # 위치/크기 self.speed = speed # 한 프레임당 이동 픽셀 self.color = color def handle_input(self): # 현재 눌려 있는 키 상태를 한 번에 가져옵니다. keys = pygame.key.get_pressed() # ← 방향키가 눌렸으면 x값을 감소시켜서 위치를 왼쪽으로 이동 if keys[pygame.K_LEFT]: self.rect.x -= self.speed # → 방향키가 눌렸으면 x값을 증가시켜서 위치를 오른쪽으로 이동 if keys[pygame.K_RIGHT]: self.rect.x += self.speed def draw(self, screen): # 플레이어(검정 사각형) 그리기 pygame.draw.rect(screen, self.color, self.rect) class FallObject: def __init__(self): x = random.randint(0, WIDTH - OBJECT_SIZE ) y = -OBJECT_SIZE # 화면 위(밖)에서 시작 self.rect = pygame.Rect(x, y, OBJECT_SIZE , OBJECT_SIZE ) self.speed = 5 # 낙하 속도 def update(self): self.rect.y += self.speed def draw(self, screen): cx, cy = self.rect.center r = OBJECT_SIZE // 2 pygame.draw.circle(screen, BROWN, (cx, cy), r) class Game: def __init__(self): # Pygame 초기화 pygame.init() #위에서 설정한 변수로 게임 스크린 크기 설정 self.screen = pygame.display.set_mode( (WIDTH, HEIGHT) ) # 창 제목 설정 pygame.display.set_caption("Suberunker Game") # FPS를 제어해주는 '시계' 생성 self.clock = pygame.time.Clock() #run이라는 함수를 계속 돌릴지 여부 self.running = True # 플레이어 화면 아래 중앙 배치 px = WIDTH//2 - 20; py = HEIGHT - 60 self.player = Player(px, py, 40, 40, 5, BLACK) # 떨어지는 오브젝트 리스트 self.objects = [] # 일정 주기로 자동 생성되는 이벤트 self.SPAWN = pygame.USEREVENT + 1 pygame.time.set_timer(self.SPAWN, 600) def spawn_object(self): self.objects.append(FallObject()) def update_objects(self): for p in self.objects[:]: p.update() def draw_objects(self): for p in self.objects: p.draw(self.screen) def check_collision(self): for p in self.objects: if self.player.rect.colliderect(p.rect): self.running = False # ← '맞으면 끝' break def run(self): while self.running: # running이 True인 동안 계속 반복 self.clock.tick(FPS) # 프레임 속도 제어 for e in pygame.event.get(): # 마우스/키보드 등 이벤트를 꺼낸다. if e.type == pygame.QUIT: # 꺼낸 이벤트가 종료라면 running을 self.running = False # false로 만들어서 게임 종료. if e.type == self.SPAWN: self.spawn_object() self.player.handle_input() # 입력처리 self.update_objects() self.check_collision() # 충돌감지 self.screen.fill(WHITE) # 배경을 하얀색으로 칠하고 self.player.draw(self.screen) # 플레이어 그리기 self.draw_objects() pygame.display.flip() # 화면 업데이트 pygame.quit() #Pygame 닫기 sys.exit() #파이썬 프로그램 완전 종료 game = Game() game.run()
Python
복사
지난 시간에 했던 코드입니다. 이번호부터 보시는 분들은 이걸 복사해서 같이 따라해보시죠.

떨어지는 도형 화면 밖으로 나가면 삭제하기

1.
게임 루프 확인
self.player.handle_input() # 입력처리 self.update_objects() self.check_collision() # 충돌감지
Python
복사
지금 이 게임은 매 프레임마다 이렇게 동작하고 있는데요. 지금 떨어지는 오브젝트들이 화면 밖으로 벗어나도 저 떨어지는 오브젝트가 화면에서만 안보일 뿐, 실제로 사라지고 있지는 않습니다.
즉, 가지고 있는 떨어지는 오브젝트들이 update하고 이후에는 또 그려질텐데, 화면에만 안보일뿐 계속 늘어나고 있다는 겁니다.
⇒ 이렇게되면 연산량이 많아져서 게임을 계속 플레이하다보면 렉걸린 것처럼 느껴지게 될겁니다.
1.
update_objects 메서드 수정
def update_objects(self): for p in self.objects[:]: p.update() # 화면 아래로 완전히 벗어났다면 제거 if p.rect.top > HEIGHT: self.objects.remove(p)
Python
복사
update_objects메서드에 remove()를 위와 같이 추가하여 화면 아래로 벗어났다면 제거하도록 하겠습니다.

떨어지는 오브젝트 속도 다르게 하기

- 지금은 모든 오브젝트가 동일한 속도로 떨어지고 있습니다. 이러면 게임이 지루해지겠죠? 속도를 다르게 해서 긴장감을 조성해봅시다!
1.
FallObject 생성자 수정
class FallObject: def __init__(self): x = random.randint(0, WIDTH - OBJECT_SIZE ) y = -OBJECT_SIZE # 화면 위(밖)에서 시작 self.rect = pygame.Rect(x, y, OBJECT_SIZE , OBJECT_SIZE ) self.speed = random.randint(3, 8) # 낙하 속도
Python
복사
위와 같이 수정하고 게임을 실행시켜본다면, 아래와 같이 오브젝트마다 속도가 달라져서 피해야 하는 긴장감이 더해질 겁니다!

점수 추가

이번에는 플레이어가 얼마나 잘 피했는지 확인할 수 있게 점수를 추가하겠습니다. 점수는 떨어지는 오브젝트가 화면 아래로 무사히 내려가면 1점씩 부여할게요! 잘피했다는 의미죠 ㅎㅎ
1.
Game 생성자 수정
class Game: def __init__(self): # Pygame 초기화 pygame.init() #위에서 설정한 변수로 게임 스크린 크기 설정 self.screen = pygame.display.set_mode( (WIDTH, HEIGHT) ) # 창 제목 설정 pygame.display.set_caption("Suberunker Game") # FPS를 제어해주는 '시계' 생성 self.clock = pygame.time.Clock() #run이라는 함수를 계속 돌릴지 여부 self.running = True # 플레이어 화면 아래 중앙 배치 px = WIDTH//2 - 20; py = HEIGHT - 60 self.player = Player(px, py, 40, 40, 5, BLACK) # 떨어지는 오브젝트 리스트 self.objects = [] # 일정 주기로 자동 생성되는 이벤트 self.SPAWN = pygame.USEREVENT + 1 pygame.time.set_timer(self.SPAWN, 600) # 점수 self.score = 0 # 폰트 self.font = pygame.font.Font(None,32)
Python
복사
Game 생성자에 score를 0으로 초기화하고, 폰트도 기본 폰트로 32크기로 쓰겠습니다.
2.
Game update_objects 수정
def update_objects(self): for p in self.objects[:]: p.update() # 화면 아래로 완전히 벗어났다면 제거 if p.rect.top > HEIGHT: self.objects.remove(p) self.score +=1
Python
복사
여기다가 화면 아래로 벗어나는 제거하는 순간에 score를 증가시켜주겠습니다.
3.
Game run 수정
def run(self): while self.running: # running이 True인 동안 계속 반복 self.clock.tick(FPS) # 프레임 속도 제어 for e in pygame.event.get(): # 마우스/키보드 등 이벤트를 꺼낸다. if e.type == pygame.QUIT: # 꺼낸 이벤트가 종료라면 running을 self.running = False # false로 만들어서 게임 종료. if e.type == self.SPAWN: self.spawn_object() self.player.handle_input() # 입력처리 self.update_objects() self.check_collision() # 충돌감지 self.screen.fill(WHITE) # 배경을 하얀색으로 칠하고 self.player.draw(self.screen) # 플레이어 그리기 self.draw_objects() score_text = self.font.render(f"Score : {self.score}", True, BLACK) self.screen.blit(score_text, (10, 10)) pygame.display.flip() # 화면 업데이트 pygame.quit() #Pygame 닫기 sys.exit() #파이썬 프로그램 완전 종료
Python
복사
증가되고 있는 score를 그려주는 함수를 추가하겠습니다.

이미지 추가

1.
이미지 찾기 및 다운로드
게임 이미지는 다양한 곳에서 찾을 수 있지만, 많이 쓰는 사이트 중 하나인 https://opengameart.org/ 에서 찾아서 플레이어는 가공을 조금 해가지고 드리겠습니다. 아래 2개의 이미지를 각각 플레이어와 떨어지는 오브젝트에 적용시키겠습니다.
player.png
684 B
fallobject.png
1.7 KiB
위 파일 2개를 다운받아주세요.
이미지 출처)
떨어지는 돌: link iconOpenGameArt.orgRock
Player sprite: Free to use, no attribution required (Original Author) Rock sprite: Viktor Hahn, CC BY 4.0 https://creativecommons.org/licenses/by/4.0/
Python
복사
2.
이미지 옮기기
이렇게 다운받은 파일을 옮겨주세요!
3.
이미지 불러오기 - Game 생성자에 추가
class Game: def __init__(self): # Pygame 초기화 pygame.init() #위에서 설정한 변수로 게임 스크린 크기 설정 self.screen = pygame.display.set_mode( (WIDTH, HEIGHT) ) # 창 제목 설정 pygame.display.set_caption("Suberunker Game") # FPS를 제어해주는 '시계' 생성 self.clock = pygame.time.Clock() #run이라는 함수를 계속 돌릴지 여부 self.running = True # 이미지 self.player_img = pygame.image.load("player.png") self.object_img = pygame.image.load("fallobject.png") # 플레이어 화면 아래 중앙 배치 px = WIDTH//2 - 20; py = HEIGHT - 60 self.player = Player(px, py, 26, 31, 5, BLACK,self.player_img) # 떨어지는 오브젝트 리스트 self.objects = [] # 일정 주기로 자동 생성되는 이벤트 self.SPAWN = pygame.USEREVENT + 1 pygame.time.set_timer(self.SPAWN, 600) # 점수 self.score = 0 # 폰트 self.font = pygame.font.Font(None,32)
Python
복사
받은 파일을 추가해봅시다.
4.
Player 및 FallObject 클래스 수정
class Player: def __init__(self, x, y, w, h, speed, color,image=None): self.rect = pygame.Rect(x, y, w, h) # 위치/크기 self.speed = speed # 한 프레임당 이동 픽셀 self.color = color self.image = image def draw(self, screen): # 플레이어(검정 사각형) 그리기 #pygame.draw.rect(screen, self.color, self.rect) screen.blit(self.image, self.rect.topleft) class FallObject: def __init__(self,image=None): x = random.randint(0, WIDTH - OBJECT_SIZE ) y = -OBJECT_SIZE # 화면 위(밖)에서 시작 self.rect = pygame.Rect(x, y, OBJECT_SIZE , OBJECT_SIZE ) self.speed = random.randint(3, 8) # 낙하 속도 self.image= image def draw(self, screen): screen.blit(self.image,self.rect.topleft) #cx, cy = self.rect.center #r = OBJECT_SIZE // 2 #pygame.draw.circle(screen, BROWN, (cx, cy), r)
Python
복사
생성자에서 image를 받아서 멤버로 들고있고, draw에서 이미지를 그려주는 함수로 변경하겠습니다.
5.
이미지에 맞춰서 플레이어와 오브젝트 크기 조절
OBJECT_SIZE = 32
Python
복사
돌 크기가 32라서 이렇게 변경해주세요.
self.player = Player(px, py, 26, 31, 5, BLACK,self.player_img)
Python
복사
플레이어 이미지는 26x31이기때문에 Game 생성자에 플레이어 크기 값을 변경해주세요.
여기까지 잘 따라오셨다면 위와 같이 떨어지는 오브젝트는 돌로, 플레이어는 사각형에서 귀여운 캐릭터로 변경된 것을 확인할 수 있습니다!
기본틀이 완성된 상태에서 하나씩 기능을 추가하고 구조를 이해하다 보니, 단순한 예제게임이 조금 더 ‘게임다운’ 모습으로 발전했죠?
이런 수업을 진행하게 되면 게임이 단순 플레이하는 대상이 아니라, 논리와 상상력으로 만들어가는 결과물이라는 것을 학생들이 느끼게 될 것입니다.
프로그래밍 언어를 단순히 배우고 끝나는 것이 아니라, 흥미로운 게임 개발로 이어진다면 학생들에게 이보다 더 좋은 동기부여는 없지 않을까요?
다음에 더 발전된 게임으로 찾아뵙겠습니다. 감사합니다.