点与列表中包含的线的距离

问题描述 投票:0回答:1

我正在为一个项目制作一个Python动画,在该项目中,我采用了一个星形边界,其中有两个球在该星形内部移动。如果球与其他球碰撞,则会形成一个新球。星形边界充当房间的墙壁,如果球接触到它,就会被弹开(根据反射角度),我面临的问题是如何定义弹跳函数,我使用线段制作了星形,所有这些线段都存储在一个列表中。我想这样定义它,如果列表中的任何线段与球之间的距离小于球的半径,那么它就会被弹开。问题是,如果我定义该函数,那么它会采用直线的完整方程,并且作为星形边界的直线(如果延伸)也会穿过星形内部,并且球会从那些看不见的线弹开。我如何定义该函数仅适用于线段而不适用于延长线。我为一个圆做了这个动画,用圆处理它很容易,因为只有一条线“该圆的周长”来定义函数。这是圆的工作代码。

import pygame
import sys
import math
import random

# Initialize Pygame
pygame.init()

# Set up the window
width, height = 600, 600
window = pygame.display.set_mode((width, height))
pygame.display.set_caption("Bouncing Balls Inside a Circle")

# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 0, 255), (0, 255, 255)]

# Circle parameters
circle_center = (width // 2, height // 2)
circle_radius = 200
circle_thickness = 3

# Ball parameters
ball_radius = 10
balls = []

# Function to create a new ball with a random color
def create_ball():
    angle = random.uniform(0, 2 * math.pi)
    distance = random.uniform(0, circle_radius - ball_radius)
    x = circle_center[0] + distance * math.cos(angle)
    y = circle_center[1] + distance * math.sin(angle)
    speed = [random.choice([-.25, .25]), random.choice([-.25, .25])]  # Random initial speed
    color = random.choice(colors)
    return {"pos": [x, y], "speed": speed, "color": color}

# Function to check collision between balls
def check_collision(ball1, ball2):
    dist = math.sqrt((ball1["pos"][0] - ball2["pos"][0]) ** 2 + (ball1["pos"][1] - ball2["pos"][1]) ** 2)
    return dist <= 2 * ball_radius

# Function to handle collision and ball bouncing
def handle_collision(ball1, ball2):
    dx = ball2["pos"][0] - ball1["pos"][0]
    dy = ball2["pos"][1] - ball1["pos"][1]
    distance = math.sqrt(dx ** 2 + dy ** 2)
    overlap = 2 * ball_radius - distance
    normal_x = dx / distance
    normal_y = dy / distance
    correction = [overlap * normal_x, overlap * normal_y]
    ball1["pos"][0] -= correction[0]
    ball1["pos"][1] -= correction[1]
    ball2["pos"][0] += correction[0]
    ball2["pos"][1] += correction[1]

    # Calculate reflection angles
    dot_product1 = ball1["speed"][0] * normal_x + ball1["speed"][1] * normal_y
    dot_product2 = ball2["speed"][0] * normal_x + ball2["speed"][1] * normal_y

    reflect_x1 = ball1["speed"][0] - 2 * dot_product1 * normal_x
    reflect_y1 = ball1["speed"][1] - 2 * dot_product1 * normal_y
    reflect_x2 = ball2["speed"][0] - 2 * dot_product2 * normal_x
    reflect_y2 = ball2["speed"][1] - 2 * dot_product2 * normal_y

    ball1["speed"] = [reflect_x1, reflect_y1]
    ball2["speed"] = [reflect_x2, reflect_y2]

# Function to add a new ball to the circle
def add_new_ball():
    if len(balls) > 0:
        balls.append(create_ball())

# Add two initial balls
balls.append(create_ball())
balls.append(create_ball())

# Main loop
while True:
    window.fill(BLACK)

    # Check for events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    # Update ball positions
    for ball in balls:
        ball["pos"][0] += ball["speed"][0]
        ball["pos"][1] += ball["speed"][1]

    # Check if any two balls collide
    for i in range(len(balls)):
        for j in range(i + 1, len(balls)):
            if check_collision(balls[i], balls[j]):
                handle_collision(balls[i], balls[j])
                add_new_ball()  # Add a new ball if collision occurs

    # Check if the balls hit the walls of the circle
    for ball in balls:
        distance_to_center = math.sqrt((ball["pos"][0] - circle_center[0]) ** 2 + (ball["pos"][1] - circle_center[1]) ** 2)
        if distance_to_center + ball_radius >= circle_radius:
            # Calculate reflection angle
            dx, dy = ball["speed"]
            normal_x = ball["pos"][0] - circle_center[0]
            normal_y = ball["pos"][1] - circle_center[1]
            mag_normal = math.sqrt(normal_x ** 2 + normal_y ** 2)
            normal_x /= mag_normal
            normal_y /= mag_normal
            dot_product = dx * normal_x + dy * normal_y
            reflect_x = dx - 2 * dot_product * normal_x
            reflect_y = dy - 2 * dot_product * normal_y
            ball["speed"][0] = reflect_x
            ball["speed"][1] = reflect_y

    # Draw the circle
    pygame.draw.circle(window, WHITE, circle_center, circle_radius, circle_thickness)

    # Draw the balls
    for ball in balls:
        pygame.draw.circle(window, ball["color"], (int(ball["pos"][0]), int(ball["pos"][1])), ball_radius)

    pygame.display.flip()

我只想用星形边界替换圆形边界。任何帮助表示赞赏。 谢谢你。

python math random pygame sys
1个回答
0
投票
  • 您的帖子被否决的原因是您要求我们修改您当前的程序并为您添加功能。

现在,我不会为你重写你的程序,但可以通过以下方式找到解决方案:

a.定义一颗星。您提到了一个很棒的“列表”,您的列表看起来类似于

star_points = [ (x, y) ]
,其中 x,y 是星形每个节点的坐标。然后你只需称呼它为
pnt1 = star_points[z]

b.由于圆圈不是星星,因此您需要重新设计碰撞和弹跳函数。

有事请更新!

© www.soinside.com 2019 - 2024. All rights reserved.