Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Pong là một trong những trò chơi điện tử đầu tiên, và cũng là bài tập hoàn hảo để học làm game bằng Python. Chỉ với thư viện pygame, bạn sẽ làm được game hai người chơi trên cùng bàn phím với bóng nảy, vợt và bảng điểm.
python -m venv venv
# kích hoạt môi trường ảo, rồi:
pip install pygameKiểm tra bằng python -c "import pygame; print(pygame.version.ver)". Nếu in ra số phiên bản là ổn.
Mọi game pygame đều có cùng bộ khung: khởi tạo, tạo cửa sổ, rồi chạy vòng lặp chính. Mỗi vòng lặp (một khung hình) làm ba việc: xử lý sự kiện, cập nhật trạng thái, vẽ lên màn hình. Đồng hồ Clock giới hạn số khung hình mỗi giây để tốc độ ổn định.
import pygame
pygame.init()
WIDTH, HEIGHT = 800, 500
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Pong")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 56)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((15, 23, 42))
pygame.display.flip()
clock.tick(60)
pygame.quit()Chạy thử, bạn sẽ có cửa sổ màu tối đóng được bằng nút X. Đây là nền để thêm mọi thứ khác.
Dùng pygame.Rect để biểu diễn vợt và bóng, nhờ đó có sẵn hàm kiểm tra va chạm. Thêm đoạn sau trước vòng lặp chính:
PADDLE_W, PADDLE_H = 12, 90
BALL_SIZE = 14
PADDLE_SPEED = 7
left = pygame.Rect(30, HEIGHT // 2 - PADDLE_H // 2, PADDLE_W, PADDLE_H)
right = pygame.Rect(WIDTH - 30 - PADDLE_W, HEIGHT // 2 - PADDLE_H // 2, PADDLE_W, PADDLE_H)
ball = pygame.Rect(WIDTH // 2, HEIGHT // 2, BALL_SIZE, BALL_SIZE)
ball_vx, ball_vy = 5, 4
score_l = score_r = 0
def reset_ball(direction):
global ball_vx, ball_vy
ball.center = (WIDTH // 2, HEIGHT // 2)
ball_vx = 5 * direction
ball_vy = 4Người chơi trái dùng phím W và S, người chơi phải dùng mũi tên lên và xuống. Đọc trạng thái phím giữ liên tục bằng get_pressed, rồi giới hạn vợt trong màn hình bằng clamp_ip.
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
left.y -= PADDLE_SPEED
if keys[pygame.K_s]:
left.y += PADDLE_SPEED
if keys[pygame.K_UP]:
right.y -= PADDLE_SPEED
if keys[pygame.K_DOWN]:
right.y += PADDLE_SPEED
left.clamp_ip(screen.get_rect())
right.clamp_ip(screen.get_rect())ball.x += ball_vx
ball.y += ball_vy
# nảy khỏi tường trên, dưới
if ball.top <= 0 or ball.bottom >= HEIGHT:
ball_vy = -ball_vy
# va chạm vợt
if ball.colliderect(left) and ball_vx < 0:
ball_vx = -ball_vx * 1.05
if ball.colliderect(right) and ball_vx > 0:
ball_vx = -ball_vx * 1.05
# ghi điểm
if ball.left <= 0:
score_r += 1
reset_ball(1)
elif ball.right >= WIDTH:
score_l += 1
reset_ball(-1)Điều kiện ball_vx < 0 khi va chạm vợt trái giúp tránh lỗi bóng "dính" vào vợt, đảo hướng liên tục khi vẫn đang chồng lên nhau. Nhân thêm 1.05 mỗi lần chạm làm bóng nhanh dần, tạo kịch tính.
screen.fill((15, 23, 42))
pygame.draw.rect(screen, (255, 255, 255), left)
pygame.draw.rect(screen, (255, 255, 255), right)
pygame.draw.ellipse(screen, (250, 204, 21), ball)
pygame.draw.aaline(screen, (71, 85, 105), (WIDTH // 2, 0), (WIDTH // 2, HEIGHT))
text = font.render(f"{score_l} {score_r}", True, (226, 232, 240))
screen.blit(text, (WIDTH // 2 - text.get_width() // 2, 20))
pygame.display.flip()
clock.tick(60)Đặt các đoạn ở bước 3, 4, 5 vào bên trong vòng lặp while running, sau phần xử lý sự kiện và thay cho hai dòng screen.fill, flip, tick ban đầu. Nhớ khai báo global hoặc đưa mọi thứ vào hàm main/lớp nếu bạn tách code, vì biến ball_vx được gán lại.
pygame.mixer.Paddle, Ball để dễ mở rộng.Bạn đã áp dụng vòng lặp game, xử lý phím, hình chữ nhật va chạm và bảng điểm, những viên gạch của mọi game 2D. Hãy thử biến Pong thành Breakout hoặc game thiên thạch để luyện tiếp.
Nếu muốn học Python và làm game có hướng dẫn chi tiết, bạn có thể tham khảo các khóa học tại codebem.com.
Nguyễn Đình Cường
0 comment