코딩

[Python 3] 벽돌깨기 게임

안녕 나의 20대 2024. 10. 17.
반응형

 

# breakout_game_with_extra_life_and_particles.py
import pygame
import sys
import random

# 초기화
pygame.init()

# 색상 정의
WHITE = (255, 255, 255)
RED = (255, 0, 0)
ORANGE = (255, 165, 0)
YELLOW = (255, 255, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)

# 화면 설정
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
INFO_HEIGHT = 100  # 상단 정보 표시 공간 높이
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Breakout Game with Extra Life and Particle Effects")

# 게임 변수 설정
paddle_width = 100
paddle_height = 10
ball_size = 10
brick_width = 60
brick_height = 20
rows_of_bricks = 6  # 벽돌 줄 수 증가
cols_of_bricks = 10
initial_ball_speed = [4, -4]
ball_speed_increase = 0.5
difficulty_level = 1

# 속도
clock = pygame.time.Clock()
FPS = 60

# 플레이어 변수 설정
lives = 3
score = 0
high_score = 0
difficulty_timer = 0  # 난이도 증가를 위한 시간 관리

# 패들 생성
paddle = pygame.Rect(SCREEN_WIDTH // 2 - paddle_width // 2, SCREEN_HEIGHT - 30, paddle_width, paddle_height)

# 공 생성
ball = pygame.Rect(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2, ball_size, ball_size)
ball_speed = initial_ball_speed[:]

# 벽돌 생성
brick_colors = [RED, ORANGE, YELLOW, GREEN, BLUE, WHITE]  # 각 줄의 벽돌 색상 및 점수
brick_points = [50, 40, 30, 20, 10, 5]  # 추가된 벽돌의 색상과 점수
bricks = []

# 파워업 및 파티클 변수
powerup_chance = 0.2  # 파워업 등장 확률
powerups = []  # 활성화된 파워업을 추적
particles = []  # 파티클 효과
powerup_active = None
powerup_timer = 0

def create_bricks():
    # 벽돌을 생성하고 색상 및 점수를 할당
    global bricks
    bricks = []
    for i in range(rows_of_bricks):
        for j in range(cols_of_bricks):
            brick = pygame.Rect(j * (brick_width + 5) + 35, i * (brick_height + 5) + INFO_HEIGHT + 10, brick_width, brick_height)
            bricks.append((brick, brick_colors[i], brick_points[i]))

create_bricks()

# 텍스트 렌더링 함수
font = pygame.font.Font(None, 36)
def draw_text(text, x, y, color=WHITE):
    # 화면에 텍스트를 표시하는 함수
    img = font.render(text, True, color)
    screen.blit(img, (x, y))

def reset_ball():
    # 공을 화면 중앙에 다시 배치하고 초기 속도로 설정
    global ball, ball_speed
    ball.x, ball.y = SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2
    ball_speed = initial_ball_speed[:]

def activate_powerup(powerup_type):
    # 파워업 효과 적용
    global paddle, score, lives, powerup_active, powerup_timer
    if powerup_type == "wider_paddle":
        paddle.width += 50  # 패들 넓이 증가
    elif powerup_type == "extra_score":
        score += 50  # 추가 점수 획득
    elif powerup_type == "extra_life":
        lives += 1  # 생명 증가
    powerup_active = powerup_type
    powerup_timer = pygame.time.get_ticks()  # 파워업 활성화 시간 기록

def create_particles(x, y, color):
    # 파티클을 생성하고 일정 시간 동안 이동하도록 설정
    for _ in range(10):  # 10개의 파티클 생성
        direction = [random.choice([-1, 1]) * random.random(), random.choice([-1, 1]) * random.random()]
        particle = {'pos': [x, y], 'direction': direction, 'color': color, 'life': 30}  # life는 파티클 지속 시간
        particles.append(particle)

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

    # 패들 이동
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT] and paddle.left > 0:
        paddle.x -= 6
    if keys[pygame.K_RIGHT] and paddle.right < SCREEN_WIDTH:
        paddle.x += 6

    # 공 이동
    ball.x += ball_speed[0]
    ball.y += ball_speed[1]

    # 벽과 충돌 처리
    if ball.left <= 0 or ball.right >= SCREEN_WIDTH:
        ball_speed[0] = -ball_speed[0]  # 좌우 벽에서 반사
    if ball.top <= INFO_HEIGHT:
        ball_speed[1] = -ball_speed[1]  # 상단에서 반사
    if ball.bottom >= SCREEN_HEIGHT:
        lives -= 1  # 바닥에 닿으면 생명 감소
        reset_ball()
        if lives <= 0:  # 생명이 0이 되면 게임 리셋
            if score > high_score:
                high_score = score  # 최고 점수 갱신
            score = 0
            lives = 3
            create_bricks()
            difficulty_level = 1
            ball_speed = initial_ball_speed[:]
            paddle.width = 100  # 패들 크기 초기화

    # 패들과 충돌 처리 및 각도 조절
    if ball.colliderect(paddle):
        if ball.bottom >= paddle.top and ball.centery < paddle.centery:
            # 공의 위치에 따라 반사 각도 조절
            relative_intersect_x = (ball.x + ball.width / 2) - (paddle.x + paddle.width / 2)
            normalized_intersect_x = relative_intersect_x / (paddle.width / 2)
            bounce_angle = normalized_intersect_x * (5 * ball_speed_increase)
            ball_speed[0] = bounce_angle
            ball_speed[1] = -abs(ball_speed[1])
            ball.y = paddle.top - ball_size  # 패들 위쪽으로 공 위치 보정

    # 벽돌과 충돌 처리
    for brick, color, points in bricks[:]:
        if ball.colliderect(brick):
            ball_speed[1] = -ball_speed[1]  # 공 반사
            bricks.remove((brick, color, points))
            score += points  # 점수 증가
            create_particles(brick.x + brick_width // 2, brick.y + brick_height // 2, color)  # 파티클 생성
            if random.random() < powerup_chance:  # 확률적으로 파워업 생성
                powerup_rect = pygame.Rect(brick.x, brick.y, 20, 20)
                powerup_type = random.choice(["wider_paddle", "extra_score", "extra_life"])
                powerups.append((powerup_rect, powerup_type))
            break

    # 파워업 이동 및 충돌 처리
    for powerup_rect, powerup_type in powerups[:]:
        powerup_rect.y += 3  # 파워업 떨어짐
        if powerup_rect.colliderect(paddle):
            activate_powerup(powerup_type)  # 파워업 획득
            powerups.remove((powerup_rect, powerup_type))
        elif powerup_rect.top > SCREEN_HEIGHT:
            powerups.remove((powerup_rect, powerup_type))  # 화면 아래로 떨어지면 제거

    # 파티클 업데이트
    for particle in particles[:]:
        particle['pos'][0] += particle['direction'][0] * 3
        particle['pos'][1] += particle['direction'][1] * 3
        particle['life'] -= 1  # 파티클 생명 감소
        if particle['life'] <= 0:
            particles.remove(particle)  # 생명이 다한 파티클 제거

    # 파워업 효과 종료 처리
    if powerup_active == "wider_paddle" and pygame.time.get_ticks() - powerup_timer > 5000:
        paddle.width = 100  # 5초 후 패들 크기 초기화
        powerup_active = None

    # 난이도 증가 처리
    difficulty_timer += 1
    if difficulty_timer % (FPS * 10) == 0:  # 10초마다 난이도 증가
        ball_speed[0] += ball_speed_increase if ball_speed[0] > 0 else -ball_speed_increase
        ball_speed[1] += ball_speed_increase if ball_speed[1] > 0 else -ball_speed_increase
        difficulty_level += 1

    # 화면 그리기
    screen.fill(BLACK)
    draw_text(f"Score: {score}", 20, 20)
    draw_text(f"Lives: {lives}", 20, 60)
    draw_text(f"High Score: {high_score}", SCREEN_WIDTH - 200, 20)
    draw_text(f"Difficulty: {difficulty_level}", SCREEN_WIDTH - 200, 60)
    
    # 패들, 공, 벽돌, 파워업 그리기
    pygame.draw.rect(screen, WHITE, paddle)
    pygame.draw.ellipse(screen, WHITE, ball)
    for brick, color, _ in bricks:
        pygame.draw.rect(screen, color, brick)
    for powerup_rect, powerup_type in powerups:
        pygame.draw.rect(screen, BLUE if powerup_type == "wider_paddle" else GREEN if powerup_type == "extra_score" else ORANGE, powerup_rect)
    
    # 파티클 그리기
    for particle in particles:
        pygame.draw.circle(screen, particle['color'], (int(particle['pos'][0]), int(particle['pos'][1])), 3)

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

기존 파이썬 벽돌깨기에서 추가된 점

추가 생명 기능
파티클 애니메이션
최고점수 표기
목숨 표기
시간과 점수에 따라 점진적으로 난이도 상승

텍스트 공간 분리

난이도 표시

벽돌의 색상 및 점수

버그 수정

가끔 벽돌이 아래에 있는 바에 튕겨지지 않는 버그

# 패들과 충돌 처리
if ball.colliderect(paddle):
    if ball.bottom >= paddle.top and ball.centery < paddle.centery:  # 공이 패들의 위쪽에서 충돌하는지 확인
        ball_speed[1] = -abs(ball_speed[1])  # 공을 위로 반사
        ball.y = paddle.top - ball_size  # 공이 패들 위쪽에 위치하도록 보정

를 참고 적용하여 수정하였음

 

반응형

'코딩' 카테고리의 다른 글

[Python 3] 지렁이 게임  (0) 2024.09.29
펌웨어 사전기초  (1) 2024.09.24

댓글

💲 추천 글