Learn realistic physics to make your games feel amazing!
Real-world physics makes games feel more natural and fun! Here are the key concepts:
Pulls objects downward
velocity_y += gravity How fast and in what direction
x += velocity_x When objects hit each other
velocity = -velocity * bounce Objects slow down over time
velocity_x *= friction Create a ball that falls with gravity and bounces realistically:
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Physics Ball!")
clock = pygame.time.Clock()
# Colors
BLACK = (0, 0, 0)
RED = (255, 100, 100)
WHITE = (255, 255, 255)
# Ball properties
ball_x = 400
ball_y = 100
ball_radius = 20
velocity_x = 5 # Horizontal speed
velocity_y = 0 # Vertical speed (starts at 0)
gravity = 0.5 # How fast things fall
bounce = 0.8 # Energy lost when bouncing
friction = 0.99 # Air resistance
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
# Reset ball position
ball_x, ball_y = 400, 100
velocity_x, velocity_y = 5, 0
# Apply physics
velocity_y += gravity # Gravity pulls down
velocity_x *= friction # Air slows things down
velocity_y *= friction
# Move the ball
ball_x += velocity_x
ball_y += velocity_y
# Bounce off walls
if ball_x <= ball_radius or ball_x >= 800 - ball_radius:
velocity_x = -velocity_x * bounce
ball_x = max(ball_radius, min(800 - ball_radius, ball_x))
# Bounce off ground and ceiling
if ball_y <= ball_radius or ball_y >= 600 - ball_radius:
velocity_y = -velocity_y * bounce
ball_y = max(ball_radius, min(600 - ball_radius, ball_y))
# Draw everything
screen.fill(BLACK)
pygame.draw.circle(screen, RED, (int(ball_x), int(ball_y)), ball_radius)
# Show physics info
font = pygame.font.Font(None, 24)
text = font.render(f"Velocity: ({velocity_x:.1f}, {velocity_y:.1f})", True, WHITE)
screen.blit(text, (10, 10))
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit() Try this: Watch how the ball bounces lower each time due to energy loss! Press SPACE to reset.
Build a character that can jump on platforms with realistic physics:
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Physics Platformer!")
clock = pygame.time.Clock()
# Colors
BLACK = (0, 0, 0)
BLUE = (100, 150, 255)
BROWN = (139, 69, 19)
WHITE = (255, 255, 255)
class Player:
def __init__(self):
self.x = 100
self.y = 400
self.width = 30
self.height = 40
self.velocity_x = 0
self.velocity_y = 0
self.on_ground = False
self.speed = 5
self.jump_power = -12
self.gravity = 0.8
def update(self, platforms):
# Handle input
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
self.velocity_x = -self.speed
elif keys[pygame.K_RIGHT]:
self.velocity_x = self.speed
else:
self.velocity_x *= 0.8 # Friction when not moving
if keys[pygame.K_SPACE] and self.on_ground:
self.velocity_y = self.jump_power
self.on_ground = False
# Apply gravity
self.velocity_y += self.gravity
# Update position
self.x += self.velocity_x
self.y += self.velocity_y
# Check platform collisions
self.on_ground = False
for platform in platforms:
if self.check_collision(platform):
# Landing on top of platform
if self.velocity_y > 0 and self.y < platform['y']:
self.y = platform['y'] - self.height
self.velocity_y = 0
self.on_ground = True
# Keep player on screen
if self.x < 0:
self.x = 0
elif self.x > 800 - self.width:
self.x = 800 - self.width
# Ground collision
if self.y > 600 - self.height:
self.y = 600 - self.height
self.velocity_y = 0
self.on_ground = True
def check_collision(self, platform):
return (self.x < platform['x'] + platform['width'] and
self.x + self.width > platform['x'] and
self.y < platform['y'] + platform['height'] and
self.y + self.height > platform['y'])
def draw(self, screen):
# Body
pygame.draw.rect(screen, BLUE, (self.x, self.y, self.width, self.height))
# Eyes
pygame.draw.circle(screen, WHITE, (self.x + 8, self.y + 10), 3)
pygame.draw.circle(screen, WHITE, (self.x + 22, self.y + 10), 3)
# Create platforms
platforms = [
{'x': 200, 'y': 500, 'width': 150, 'height': 20},
{'x': 400, 'y': 400, 'width': 150, 'height': 20},
{'x': 600, 'y': 300, 'width': 150, 'height': 20},
{'x': 300, 'y': 200, 'width': 200, 'height': 20},
]
player = Player()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Update
player.update(platforms)
# Draw everything
screen.fill(BLACK)
# Draw platforms
for platform in platforms:
pygame.draw.rect(screen, BROWN, (platform['x'], platform['y'], platform['width'], platform['height']))
# Draw ground
pygame.draw.rect(screen, BROWN, (0, 580, 800, 20))
# Draw player
player.draw(screen)
# Instructions
font = pygame.font.Font(None, 24)
text1 = font.render("Arrow Keys: Move", True, WHITE)
text2 = font.render("Space: Jump", True, WHITE)
screen.blit(text1, (10, 10))
screen.blit(text2, (10, 35))
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit() Game Controls: Use arrow keys to move and SPACE to jump between platforms!
Create a cannon that shoots projectiles with realistic arc trajectories:
import pygame
import math
import sys
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Projectile Physics!")
clock = pygame.time.Clock()
# Colors
BLACK = (0, 0, 0)
RED = (255, 100, 100)
YELLOW = (255, 255, 100)
WHITE = (255, 255, 255)
GRAY = (128, 128, 128)
class Projectile:
def __init__(self, x, y, velocity_x, velocity_y):
self.x = x
self.y = y
self.velocity_x = velocity_x
self.velocity_y = velocity_y
self.gravity = 0.3
self.active = True
def update(self):
if self.active:
# Apply gravity
self.velocity_y += self.gravity
# Update position
self.x += self.velocity_x
self.y += self.velocity_y
# Remove if off screen
if self.x < 0 or self.x > 800 or self.y > 600:
self.active = False
def draw(self, screen):
if self.active:
pygame.draw.circle(screen, YELLOW, (int(self.x), int(self.y)), 5)
# Cannon properties
cannon_x = 50
cannon_y = 550
cannon_angle = -45 # Degrees
cannon_length = 40
launch_power = 15
projectiles = []
charging = False
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
cannon_angle = max(-90, cannon_angle - 5)
elif event.key == pygame.K_DOWN:
cannon_angle = min(0, cannon_angle + 5)
elif event.key == pygame.K_SPACE:
# Fire projectile
angle_rad = math.radians(cannon_angle)
vel_x = math.cos(angle_rad) * launch_power
vel_y = math.sin(angle_rad) * launch_power
projectiles.append(Projectile(cannon_x, cannon_y, vel_x, vel_y))
# Update projectiles
for projectile in projectiles[:]:
projectile.update()
if not projectile.active:
projectiles.remove(projectile)
# Draw everything
screen.fill(BLACK)
# Draw ground
pygame.draw.rect(screen, GRAY, (0, 570, 800, 30))
# Draw cannon
end_x = cannon_x + math.cos(math.radians(cannon_angle)) * cannon_length
end_y = cannon_y + math.sin(math.radians(cannon_angle)) * cannon_length
pygame.draw.line(screen, RED, (cannon_x, cannon_y), (end_x, end_y), 8)
pygame.draw.circle(screen, RED, (cannon_x, cannon_y), 15)
# Draw projectiles
for projectile in projectiles:
projectile.draw(screen)
# Instructions
font = pygame.font.Font(None, 24)
text1 = font.render("Up/Down: Aim cannon", True, WHITE)
text2 = font.render("Space: Fire!", True, WHITE)
text3 = font.render(f"Angle: {int(cannon_angle)}°", True, WHITE)
screen.blit(text1, (10, 10))
screen.blit(text2, (10, 35))
screen.blit(text3, (10, 60))
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit() Physics Challenge: Try different angles to see how projectiles follow curved paths due to gravity!
Ready for advanced physics?
Next: Advanced Physics →