Menu
CoddyTech

Đánh bóng theo góc

Thuộc phần Dự án trong hành trình Pygame của Coddy. Bài học 18 trên 33.

Trong Pong, vị trí bóng chạm vào thanh đỡ quyết định hướng bóng bay. Chạm gần đầu trên thì bóng bay lên, gần đầu dưới thì bay xuống, còn ở giữa thì bay ngang.

Đo khoảng cách giữa tâm bóng và tâm thanh đỡ, rồi dùng khoảng cách đó làm giá trị mới cho vy:

if ball.colliderect(right):
    vx = -abs(vx)
    vy = (ball.centery - right.centery) // 6

Ở phía trên điểm giữa, hiệu số là số âm nên bóng bay lên; ở phía dưới, hiệu số là số dương. Chia cho 6 giúp bóng không bay quá nhanh: cú chạm ở tận đầu thanh đỡ tạo ra vy khoảng 7.

Nhờ vậy, Pong trở thành trò chơi đòi hỏi kỹ năng: bạn ngắm hướng bóng bằng thanh đỡ.

challenge icon

Thử thách

Khó

Điều khiển hướng bóng bằng các thanh đỡ.

  1. Trong cả hai lần bóng va chạm với thanh đỡ, sau khi đặt vx, hãy đặt vy bằng vị trí giữa của bóng trừ đi vị trí giữa của thanh đỡ đó.
  2. Chia kết quả cho 6 bằng //.

Nhấn Chơi rồi đánh bóng bằng đầu thanh đỡ: bóng sẽ bay theo một góc. Sau đó nhấn Kiểm tra.

Tự làm thử

import pygame

pygame.init()
screen = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Pong")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 36)

ball = pygame.Rect(293, 193, 14, 14)
vx, vy = 5, 4
left = pygame.Rect(20, 160, 12, 80)
right = pygame.Rect(568, 160, 12, 80)
left_score = 0
right_score = 0
waiting = False

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
            waiting = False

    keys = pygame.key.get_pressed()
    if keys[pygame.K_w]:
        left.y -= 6
    if keys[pygame.K_s]:
        left.y += 6
    if keys[pygame.K_UP]:
        right.y -= 6
    if keys[pygame.K_DOWN]:
        right.y += 6
    left.clamp_ip(screen.get_rect())
    right.clamp_ip(screen.get_rect())

    if not waiting:
        ball.x += vx
        ball.y += vy
        if ball.top <= 0 or ball.bottom >= 400:
            vy = -vy
        if ball.colliderect(left):
            vx = abs(vx)
        if ball.colliderect(right):
            vx = -abs(vx)
        if ball.left > 600:
            left_score += 1
            ball.center = (300, 200)
            vx = -vx
            waiting = True
        if ball.right < 0:
            right_score += 1
            ball.center = (300, 200)
            vx = -vx
            waiting = True

    screen.fill((30, 30, 46))
    pygame.draw.rect(screen, (80, 160, 255), left)
    pygame.draw.rect(screen, (235, 80, 80), right)
    pygame.draw.rect(screen, (255, 196, 0), ball)
    score = font.render(f"{left_score} : {right_score}", True, (240, 240, 240))
    screen.blit(score, score.get_rect(center=(300, 30)))
    if waiting:
        message = font.render("Press Space to serve", True, (240, 240, 240))
        screen.blit(message, message.get_rect(center=(300, 360)))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Tất cả bài học trong Dự án

Tự luyện tập: Playground Pygame