Untitled
unknown
plain_text
9 months ago
5.3 kB
4
Indexable
import pygame
import math
import random
# --- Constants ---
WIDTH, HEIGHT = 800, 600
FPS = 60
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (100, 100, 100)
BALL_COLOR = (255, 0, 0)
HEXAGON_COLOR = GRAY
# --- Classes ---
class Ball:
def __init__(self, x, y, radius, color):
self.x = x
self.y = y
self.radius = radius
self.color = color
self.velocity_x = 0
self.velocity_y = 0
self.gravity = 0.2 # Strength of gravity
self.friction = 0.02 # Friction coefficient
def update(self, rotation_angle):
# Apply gravity
self.velocity_y += self.gravity
# Apply friction (only on x-velocity)
if self.velocity_x > 0:
self.velocity_x -= self.friction
if self.velocity_x < 0:
self.velocity_x = 0
elif self.velocity_x < 0:
self.velocity_x += self.friction
if self.velocity_x > 0:
self.velocity_x = 0
# Update position
self.x += self.velocity_x
self.y += self.velocity_y
def draw(self, screen):
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.radius)
class Hexagon:
def __init__(self, x, y, radius, color):
self.x = x
self.y = y
self.radius = radius
self.color = color
self.rotation_angle = 0
self.rotation_speed = 0.5 # Angle per frame
def get_points(self):
points = []
for i in range(6):
angle = math.radians(self.rotation_angle + i * 60)
x = self.x + self.radius * math.cos(angle)
y = self.y + self.radius * math.sin(angle)
points.append((x, y))
return points
def update(self):
self.rotation_angle += self.rotation_speed
if self.rotation_angle >= 360:
self.rotation_angle -= 360
def draw(self, screen):
points = self.get_points()
pygame.draw.polygon(screen, self.color, points, 1) # 1 for outline
def check_collision_with_ball(self, ball):
points = self.get_points()
for i in range(6):
p1 = points[i]
p2 = points[(i + 1) % 6] # Wrap around to the first point
# Line segment to circle collision check:
# 1. Project the ball's center onto the line segment
dx = p2[0] - p1[0]
dy = p2[1] - p1[1]
if dx == 0 and dy == 0: # If the points are the same (degenerate)
continue # Skip the check
segment_length_squared = dx * dx + dy * dy
if segment_length_squared == 0:
continue # Skip the check if the segment has zero length
t = ((ball.x - p1[0]) * dx + (ball.y - p1[1]) * dy) / segment_length_squared
# 2. Clamp t to be within the line segment's bounds (0 to 1)
t = max(0, min(1, t))
# 3. Find the closest point on the segment to the ball's center
closest_x = p1[0] + t * dx
closest_y = p1[1] + t * dy
# 4. Calculate distance from the ball's center to the closest point
distance_x = ball.x - closest_x
distance_y = ball.y - closest_y
distance_squared = distance_x * distance_x + distance_y * distance_y
# 5. Collision Detection and Response
if distance_squared <= ball.radius * ball.radius:
# Collision detected! Calculate normal and reflect.
# Calculate the collision normal (vector perpendicular to the edge)
nx = distance_x / math.sqrt(distance_squared) # Normalize x component
ny = distance_y / math.sqrt(distance_squared) # Normalize y component
# Calculate the dot product of the ball's velocity and the normal
dot_product = ball.velocity_x * nx + ball.velocity_y * ny
# Reflect the velocity vector.
ball.velocity_x -= 2 * nx * dot_product
ball.velocity_y -= 2 * ny * dot_product
# Slight adjustment to prevent the ball from getting stuck
ball.x += nx * (ball.radius - math.sqrt(distance_squared)) # Push ball out
ball.y += ny * (ball.radius - math.sqrt(distance_squared))
# --- Initialize ---
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Bouncing Ball in a Spinning Hexagon")
clock = pygame.time.Clock()
# --- Create Objects ---
ball = Ball(WIDTH // 2, HEIGHT // 2, 15, BALL_COLOR)
hexagon = Hexagon(WIDTH // 2, HEIGHT // 2, 150, HEXAGON_COLOR)
# --- Main Loop ---
running = True
while running:
# --- Event Handling ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# --- Update ---
hexagon.update()
ball.update(hexagon.rotation_angle)
# Collision Detection
hexagon.check_collision_with_ball(ball)
# --- Draw ---
screen.fill(BLACK)
hexagon.draw(screen)
ball.draw(screen)
pygame.display.flip()
# --- Control Frame Rate ---
clock.tick(FPS)
# --- Quit ---
pygame.quit()Editor is loading...
Leave a Comment