为什么我的 pygame rect 敌人在被杀死后速度变慢了?

Why are my pygame rect enemies slowing down after being killed?

出于某种原因,我所有的敌人在与子弹相撞后都在减速。为什么会这样?我在下面附上了一个 GIF。这个游戏是不完整的,我对 pygame 还很陌生。根据需要提供任何建议。我之前发了一个post 不一样的,可以的话也请回复一下

Attached GIF

import pygame, sys, random
from pygame.locals import *
pygame.init()
screen_height = 870
screen_width = 1530
screen = pygame.display.set_mode((screen_width, screen_height))
fpsfunc = pygame.time.Clock()
enemy_speed = 6
enemy_motion = 1
SPAWNENEMY = USEREVENT + 1
SPAWNEASY = USEREVENT + 2
SPAWNMED = USEREVENT + 3
SPAWNHARD = USEREVENT + 4
pygame.time.set_timer(SPAWNENEMY, 1000)
cenx = screen_width / 2
ceny = screen_height / 2
gen1 = [cenx-200,ceny-200,cenx-100,ceny-100,cenx,ceny,cenx+100,ceny+100,cenx+200,ceny+200]
gen2 = []
gen3 = []
choices = [gen1]

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.surf = pygame.Surface((50, 50))
        self.surf.fill((255, 0, 0))
        self.rect = self.surf.get_rect(center=(screen_width / 2,
                                               screen_height - 100))

    def update(self, pressed_keys):
        if pressed_keys[K_d]:
            self.rect.move_ip(3, 0)
        if pressed_keys[K_a]:
            self.rect.move_ip(-3, 0)
        if pressed_keys[K_w]:
            self.rect.move_ip(0, -5)
        if pressed_keys[K_s]:
            self.rect.move_ip(0, 2)
        if self.rect.left <= 0:
            self.rect.left = 0
        if self.rect.top <= 0:
            self.rect.top = 0
        if pressed_keys[K_SPACE]:
            bullet_sprites.add(player.create_bullet())

    def create_bullet(self):
        return PlayerBullet(self.rect.x + 25, self.rect.y)

class PlayerBullet(pygame.sprite.Sprite):
    def __init__(self, pos_x, pos_y):
        super().__init__()
        self.image = pygame.Surface((10, 30))
        self.image.fill((0, 255, 255))
        self.rect = self.image.get_rect(center=(pos_x, pos_y))

    def update(self):
        self.rect.y -= 5
        if self.rect.y + 30 < 0:
          self.kill()

class Enemy(pygame.sprite.Sprite):
    def __init__(self, cenx, ceny):
        super(Enemy, self).__init__()
        self.image = pygame.Surface((35,35))
        self.image.fill((0,0,255))
        self.rect = self.image.get_rect(center = (cenx, ceny))
    def update(self):
        global enemy_motion, enemy_speed, cycle
        if pygame.sprite.spritecollide(self, bullet_sprites, True):
            self.kill()
        for enemy in enemy_sprites:
            if enemy not in enemy_dir_data:
                enemy_dir_data[enemy] = 1
            if enemy.rect.right >= screen_width:
                enemy_dir_data[enemy] = -1
            if enemy.rect.left <= 0:
                enemy_dir_data[enemy] = 1
            enemy.rect.x += enemy_speed * enemy_dir_data[enemy]
    

def createnem(pos1, pos2):
    return Enemy(pos1, pos2)

player = Player()
bullet_sprites = pygame.sprite.Group()
enemy_sprites = pygame.sprite.Group()
enemy_dir_data = {}

start_ticks=pygame.time.get_ticks()
while True:
    seconds=(pygame.time.get_ticks()-start_ticks)/1000
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                pygame.quit()
                sys.exit()
        if event.type == MOUSEBUTTONDOWN:
            bullet_sprites.add(player.create_bullet())
    #print(seconds)
    if seconds >= 10:
        enemy_sprites.empty()
    if len(enemy_sprites) == 0:
        selected = random.choice(choices)
        for create in range(0,len(selected),2):
            x = create
            y = create + 1
            print(selected[x],selected[y])
            enemy_sprites.add(createnem(gen1[x], gen1[y]))
            enemy_dir_data = {}
        start_ticks=pygame.time.get_ticks()
        

    pressed_keys = pygame.key.get_pressed()
    screen.fill((0, 0, 0))
    screen.blit(player.surf, player.rect)
    bullet_sprites.draw(screen)
    enemy_sprites.draw(screen)
    player.update(pressed_keys)
    enemy_sprites.update()
    bullet_sprites.update()
    pygame.display.update()
    fpsfunc.tick(60)

尝试:

pygame.sprite.Sprite.kill(self)

而不是self.kill

由于 Enemy.update 中的 for 循环,敌人的速度取决于敌人的数量。 update 中的每个敌人调用一次。由于 for 循环,每个敌人每帧移动多次。
阅读 Method Objects 并仅移动 update:

中的“self”实例对象
class Enemy(pygame.sprite.Sprite):
    # [...]
    def update(self):
        global enemy_motion, enemy_speed, cycle
        if pygame.sprite.spritecollide(self, bullet_sprites, True):
            self.kill()
        if self not in enemy_dir_data:
            enemy_dir_data[self] = 1
        if self.rect.right >= screen_width:
            enemy_dir_data[self] = -1
        if self.rect.left <= 0:
            enemy_dir_data[self] = 1
        self.rect.x += enemy_speed * enemy_dir_data[self]

pygame.sprite.Group.draw() and pygame.sprite.Group.update()pygame.sprite.Group.

提供的方法

前者委托给包含pygame.sprite.Sprites - you have to implement the method. See pygame.sprite.Group.update()update方法:

Calls the update() method on all Sprites in the Group [...]

后者使用包含的pygame.sprite.Spriteimagerect属性来绘制对象——你必须确保pygame.sprite.Sprite具有所需的属性。见 pygame.sprite.Group.draw():

Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]


您根本不需要字典 enemy_dir_data。而是将属性 enemy_dir 添加到 Enemy class:

class Enemy(pygame.sprite.Sprite):
    def __init__(self, cenx, ceny):
        super(Enemy, self).__init__()
        self.image = pygame.Surface((35,35))
        self.image.fill((0,0,255))
        self.rect = self.image.get_rect(center = (cenx, ceny))
        self.enemy_dir = 1
    def update(self):
        global enemy_motion, enemy_speed, cycle
        if pygame.sprite.spritecollide(self, bullet_sprites, True):
            self.kill()
        if self.rect.right >= screen_width:
            self.enemy_dir = -1
        if self.rect.left <= 0:
            self.enemy_dir = 1
        self.rect.x += enemy_speed * self.enemy_dir