Menu
CoddyTech

Acceleration and Friction

Part of the The Game Loop section of Coddy's Pygame journey. Lesson 21 of 32.

The puck starts at full speed and stops dead when you let go. On ice it should build up speed and slide. Two changes do that.

Acceleration is how fast the velocity changes, in pixels per second, each second. The keys set the acceleration, and the acceleration changes the velocity:

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

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

Make acc new in each frame, so it is zero when no key is held. The velocity keeps its value from frame to frame, so the puck slides on.

Friction is the second line. vel * 2 * dt is a small part of the velocity, bigger when the puck is fast. Taking it away every frame slows a fast puck quickly and a slow one gently, until it stops. A bigger number than 2 is a rougher floor.

Held long enough, the push and the friction balance at a top speed of 600 / 2 = 300 pixels a second.

challenge icon

Challenge

Medium
  1. In the loop, replace vel = pygame.Vector2(0, 0) with acc = pygame.Vector2(0, 0), and make each arrow set acc.x or acc.y to 600 or -600.
  2. Before moving the puck, add acc * dt to vel, then take vel * 2 * dt away from it.

Try it yourself

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()

All lessons in The Game Loop

Practice on your own: Pygame playground