Untitled
unknown
plain_text
2 months ago
5.3 kB
3
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