鱼C论坛

 找回密码
 立即注册
查看: 2146|回复: 1

[已解决]碰撞检测

[复制链接]
发表于 2023-2-12 11:40:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 歌者文明清理员 于 2023-2-12 11:43 编辑

源代码
只要看第 129 到 133 行就行了
  1. # -*- coding: utf-8 -*-
  2. import pygame
  3. import math
  4. import numpy as np
  5. import random
  6. from trail import TrailSprite
  7. from tkinter import *

  8. pygame.init()
  9. G = 1
  10. pygame.time.set_timer(pygame.USEREVENT, 5000)


  11. class Star(pygame.sprite.Sprite, TrailSprite):
  12.     def __init__(self, radius, mass, init_speed, pos):
  13.         pygame.sprite.Sprite.__init__(self)
  14.         self.radius = radius
  15.         self.mass = mass
  16.         self.color = rand_color()
  17.         if init_speed:
  18.             self.speed = init_speed
  19.         self.image = pygame.Surface((radius * 2, radius * 2)).convert_alpha()
  20.         self.image.fill((0, 0, 0, 0))
  21.         pygame.draw.circle(self.image, self.color, (radius, radius), radius)
  22.         TrailSprite.__init__(self, self.color, self.image, 1)
  23.         TrailSprite.set_screen(self, screen)
  24.         self.rect.center = pos

  25.     def move(self):
  26.         TrailSprite.update(self)
  27.         self.rect.centerx += self.speed[0]
  28.         self.rect.centery += self.speed[1]
  29.         # 跑出窗口从另一边回来
  30.         if self.rect.left <= 0 or self.rect.right >= width:
  31.             self.rect.centerx %= width
  32.             self.clear_trail()
  33.         if self.rect.top <= 0 or self.rect.bottom >= height:
  34.             self.rect.centery %= height
  35.             self.clear_trail()


  36. def all_clear_trail():
  37.     for st in stars:
  38.         st.clear_trail()


  39. def rand_color():
  40.     r = random.randint(0, 255)
  41.     g = random.randint(0, 255)
  42.     b = random.randint(0, 255)
  43.     return r, g, b


  44. def set_speed():
  45.     global step
  46.     if not entry.get().isdigit():
  47.         return
  48.     step = entry.get()
  49.     root.destroy()


  50. pygame.init()

  51. size = width, height = 640, 480
  52. bg = (0, 0, 0)

  53. screen = pygame.display.set_mode(size)
  54. pygame.display.set_caption("StarMotionSimulator")

  55. stars = []  # 随机生成天体

  56. clock = pygame.time.Clock()

  57. step = 1
  58. stop_moving = False
  59. down = False
  60. star_pos = (0, 0)
  61. rel = [0, 0]
  62. running = True
  63. while running:
  64.     clock.tick(60)
  65.     for event in pygame.event.get():
  66.         if event.type == pygame.QUIT:
  67.             running = False
  68.         elif event.type == pygame.KEYDOWN:
  69.             if event.key == pygame.K_SPACE:
  70.                 stop_moving = not stop_moving
  71.                 all_clear_trail()
  72.             elif event.key == pygame.K_r:
  73.                 stars.clear()
  74.             elif event.key == pygame.K_s:
  75.                 root = Tk()
  76.                 root.title('SpeedEditor')
  77.                 root.geometry('100x50')
  78.                 label = Label(root, text='Speed')
  79.                 label.pack()
  80.                 entry = Entry(root)
  81.                 entry.pack()
  82.                 submit = Button(root, text='Confirm')
  83.                 submit['command'] = set_speed
  84.                 submit.pack()
  85.                 root.mainloop()
  86.         elif event.type == pygame.MOUSEBUTTONDOWN:
  87.             if not down:
  88.                 star_pos = event.pos
  89.                 down = True
  90.         elif event.type == pygame.MOUSEBUTTONUP:
  91.             down = False
  92.             star = Star(5, 100, (-rel[0] // 4, -rel[1] // 4), event.pos)
  93.             stars.append(star)
  94.             rel.clear()
  95.             rel.extend((0, 0))
  96.         elif event.type == pygame.MOUSEMOTION:
  97.             if down:  # 按下 + 移动 = 拖动
  98.                 rel[0] += event.rel[0]
  99.                 rel[1] += event.rel[1]
  100.         elif event.type == pygame.USEREVENT:
  101.             all_clear_trail()

  102.     screen.fill((0, 0, 0))
  103.     for star in stars:
  104.         screen.blit(star.image, star.rect)
  105.     if not stop_moving:
  106.         for i in range(len(stars)):
  107.             star = stars[i]
  108.             for star2 in stars[(i + 1):]:
  109.                 distance = math.dist(star.rect.center, star2.rect.center)
  110.                 #### 从这里开始看
  111.                 if pygame.sprite.collide_circle(star, star2):
  112.                     star.mass += star2.mass
  113.                     stars.remove(star2)
  114.                     continue
  115.                 #### 就是上面这段代码,一碰撞就报错
  116.                 if distance < 100:
  117.                     distance = 100
  118.                 # 万有引力公式F=GMm/r**2,0.1是为了适当缩小万有引力,否则会出现天体一直在转圈,你可以自己调整数值
  119.                 f = (G * (star.mass * star2.mass)) / distance ** 2 * 0.1 * step
  120.                 relative_position = np.subtract(star.rect.center, star2.rect.center)
  121.                 angle = math.atan2(*relative_position[::-1])
  122.                 dx = math.cos(angle) * f
  123.                 dy = math.sin(angle) * f
  124.                 star.speed = np.subtract(star.speed, [dx, dy])
  125.                 star2.speed = np.add(star2.speed, [dx, dy])
  126.             star.speed = [x for x in star.speed]  # 虽然天体是在做匀速直线运动,但不做衰减的话速度会一直叠加导致过快
  127.             star.move()
  128.     pygame.display.flip()
  129. pygame.quit()
复制代码

一碰撞就报错
IndexError: index out of range
链接放后面
感谢@鱼cpython学习者
最佳答案
2023-2-12 13:41:13
永远不要尝试一边迭代一个容器一边删除容器里面的东西,我吃过很多次亏
我的建议是把
  1. stars.remove(star2)
复制代码
换成
  1. star2.mass = 0
  2. destroyed.append(star2)
复制代码

等到全部弄完再遍历destroyed,删除star
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-2-12 13:41:13 | 显示全部楼层    本楼为最佳答案   
永远不要尝试一边迭代一个容器一边删除容器里面的东西,我吃过很多次亏
我的建议是把
  1. stars.remove(star2)
复制代码
换成
  1. star2.mass = 0
  2. destroyed.append(star2)
复制代码

等到全部弄完再遍历destroyed,删除star
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-24 18:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表