首页 > 解决方案 > 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()

标签: pythonperformancepygame

解决方案


一个明显的问题是内部循环从 2 运行到len(lista_bolas). 由于您只想移动每个球一次并且只想检查一次球之间的碰撞,因此运行内部循环 from indice+1to就足够了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()

推荐阅读