Chat
Search
Ithy Logo

Spinning Hexagon with Bouncing Ball Simulation in Python

A Python implementation using Pygame for realistic physics

rotating hexagon with bouncing ball

Key Insights

  • Realistic Physics: The simulation includes gravity, friction, and elastic collision responses when the ball hits the hexagon walls.
  • Hexagon Rotation: The hexagon rotates continuously, and the ball’s collision response is calculated relative to the dynamically transformed edges.
  • Structured Pygame Code: The implementation is divided into clear sections (initialization, classes for the ball and hexagon, collision handling, and drawing/updating) for readability and further modification.

Below is a complete Python code implementation that simulates a ball bouncing inside a spinning hexagon. The simulation is built using Pygame and factors in gravity and friction. The code is structured to first set up the simulation environment, then define the classes for both the ball and the hexagon, and finally put everything together in a main loop that handles updating positions, processing collisions, and drawing the graphics on the screen.

Overview of the Implementation

Initialization and Environment Setup

The program initializes Pygame and sets up the display window. Constants such as screen width, height, gravity, and friction are established. The hexagon’s vertices are computed based on its radius and center coordinates to form the boundary.

Defining the Ball and Hexagon Classes

Two main classes are defined:

  • Ball Class: Contains attributes for position, velocity, and radius. The update method is responsible for applying gravity and friction to the ball's movement. The collision response with the spinning hexagon is handled in a dedicated method that calculates the wall normals and reflects the velocity vector appropriately.
  • Hexagon Class: Responsible for maintaining the current rotation angle and computing the positions of its six vertices after applying rotation. The rotation provides a dynamic environment affecting how the ball bounces.

Collision Detection and Response

Collision detection involves checking the distance from the ball’s center to each edge of the hexagon and determining if the ball is penetrating an edge. Upon collision, the velocity is reflected relative to the surface normal, and an energy loss factor simulates inelastic bounce while friction slows the ball.

Main Simulation Loop

The main loop updates the ball’s position, updates the hexagon’s rotation, checks for collisions, and renders both objects on the screen. The loop runs at a fixed frame rate to maintain smooth animation.


Python Code Implementation

Below is the complete Python code. You can run this script in an environment with Pygame installed.


# Importing necessary libraries
import pygame
import math

# Initialize Pygame and create display window
pygame.init()
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Bouncing Ball in Spinning Hexagon")
clock = pygame.time.Clock()

# Define colors and physics constants
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GRAVITY = 0.2       # Gravity acceleration per frame
FRICTION = 0.99     # Friction coefficient for ball's velocity reduction

# Class representing the bouncing ball with physics updates and collision handling
class Ball:
    def __init__(self, x, y, radius):
        self.x = x
        self.y = y
        self.radius = radius
        self.vx = 5          # Initial horizontal velocity
        self.vy = -5         # Initial vertical velocity
        self.gravity = GRAVITY
        self.friction = FRICTION

    def update(self):
        # Apply gravity to vertical velocity
        self.vy += self.gravity
        # Update position based on the current velocity
        self.x += self.vx
        self.y += self.vy
        # Apply friction to both velocity components
        self.vx *= self.friction
        self.vy *= self.friction

    def draw(self, surface):
        pygame.draw.circle(surface, RED, (int(self.x), int(self.y)), self.radius)

    def bounce_off_edge(self, p1, p2):
        # Calculate the edge vector from p1 to p2
        edge_dx = p2[0] - p1[0]
        edge_dy = p2[1] - p1[1]
        edge_length = math.sqrt(edge_dx <b> 2 + edge_dy </b> 2)

        # Calculate the unit normal vector for the edge (-dy, dx) normalized
        normal_x = -(edge_dy) / edge_length
        normal_y = (edge_dx) / edge_length

        # Compute vector from one vertex to the ball center
        vx = self.x - p1[0]
        vy = self.y - p1[1]
        # Dot product between velocity vector and the normal vector
        dot = self.vx * normal_x + self.vy * normal_y

        # Reflect the ball's velocity across the collision normal with energy loss
        self.vx -= 2 * dot * normal_x
        self.vy -= 2 * dot * normal_y
        self.vx *= 0.9
        self.vy *= 0.9

    def handle_collision(self, hex_vertices):
        # Check collision with each edge of the hexagon
        for i in range(6):
            p1 = hex_vertices[i]
            p2 = hex_vertices[(i + 1) % 6]  # Wrap around

            # Compute line equation parameters for edge p1 to p2
            edge_dx = p2[0] - p1[0]
            edge_dy = p2[1] - p1[1]
            edge_length = math.sqrt(edge_dx <b> 2 + edge_dy </b> 2)
            if edge_length == 0:
                continue  # Prevent division by zero

            # Find the distance from the ball's center to the edge
            distance = abs(edge_dy * self.x - edge_dx * self.y + p2[0]*p1[1] - p2[1]*p1[0]) / edge_length

            # Simple collision check: if the ball is very close to the edge
            if distance <= self.radius:
                # Adjust position to overcome penetration (optional)
                self.bounce_off_edge(p1, p2)

# Class representing the rotating hexagon container
class SpinningHexagon:
    def __init__(self, center, radius, rotation_speed):
        self.center = center
        self.radius = radius
        self.rotation_speed = rotation_speed
        self.angle = 0  # Initial rotation angle

    def update(self):
        # Increase rotation angle over time
        self.angle += self.rotation_speed

    def get_vertices(self):
        vertices = []
        cx, cy = self.center
        for i in range(6):
            # Calculate each vertex angle; add current rotation angle for spinning effect
            theta = self.angle + i * math.pi / 3
            x = cx + self.radius * math.cos(theta)
            y = cy + self.radius * math.sin(theta)
            vertices.append((x, y))
        return vertices

    def draw(self, surface):
        vertices = self.get_vertices()
        pygame.draw.polygon(surface, WHITE, vertices, 2)

# Main simulation loop combining hexagon rotation, ball movement, and collision handling
def main():
    hexagon = SpinningHexagon(center=(WIDTH // 2, HEIGHT // 2), radius=200, rotation_speed=0.02)
    ball = Ball(WIDTH // 2, HEIGHT // 2 - 150, radius=20)

    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        # Update simulation physics
        ball.update()
        hexagon.update()

        # Get current hexagon vertices after rotation
        vertices = hexagon.get_vertices()
        ball.handle_collision(vertices)

        # Drawing section
        screen.fill(BLACK)
        hexagon.draw(screen)
        ball.draw(screen)
        pygame.display.flip()

        clock.tick(60)  # Limit the frame rate to 60 FPS

    pygame.quit()

if __name__ == "__main__":
    main()
  

Supplementary Information

The code above is organized to provide readability and ease of future enhancements. Here is an overview of its structure and key parameters:

Component Description
Ball Physics Applies gravity, friction, and uses vector reflection for wall collisions.
Hexagon Rotation The hexagon’s vertices are computed dynamically based on a continuously updating rotation angle.
Collision Detection Checks proximity of the ball to each hexagon edge and reflects the velocity vector upon contact.

This implementation has been designed with clarity in mind. The performance of the simulation depends on the chosen physics parameters, such as the gravity constant, friction coefficient, and energy loss during collisions. You can adjust these values to achieve the desired simulation effect.


References

Recommended Further Queries


Last updated February 28, 2025
Ask Ithy AI
Export Article
Delete Article