测试的是:python: 小球在旋转的六边形内部滚动,逼真的模拟小球的弹性,重力以及为六边形内部边框的摩擦力,think in english,show me the code.

效果好,速度快!30秒以内
import pygame
import math
# Initialize Pygame
pygame.init()
# Screen dimensions
WIDTH = 800
HEIGHT = 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Rotating Hexagon Ball Simulation")
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
# Physics constants
GRAVITY = 0.5 # Gravity strength
FRICTION = 0.01 # Friction coefficient (adjust for desired friction)
ELASTICITY = 0.8 # Elasticity of the ball (0.0 to 1.0, 1.0 is perfectly elastic)
ROTATION_SPEED = 0.02 # Speed of hexagon rotation
class Ball:
def __init__(self, x, y, radius, color):
self.x = x
self.y = y
self.radius = radius
self.color = color
self.vx = 0 # Velocity in x direction
self.vy = 0 # Velocity in y direction
def draw(self, screen):
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.radius)
def move(self):
self.vy += GRAVITY # Apply gravity
# Apply friction (simple linear friction opposing velocity)
friction_x = -FRICTION * self.vx
friction_y = -FRICTION * self.vy
self.vx += friction_x
self.vy += friction_y
self.x += self.vx
self.y += self.vy
class Hexagon:
def __init__(self, center_x, center_y, radius, color):
self.center_x = center_x
self.center_y = center_y
self.radius = radius
self.color = color
self.rotation_angle = 0 # Rotation angle in radians
def get_vertices(self):
vertices = []
for i in range(6):
angle_deg = 60 * i - 90 # Start from top vertex
angle_rad = math.radians(angle_deg)
x = self.center_x + self.radius * math.cos(angle_rad)
y = self.center_y + self.radius * math.sin(angle_rad)
vertices.append((x, y))
return vertices
def get_rotated_vertices(self):
vertices = self.get_vertices()
rotated_vertices = []
for x, y in vertices:
angle = self.rotation_angle
rotated_x = math.cos(angle) * (x - self.center_x) - math.sin(angle) * (y - self.center_y) + self.center_x
rotated_y = math.sin(angle) * (x - self.center_x) + math.cos(angle) * (y - self.center_y) + self.center_y
rotated_vertices.append((rotated_x, rotated_y))
return rotated_vertices
def draw(self, screen):
rotated_vertices = self.get_rotated_vertices()
pygame.draw.polygon(screen, self.color, rotated_vertices, 2) # Draw hexagon outline
def check_collision(ball, hexagon):
rotated_vertices = hexagon.get_rotated_vertices()
num_vertices = len(rotated_vertices)
for i in range(num_vertices):
p1 = rotated_vertices[i]
p2 = rotated_vertices[(i + 1) % num_vertices] # Next vertex, wrap around to the first
# Calculate the vector representing the edge
edge_vector_x = p2[0] - p1[0]
edge_vector_y = p2[1] - p1[1]
# Calculate the vector from point p1 to the ball's center
ball_vector_x = ball.x - p1[0]
ball_vector_y = ball.y - p1[1]
# Project ball_vector onto the normal of the edge vector.
# Normal vector can be found by swapping and negating components of edge_vector
normal_vector_x = -edge_vector_y
normal_vector_y = edge_vector_x
# Normalize the normal vector
normal_magnitude = math.sqrt(normal_vector_x**2 + normal_vector_y**2)
if normal_magnitude == 0: # Avoid division by zero if edge has zero length (shouldn't happen in regular hexagon)
continue
normal_vector_x /= normal_magnitude
normal_vector_y /= normal_magnitude
# Project ball_vector onto the normal vector (dot product)
projection_length = ball_vector_x * normal_vector_x + ball_vector_y * normal_vector_y
# If the projection length is less than or equal to the ball's radius, there's a potential collision
if projection_length <= ball.radius:
# Further check if the closest point on the edge is actually within the segment p1-p2
# Project ball_vector onto the edge vector
edge_magnitude_sq = edge_vector_x**2 + edge_vector_y**2
if edge_magnitude_sq == 0: # Avoid division by zero if edge has zero length
continue
projection_on_edge = (ball_vector_x * edge_vector_x + ball_vector_y * edge_vector_y) / edge_magnitude_sq
# Check if the projection falls within the segment (0 <= projection_on_edge <= 1)
if 0 <= projection_on_edge <= 1:
# Collision detected! Reflect the ball's velocity along the normal
# Dot product of velocity and normal vector
dot_product = ball.vx * normal_vector_x + ball.vy * normal_vector_y
# Reflect velocity components
ball.vx -= 2 * dot_product * normal_vector_x * ELASTICITY
ball.vy -= 2 * dot_product * normal_vector_y * ELASTICITY
# Slightly move ball out of collision to prevent sticking
ball.x += normal_vector_x * (ball.radius - projection_length) * 1.1 # 1.1 to push slightly out
ball.y += normal_vector_y * (ball.radius - projection_length) * 1.1
return True # Collision handled, no need to check other edges for this frame
return False # No collision
# Create ball and hexagon objects
ball = Ball(WIDTH // 2, HEIGHT // 4, 20, RED)
hexagon = Hexagon(WIDTH // 2, HEIGHT // 2, 150, WHITE)
# Game loop
running = True
clock = pygame.time.Clock()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Update game state
hexagon.rotation_angle += ROTATION_SPEED # Rotate the hexagon
ball.move() # Move the ball based on physics
# Collision detection
check_collision(ball, hexagon)
# Keep ball within screen bounds (optional, but prevents ball from going too far out)
if ball.x - ball.radius < 0:
ball.x = ball.radius
ball.vx = -ball.vx * ELASTICITY # Bounce off left wall
if ball.x + ball.radius > WIDTH:
ball.x = WIDTH - ball.radius
ball.vx = -ball.vx * ELASTICITY # Bounce off right wall
if ball.y - ball.radius < 0:
ball.y = ball.radius
ball.vy = -ball.vy * ELASTICITY # Bounce off top wall
if ball.y + ball.radius > HEIGHT:
ball.y = HEIGHT - ball.radius
ball.vy = -ball.vy * ELASTICITY # Bounce off bottom wall
# Drawing
screen.fill(BLACK) # Clear screen
hexagon.draw(screen) # Draw hexagon
ball.draw(screen) # Draw ball
pygame.display.flip() # Update the display
clock.tick(60) # Limit frame rate to 60 FPS
pygame.quit()


