Menu
CoddyTech

Gia tốc và ma sát

Thuộc phần Vòng lặp trò chơi trong hành trình Pygame của Coddy. Bài học 24 trên 35.

Quả puck bắt đầu với tốc độ tối đa và dừng hẳn khi bạn buông phím. Trên băng, nó nên tăng tốc rồi trượt đi. Hai thay đổi sẽ giúp làm được điều đó.

Gia tốc (acceleration) cho biết vận tốc thay đổi nhanh đến mức nào, tính bằng pixel mỗi giây, trong mỗi giây. Các phím điều khiển gia tốc, còn gia tốc làm thay đổi vận tốc:

acc = pygame.Vector2(0, 0)
if keys[pygame.K_RIGHT]:
    acc.x = 600

vel += acc * dt
vel -= vel * 2 * dt
pos += vel * dt

Tạo mới acc trong mỗi khung hình để nó bằng không khi không có phím nào được nhấn. Vận tốc giữ nguyên giá trị qua từng khung hình, nên quả puck tiếp tục trượt.

Lực ma sát (friction) nằm ở dòng thứ hai. vel * 2 * dt là một phần nhỏ của vận tốc, phần này lớn hơn khi quả puck chạy nhanh. Trừ phần đó đi trong mỗi khung hình sẽ làm quả puck chạy nhanh chậm lại nhanh chóng, còn quả puck chạy chậm thì chậm lại từ từ cho đến khi dừng hẳn. Số lớn hơn 2 tạo ra mặt sàn gồ ghề hơn.

Nếu giữ phím đủ lâu, lực đẩy và lực ma sát sẽ cân bằng ở tốc độ tối đa 600 / 2 = 300 pixel mỗi giây.

challenge icon

Thử thách

Trung bình

Làm cho đĩa trượt như trên băng.

  1. Trong vòng lặp, thay vel = pygame.Vector2(0, 0) bằng acc = pygame.Vector2(0, 0), rồi đặt mỗi phím mũi tên làm cho acc.x hoặc acc.y có giá trị 600 hoặc -600.
  2. Trước khi di chuyển đĩa, cộng acc * dt vào vel, rồi trừ vel * 2 * dt khỏi nó.

Nhấn Chơi rồi nhấn một phím mũi tên: đĩa sẽ trượt và chậm dần. Sau đó, nhấn Kiểm tra.

Tự làm thử

import pygame

pygame.init()
screen = pygame.display.set_mode((480, 360))
pygame.display.set_caption("Ice Puck")
clock = pygame.time.Clock()

pos = pygame.Vector2(240, 180)
vel = pygame.Vector2(0, 0)
dt = 0

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

    keys = pygame.key.get_pressed()
    vel = pygame.Vector2(0, 0)
    if keys[pygame.K_LEFT]:
        vel.x = -200
    if keys[pygame.K_RIGHT]:
        vel.x = 200
    if keys[pygame.K_UP]:
        vel.y = -200
    if keys[pygame.K_DOWN]:
        vel.y = 200

    pos += vel * dt
    pos.x = max(14, min(pos.x, 466))
    pos.y = max(14, min(pos.y, 346))

    screen.fill((200, 225, 240))
    pygame.draw.circle(screen, (40, 50, 70), pos, 14)
    pygame.display.flip()
    dt = clock.tick(60) / 1000

pygame.quit()

Tất cả bài học trong Vòng lặp trò chơi

Tự luyện tập: Playground Pygame