Untitled
unknown
plain_text
10 months ago
3.8 kB
12
Indexable
import pygame
import math
from pygame.math import Vector2
# Initialize pygame
pygame.init()
# Screen dimensions
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Bouncing Ball in Spinning Hexagon")
clock = pygame.time.Clock()
FPS = 60
# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
# Hexagon parameters
hex_center = Vector2(WIDTH/2, HEIGHT/2)
hex_radius = 250 # Distance from center to vertex
hex_rotation = 0 # Initial rotation angle in radians
angular_velocity = 0.01 # Rotation speed (radians per frame)
# Ball parameters
ball_radius = 15
ball_pos = Vector2(WIDTH/2, HEIGHT/2 - 100)
ball_vel = Vector2(3, 0)
gravity = Vector2(0, 0.2) # Constant acceleration downward
ball_color = RED
# Physics parameters
restitution = 0.9 # Bounce damping factor (energy loss on impact)
global_friction = 0.999 # Damping applied every frame
def compute_hexagon_vertices(center, radius, rotation):
"""Compute the vertices of a regular hexagon given a center, radius, and rotation."""
vertices = []
for i in range(6):
angle = rotation + i * (2 * math.pi / 6)
x = center.x + radius * math.cos(angle)
y = center.y + radius * math.sin(angle)
vertices.append(Vector2(x, y))
return vertices
def point_line_distance(p, a, b):
"""
Returns the distance from point p to the line segment defined by points a and b,
along with the closest point on the segment.
"""
ap = p - a
ab = b - a
t = ap.dot(ab) / ab.length_squared()
t = max(0, min(1, t))
closest = a + ab * t
return (p - closest).length(), closest
running = True
while running:
dt = clock.tick(FPS) / 1000.0 # dt in seconds (not used extensively)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Update hexagon rotation
hex_rotation += angular_velocity
# Update ball physics: gravity and friction
ball_vel += gravity
ball_vel *= global_friction
ball_pos += ball_vel
# Get current hexagon vertices (rotating each frame)
vertices = compute_hexagon_vertices(hex_center, hex_radius, hex_rotation)
# Check collision with each hexagon edge
for i in range(len(vertices)):
a = vertices[i]
b = vertices[(i+1) % len(vertices)]
dist, closest = point_line_distance(ball_pos, a, b)
if dist < ball_radius:
# Collision detected: compute collision normal (from wall toward ball)
normal = (ball_pos - closest).normalize()
# Compute the wall's velocity at the collision point due to rotation.
# For a rotating body, v = ω × r. Here r = (collision point - hex_center)
r = closest - hex_center
wall_vel = angular_velocity * Vector2(-r.y, r.x)
# Compute ball velocity relative to the moving wall
rel_vel = ball_vel - wall_vel
# Reflect the relative velocity along the collision normal
rel_vel_reflected = rel_vel - 2 * rel_vel.dot(normal) * normal
# New ball velocity is the reflected relative velocity plus wall velocity,
# scaled by the restitution coefficient to simulate energy loss.
ball_vel = wall_vel + rel_vel_reflected * restitution
# Reposition ball just outside the wall to prevent sticking.
overlap = ball_radius - dist
ball_pos += normal * overlap
# Drawing
screen.fill(BLACK)
# Draw hexagon (outline)
pygame.draw.polygon(screen, WHITE, [(v.x, v.y) for v in vertices], 2)
# Draw ball
pygame.draw.circle(screen, ball_color, (int(ball_pos.x), int(ball_pos.y)), ball_radius)
pygame.display.flip()
pygame.quit()
Editor is loading...
Leave a Comment