본문 바로가기

[Pygame] ✈️ 전투기 슈팅 게임 만들기 9강 | 플레이어 체력 구현하기

@도마22026. 1. 19. 19:00
728x90


1. 이번 강의 목표

이번 강의에서는 다음 기능을 추가합니다.

  • 적 전투기와 플레이어가 충돌하면 체력 감소
  • 체력이 0이 되면 게임 오버 준비 상태
  • 화면에 HP UI 표시(숫자 + 간단한 체력바)

2. 체력 변수 만들기

먼저 플레이어 체력을 추가합니다.

max_hp = 3
hp = max_hp

이번 강의에서는 이해를 위해 체력을 3으로 시작합니다.
(나중에 난이도에 따라 얼마든지 조절 가능합니다.)


3. “연속으로 맞는 문제” 방지: 무적 시간(피격 쿨타임)

적과 닿는 순간 프레임마다 체력이 깎이면, 한 번 스치기만 해도 즉사합니다.
그래서 보통 피격 후 잠깐 무적 시간을 줍니다.

hit_delay = 1000  # ms (1초)
last_hit_time = 0

 

  • hit_delay: 피격 후 무적 시간
  • last_hit_time: 마지막으로 피격된 시간

4. 플레이어 ↔ 적 충돌 처리

적과 플레이어의 충돌은 Rect끼리 비교하면 됩니다.

now = pygame.time.get_ticks()
if now - last_hit_time >= hit_delay:
    for e in enemies[:]:
        if player_rect.colliderect(e):
            hp -= 1
            last_hit_time = now
            enemies.remove(e)
            break

 

 

  • 충돌하면 HP 1 감소
  • 해당 적은 제거(연속 충돌 방지 + 타격감)
  • 무적 시간 동안은 맞지 않음

5. HP UI 표시하기

(1) HP 숫자 표시

점수처럼 폰트를 이용합니다.

hp_text = font.render(f"HP : {hp}", True, (255, 255, 255))
screen.blit(hp_text, (10, 45))

 

(2) 간단한 체력바 표시

체력을 시각적으로 보이게 해주면 훨씬 게임 같아집니다.

bar_w = 100
bar_h = 12
bar_x = 80
bar_y = 53

pygame.draw.rect(screen, (80, 80, 80), (bar_x, bar_y, bar_w, bar_h))  # 배경
current_w = int(bar_w * (hp / max_hp))
pygame.draw.rect(screen, (255, 255, 255), (bar_x, bar_y, current_w, bar_h))  # 현재 HP

6. 실행 결과

이제 실행하면 다음이 됩니다.

  • 적과 부딪히면 HP가 1 감소합니다.
  • 1초 동안 무적이라 연속 피격되지 않습니다.
  • 화면에 HP가 표시됩니다.
  • 다음 강의에서 HP 0이면 게임 오버로 넘어갈 준비가 됩니다.


7. 마무리

이번 강의에서는 다음을 구현했습니다.

  • 플레이어 체력 시스템(HP)
  • 피격 시 HP 감소
  • 무적 시간(피격 쿨타임) 적용
  • HP UI 표시(숫자 + 체력바)

이제 게임은 “끝나는 조건”을 갖춘 상태입니다.


전체 코드

더보기
import pygame
import sys
import random

pygame.init()

# 화면 설정
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 640
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Shooting Game")

# FPS 설정
clock = pygame.time.Clock()
FPS = 60

# ===== 스프라이트 로드 =====
player_img = pygame.image.load("images/player.png").convert_alpha()
enemy_img = pygame.image.load("images/enemy.png").convert_alpha()
bullet_img = pygame.image.load("images/bullet.png").convert_alpha()

# ===== 스프라이트 크기 조정 =====
PLAYER_SIZE = (40, 40)
ENEMY_SIZE = (40, 40)
BULLET_SIZE = (6, 16)

player_img = pygame.transform.scale(player_img, PLAYER_SIZE)
enemy_img = pygame.transform.scale(enemy_img, ENEMY_SIZE)
bullet_img = pygame.transform.scale(bullet_img, BULLET_SIZE)

# 플레이어 설정
player_speed = 5
player_rect = player_img.get_rect()
player_rect.centerx = SCREEN_WIDTH // 2
player_rect.bottom = SCREEN_HEIGHT - 20

# 총알 설정
bullet_speed = 8
bullets = []

# 연사 제한
fire_delay = 150
last_fire_time = 0

# 적 설정
enemy_speed = 3
enemies = []
enemy_spawn_delay = 60
enemy_timer = 0

# 점수 설정
score = 0
font = pygame.font.SysFont(None, 36)

# ===== 체력(HP) 설정 =====
max_hp = 3
hp = max_hp

# 피격 무적 시간(피격 쿨타임)
hit_delay = 1000  # ms
last_hit_time = 0

# 게임 루프
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    keys = pygame.key.get_pressed()
    now = pygame.time.get_ticks()

    # 플레이어 이동
    if keys[pygame.K_w]:
        player_rect.y -= player_speed
    if keys[pygame.K_s]:
        player_rect.y += player_speed
    if keys[pygame.K_a]:
        player_rect.x -= player_speed
    if keys[pygame.K_d]:
        player_rect.x += player_speed

    # 화면 밖 제한
    if player_rect.left < 0:
        player_rect.left = 0
    if player_rect.right > SCREEN_WIDTH:
        player_rect.right = SCREEN_WIDTH
    if player_rect.top < 0:
        player_rect.top = 0
    if player_rect.bottom > SCREEN_HEIGHT:
        player_rect.bottom = SCREEN_HEIGHT

    # 총알 발사 (연사 제한)
    if keys[pygame.K_SPACE]:
        if now - last_fire_time >= fire_delay:
            last_fire_time = now
            bullet_rect = bullet_img.get_rect()
            bullet_rect.centerx = player_rect.centerx
            bullet_rect.bottom = player_rect.top
            bullets.append(bullet_rect)

    # 총알 이동
    for b in bullets:
        b.y -= bullet_speed

    # 총알 제거
    for b in bullets[:]:
        if b.bottom < 0:
            bullets.remove(b)

    # 적 생성
    enemy_timer += 1
    if enemy_timer >= enemy_spawn_delay:
        enemy_timer = 0
        enemy_rect = enemy_img.get_rect()
        enemy_rect.x = random.randint(0, SCREEN_WIDTH - enemy_rect.width)
        enemy_rect.y = -enemy_rect.height
        enemies.append(enemy_rect)

    # 적 이동
    for e in enemies:
        e.y += enemy_speed

    # 적 제거
    for e in enemies[:]:
        if e.top > SCREEN_HEIGHT:
            enemies.remove(e)

    # 충돌 처리 (총알 vs 적)
    for b in bullets[:]:
        for e in enemies[:]:
            if b.colliderect(e):
                bullets.remove(b)
                enemies.remove(e)
                score += 10
                break

    # ===== 플레이어 피격 처리 (플레이어 vs 적) =====
    if now - last_hit_time >= hit_delay:
        for e in enemies[:]:
            if player_rect.colliderect(e):
                hp -= 1
                last_hit_time = now
                enemies.remove(e)
                break

    # ===== 화면 그리기 =====
    screen.fill((0, 0, 0))

    # 플레이어
    screen.blit(player_img, player_rect)

    # 총알
    for b in bullets:
        screen.blit(bullet_img, b)

    # 적
    for e in enemies:
        screen.blit(enemy_img, e)

    # 점수 UI
    score_text = font.render(f"Score : {score}", True, (255, 255, 255))
    screen.blit(score_text, (10, 10))

    # HP UI (숫자)
    hp_text = font.render(f"HP : {hp}", True, (255, 255, 255))
    screen.blit(hp_text, (10, 45))

    # HP UI (간단 체력바)
    bar_w = 100
    bar_h = 12
    bar_x = 80
    bar_y = 53

    pygame.draw.rect(screen, (80, 80, 80), (bar_x, bar_y, bar_w, bar_h))
    current_w = int(bar_w * (hp / max_hp))
    pygame.draw.rect(screen, (255, 255, 255), (bar_x, bar_y, current_w, bar_h))

    pygame.display.update()
    clock.tick(FPS)

pygame.quit()
sys.exit()

728x90
도마2
@도마2 :: 도마의 코드노트

초보자를 위한 코딩 강의를 정리합니다. 파이썬부터 C#, Unity 게임 제작까지 차근차근 기록합니다. — 도마

목차