Pygame 精灵重叠问题
Pygame sprites overlapping issue
我正在自学 python,并从与 pygame 的一个简单游戏开始。
到目前为止,游戏包括一个被其他球追逐的球,我已经创建了一个循环来避免追逐球重叠。
循环的工作方式是通过嵌套循环移动通过包含所有追逐球的列表,然后测量它们之间的距离,如果距离小于球半径,则将其移开。
它似乎大部分时间都有效,但有时球会重叠。我不知道为什么,如果有人可以看一下我的代码并给我一个提示,我会很感激,我认为错误发生在超过 3 个球以及球员的球 (pelota) 碰撞的那一刻。
import pygame, random, math
pygame.init()
ancho , alto = 800 , 600
negro = (0,0,0)
blanco=(255,255,255)
FPS = 60
velocidad = 7
velocidadnalguis = velocidad - 2
contadordecolisiones = 1
perseguidores = []
pantalla=pygame.display.set_mode((ancho,alto))
pygame.display.set_caption("un jueguito")
reloj=pygame.time.Clock()
class Pelota(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("pelota.png").convert()
self.image = pygame.transform.scale(self.image, (30, 30))
self.image.set_colorkey(negro)
self.rect = self.image.get_rect()
self.rect.center = (ancho/2,alto/2)
self.speed = 0
def update(self):
self.speedx = 0
self.speedy = 0
tecla = pygame.key.get_pressed()
if tecla[pygame.K_LEFT]:
self.speedx = -velocidad
if tecla[pygame.K_RIGHT]:
self.speedx = velocidad
if tecla[pygame.K_UP]:
self.speedy = -velocidad
if tecla[pygame.K_DOWN]:
self.speedy = velocidad
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.right > ancho:
self.rect.right = ancho
if self.rect.bottom > alto:
self.rect.bottom = alto
if self.rect.left < 0:
self.rect.left = 0
if self.rect.top < 0:
self.rect.top = 0
pelota = Pelota()
class Perseguidor(pygame.sprite.Sprite):
def __init__(self,):
super().__init__()
self.image = pygame.image.load('nalguis.png').convert()
self.image = pygame.transform.scale(self.image, (30, 30))
self.image.set_colorkey(negro)
self.rect = self.image.get_rect()
self.velocidad = velocidadnalguis
self.radius = self.rect.width/2
self.center = self.rect.center
self.contadordecolisiones = 1
self.enerandom = random.randint(0,4)
if self.enerandom == 0:
self.rect.center = (random.randrange(-130,-30),random.randrange(-130,alto+130))
if self.enerandom == 1:
self.rect.center = (random.randrange(-130,ancho+130),random.randrange(-130,-30))
if self.enerandom == 2:
self.rect.center = (random.randrange(ancho+30,ancho+130),random.randrange(-130,alto+130))
if self.enerandom == 3:
self.rect.center = (random.randrange(-130,ancho+130),random.randrange(alto+30,alto+130))
def update(self):
self.pely = pelota.rect.y
self.pelx = pelota.rect.x
self.perx = self.rect.x
self.pery = self.rect.y
self.dist = math.sqrt(((self.pely-self.pery)**2) + ((self.pelx-self.perx)**2))/velocidadnalguis
self.angulo = math.atan2(self.pely-self.pery,self.pelx-self.perx)
self.speedx = 0
self.speedy = 0
self.speedx = math.cos(self.angulo)
self.speedy = math.sin(self.angulo)
if self.dist>=1:
self.rect.x += velocidadnalguis * self.speedx
self.rect.y += velocidadnalguis * self.speedy
all_sprites = pygame.sprite.Group()
perseguidor_grupo = pygame.sprite.Group()
all_sprites.add(pelota)
terminar=False
while not terminar:
reloj.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
terminar=True
if len(perseguidor_grupo)<1:
perseguidor=Perseguidor()
perseguidor_grupo.add(perseguidor)
all_sprites.add(perseguidor)
hit = pygame.sprite.spritecollide(pelota, perseguidor_grupo, True, pygame.sprite.collide_circle)
if hit:
if len(perseguidor_grupo)<25:
perseguidor = Perseguidor()
perseguidor1 = Perseguidor()
all_sprites.add(perseguidor, perseguidor1)
perseguidor_grupo.add(perseguidor, perseguidor1)
perseguidores.append(perseguidor1)
perseguidores.append(perseguidor)
else :
perseguidor = Perseguidor()
all_sprites.add(perseguidor)
perseguidor_grupo.add(perseguidor)
perseguidores.append(perseguidor)
dist=1
for i in range (len(perseguidores)):
for j in range(i+1,len(perseguidores)):
perseguidoresxy = [perseguidores[i].rect.centerx,perseguidores[i].rect.centery]
dist=math.hypot(perseguidores[i].rect.centerx - perseguidores[j].rect.centerx , perseguidores[i].rect.centery - perseguidores[j].rect.centery)
if dist <= perseguidor.radius*2:
if perseguidores[i].rect.centerx < perseguidores[j].rect.centerx:
perseguidores[i].rect.centerx -= 3
if perseguidores[i].rect.centery < perseguidores[j].rect.centery:
perseguidores[i].rect.centery -= 3
if perseguidores[i].rect.centerx > perseguidores[j].rect.centerx:
perseguidores[i].rect.centerx += 3
if perseguidores[i].rect.centery > perseguidores[j].rect.centery:
perseguidores[i].rect.centery -= 3
if len(perseguidores)> len(perseguidor_grupo):
del perseguidores [0]
all_sprites.update()
pantalla .fill(negro)
all_sprites.draw(pantalla)
pygame.display.flip()
pygame.quit()
quit()
[...] then measures the distance between them, if the distance is less than the ball radius, it is moved away. It seems to work most of the time, but sometimes a ball overlaps. [...]
的course.You在移走一个球时只考虑2个球。
这意味着如果您将一个球从一个球移开,您可能会将它直接移到另一个球上。
你需要检查你移动球的位置是否没有其他球。
确保球在生成时不会重叠:
requested_balls = 1
while not terminar:
# [...]
hit = pygame.sprite.spritecollide(pelota, perseguidor_grupo, True, pygame.sprite.collide_circle)
if hit:
requested_balls = min(25, requested_balls+1)
if len(perseguidor_grupo) < requested_balls:
perseguidor = Perseguidor()
if not pygame.sprite.spritecollide(perseguidor, perseguidor_grupo, True, pygame.sprite.collide_circle):
all_sprites.add(perseguidor)
perseguidor_grupo.add(perseguidor)
perseguidores.append(perseguidor)
只有当球的新位置还没有被球占据时才移动球:
class Perseguidor(pygame.sprite.Sprite):
# [...]
def update(self):
# [...]
old_rect = self.rect.copy()
if self.dist>=1:
self.rect.x += velocidadnalguis * self.speedx
self.rect.y += velocidadnalguis * self.speedy
hit = pygame.sprite.spritecollide(self, perseguidor_grupo, False, pygame.sprite.collide_circle)
if len(hit) > 1: # at last 1, because the ball hits itself
if random.randrange(2) == 0:
self.rect.x = old_rect.x
else:
self.rect.y = old_rect.y
hit = pygame.sprite.spritecollide(self, perseguidor_grupo, False, pygame.sprite.collide_circle)
if len(hit) > 1:
self.rect = old_rect
完整示例:
import pygame, random, math
pygame.init()
ancho , alto = 800 , 600
negro = (0,0,0)
blanco=(255,255,255)
FPS = 60
velocidad = 7
velocidadnalguis = velocidad - 2
contadordecolisiones = 1
perseguidores = []
pantalla=pygame.display.set_mode((ancho,alto))
pygame.display.set_caption("un jueguito")
reloj=pygame.time.Clock()
class Pelota(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("pelota.png").convert()
self.image = pygame.transform.scale(self.image, (30, 30))
self.image.set_colorkey(negro)
self.rect = self.image.get_rect()
self.rect.center = (ancho/2,alto/2)
self.speed = 0
def update(self):
self.speedx = 0
self.speedy = 0
tecla = pygame.key.get_pressed()
if tecla[pygame.K_LEFT]:
self.speedx = -velocidad
if tecla[pygame.K_RIGHT]:
self.speedx = velocidad
if tecla[pygame.K_UP]:
self.speedy = -velocidad
if tecla[pygame.K_DOWN]:
self.speedy = velocidad
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.right > ancho:
self.rect.right = ancho
if self.rect.bottom > alto:
self.rect.bottom = alto
if self.rect.left < 0:
self.rect.left = 0
if self.rect.top < 0:
self.rect.top = 0
pelota = Pelota()
class Perseguidor(pygame.sprite.Sprite):
def __init__(self,):
super().__init__()
self.image = pygame.image.load('nalguis.png').convert()
self.image = pygame.transform.scale(self.image, (30, 30))
self.image.set_colorkey(negro)
self.rect = self.image.get_rect()
self.velocidad = velocidadnalguis
self.radius = self.rect.width/2
self.center = self.rect.center
self.contadordecolisiones = 1
self.enerandom = random.randint(0,4)
if self.enerandom == 0:
self.rect.center = (random.randrange(-130,-30),random.randrange(-130,alto+130))
if self.enerandom == 1:
self.rect.center = (random.randrange(-130,ancho+130),random.randrange(-130,-30))
if self.enerandom == 2:
self.rect.center = (random.randrange(ancho+30,ancho+130),random.randrange(-130,alto+130))
if self.enerandom == 3:
self.rect.center = (random.randrange(-130,ancho+130),random.randrange(alto+30,alto+130))
def update(self):
self.pely = pelota.rect.y
self.pelx = pelota.rect.x
self.perx = self.rect.x
self.pery = self.rect.y
self.dist = math.sqrt(((self.pely-self.pery)**2) + ((self.pelx-self.perx)**2))/velocidadnalguis
self.angulo = math.atan2(self.pely-self.pery,self.pelx-self.perx)
self.speedx = 0
self.speedy = 0
self.speedx = math.cos(self.angulo)
self.speedy = math.sin(self.angulo)
old_rect = self.rect.copy()
if self.dist>=1:
self.rect.x += velocidadnalguis * self.speedx
self.rect.y += velocidadnalguis * self.speedy
hit = pygame.sprite.spritecollide(self, perseguidor_grupo, False, pygame.sprite.collide_circle)
if len(hit) > 1: # at last 1, because the ball hits itself
if random.randrange(2) == 0:
self.rect.x = old_rect.x
else:
self.rect.y = old_rect.y
hit = pygame.sprite.spritecollide(self, perseguidor_grupo, False, pygame.sprite.collide_circle)
if len(hit) > 1:
self.rect = old_rect
all_sprites = pygame.sprite.Group()
perseguidor_grupo = pygame.sprite.Group()
all_sprites.add(pelota)
terminar=False
requested_balls = 1
while not terminar:
reloj.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
terminar=True
if len(perseguidor_grupo)<1:
perseguidor=Perseguidor()
perseguidor_grupo.add(perseguidor)
all_sprites.add(perseguidor)
hit = pygame.sprite.spritecollide(pelota, perseguidor_grupo, True, pygame.sprite.collide_circle)
if hit:
requested_balls = min(25, requested_balls+1)
if len(perseguidor_grupo) < requested_balls:
perseguidor = Perseguidor()
if not pygame.sprite.spritecollide(perseguidor, perseguidor_grupo, True, pygame.sprite.collide_circle):
all_sprites.add(perseguidor)
perseguidor_grupo.add(perseguidor)
perseguidores.append(perseguidor)
dist=1
if len(perseguidores)> len(perseguidor_grupo):
del perseguidores [0]
all_sprites.update()
pantalla .fill(negro)
all_sprites.draw(pantalla)
pygame.display.flip()
pygame.quit()
quit()
我正在自学 python,并从与 pygame 的一个简单游戏开始。 到目前为止,游戏包括一个被其他球追逐的球,我已经创建了一个循环来避免追逐球重叠。 循环的工作方式是通过嵌套循环移动通过包含所有追逐球的列表,然后测量它们之间的距离,如果距离小于球半径,则将其移开。 它似乎大部分时间都有效,但有时球会重叠。我不知道为什么,如果有人可以看一下我的代码并给我一个提示,我会很感激,我认为错误发生在超过 3 个球以及球员的球 (pelota) 碰撞的那一刻。
import pygame, random, math
pygame.init()
ancho , alto = 800 , 600
negro = (0,0,0)
blanco=(255,255,255)
FPS = 60
velocidad = 7
velocidadnalguis = velocidad - 2
contadordecolisiones = 1
perseguidores = []
pantalla=pygame.display.set_mode((ancho,alto))
pygame.display.set_caption("un jueguito")
reloj=pygame.time.Clock()
class Pelota(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("pelota.png").convert()
self.image = pygame.transform.scale(self.image, (30, 30))
self.image.set_colorkey(negro)
self.rect = self.image.get_rect()
self.rect.center = (ancho/2,alto/2)
self.speed = 0
def update(self):
self.speedx = 0
self.speedy = 0
tecla = pygame.key.get_pressed()
if tecla[pygame.K_LEFT]:
self.speedx = -velocidad
if tecla[pygame.K_RIGHT]:
self.speedx = velocidad
if tecla[pygame.K_UP]:
self.speedy = -velocidad
if tecla[pygame.K_DOWN]:
self.speedy = velocidad
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.right > ancho:
self.rect.right = ancho
if self.rect.bottom > alto:
self.rect.bottom = alto
if self.rect.left < 0:
self.rect.left = 0
if self.rect.top < 0:
self.rect.top = 0
pelota = Pelota()
class Perseguidor(pygame.sprite.Sprite):
def __init__(self,):
super().__init__()
self.image = pygame.image.load('nalguis.png').convert()
self.image = pygame.transform.scale(self.image, (30, 30))
self.image.set_colorkey(negro)
self.rect = self.image.get_rect()
self.velocidad = velocidadnalguis
self.radius = self.rect.width/2
self.center = self.rect.center
self.contadordecolisiones = 1
self.enerandom = random.randint(0,4)
if self.enerandom == 0:
self.rect.center = (random.randrange(-130,-30),random.randrange(-130,alto+130))
if self.enerandom == 1:
self.rect.center = (random.randrange(-130,ancho+130),random.randrange(-130,-30))
if self.enerandom == 2:
self.rect.center = (random.randrange(ancho+30,ancho+130),random.randrange(-130,alto+130))
if self.enerandom == 3:
self.rect.center = (random.randrange(-130,ancho+130),random.randrange(alto+30,alto+130))
def update(self):
self.pely = pelota.rect.y
self.pelx = pelota.rect.x
self.perx = self.rect.x
self.pery = self.rect.y
self.dist = math.sqrt(((self.pely-self.pery)**2) + ((self.pelx-self.perx)**2))/velocidadnalguis
self.angulo = math.atan2(self.pely-self.pery,self.pelx-self.perx)
self.speedx = 0
self.speedy = 0
self.speedx = math.cos(self.angulo)
self.speedy = math.sin(self.angulo)
if self.dist>=1:
self.rect.x += velocidadnalguis * self.speedx
self.rect.y += velocidadnalguis * self.speedy
all_sprites = pygame.sprite.Group()
perseguidor_grupo = pygame.sprite.Group()
all_sprites.add(pelota)
terminar=False
while not terminar:
reloj.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
terminar=True
if len(perseguidor_grupo)<1:
perseguidor=Perseguidor()
perseguidor_grupo.add(perseguidor)
all_sprites.add(perseguidor)
hit = pygame.sprite.spritecollide(pelota, perseguidor_grupo, True, pygame.sprite.collide_circle)
if hit:
if len(perseguidor_grupo)<25:
perseguidor = Perseguidor()
perseguidor1 = Perseguidor()
all_sprites.add(perseguidor, perseguidor1)
perseguidor_grupo.add(perseguidor, perseguidor1)
perseguidores.append(perseguidor1)
perseguidores.append(perseguidor)
else :
perseguidor = Perseguidor()
all_sprites.add(perseguidor)
perseguidor_grupo.add(perseguidor)
perseguidores.append(perseguidor)
dist=1
for i in range (len(perseguidores)):
for j in range(i+1,len(perseguidores)):
perseguidoresxy = [perseguidores[i].rect.centerx,perseguidores[i].rect.centery]
dist=math.hypot(perseguidores[i].rect.centerx - perseguidores[j].rect.centerx , perseguidores[i].rect.centery - perseguidores[j].rect.centery)
if dist <= perseguidor.radius*2:
if perseguidores[i].rect.centerx < perseguidores[j].rect.centerx:
perseguidores[i].rect.centerx -= 3
if perseguidores[i].rect.centery < perseguidores[j].rect.centery:
perseguidores[i].rect.centery -= 3
if perseguidores[i].rect.centerx > perseguidores[j].rect.centerx:
perseguidores[i].rect.centerx += 3
if perseguidores[i].rect.centery > perseguidores[j].rect.centery:
perseguidores[i].rect.centery -= 3
if len(perseguidores)> len(perseguidor_grupo):
del perseguidores [0]
all_sprites.update()
pantalla .fill(negro)
all_sprites.draw(pantalla)
pygame.display.flip()
pygame.quit()
quit()
[...] then measures the distance between them, if the distance is less than the ball radius, it is moved away. It seems to work most of the time, but sometimes a ball overlaps. [...]
的course.You在移走一个球时只考虑2个球。 这意味着如果您将一个球从一个球移开,您可能会将它直接移到另一个球上。 你需要检查你移动球的位置是否没有其他球。
确保球在生成时不会重叠:
requested_balls = 1
while not terminar:
# [...]
hit = pygame.sprite.spritecollide(pelota, perseguidor_grupo, True, pygame.sprite.collide_circle)
if hit:
requested_balls = min(25, requested_balls+1)
if len(perseguidor_grupo) < requested_balls:
perseguidor = Perseguidor()
if not pygame.sprite.spritecollide(perseguidor, perseguidor_grupo, True, pygame.sprite.collide_circle):
all_sprites.add(perseguidor)
perseguidor_grupo.add(perseguidor)
perseguidores.append(perseguidor)
只有当球的新位置还没有被球占据时才移动球:
class Perseguidor(pygame.sprite.Sprite):
# [...]
def update(self):
# [...]
old_rect = self.rect.copy()
if self.dist>=1:
self.rect.x += velocidadnalguis * self.speedx
self.rect.y += velocidadnalguis * self.speedy
hit = pygame.sprite.spritecollide(self, perseguidor_grupo, False, pygame.sprite.collide_circle)
if len(hit) > 1: # at last 1, because the ball hits itself
if random.randrange(2) == 0:
self.rect.x = old_rect.x
else:
self.rect.y = old_rect.y
hit = pygame.sprite.spritecollide(self, perseguidor_grupo, False, pygame.sprite.collide_circle)
if len(hit) > 1:
self.rect = old_rect
完整示例:
import pygame, random, math
pygame.init()
ancho , alto = 800 , 600
negro = (0,0,0)
blanco=(255,255,255)
FPS = 60
velocidad = 7
velocidadnalguis = velocidad - 2
contadordecolisiones = 1
perseguidores = []
pantalla=pygame.display.set_mode((ancho,alto))
pygame.display.set_caption("un jueguito")
reloj=pygame.time.Clock()
class Pelota(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("pelota.png").convert()
self.image = pygame.transform.scale(self.image, (30, 30))
self.image.set_colorkey(negro)
self.rect = self.image.get_rect()
self.rect.center = (ancho/2,alto/2)
self.speed = 0
def update(self):
self.speedx = 0
self.speedy = 0
tecla = pygame.key.get_pressed()
if tecla[pygame.K_LEFT]:
self.speedx = -velocidad
if tecla[pygame.K_RIGHT]:
self.speedx = velocidad
if tecla[pygame.K_UP]:
self.speedy = -velocidad
if tecla[pygame.K_DOWN]:
self.speedy = velocidad
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.right > ancho:
self.rect.right = ancho
if self.rect.bottom > alto:
self.rect.bottom = alto
if self.rect.left < 0:
self.rect.left = 0
if self.rect.top < 0:
self.rect.top = 0
pelota = Pelota()
class Perseguidor(pygame.sprite.Sprite):
def __init__(self,):
super().__init__()
self.image = pygame.image.load('nalguis.png').convert()
self.image = pygame.transform.scale(self.image, (30, 30))
self.image.set_colorkey(negro)
self.rect = self.image.get_rect()
self.velocidad = velocidadnalguis
self.radius = self.rect.width/2
self.center = self.rect.center
self.contadordecolisiones = 1
self.enerandom = random.randint(0,4)
if self.enerandom == 0:
self.rect.center = (random.randrange(-130,-30),random.randrange(-130,alto+130))
if self.enerandom == 1:
self.rect.center = (random.randrange(-130,ancho+130),random.randrange(-130,-30))
if self.enerandom == 2:
self.rect.center = (random.randrange(ancho+30,ancho+130),random.randrange(-130,alto+130))
if self.enerandom == 3:
self.rect.center = (random.randrange(-130,ancho+130),random.randrange(alto+30,alto+130))
def update(self):
self.pely = pelota.rect.y
self.pelx = pelota.rect.x
self.perx = self.rect.x
self.pery = self.rect.y
self.dist = math.sqrt(((self.pely-self.pery)**2) + ((self.pelx-self.perx)**2))/velocidadnalguis
self.angulo = math.atan2(self.pely-self.pery,self.pelx-self.perx)
self.speedx = 0
self.speedy = 0
self.speedx = math.cos(self.angulo)
self.speedy = math.sin(self.angulo)
old_rect = self.rect.copy()
if self.dist>=1:
self.rect.x += velocidadnalguis * self.speedx
self.rect.y += velocidadnalguis * self.speedy
hit = pygame.sprite.spritecollide(self, perseguidor_grupo, False, pygame.sprite.collide_circle)
if len(hit) > 1: # at last 1, because the ball hits itself
if random.randrange(2) == 0:
self.rect.x = old_rect.x
else:
self.rect.y = old_rect.y
hit = pygame.sprite.spritecollide(self, perseguidor_grupo, False, pygame.sprite.collide_circle)
if len(hit) > 1:
self.rect = old_rect
all_sprites = pygame.sprite.Group()
perseguidor_grupo = pygame.sprite.Group()
all_sprites.add(pelota)
terminar=False
requested_balls = 1
while not terminar:
reloj.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
terminar=True
if len(perseguidor_grupo)<1:
perseguidor=Perseguidor()
perseguidor_grupo.add(perseguidor)
all_sprites.add(perseguidor)
hit = pygame.sprite.spritecollide(pelota, perseguidor_grupo, True, pygame.sprite.collide_circle)
if hit:
requested_balls = min(25, requested_balls+1)
if len(perseguidor_grupo) < requested_balls:
perseguidor = Perseguidor()
if not pygame.sprite.spritecollide(perseguidor, perseguidor_grupo, True, pygame.sprite.collide_circle):
all_sprites.add(perseguidor)
perseguidor_grupo.add(perseguidor)
perseguidores.append(perseguidor)
dist=1
if len(perseguidores)> len(perseguidor_grupo):
del perseguidores [0]
all_sprites.update()
pantalla .fill(negro)
all_sprites.draw(pantalla)
pygame.display.flip()
pygame.quit()
quit()