python中的对象移动问题



如果你读到这篇文章,我很感谢你抽出时间,并提前感谢你。

因此,我目前的目标是让中子在源(x,y(以随机速度向随机方向发射。

我遇到了一堆相关的问题,我现在用我的知识无法解决(我在编程方面相当缺乏经验(

问题如下:

1。";移动";程序中的方法没有按预期工作=每生成一个新对象(中子类(,对象就会变得更快。

2.

我无法将移动方法分配给"中的对象;中子";单独列出。要么是所有物体都朝着同一方向移动

以相同的速度或仅仅是最后一个元件;中子";列表移动,其余的保持静止。

程序中的示例:

for n in neutrons:
n.draw(screen)
neutrons[-1].move(angle_list, neutr_v_list)  #newest neutron moves, the rest stays still
n.move(angle_list, neutr_v_list)    #Every Neutron moves the same

如果我定义";移动";方法如下:

self.x += math.cos(random.randint(0,360)) * 2
self.y += math.sin(random.randint(0,360)) * 2

在这个循环中发生的是:

for n in neutrons:
n.move()

随机值一次又一次地生成,这导致单个对象不在直线上移动。它们像一只被喂食了咖啡因的蜜蜂一样移动。

目前的最终目标是,当一个物体(在这种情况下是中子(撞击另一个物体时(铀原子(,它应该在碰撞的x、y中产生3个新的中子,这些中子应该朝着随机的方向飞出,并可能撞击到另一个铀原子。

程序的Github链接:https://github.com/Magicalsauce69/Nuclear-simulation-in-python.git

完整代码:

#imports
from typing_extensions import Self
import pygame
#Imports
import pygame as py
import os
import random 
import math
import time
from random import *
import random
#Framerate
FPS = 60
#Creating the lists
angle_list = []
neutrons = []    
neutr_v_list = []

#Colors 
RED = (255, 0, 0)
BLUE = (51, 51, 255)
LIGHT_BLUE = (173,216,230)
WHITE = (255, 255, 255)
PURPLE = (204, 0, 204)
GRAY = (128, 128, 128)

#Creating a window
py.init
WIDTH, HEIGHT = 700, 700  #aspect ratio is  ...
screen = py.display.set_mode((WIDTH, HEIGHT))
py.display.set_caption("Starting to loose it")

#function that gets called in the mainloop that draws stuff on the screen
def draw_screen():
screen.fill(WHITE)
py.display.update()

#The Neutron class
class c_Neutron():
def __init__(self, x, y, r, v, name,):
self.x = x
self.y = y 
self.r = r
self.v = v
self.name = name
self.color = LIGHT_BLUE

def draw(self, screen):
py.draw.circle(screen, self.color, (self.x - self.r, self.y - self.r), self.r, 10)


def move(self, angle_list, neutr_v_list):
self.x += math.cos(angle_list[-1]) * neutr_v_list[-1]    #Im trying to generate random directions and speeds for every neutron specifically
self.y += math.sin(angle_list[-1]) * neutr_v_list[-1]     #Another issue is that they get faster with every neutron generated


#The Uran class

class n_Uran():
def __init__(self, x, y, r,):
self.x = x
self.y = y
self.r = r

self.color = [RED]
def draw(self, screen):
py.draw.circle(screen, self.color, (self.x - self.r, self.y - self.r), self.r, 10)


#Amount of Neutrons
Anz_neutronen = len(neutrons)   #Should return how many elements are in the list
print(Anz_neutronen)


#Mainloop
def main():



clock = pygame.time.Clock()
keydown_list = []


while True:

for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
keydown_list.append(1)
print(len(keydown_list))   
neutrons.append(c_Neutron(200,200,5,random.randint(1,3),"")  )
angle_list.append(random.randint(0, 360))
neutr_v_list.append(random.randint(1, 3))
print(neutrons)

screen.fill(WHITE)

for n in neutrons:                    
n.draw(screen)
neutrons[-1].move(angle_list, neutr_v_list)           #Only the newest neutron moves and the rest stays still
n.move(angle_list, neutr_v_list)                       #Every Neutron moves the same


py.display.update()                           
clock.tick(FPS)
#Run the main game loop
if __name__ == "__main__":
main()

问题1
我没有遇到这个问题;这可能只是在你的考试中偶然发生的。不管怎样,我创建的代码都不会发生这种情况。

问题2
您尝试了两种方法,但都不起作用,原因如下:

  • 当您使用n.move(angle_list, neutr_v_list)时,您将向每个中子传递相同的参数,因此它们当然都以相同的方式移动
  • 使用neutrons[-1].move(angle_list, neutr_v_list)时,neutrons[-1]指的是列表neutrons中的最后一个对象,因此只有最后一个中子被移动

实现这一点的正确方法是将每个中子的角度和速度存储为该神经元的属性,而不是使move方法采用任何属性。

问题3
在这里,您尝试了另一种解决问题2的方法,但由于您在问题中所述的原因,该方法也不起作用。

正确的方法是,当每个中子被创建时,只生成一个随机值,并将其存储为该中子的属性,正如我上面所说的。

工作代码
这是我的工作版本的代码。我还更改了一些其他内容:

  • 格式化和变量名,以适应PEP8
  • 为了避免代码重复,我为NeutronUranium添加了一个要继承的基本Particle
  • pygame.init->pygame.init(),现在在main()内部
  • 将其他一些代码移动到main()内部
  • 删除了重复导入并使PyGame的所有使用都是pygame而不是py
  • 不是计算每个中子的X和Y每次应该改变多少,而是对每个中子使用cached_property只计算一次
  • 其他一些影响不大的小事
import os
import random
import math
import time
import sys
import pygame
try:
# Python 3.8+ only
from functools import cached_property
except ImportError:
# Does the same exact thing, but works on all python versions
# Remove this if guaranteed to be using Python 3.8+
from functools import lru_cache
cached_property = lambda method: property(
lru_cache(maxsize=None)(method)
)
RED = (255, 0, 0)
BLUE = (51, 51, 255)
LIGHT_BLUE = (173, 216, 230)
WHITE = (255, 255, 255)
PURPLE = (204, 0, 204)
GRAY = (128, 128, 128)
FPS = 60
WIDTH, HEIGHT = 900, 600

class Particle:
def __init__(self, x, y, radius, color):
self.x = x
self.y = y
self.radius = radius
self.color = color
def draw(self, screen):
pygame.draw.circle(
screen,
self.color,
(int(self.x - self.radius // 2), int(self.y - self.radius // 2)),
self.radius,
)

class Neutron(Particle):
def __init__(self, x, y, radius, velocity, angle):
super().__init__(x, y, radius, color=LIGHT_BLUE)

self.velocity = velocity
self.angle = angle
@cached_property
def dx(self):
return math.cos(self.angle) * self.velocity
@cached_property
def dy(self):
return math.sin(self.angle) * self.velocity
def move(self):
self.x += self.dx
self.y += self.dy

class Uranium(Particle):
def __init__(self, x, y, radius):
super().__init__(x, y, radius, color=RED)

def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Starting to lose it")

clock = pygame.time.Clock()
neutrons = []
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
neutrons.append(Neutron(
x=int(WIDTH // 2),
y=int(HEIGHT // 2),
radius=5,
velocity=random.randint(1, 3),
angle=random.randint(1, 360)
))
screen.fill(WHITE)
for n in neutrons:
n.draw(screen)
n.move()
pygame.display.update()                           
clock.tick(FPS)

if __name__ == "__main__":
main()

最新更新