python - Pygame 对象实例速度增加
问题描述
我制作了这个伪游戏,其中一个球被另一个球追赶,当我改变红球(跟随球)的数量时,游戏的速度会增加,我想这是由于循环的迭代导致移动并发现碰撞在主循环中,游戏中的球越多,迭代次数越多,因此球的速度越来越快。有关如何解决此问题的任何建议?
import pygame, math, random
pygame.init()
vel = 2
ancho = 600
alto = 500
tamaño=15
tamaño_estat = tamaño * 3
color = (250,0,0)
color2= (0,0,250)
FPS = 60
negro= 0,0,0
pantalla = pygame.display.set_mode((ancho, alto))
reloj = pygame.time.Clock()
pos_flechas = ancho / 2, alto / 2
posiciones_xy = []
indice = 0
lista_bolas = []
x, y = 0, 0
step = vel + 3
class Bolas():
def __init__(self, color, xyb, tamaño, indice):
super().__init__()
self.color = color
self.xyb = xyb
self.tamaño = tamaño
self.vel = vel
self.indice = indice
posiciones_xy.insert(self.indice,xyb)
def draw(self):
posicion = posiciones_xy[self.indice][0], posiciones_xy[self.indice][1]
pygame.draw.circle(pantalla, self.color, posicion, self.tamaño)
def mover(self, xyb, xyb_new, indice): # makes red balls moves towards blue ball, main ball.
dx, dy = xyb_new[0]- xyb[0], xyb_new[1]- xyb[1]
dist = abs(math.hypot(dx,dy))
if dist > 0:
dx, dy = round(dx * vel / dist), round(dy * vel / dist)
xyb = [xyb[0] + dx , xyb[1] + dy]
if dist < vel:
xyb = xyb_new
posiciones_xy[indice] = xyb
return xyb
def colision(self, xyb, xyb1, indice, tamaño): # detects collision between balls
dx, dy = round(xyb1[0]- xyb[0]), round(xyb1[1]- xyb[1])
dist_col = abs(math.hypot(dx,dy))
if dist_col < tamaño * 2 and dist_col != 0:
colision = True
else:
colision = False
return colision , dist_col
def reaccion(self, xyb, xyb1, indice): # moves colliding balls away
if colision == True:
dx, dy = round(xyb1[0]- xyb[0]), round(xyb1[1]- xyb[1])
overlap = (tamaño * 2 - dist_col)/dist_col
xyb = [xyb[0] - dx * overlap , xyb[1] - dy * overlap]
if dist_col <= tamaño * 2:
vel = 0
posiciones_xy[indice] = xyb
def colision_estatica(self, xyb, xyb_estatica, indice): #check and react when a ball hit central circle
dx, dy = xyb_estatica[0] - xyb[0], xyb_estatica[1] - xyb[1]
dist_estat = math.hypot(dx, dy)
if dist_estat != 0:
overlap = (tamaño + tamaño_estat - dist_estat) / dist_estat
if dist_estat < tamaño + tamaño_estat:
xyb = [xyb[0] - dx * overlap, xyb[1] - dy * overlap]
posiciones_xy[indice] = xyb
def seguir_flechas(self, xyb, xy_flechas, indice): # set main ball move with keyboard arrows
xyb[0] += xy_flechas[0]
xyb[1] += xy_flechas[1]
if xyb[0] < 0 + tamaño:
xyb[0] = tamaño
if xyb[1] < 0 + tamaño:
xyb[1] = tamaño
if xyb[0] > ancho - tamaño:
xyb[0] = ancho - tamaño
if xyb[1] > alto - tamaño:
xyb[1] = alto - tamaño
posiciones_xy[indice] = xyb
def pos_ini(): # set the position where the red balls spawn
randomX1 , randomX2 = ancho + random.randrange(10,50), 0 - random.randrange(10,50)
x_ini = random.choice([randomX1 , randomX2])
randomY1 , randomY2 = alto + random.randrange(10,50), 0 - random.randrange(10,50)
y_ini = random.choice([randomY1 , randomY2])
xyb_ini = [x_ini, y_ini]
return xyb_ini
bola_ppal = Bolas(color2, [ancho / 3, alto / 3], tamaño, 0) #creates the main ball, blue, which you can control with keyboard.
lista_bolas.append(bola_ppal)
bola_central = Bolas((0,250,0), [ancho / 2, alto / 2], tamaño_estat, 1) #creates central static circle
lista_bolas.append(bola_central)
for indice in range(2,4): # loop creates red balls, range starts at 2 because the tow first places in the list correspond to main ball and center circle
lista_bolas.append(Bolas(color,pos_ini(), tamaño, indice))
#main loop
terminar = False
while not terminar:
reloj.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
terminar=True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x = -step
if event.key == pygame.K_UP:
y = -step
if event.key == pygame.K_RIGHT:
x = step
if event.key == pygame.K_DOWN:
y = step
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y = 0
pantalla.fill(negro)
bola_ppal.seguir_flechas(posiciones_xy[0], [x, y],0)
pos_flechas = posiciones_xy[0]
for indice in range(2,len(lista_bolas)):
for indicej in range(2,len(lista_bolas)):
if indice != indicej:
lista_bolas[indice].mover(posiciones_xy[indice], pos_flechas,indice)
colision, dist_col = lista_bolas[indice].colision(posiciones_xy[indice], posiciones_xy[indicej], indice, tamaño)
lista_bolas[indice].reaccion(posiciones_xy[indice], posiciones_xy[indicej], indice)
lista_bolas[indice].colision_estatica(posiciones_xy[indice], [ancho / 2, alto / 2] , indice) # colision estatica bola central vs bolas perseguidor
lista_bolas[indice].colision_estatica(posiciones_xy[0], [ancho / 2, alto / 2] , 0) # colision estatica bola central con bola azul
colision, dist_col = lista_bolas[0].colision(posiciones_xy[0], posiciones_xy[indicej], 0, tamaño) # colision con la bola principal
lista_bolas[0].reaccion(posiciones_xy[0], posiciones_xy[indicej], 0) # reaccion bola principal
lista_bolas[indice].draw()
bola_ppal.draw()
bola_central.draw()
pygame.display.update()
pygame.quit()
quit()
解决方案
一个明显的问题是内部循环从 2 运行到len(lista_bolas)
. 由于您只想移动每个球一次并且只想检查一次球之间的碰撞,因此运行内部循环 from indice+1
to就足够了len(lista_bolas)
。
此外,您需要在外循环中移动每个球一次,而不是在内循环中重复移动:
while not terminar:
# [...]
for indice in range(2,len(lista_bolas)):
lista_bolas[indice].mover(posiciones_xy[indice], pos_flechas,indice)
for indicej in range(indice+1,len(lista_bolas)):
colision, dist_col = lista_bolas[indice].colision(posiciones_xy[indice], posiciones_xy[indicej], indice, tamaño)
lista_bolas[indice].reaccion(posiciones_xy[indice], posiciones_xy[indicej], indice)
lista_bolas[indice].colision_estatica(posiciones_xy[indice], [ancho / 2, alto / 2] , indice) # colision estatica bola central vs bolas perseguidor
lista_bolas[indice].colision_estatica(posiciones_xy[0], [ancho / 2, alto / 2] , 0) # colision estatica bola central con bola azul
colision, dist_col = lista_bolas[0].colision(posiciones_xy[0], posiciones_xy[indice], 0, tamaño) # colision con la bola principal
lista_bolas[0].reaccion(posiciones_xy[0], posiciones_xy[indice], 0) # reaccion bola principal
lista_bolas[indice].draw()
bola_ppal.draw()
bola_central.draw()
pygame.display.update()
推荐阅读
- java - Spark 3.0 排序并应用于组 Scala/Java
- node.js - 如何使用云功能检查云存储中的文件路径是否有效?
- reactjs - 如何在 React js 中检测移动视图和移动应用程序视图
- html - 使用 CSS/HTML 删除特定元素的边距
- azure-devops - 如何在 Azure Devops 中阻止用户读取分支的另一个用户?
- ios - SwiftUI - @Published 属性未从协调器更新视图
- python - DataError:使用 groupby 和 rank 时没有要聚合的数字类型
- python - 带有可变类命令的 Python Tkinter 按钮
- javascript - CSS:数组中元素之间的平滑过渡
- flutter - 如果 Firestore 最初返回 0 个文档,StreamBuilder 不会重建?