파이썬 PyGame으로 움직이는 사각형 게임 만들기

파이썬 PyGame으로 움직이는 사각형 게임 만들기

처음 만드는 게임은 거대한 클래스 설계보다 게임 루프가 어떻게 반복되는지 이해하는 것이 중요합니다. 아래 예제는 창을 열고, 방향키로 사각형을 움직이고, 창 닫기까지 정상 처리하는 하나의 완성된 프로그램입니다.

설치와 실행 준비

python -m pip install pygame

파일 이름을 pygame.py로 저장하면 설치된 패키지 대신 자신의 파일을 불러오는 문제가 생길 수 있습니다. 예제 파일은 moving_box.py처럼 다른 이름으로 저장하십시오.

게임 루프의 네 단계

한 프레임은 이벤트 처리, 입력 확인, 상태 갱신, 화면 그리기 순서로 진행됩니다. 이 과정이 초당 여러 번 반복되면서 움직임처럼 보입니다.

import pygame

pygame.init()
screen = pygame.display.set_mode((640, 360))
pygame.display.set_caption("Moving Box")
clock = pygame.time.Clock()

x, y = 295, 155
speed = 240
box_size = 50
running = True

while running:
    dt = clock.tick(60) / 1000

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        x -= speed * dt
    if keys[pygame.K_RIGHT]:
        x += speed * dt
    if keys[pygame.K_UP]:
        y -= speed * dt
    if keys[pygame.K_DOWN]:
        y += speed * dt

    x = max(0, min(x, 640 - box_size))
    y = max(0, min(y, 360 - box_size))

    screen.fill((28, 32, 40))
    pygame.draw.rect(screen, (80, 200, 140), (x, y, box_size, box_size))
    pygame.display.flip()

pygame.quit()

dt를 곱하는 이유

컴퓨터마다 실제 프레임 수가 조금씩 다릅니다. 프레임마다 5픽셀을 이동하면 빠른 컴퓨터에서 더 빨리 움직일 수 있습니다. dt는 이전 프레임 이후 흐른 초이므로, 초당 240픽셀이라는 속도를 환경에 관계없이 비슷하게 유지합니다.

화면 밖으로 나가지 않게 하기

max()min()으로 좌표를 0과 화면 크기에서 사각형 크기를 뺀 값 사이로 제한했습니다. 중심 좌표를 사용하는 이미지라면 제한 계산도 달라집니다.

다음 기능을 추가하는 순서

  1. 목표물 하나를 그리고 사각형과 충돌하는지 검사합니다.
  2. 충돌하면 점수를 1 올리고 목표 위치를 바꿉니다.
  3. 제한 시간을 표시하고 종료 화면을 만듭니다.
  4. 효과음과 이미지는 게임 규칙이 완성된 뒤 추가합니다.

기능을 추가할 때 이벤트, 상태 갱신, 그리기를 각각 함수로 분리하면 오류 위치를 찾기 쉬워집니다. 작은 게임에는 처음부터 클래스가 반드시 필요하지 않습니다.

자주 생기는 문제

  • 창이 바로 닫힘: 게임 루프나 이벤트 처리가 빠졌는지 확인합니다.
  • 창이 응답 없음: 매 프레임 pygame.event.get()을 호출해야 합니다.
  • 움직임이 너무 빠름: clock.tick()과 시간 기반 이동을 사용합니다.
  • 종료 후 프로세스가 남음: 루프 밖에서 pygame.quit()을 호출합니다.

충돌 판정을 추가해 보기

플레이어와 목표물을 pygame.Rect로 만들면 colliderect()로 겹침을 확인할 수 있습니다.

player = pygame.Rect(x, y, box_size, box_size)
target = pygame.Rect(500, 200, 30, 30)

if player.colliderect(target):
    score += 1
    target.x, target.y = 80, 80

충돌 후 목표 위치를 바꾸지 않으면 겹쳐 있는 매 프레임마다 점수가 올라갑니다. 한 번의 접촉을 한 번만 처리하려면 목표를 즉시 이동하거나 충돌 상태가 시작되는 순간만 감지해야 합니다.

연습: 30초 제한 게임

pygame.time.get_ticks()로 시작 이후 경과 시간을 계산하고 30초가 지나면 게임을 끝내 보십시오. 화면에는 남은 시간과 점수를 표시합니다. 프레임 수를 시간으로 사용하면 컴퓨터 성능에 따라 제한 시간이 달라지므로 실제 밀리초를 기준으로 해야 합니다.

정리

게임의 핵심은 화면을 그리는 한 줄이 아니라 입력과 상태와 렌더링을 계속 갱신하는 루프입니다. 위 예제를 그대로 실행한 뒤 목표물과 점수를 한 기능씩 추가해 보십시오.