为什么球如此不稳定?

3

这是一个物理模拟,将球限制在圆形区域内。

我最初使用Scratch编写了原始代码,并在Pygame中将其转换为Python。 当我运行模拟时,所有的球都在晃动,与原始代码相比。

我将速度限制为最大20,但没有帮助。

我为每个帧创建了子步骤,但也没有帮助。

import pygame
import math
import random

screen = pygame.display.set_mode((16*120,9*120))
pygame.display.set_caption('')
clock = pygame.time.Clock()

mx = 16*60
my = 9*60

global x
global y
x = []
y = []
xv = []
yv = []
prevx = []
prevy = []

for i in range(20):
    x.append(random.randint(-200,200))
    y.append(random.randint(-200,200))
    xv.append(0)
    yv.append(0)
    prevx.append(0)
    prevy.append(0)

r = 25
size = 300

sub = 20
maxvel = 20

global dist
global dx
global dy
global d

#points at something
def pointat(px,py):
    global d
    dx = px-x[i]
    dy = py-y[i]

    if dy == 0:
        if dx < 0:
            d = -90
        else:
            d = 90
    else:
        if dy < 0:
            d = 180+math.atan(dx/dy)
        else:
            d = math.atan(dx/dy)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
    screen.fill((10,10,10))
    pygame.draw.circle(screen,(100,100,100),(mx,my),size)
    for i in range(len(x)):
        pygame.draw.circle(screen,(255,255,255),(mx+x[i],my+y[i]*-1),r)

    for i in range(len(x)):
        prevx[i] = x[i]
        prevy[i] = y[i]
        for j in range(sub):

            x[i] += xv[i]/sub
            y[i] += yv[i]/sub

            y[i] -= 1/sub
            
            a = 0
            for k in range(len(x)-1):
                if a == i:
                    a += 1
                dist = math.sqrt(((x[i]-x[a])*(x[i]-x[a]))+((y[i]-y[a])*(y[i]-y[a])))
                if dist < r*2:
                    pointat(x[a],y[a])
                    x[i] += (math.sin(d)*(dist-(r*2)))
                    y[i] += (math.cos(d)*(dist-(r*2)))
                    x[a] -= (math.sin(d)*(dist-(r*2)))
                    y[a] -= (math.cos(d)*(dist-(r*2)))
                
                dist = math.sqrt((x[i]*x[i])+(y[i]*y[i]))
                if dist > size-r:
                    pointat(0,0)
                    x[i] += (math.sin(d)*(dist-(size-r)))
                    y[i] += (math.cos(d)*(dist-(size-r)))
                a += 1

        xv[i] = x[i]-prevx[i]
        yv[i] = y[i]-prevy[i]
        if xv[i] > maxvel:
            xv[i] = maxvel
        if xv[i] < -maxvel:
            xv[i] = -maxvel
        if yv[i] > maxvel:
            yv[i] = maxvel
        if yv[i] < -maxvel:
            yv[i] = -maxvel

    pygame.display.update()
    clock.tick(60)

你是否尝试过简单地增加帧率,例如将 clock.tick(60) 改为 clock.tick(600) - Caridorc
1个回答

3

math 模块中的三角函数的角度是以弧度而非度数来衡量的。 d 不应该是全局变量,你可以直接从 pointat 返回角度:

def pointat(px,py):
    dx = px-x[i]
    dy = py-y[i]

    if dy == 0:
        if dx < 0:
            d = -math.pi/2
        else:
            d = math.pi/2
    else:
        if dy < 0:
            d = math.pi+math.atan(dx/dy)
        else:
            d = math.atan(dx/dy)
    return d

while True:
    # [...]

    for i in range(len(x)):
        # [...]
        for j in range(sub):
            # [...]

            for k in range(len(x)-1):
                if a == i:
                    a += 1
                dist = math.sqrt(((x[i]-x[a])*(x[i]-x[a]))+((y[i]-y[a])*(y[i]-y[a])))
                if dist < r*2:
                    d = pointat(x[a],y[a])
                    x[i] += (math.sin(d)*(dist-(r*2)))
                    y[i] += (math.cos(d)*(dist-(r*2)))
                    x[a] -= (math.sin(d)*(dist-(r*2)))
                    y[a] -= (math.cos(d)*(dist-(r*2)))
                
                dist = math.sqrt((x[i]*x[i])+(y[i]*y[i]))
                if dist > size-r:
                    d = pointat(0,0)
                    x[i] += (math.sin(d)*(dist-(size-r)))
                    y[i] += (math.cos(d)*(dist-(size-r)))
                a += 1

总的来说,循环中的代码可以大大简化。我建议按照以下方式重构您的代码:

while True:
    # [...]

    for i in range(len(x)):
        prevx[i] = x[i]
        prevy[i] = y[i]
        
        for j in range(sub):
            x[i] += xv[i]/sub
            y[i] += yv[i]/sub
            y[i] -= 1/sub
            
            for a in range(len(x)):
                if a == i:
                   continue
                dx = x[i]-x[a]
                dy = y[i]-y[a]   
                dist = math.sqrt(dx*dx + dy*dy)
                if dist < r*2 and dist != 0:
                    x[i] -= dx/dist * (dist-r*2)
                    y[i] -= dy/dist * (dist-r*2)
                    x[a] += dx/dist * (dist-r*2)
                    y[a] += dy/dist * (dist-r*2)
                
                dist = math.sqrt(x[i]*x[i] + y[i]*y[i])
                if dist > size-r:
                    x[i] -= x[i]/dist * (dist-(size-r))
                    y[i] -= y[i]/dist * (dist-(size-r))

        xv[i] = max(-maxvel, min(maxvel, x[i]-prevx[i]))
        yv[i] = max(-maxvel, min(maxvel, y[i]-prevy[i]))

非常感谢!现在稳定多了! - just_banana3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接