파이썬으로 만드는 레이싱 게임: 짜릿한 속도감을 코드로 구현하기! 🏎️🐍
안녕하세요! Python Game Dev 블로그의 스물한 번째 포스팅입니다. 지난 포스팅에서는 고전 아케이드 게임의 대명사 '팩맨'을 Pygame으로 구현해 보았는데요, 오늘은 약속드린 대로 흥미진진한 '레이싱 게임'을 파이썬으로 만들어 보겠습니다. 키보드로 조작하는 자동차, 도로 위의 장애물, 점점 빨라지는 속도감까지! 함께 만들어보세요!
오늘의 게임: 파이썬으로 만드는 레이싱 게임 🏁🏎️
레이싱 게임은 단순하면서도 빠른 반응속도를 요구하는 게임 장르입니다. 우리가 만들 게임은 횡스크롤 방식의 2D 레이싱 게임으로, 플레이어는 차량을 좌우로 조작하며 다가오는 장애물과 다른 차량을 피해야 합니다. 게임 시간이 지날수록 속도는 점점 빨라지고 난이도는 높아집니다!
게임의 규칙📜
- 플레이어는 팩맨을 조종하여 미로 속의 모든 점을 먹어야 합니다.
- 유령들은 팩맨을 쫓아다니며, 팩맨과 접촉하면 생명을 잃습니다.
- 파워 알약을 먹으면 일정 시간 동안 팩맨이 유령을 잡아먹을 수 있습니다.
- 모든 점을 먹거나 특정 조건을 만족하면 다음 단계로 넘어갑니다.
- (선택 사항) 다양한 유령 패턴, 보너스 아이템, 추가 미로 등을 추가하여 게임의 재미를 높일 수 있습니다.
전체 코드 💻
import pygame
import random
import time
import sys
# 게임 초기화
pygame.init()
# 화면 설정
WIDTH = 800
HEIGHT = 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Python Racing Game")
# 색상 정의
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
GRAY = (100, 100, 100)
# 게임 변수
clock = pygame.time.Clock()
FPS = 60
game_speed = 5
score = 0
life = 3
game_over = False
start_time = time.time()
# 도로 설정
road_width = 400
road_left = (WIDTH - road_width) // 2
road_right = road_left + road_width
# 차선 설정
lane_width = road_width // 3
lanes = [road_left + lane_width * i + lane_width // 2 for i in range(3)]
# 플레이어 차량 설정
player_width = 50
player_height = 80
player_x = lanes[1] - player_width // 2
player_y = HEIGHT - player_height - 20
player_speed = 8
# 장애물/적 차량 설정
obstacle_width = 50
obstacle_height = 80
obstacle_speed = game_speed
obstacles = []
obstacle_spawn_time = 0
obstacle_frequency = 1.5 # 초당 생성 빈도
# 도로 애니메이션 설정
road_marks = []
for i in range(0, HEIGHT, 60):
road_marks.append([WIDTH // 2 - 5, i, 10, 30])
road_marks.append([road_left + lane_width - 5, i, 10, 30])
road_marks.append([road_left + lane_width * 2 - 5, i, 10, 30])
# 이미지 로드 (간소화를 위해 이미지 대신 도형으로 대체)
player_img = pygame.Surface((player_width, player_height))
player_img.fill(RED)
obstacle_img = pygame.Surface((obstacle_width, obstacle_height))
obstacle_img.fill(BLUE)
# 폰트 설정
font = pygame.font.SysFont(None, 36)
title_font = pygame.font.SysFont(None, 72)
# 게임 상태 변수
MENU = 0
PLAYING = 1
GAME_OVER = 2
game_state = MENU
# 장애물 생성 함수
def create_obstacle():
lane = random.randint(0, 2)
x = lanes[lane] - obstacle_width // 2
y = -obstacle_height
obstacles.append([x, y])
# 메인 메뉴 그리기 함수
def draw_menu():
screen.fill(BLACK)
title = title_font.render("PYTHON RACING", True, WHITE)
start_text = font.render("Press SPACE to Start", True, WHITE)
instruction = font.render("Use LEFT/RIGHT to move", True, WHITE)
screen.blit(title, (WIDTH // 2 - title.get_width() // 2, HEIGHT // 3))
screen.blit(start_text, (WIDTH // 2 - start_text.get_width() // 2, HEIGHT // 2))
screen.blit(instruction, (WIDTH // 2 - instruction.get_width() // 2, HEIGHT // 2 + 50))
# 게임 오버 화면 그리기 함수
def draw_game_over():
screen.fill(BLACK)
title = title_font.render("GAME OVER", True, RED)
score_text = font.render(f"Final Score: {score}", True, WHITE)
restart_text = font.render("Press SPACE to Restart", True, WHITE)
quit_text = font.render("Press ESC to Quit", True, WHITE)
screen.blit(title, (WIDTH // 2 - title.get_width() // 2, HEIGHT // 3))
screen.blit(score_text, (WIDTH // 2 - score_text.get_width() // 2, HEIGHT // 2))
screen.blit(restart_text, (WIDTH // 2 - restart_text.get_width() // 2, HEIGHT // 2 + 50))
screen.blit(quit_text, (WIDTH // 2 - quit_text.get_width() // 2, HEIGHT // 2 + 100))
# 게임 초기화 함수
def reset_game():
global score, life, game_speed, obstacles, start_time, game_over
score = 0
life = 3
game_speed = 5
obstacles = []
start_time = time.time()
game_over = False
# 게임 루프
running = True
while running:
# 이벤트 처리
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
if event.key == pygame.K_SPACE:
if game_state == MENU:
game_state = PLAYING
reset_game()
elif game_state == GAME_OVER:
game_state = PLAYING
reset_game()
# 메인 메뉴 상태
if game_state == MENU:
draw_menu()
# 게임 오버 상태
elif game_state == GAME_OVER:
draw_game_over()
# 게임 플레이 상태
elif game_state == PLAYING:
# 점수 업데이트
current_time = time.time()
score = int((current_time - start_time) * 10)
# 속도 증가 (일정 점수마다)
if score > 0 and score % 100 == 0:
game_speed = min(20, game_speed + 0.1)
obstacle_speed = game_speed
# 보너스 라이프 (500점마다)
if score > 0 and score % 500 == 0 and score != 0:
life += 1
# 키 입력 처리 (플레이어 이동)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and player_x > road_left + 10:
player_x -= player_speed
if keys[pygame.K_RIGHT] and player_x < road_right - player_width - 10:
player_x += player_speed
# 도로 그리기
screen.fill(GREEN) # 배경색 (잔디)
pygame.draw.rect(screen, GRAY, (road_left, 0, road_width, HEIGHT)) # 도로
# 차선 이동 및 그리기
for mark in road_marks:
mark[1] += game_speed
if mark[1] > HEIGHT:
mark[1] = -mark[3]
pygame.draw.rect(screen, WHITE, mark)
# 장애물 생성
current_time = time.time()
if current_time - obstacle_spawn_time > obstacle_frequency:
create_obstacle()
obstacle_spawn_time = current_time
# 게임 진행에 따라 장애물 빈도 증가
obstacle_frequency = max(0.5, obstacle_frequency - 0.01)
# 장애물 이동 및 그리기
for obstacle in obstacles[:]:
obstacle[1] += obstacle_speed
screen.blit(obstacle_img, (obstacle[0], obstacle[1]))
# 충돌 감지
if (player_x < obstacle[0] + obstacle_width and
player_x + player_width > obstacle[0] and
player_y < obstacle[1] + obstacle_height and
player_y + player_height > obstacle[1]):
obstacles.remove(obstacle)
life -= 1
if life <= 0:
game_state = GAME_OVER
# 화면 밖으로 나간 장애물 제거
if obstacle[1] > HEIGHT:
obstacles.remove(obstacle)
# 플레이어 그리기
screen.blit(player_img, (player_x, player_y))
# 점수 및 라이프 표시
score_text = font.render(f"Score: {score}", True, WHITE)
life_text = font.render(f"Life: {life}", True, WHITE)
speed_text = font.render(f"Speed: {int(game_speed)}", True, WHITE)
screen.blit(score_text, (10, 10))
screen.blit(life_text, (10, 50))
screen.blit(speed_text, (10, 90))
# 화면 업데이트
pygame.display.flip()
clock.tick(FPS)
# 게임 종료
pygame.quit()
sys.exit()
게임 화면 📸
게임을 실행하면 다음과 같은 화면을 볼 수 있습니다:
- 시작 화면: 게임 제목과 시작 방법이 표시됩니다
- 게임 화면: 도로, 플레이어 차량, 장애물이 표시됩니다
- 게임 오버 화면: 최종 점수와 재시작 방법이 표시됩니다
화면 구성요소 코드 설명 📝
1. 게임 초기화 및 설정
# 게임 초기화
pygame.init()
# 화면 설정
WIDTH = 800
HEIGHT = 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Python Racing Game")
게임 창의 크기를 800x600으로 설정하고 게임 제목을 "Python Racing Game"으로 지정했습니다.
2. 도로 설계
# 도로 설정
road_width = 400
road_left = (WIDTH - road_width) // 2
road_right = road_left + road_width
# 차선 설정
lane_width = road_width // 3
lanes = [road_left + lane_width * i + lane_width // 2 for i in range(3)]
도로의 너비를 400픽셀로 설정하고, 화면 중앙에 배치했습니다. 도로는 3개의 차선으로 나누어 플레이어가 차선을 변경할 수 있도록 했습니다.
3. 플레이어 차량 및 장애물 설정
# 플레이어 차량 설정
player_width = 50
player_height = 80
player_x = lanes[1] - player_width // 2
player_y = HEIGHT - player_height - 20
player_speed = 8
플레이어의 차량을 중앙 차선에 위치시키고 하단에 배치했습니다. 장애물은 무작위 차선에서 생성되어 위에서 아래로 이동합니다.
게임 실행 방법 🚀
- 필요한 라이브러리 설치하기:
pip install pygame
- 코드를 racing_game.py 파일로 저장하기
- 파이썬으로 실행하기:
python racing_game.py
- 게임 조작 방법:
- 스페이스바: 게임 시작/재시작
- 왼쪽/오른쪽 방향키: 차량 이동
- ESC: 게임 종료
게임에서 사용된 프로그래밍 개념 📚
- 객체 지향 프로그래밍: 차량과 장애물을 분리된 객체로 관리
- 이벤트 처리: Pygame의 이벤트 시스템을 활용한 키보드 입력 처리
- 상태 관리: 메뉴, 게임 플레이, 게임 오버 등 상태에 따른 게임 흐름 관리
- 충돌 감지: 직사각형 충돌 알고리즘을 사용한 차량 간 충돌 체크
- 랜덤화: 장애물의 위치와 생성 타이밍에 무작위성 부여
- 시간 기반 제어: 게임 속도 및 점수 계산을 시간 기반으로 구현
알고리즘 설명 🧮
1. 충돌 감지 알고리즘
게임에서 가장 중요한 부분 중 하나인 충돌 감지는 다음과 같이 구현되었습니다:
if (player_x < obstacle[0] + obstacle_width and
player_x + player_width > obstacle[0] and
player_y < obstacle[1] + obstacle_height and
player_y + player_height > obstacle[1]):
# 충돌 발생!
이 코드는 두 사각형(플레이어와 장애물)이 겹치는지 확인하는 AABB(Axis-Aligned Bounding Box) 충돌 감지 알고리즘을 사용합니다. 두 객체의 x축과 y축 범위가 모두 겹칠 때만 충돌이 발생합니다.
2. 난이도 조절 알고리즘
게임 진행에 따라 점진적으로 난이도를 높이기 위해 다음과 같은 알고리즘을 사용했습니다:
if score > 0 and score % 100 == 0:
game_speed = min(20, game_speed + 0.1)
obstacle_speed = game_speed
# 게임 진행에 따라 장애물 빈도 증가
obstacle_frequency = max(0.5, obstacle_frequency - 0.01)
이 코드는 점수가 증가함에 따라 게임 속도를 점진적으로 증가시키고, 장애물 생성 빈도를 높여 게임의 난이도를 조절합니다.
다음 포스팅 예고 🔮
다음 포스팅에서는 '파이썬으로 만드는 퍼즐 게임(Puzzle Game)'에 대해 알아보겠습니다. 테트리스나 캔디크러쉬 같은 인기 퍼즐 게임의 메커니즘을 Pygame으로 구현해 볼 예정입니다.
블록 매칭, 색상 조합, 중력 효과, 콤보 시스템 등 퍼즐 게임의 핵심 요소들을 구현하는 방법을 자세히 살펴보겠습니다. 또한 점수 시스템, 레벨 진행, 그리고 게임 난이도 조절 방법에 대해서도 알아볼 계획입니다. 더불어 게임에 특수 블록과 파워업을 추가하여 게임의 재미와 전략적 깊이를 더하는 방법도 소개해 드리겠습니다.
여러분의 의견과 질문은 언제나 환영합니다. 행복한 코딩 되세요! 🐍🎮✨
'파이썬 기초문법 > 파이썬 게임 만들기' 카테고리의 다른 글
파이썬 게임 만들기 - 팩맨 게임👾🧱 (0) | 2025.03.18 |
---|---|
파이썬 게임 만들기 - 갤러그 게임🚀👾 (0) | 2025.03.18 |
파이썬 게임 만들기 - 미로 탈출 게임 ️🧠🧩 (0) | 2025.03.15 |
파이썬 게임 만들기 - 두더지 잡기 게임 🦔🔨 (1) | 2025.03.15 |
파이썬 게임 만들기 - 플래피 버드 🐦🌵 (1) | 2025.03.15 |