gpt4 book ai didi

python - 相互吸引的粒子无法正常工作

转载 作者:太空宇宙 更新时间:2023-11-03 15:31:27 24 4
gpt4 key购买 nike

我试图让粒子在 Python 中相互吸引。它有点工作,但它们总是移动到左上角 (0;0)。

一年前,CodeParade 发布了 video about a game of life he made with particles .我觉得它很酷,想用 Python 自己重新创建它。这并不难,但我有一个问题。每当一些粒子靠得足够近以相互吸引时,它们就会靠得更近一点,但同时它们会“跑”到恰好是 (0;0) 的左上角。我起初以为我没有正确应用吸引力效果,但在多次重新阅读后我没有发现任何错误。有人知道为什么它不能按预期工作吗?

/这是代码/

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygame, random, time
import numpy as np

attraction = [ [-2.6,8.8,10.2,0.7],
[4.1,-3.3,-3.1,4.4],
[0.6,3.7,-0.4,5.1],
[-7.8,0.3,0.3,0.0]]

minR = [[100.0,100.0,100.0,100.0],
[100.0,100.0,100.0,100.0],
[100.0,100.0,100.0,100.0],
[100.0,100.0,100.0,100.0]]

maxR = [[41.7,16.4,22.1,15.0],
[16.4,41.7,32.0,75.1],
[22.1,32.0,55.7,69.9],
[15.0,75.1,69.9,39.5]]

colors = [ (200,50,50),
(200,100,200),
(100,255,100),
(50,100,100)]

#Rouge
#Violet
#Vert
#Cyan

particles = []

#Number of particles
numberParticles = 5

#Width
w = 500

#Height
h = 500

#Radius of particles
r = 4

#Rendering speed
speed = 0.05

#Attraction speed factor
speedFactor = 0.01

#Min distance factor
minRFactor = 0.1

#Max distance factor
maxRFactor = 2

#Attraction factor
attractionFactor = 0.01

def distance(ax, ay, bx, by):
return intg((ax - bx)**2 + (ay - by)**2)

def intg(x):
return int(round(x))

def display(plan):
#Fill with black
#Momentarily moved to main
#pygame.Surface.fill(plan,(0,0,0))

#For each particle, draw it
for particle in particles:
pygame.draw.circle(plan,colors[particle[0]],(particle[1],particle[2]),r)

#Update display
pygame.display.flip()

def update(particles):
newParticles = []

for particleIndex in xrange(len(particles)):
typeId, x, y = particles[particleIndex]

othersX = [[],[],[],[]]
othersY = [[],[],[],[]]

#For every other particles
for otherParticle in particles[0:particleIndex]+particles[particleIndex+1:]:

otherTypeId, otherX, otherY = otherParticle


"""
#Draw minR and maxR of attraction for each color
pygame.draw.circle(screen,colors[otherTypeId],(x,y),intg(minR[typeId][otherTypeId] * minRFactor),1)
pygame.draw.circle(screen,colors[otherTypeId],(x,y),intg(maxR[typeId][otherTypeId] * maxRFactor),1)
"""

#If otherParticle is between minR and maxR from (x;y)
if (minR[typeId][otherTypeId] * minRFactor)**2 <= distance(x,y,otherX,otherY) <= (maxR[typeId][otherTypeId] * maxRFactor)**2:

#Append otherParticle's coordinates to othersX and othersY respectively
othersX[otherTypeId].append(otherX)
othersY[otherTypeId].append(otherY)

#Take the average attractions for each color
othersX = [np.mean(othersX[i]) * attraction[typeId][i] * attractionFactor for i in xrange(len(othersX)) if othersX[i] != []]
othersY = [np.mean(othersY[i]) * attraction[typeId][i] * attractionFactor for i in xrange(len(othersY)) if othersY[i] != []]

#If not attracted, stay in place
if othersX == []:
newX = x

else:

#Take the average attraction
avgX = np.mean(othersX)

#Determine the new x position
newX = x - (x - avgX) * speedFactor

#If out of screen, warp
if newX > w:
newX -= w

elif newX < 0:
newX += w

#If not attracted, stay in place
if othersY == []:
newY = y

else:

#Take the average attraction
avgY = np.mean(othersY)

#Determine the new y position
newY = y - (y - avgY) * speedFactor

#If out of screen, warp
if newY > h:
newY -= h

elif newY < 0:
newY += h

#Append updated particle to newParticles
newParticles.append([typeId,intg(newX),intg(newY)])

return newParticles

if __name__ == "__main__":

#Initialize pygame screen
pygame.init()
screen = pygame.display.set_mode([w,h])

#Particle = [type,posX,posY]
#Create randomly placed particles of random type
for x in xrange(numberParticles):
particles.append([random.randint(0,3),random.randint(0,w),random.randint(0,h)])

display(screen)

#Wait a bit
time.sleep(1)

while True:
#raw_input()
#Fill the screen with black
pygame.Surface.fill(screen,(0,0,0))

#Update particles
particles = update(particles)

#Display particles
display(screen)

#Wait a bit
time.sleep(speed)

最佳答案

问题在于:

othersX = [np.mean(othersX[i]) * attraction[typeId][i] * attractionFactor for i in range(len(othersX)) if othersX[i] != []]
othersY = [np.mean(othersY[i]) * attraction[typeId][i] * attractionFactor for i in range(len(othersY)) if othersY[i] != []]

othersXothersY 应该是位置,但由于坐标乘以 attraction[typeId][i] * attractionFactor,坐标移到左上角。

这可以通过忽略以下因素轻松评估:

othersX = [np.mean(othersX[i]) for i in range(len(othersX)) if othersX[i] != []]
othersY = [np.mean(othersY[i]) for i in range(len(othersY)) if othersY[i] != []]

一种选择是使用向量形式 (x, y) 到 (otherX, otherY) 而不是比职位:

for otherParticle in particles[0:particleIndex]+particles[particleIndex+1:]:
otherTypeId, otherX, otherY = otherParticle

if (minR[typeId][otherTypeId] * minRFactor)**2 <= distance(x,y,otherX,otherY) <= (maxR[typeId][otherTypeId] * maxRFactor)**2:

# Append otherParticle's coordinates to othersX and othersY respectively
othersX[otherTypeId].append(otherX - x)
othersY[otherTypeId].append(otherY - y)

othersX = [np.mean(othersX[i]) * attraction[typeId][i] * attractionFactor for i in range(len(othersX)) if othersX[i] != []]
othersY = [np.mean(othersY[i]) * attraction[typeId][i] * attractionFactor for i in range(len(othersY)) if othersY[i] != []]

当然,您也必须调整新位置的计算:

avgX = np.mean(othersX)
newX = x + avgX * speedFactor
avgY = np.mean(othersY)
newY = y + avgY * speedFactor

如另一个答案中所述,您应该使用 float 进行计算:

def distance(ax, ay, bx, by):
# return intg((ax - bx)**2 + (ay - by)**2)
return (ax - bx)**2 + (ay - by)**2
# newParticles.append([typeId,intg(newX),intg(newY)])
newParticles.append([typeId, newX, newY])

但是当你画圆的时候四舍五入到整数坐标:

for particle in particles:
# pygame.draw.circle(plan,colors[particle[0]],(particle[1],particle[2]),r)
pygame.draw.circle(plan,colors[particle[0]],(intg(particle[1]),intg(particle[2])),r)

关于python - 相互吸引的粒子无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57679202/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com