|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 歌者文明清理员 于 2023-2-12 11:43 编辑
源代码
只要看第 129 到 133 行就行了
- # -*- coding: utf-8 -*-
- import pygame
- import math
- import numpy as np
- import random
- from trail import TrailSprite
- from tkinter import *
- pygame.init()
- G = 1
- pygame.time.set_timer(pygame.USEREVENT, 5000)
- class Star(pygame.sprite.Sprite, TrailSprite):
- def __init__(self, radius, mass, init_speed, pos):
- pygame.sprite.Sprite.__init__(self)
- self.radius = radius
- self.mass = mass
- self.color = rand_color()
- if init_speed:
- self.speed = init_speed
- self.image = pygame.Surface((radius * 2, radius * 2)).convert_alpha()
- self.image.fill((0, 0, 0, 0))
- pygame.draw.circle(self.image, self.color, (radius, radius), radius)
- TrailSprite.__init__(self, self.color, self.image, 1)
- TrailSprite.set_screen(self, screen)
- self.rect.center = pos
- def move(self):
- TrailSprite.update(self)
- self.rect.centerx += self.speed[0]
- self.rect.centery += self.speed[1]
- # 跑出窗口从另一边回来
- if self.rect.left <= 0 or self.rect.right >= width:
- self.rect.centerx %= width
- self.clear_trail()
- if self.rect.top <= 0 or self.rect.bottom >= height:
- self.rect.centery %= height
- self.clear_trail()
- def all_clear_trail():
- for st in stars:
- st.clear_trail()
- def rand_color():
- r = random.randint(0, 255)
- g = random.randint(0, 255)
- b = random.randint(0, 255)
- return r, g, b
- def set_speed():
- global step
- if not entry.get().isdigit():
- return
- step = entry.get()
- root.destroy()
- pygame.init()
- size = width, height = 640, 480
- bg = (0, 0, 0)
- screen = pygame.display.set_mode(size)
- pygame.display.set_caption("StarMotionSimulator")
- stars = [] # 随机生成天体
- clock = pygame.time.Clock()
- step = 1
- stop_moving = False
- down = False
- star_pos = (0, 0)
- rel = [0, 0]
- running = True
- while running:
- clock.tick(60)
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- running = False
- elif event.type == pygame.KEYDOWN:
- if event.key == pygame.K_SPACE:
- stop_moving = not stop_moving
- all_clear_trail()
- elif event.key == pygame.K_r:
- stars.clear()
- elif event.key == pygame.K_s:
- root = Tk()
- root.title('SpeedEditor')
- root.geometry('100x50')
- label = Label(root, text='Speed')
- label.pack()
- entry = Entry(root)
- entry.pack()
- submit = Button(root, text='Confirm')
- submit['command'] = set_speed
- submit.pack()
- root.mainloop()
- elif event.type == pygame.MOUSEBUTTONDOWN:
- if not down:
- star_pos = event.pos
- down = True
- elif event.type == pygame.MOUSEBUTTONUP:
- down = False
- star = Star(5, 100, (-rel[0] // 4, -rel[1] // 4), event.pos)
- stars.append(star)
- rel.clear()
- rel.extend((0, 0))
- elif event.type == pygame.MOUSEMOTION:
- if down: # 按下 + 移动 = 拖动
- rel[0] += event.rel[0]
- rel[1] += event.rel[1]
- elif event.type == pygame.USEREVENT:
- all_clear_trail()
- screen.fill((0, 0, 0))
- for star in stars:
- screen.blit(star.image, star.rect)
- if not stop_moving:
- for i in range(len(stars)):
- star = stars[i]
- for star2 in stars[(i + 1):]:
- distance = math.dist(star.rect.center, star2.rect.center)
- #### 从这里开始看
- if pygame.sprite.collide_circle(star, star2):
- star.mass += star2.mass
- stars.remove(star2)
- continue
- #### 就是上面这段代码,一碰撞就报错
- if distance < 100:
- distance = 100
- # 万有引力公式F=GMm/r**2,0.1是为了适当缩小万有引力,否则会出现天体一直在转圈,你可以自己调整数值
- f = (G * (star.mass * star2.mass)) / distance ** 2 * 0.1 * step
- relative_position = np.subtract(star.rect.center, star2.rect.center)
- angle = math.atan2(*relative_position[::-1])
- dx = math.cos(angle) * f
- dy = math.sin(angle) * f
- star.speed = np.subtract(star.speed, [dx, dy])
- star2.speed = np.add(star2.speed, [dx, dy])
- star.speed = [x for x in star.speed] # 虽然天体是在做匀速直线运动,但不做衰减的话速度会一直叠加导致过快
- star.move()
- pygame.display.flip()
- pygame.quit()
复制代码
一碰撞就报错
IndexError: index out of range
链接放后面
感谢@鱼cpython学习者
永远不要尝试一边迭代一个容器一边删除容器里面的东西,我吃过很多次亏 
我的建议是把 换成 - star2.mass = 0
- destroyed.append(star2)
复制代码
等到全部弄完再遍历destroyed,删除star
|
|