728x90

9강에서 할 일
9강에서는 “완성된 게임” 느낌을 위해 마무리를 합니다.
- 벽/몸 충돌 시 프로그램 종료 대신 게임 오버 화면을 띄웁니다
- 게임 오버 화면에 점수를 표시합니다
- R 키를 누르면 게임이 처음 상태로 재시작됩니다
- ESC 키를 누르면 종료됩니다
1) “게임 진행 중 / 게임 오버” 상태를 나눕니다
지금까지는 충돌하면 sys.exit()로 바로 종료했습니다.
이제는 종료하지 않고, 게임 상태를 바꿉니다.
게임 상태 변수 game_over를 만듭니다.
game_over = False
이 변수는 다음처럼 쓰입니다.
- False면 게임 진행 중입니다
- True면 게임 오버 화면을 보여줍니다
2) 재시작을 쉽게 하기 위해 초기화 함수를 만듭니다
재시작은 “초기 상태로 되돌리는 작업”입니다.
점수, 뱀, 방향, 먹이를 한 번에 초기화하는 함수가 있으면 편합니다.
다음 함수를 추가합니다.
def reset_game():
snake = [(5, 5)]
direction = "RIGHT"
next_direction = "RIGHT"
score = 0
food_x, food_y = spawn_food(snake)
return snake, direction, next_direction, score, food_x, food_y
이렇게 하면 R키를 누를 때도 그대로 재사용합니다.
3) 게임 시작 시에도 reset_game()으로 초기화합니다
아래처럼 초기화 코드를 교체합니다.
snake, direction, next_direction, score, food_x, food_y = reset_game()
game_over = False
이제 “게임의 시작 상태”가 함수로 정리됩니다.
4) 게임 오버 상태에서 입력 처리합니다
게임 오버일 때는 이동이나 먹이 판정이 필요 없습니다.
대신 입력만 받으면 됩니다.
- R 키: 재시작
- ESC 키: 종료
이벤트 처리 부분에 다음을 넣습니다.
if event.type == pygame.KEYDOWN:
if game_over:
if event.key == pygame.K_r:
snake, direction, next_direction, score, food_x, food_y = reset_game()
game_over = False
elif event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
else:
# 게임 진행 중일 때만 방향키 처리
...
이렇게 하면 게임 오버 상태에서는 방향키가 먹히지 않습니다.
5) 충돌 시 종료 대신 game_over = True로 바꿉니다
8강에서 충돌하면 종료했었습니다.
이 부분을 다음처럼 바꿉니다.
- 벽 충돌 → game_over = True
- 몸 충돌 → game_over = True
game_over = True
그리고 게임 오버가 되면 더 이상 이동 로직이 실행되지 않도록
이동 블록을 if not game_over:로 감쌉니다.
6) 게임 오버 화면을 그립니다
게임 오버일 때는 화면 중앙에 메시지를 띄웁니다.
- “GAME OVER”
- “Score: n”
- “Press R to Restart / ESC to Quit”
텍스트는 폰트를 하나 더 만들어서 크게 표시합니다.
big_font = pygame.font.SysFont(None, 60)
그리고 game_over일 때 그립니다.
9강 정리
이번 강의에서 만든 기능입니다.
- 게임이 종료되지 않고 게임 오버 화면이 뜹니다
- 점수를 보여줍니다
- R키로 재시작합니다
- ESC로 종료합니다
이제 “완성된 스네이크 게임”입니다.
전체 코드
더보기
import pygame
import sys
import random
pygame.init()
# =========================
# 기본 설정
# =========================
CELL_SIZE = 40
GRID_SIZE = 10
SCREEN_SIZE = CELL_SIZE * GRID_SIZE
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
# =========================
# 화면 설정
# =========================
screen = pygame.display.set_mode((SCREEN_SIZE, SCREEN_SIZE))
pygame.display.set_caption("10x10 Snake Game")
clock = pygame.time.Clock()
# =========================
# 폰트
# =========================
font = pygame.font.SysFont(None, 36)
big_font = pygame.font.SysFont(None, 60)
# =========================
# 먹이 생성 함수 (몸 전체와 겹침 방지)
# =========================
def spawn_food(snake):
while True:
x = random.randint(0, GRID_SIZE - 1)
y = random.randint(0, GRID_SIZE - 1)
if (x, y) not in snake:
return x, y
# =========================
# 게임 초기화 함수 (재시작용)
# =========================
def reset_game():
snake = [(5, 5)]
direction = "RIGHT"
next_direction = "RIGHT"
score = 0
food_x, food_y = spawn_food(snake)
return snake, direction, next_direction, score, food_x, food_y
snake, direction, next_direction, score, food_x, food_y = reset_game()
game_over = False
# =========================
# 게임 루프
# =========================
while True:
# 이벤트 처리
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
# 게임 오버 상태 입력
if game_over:
if event.key == pygame.K_r:
snake, direction, next_direction, score, food_x, food_y = reset_game()
game_over = False
elif event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
else:
# 게임 진행 중 방향키 입력
if event.key == pygame.K_UP and direction != "DOWN":
next_direction = "UP"
elif event.key == pygame.K_DOWN and direction != "UP":
next_direction = "DOWN"
elif event.key == pygame.K_LEFT and direction != "RIGHT":
next_direction = "LEFT"
elif event.key == pygame.K_RIGHT and direction != "LEFT":
next_direction = "RIGHT"
# 이동 및 판정 (게임 진행 중일 때만)
if not game_over:
direction = next_direction
head_x, head_y = snake[0]
if direction == "UP":
new_head = (head_x, head_y - 1)
elif direction == "DOWN":
new_head = (head_x, head_y + 1)
elif direction == "LEFT":
new_head = (head_x - 1, head_y)
else: # RIGHT
new_head = (head_x + 1, head_y)
# 벽 충돌
if (
new_head[0] < 0 or new_head[0] >= GRID_SIZE or
new_head[1] < 0 or new_head[1] >= GRID_SIZE
):
game_over = True
# 자기 몸 충돌
elif new_head in snake[1:]:
game_over = True
else:
# 머리 추가
snake.insert(0, new_head)
# 먹이 먹기
if new_head[0] == food_x and new_head[1] == food_y:
score += 1
food_x, food_y = spawn_food(snake)
else:
snake.pop()
# =========================
# 그리기
# =========================
screen.fill(BLACK)
# 점수 표시
score_text = font.render(f"Score: {score}", True, WHITE)
screen.blit(score_text, (10, 10))
# 뱀 그리기
for x, y in snake:
rect = pygame.Rect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE)
pygame.draw.rect(screen, GREEN, rect)
# 먹이 그리기
food_rect = pygame.Rect(
food_x * CELL_SIZE,
food_y * CELL_SIZE,
CELL_SIZE,
CELL_SIZE
)
pygame.draw.rect(screen, YELLOW, food_rect)
# 게임 오버 화면
if game_over:
over_text = big_font.render("GAME OVER", True, WHITE)
info_text = font.render(f"Score: {score}", True, WHITE)
restart_text = font.render("Press R to Restart / ESC to Quit", True, WHITE)
over_rect = over_text.get_rect(center=(SCREEN_SIZE // 2, SCREEN_SIZE // 2 - 40))
info_rect = info_text.get_rect(center=(SCREEN_SIZE // 2, SCREEN_SIZE // 2 + 10))
restart_rect = restart_text.get_rect(center=(SCREEN_SIZE // 2, SCREEN_SIZE // 2 + 50))
screen.blit(over_text, over_rect)
screen.blit(info_text, info_rect)
screen.blit(restart_text, restart_rect)
pygame.display.update()
clock.tick(10)
728x90
'⚙️ Python > 🎮 Pygame 실전' 카테고리의 다른 글
| [Pygame] ✈️ 전투기 슈팅 게임 만들기 2강 | 플레이어 전투기 생성과 WASD 이동 구현 (0) | 2026.01.12 |
|---|---|
| [Pygame] ✈️ 전투기 슈팅 게임 만들기 1강 | 프로젝트 시작과 세로 슈팅 게임 구조 이해 (0) | 2026.01.11 |
| [Pygame] 🐍 스네이크 게임 만들기 8강 | 자기 몸 충돌 처리하기 (0) | 2026.01.08 |
| [Pygame] 🐍 스네이크 게임 만들기 7강 | 뱀 몸 만들기 + 먹으면 길어지기 (0) | 2026.01.07 |
| [Pygame] 🐍 스네이크 게임 만들기 6강 | 먹이 처리 + 점수 (0) | 2026.01.06 |