Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import pygame
- import math
- import numpy as np
- # Initialize Pygame
- pygame.init()
- # Window settings
- WIDTH = 800
- HEIGHT = 800
- CENTER = (WIDTH // 2, HEIGHT // 2)
- screen = pygame.display.set_mode((WIDTH, HEIGHT))
- pygame.display.set_caption("Bouncing Ball in Spinning Hexagon")
- # Colors
- WHITE = (255, 255, 255)
- BLACK = (0, 0, 0)
- RED = (255, 0, 0)
- BLUE = (0, 0, 255)
- # Ball properties
- ball_radius = 15
- ball_pos = np.array([float(CENTER[0]), float(CENTER[1])])
- ball_velocity = np.array([5.0, -10.0]) # Initial velocity (x, y)
- gravity = 0.3
- friction = 0.99 # Air resistance
- elasticity = 0.8 # Energy loss on bounce
- # Hexagon properties
- hex_radius = 200
- hex_angle = 0 # Rotation angle in radians
- hex_rotation_speed = 0.02 # Radians per frame
- hex_vertices = []
- # Calculate initial hexagon vertices
- def calculate_hex_vertices():
- vertices = []
- for i in range(6):
- angle = hex_angle + (i * math.pi / 3)
- x = CENTER[0] + hex_radius * math.cos(angle)
- y = CENTER[1] + hex_radius * math.sin(angle)
- vertices.append(np.array([x, y]))
- return vertices
- # Get line segment between two vertices
- def get_hex_sides(vertices):
- sides = []
- for i in range(6):
- sides.append((vertices[i], vertices[(i + 1) % 6]))
- return sides
- # Vector operations
- def dot_product(v1, v2):
- return np.dot(v1, v2)
- def normalize(v):
- return v / np.linalg.norm(v) if np.linalg.norm(v) > 0 else v
- # Check collision between ball and line segment
- def check_collision(ball_pos, ball_radius, p1, p2):
- # Vector from p1 to p2
- line_vec = p2 - p1
- # Vector from p1 to ball center
- point_vec = ball_pos - p1
- line_len = np.linalg.norm(line_vec)
- if line_len == 0:
- return False, None
- line_unit = line_vec / line_len
- # Project point_vec onto line_unit
- t = max(0, min(line_len, dot_product(point_vec, line_unit)))
- # Get closest point on line
- projection = p1 + t * line_unit
- # Distance from ball center to closest point
- distance = np.linalg.norm(ball_pos - projection)
- if distance <= ball_radius:
- # Collision detected
- normal = normalize(ball_pos - projection)
- return True, normal
- return False, None
- # Handle collision response
- def handle_collision(ball_pos, ball_velocity, normal):
- # Reflect velocity across normal
- v_dot_n = dot_product(ball_velocity, normal)
- reflected_velocity = ball_velocity - 2 * v_dot_n * normal
- # Apply elasticity (energy loss)
- return reflected_velocity * elasticity
- # Game loop
- clock = pygame.time.Clock()
- running = True
- while running:
- # Handle events
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- running = False
- # Update hexagon rotation
- hex_angle += hex_rotation_speed
- hex_vertices = calculate_hex_vertices()
- hex_sides = get_hex_sides(hex_vertices)
- # Apply gravity and friction
- ball_velocity[1] += gravity
- ball_velocity *= friction
- # Update ball position
- ball_pos += ball_velocity
- # Check for collisions with hexagon walls
- for p1, p2 in hex_sides:
- collided, normal = check_collision(ball_pos, ball_radius, p1, p2)
- if collided:
- ball_velocity = handle_collision(ball_pos, ball_velocity, normal)
- # Push ball out of wall to prevent sticking
- penetration = ball_radius - np.linalg.norm(ball_pos - (p1 + (p2 - p1) *
- dot_product(ball_pos - p1, p2 - p1) / np.linalg.norm(p2 - p1)**2))
- if penetration > 0:
- ball_pos += normal * penetration
- # Clear screen
- screen.fill(BLACK)
- # Draw hexagon
- pygame.draw.polygon(screen, WHITE, [(v[0], v[1]) for v in hex_vertices], 2)
- # Draw ball
- pygame.draw.circle(screen, RED, (int(ball_pos[0]), int(ball_pos[1])), ball_radius)
- # Update display
- pygame.display.flip()
- clock.tick(60)
- pygame.quit()
Advertisement
Add Comment
Please, Sign In to add comment