Pygame模拟天体运动问题
代码如下:import pygame
pygame.init()
pygame.key.set_repeat(1000, 50)
G = 6
class StarObject:
def __init__(self, x, y, vx, vy, mass):
self.x = x
self.y = y
self.vx = vx
self.vy = vy
self.mass = mass
@property
def info(self):
return self.x, self.y, self.vx, self.vy, self.mass
class StarSprite(pygame.sprite.Sprite):
def __init__(self, name, star, radius, color):
pygame.sprite.Sprite.__init__(self)
self.name = name
self.star = star
self.radius = radius
self.color = color
self.trail = []
self.image = pygame.Surface((radius * 2, radius * 2)).convert_alpha()
self.image.fill((0, 0, 0, 0))
pygame.draw.circle(self.image, color, (radius, radius), radius, 0)
self.rect = self.image.get_rect()
self.rect.center = self.star.x, self.star.y
def flush(self):
self.rect.centerx = (self.star.x + rel) * scale
self.rect.centery = (self.star.y + rel) * scale
self.trail.append((self.star.x, self.star.y))
def __repr__(self):
return self.name
__str__ = __repr__
class Message(pygame.sprite.Sprite):
def __init__(self, text, pos):
pygame.sprite.Sprite.__init__(self)
self._text = text
self.image = font.render(text, False, (255, 255, 255))
self.rect = self.image.get_rect()
self.rect.topright = pos
@property
def text(self):
return self._text
@text.setter
def text(self, text):
pos = self.rect.topright
self._text = text
self.image = font.render(text, False, (255, 255, 255))
self.rect = self.image.get_rect()
self.rect.topright = pos
def get_distance(sprite1, sprite2):
x1, y1 = sprite1.star.x, sprite1.star.y
x2, y2 = sprite2.star.x, sprite2.star.y
dx = x2 - x1
dy = y2 - y1
return (dx ** 2 + dy ** 2) ** 0.5
def is_collide(sprite1, sprite2):
r1, r2 = sprite1.radius, sprite2.radius
return r1 + r2 > get_distance(sprite1, sprite2)
def move(t):
sprites_to_delete = []
for sprite1 in sprites:
star1 = sprite1.star
x1, y1, vx1, vy1, m1 = star1.info
ax1, ay1 = 0, 0
for sprite2 in sprites:
star2 = sprite2.star
if sprite1 in sprites_to_delete or sprite2 in sprites_to_delete:
break
if star1 is star2:
continue
x2, y2, vx2, vy2, m2 = star2.info
dx = x2 - x1
dy = y2 - y1
r = get_distance(sprite1, sprite2)
if is_collide(sprite1, sprite2):
heavier = sprite1 if star1.mass > star2.mass else sprite2
lighter = sprite1 if heavier is star2 else sprite2
sprites_to_delete.append(lighter)
heavier.star.vx += lighter.star.vx
heavier.star.vy += lighter.star.vy
message.text = f"{heavier} 和 {lighter} 相撞"
continue
f = G * m1 * m2 / (r ** 2)
accel = f / m1
ax1 += accel * (dx / r)
ay1 += accel * (dy / r)
x, y = (
x1 + vx1 * t + 0.5 * ax1 * (t ** 2),
y1 + vy1 * t + 0.5 * ay1 * (t ** 2)
)
tempx, tempy = star1.x, star1.y
star1.x, star1.y = x, y
star1.vx = (x - tempx) / t
star1.vy = (y - tempy) / t
sprite1.flush()
for sprite in sprites_to_delete:
sprites.remove(sprite)
size = width, height = (1000, 1000)
screen = pygame.display.set_mode((1000, 1000))
sprites = [
StarSprite("planet1", StarObject(100, 100, 2, 0, 1000), 10, "green"),
StarSprite("planet2", StarObject(800, 100, 0, 2, 1000), 10, "blue"),
StarSprite("planet3", StarObject(800, 800, -2, 0, 1000), 10, "cyan"),
StarSprite("planet4", StarObject(100, 800, 0, -2, 1000), 10, "yellow")
]
font = pygame.font.SysFont("Microsoft YaHei UI", 30)
message = Message("", (width - 10, 10))
clock = pygame.time.Clock()
drag = False
rel =
scale = 1
paused = False
running = True
while running:
screen.fill((0, 0, 0))
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
drag = True
elif event.type == pygame.MOUSEBUTTONUP:
drag = False
elif event.type == pygame.MOUSEMOTION:
if drag:
rel += event.rel
rel += event.rel
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
paused = not paused
elif event.key in (pygame.K_EQUALS, pygame.K_KP_PLUS):
scale += 0.01
elif event.key in (pygame.K_MINUS, pygame.K_KP_MINUS):
scale -= 0.01
if not paused:
move(2)
for sprite, trail in map(lambda xxx: (xxx, xxx.trail), sprites):
if len(trail) < 2:
continue
trail = list(map(lambda point: ((point + rel) * scale, (point + rel) * scale), trail))
pygame.draw.lines(screen, sprite.color, False, trail, 2)
for sprite in sprites:
screen.blit(sprite.image, sprite.rect)
screen.blit(message.image, message.rect)
pygame.display.flip()
pygame.quit()
OpenAI是什么?GPT又是什么?
为什么会出现如下现象?
???自己和自己相撞?我的代码里不是检查过这种情况了吗
OpenAI 是一家人工智能研究实验室和公司,致力于开发先进的人工智能技术。他们开发了许多重要的人工智能模型和系统,其中之一就是 GPT(Generative Pre-trained Transformer)。
GPT 是一种基于 Transformer 模型的自然语言处理模型。它通过大规模的无监督学习从海量的文本数据中抽取知识,然后可以用于生成文本、回答问题、进行对话等任务。GPT 模型在自然语言理解和生成方面表现出色,被广泛应用于各种领域。
关于你提到的现象,自己和自己相撞,可能是因为在代码中的循环遍历过程中,同一个星球对象被重复当作两个不同的 sprite 对象处理了。在 move(t) 函数中的第一个循环遍历中,如果某个 sprite1 和 sprite2 是同一个星球的话,会直接跳过当前迭代,但是在接下来的循环遍历中,两个星球对象又被重新处理了一次,导致自己和自己发生了碰撞。
为了解决这个问题,你可以在内层循环遍历前添加一个判断条件,判断两个 sprite 是否指向同一个星球对象,如果是的话就跳过当前迭代。例如,在内层循环的开始添加以下代码:
if sprite1 is sprite2:
continue
通过这个判断条件,就可以避免同一个星球对象被重复处理,避免自己和自己相撞的情况发生。
如果问题已经解决,请设置最佳答案 这个问题可能是由于你的代码中对碰撞检测的处理方式导致的。在你的代码中,你在检查每个星体的每一个相互作用时,都会检查它们是否发生碰撞。然而,当两个星体发生碰撞时,你将更轻的星体添加到了 sprites_to_delete 列表中,但是在当前的循环中,你并没有立即停止处理更重星体的其余相互作用。
这可能会导致一个问题:如果在同一个时间步中,一个较重的星体与两个较轻的星体相撞,那么当处理第二个碰撞事件时,第一个较轻的星体可能已经在 sprites_to_delete 列表中,但是第二个碰撞事件仍然会被处理,可能导致像"planet1和planet1相撞"这样的输出。
你可以通过添加一个检查来解决此问题,以确保一个星体在同一个时间步中只能发生一次碰撞。另外,你可能还需要调整你的代码,以确保在发生碰撞时立即停止处理当前星体的其他相互作用。
下面是代码片段的修改建议:
def move(t):
sprites_to_delete = []
for sprite1 in sprites:
if sprite1 in sprites_to_delete: # 添加此行
continue # 添加此行
# ...
for sprite2 in sprites:
if sprite1 in sprites_to_delete or sprite2 in sprites_to_delete: # 添加此行
break # 添加此行
# ...
if is_collide(sprite1, sprite2):
heavier = sprite1 if star1.mass > star2.mass else sprite2
lighter = sprite1 if heavier is star2 else sprite2
sprites_to_delete.append(lighter)
heavier.star.vx += lighter.star.vx
heavier.star.vy += lighter.star.vy
message.text = f"{heavier} 和 {lighter} 相撞"
break # 添加此行
# ...
这些修改可以确保在处理一个星体的相互作用时,如果检测到碰撞,我们将立即停止处理其他相互作用,并且如果一个星体已经在待删除列表中,我们将不再处理它的相互作用。
至于OpenAI和GPT,OpenAI是一个人工智能研究实验室,致力于创建和推动友好的AI,以确保人工智能的利益广泛地惠及所有人。GPT(Generative Pretrained Transformer)是OpenAI开发的一种自然语言处理(NLP)预训练模型,它能够生成类似人类的文本。 Mike_python小 发表于 2023-7-24 10:43
OpenAI 是一个人工智能研究实验室,致力于推动人工智能的发展和应用。他们开发了许多先进的技术和模型,其 ...
{:10_256:}中计了 isdkz 发表于 2023-7-24 10:43
这个问题可能是由于你的代码中对碰撞检测的处理方式导致的。在你的代码中,你在检查每个星体的每一个相互作 ...
加了还是这样,还有就算重复碰撞也不会和自己撞啊 heavier = sprite1 if star1.mass > star2.mass else sprite2
lighter = sprite1 if heavier is star2 else sprite2
应该是这里的问题 cjjJasonchen 发表于 2023-7-24 11:18
应该是这里的问题
没问题吧 加了打印
print(sprite1,sprite2)
print(heavier == lighter, sprite1 == sprite2
这是结果:
pygame 2.3.0 (SDL 2.24.2, Python 3.10.10)
Hello from the pygame community. https://www.pygame.org/contribute.html
planet1 planet2
True False cjjJasonchen 发表于 2023-7-24 11:20
加了打印
这是结果:
{:10_257:}所以是哪一步出错了? 改成这样:
heavier = sprite1 if star1.mass > star2.mass else sprite2
lighter = sprite2 if heavier is star2 else sprite1 你再试试应该可以了 cjjJasonchen 发表于 2023-7-24 11:22
改成这样:
居然搞反了{:10_257:}你很厉害{:10_327:} 谢谢你捏,你的代码写的好漂亮,装饰器我还没学,很多地方看不懂大约猜了一下竟然对了,一会去学一下装饰器{:10_328:} cjjJasonchen 发表于 2023-7-24 11:25
谢谢你捏,你的代码写的好漂亮,装饰器我还没学,很多地方看不懂大约猜了一下竟然对了,一会去学一下装饰器 ...
这不是装饰器吧,这个类似c的三目表达式
xxx if yyy else zzz
if xxx:
yyy
else:
zzz @property 这个{:10_297:} 歌者文明清理员 发表于 2023-7-24 11:26
这不是装饰器吧,这个类似c的三目表达式
xxx if yyy else zzz
if xxx:
三元表达式我还是看得懂的{:10_297:} cjjJasonchen 发表于 2023-7-24 11:28
@property 这个
哦,那个是将属性改造成类似函数的作用,甚至可以在里面执行其他语句,这就起到了监视属性操作的作用
还可以避免使用 __dict__ 偷窥 歌者文明清理员 发表于 2023-7-24 11:30
哦,那个是将属性改造成类似函数的作用,甚至可以在里面执行其他语句,这就起到了监视属性操作的作用
还 ...
{:10_257:}这样啊! 谢谢你
期待你的后续作品,我要去手搓教程啦{:10_256:} 你好厉害{:10_257:}有qq吗,私聊 Ewan-Ahiouy 发表于 2023-7-24 12:07
你好厉害有qq吗,私聊
不想用qq,去hack.chat?liu2023
页:
[1]
2