我想在事件发生后从内存中永久删除精灵。使用 self.kill() 不起作用,因为精灵的图像被删除了,但精灵仍然存在。我该怎么做才能将其从内存中永久删除?
import pygame import time BLACK = ( 0, 0, 0) WHITE = (255, 255, 255) RED = (255, 0, 0) GREY = (129, 129, 129) frame = 0 class SpriteSheet(object): def __init__(self, file_name): self.sprite_sheet = pygame.image.load(file_name).convert() def get_image(self, x, y, width, height, colour): image = pygame.Surface([width, height]).convert() image.set_colorkey(colour) image.blit(self.sprite_sheet, (0, 0), (x, y, width, height)) return image class Bomb(pygame.sprite.Sprite): change_x =0 change_y = 0 def __init__(self): super().__init__() sprite_sheet = SpriteSheet("Untitled.png") self.image = sprite_sheet.get_image(2, 2, 48, 48, WHITE) self.rect = self.image.get_rect() def move(self): self.change_y = 2 self.rect.y += self.change_y if self.rect.y > 500: self.kill() class Soldier(pygame.sprite.Sprite): def __init__(self): self.change_x = 0 self.change_y = 0 self.direction = "R" super().__init__() self.walking_frames_l = [] self.walking_frames_r = [] sprite_sheet = SpriteSheet("Picture2.png") self.image = sprite_sheet.get_image(0, 0, 150, 205, GREY) self.walking_frames_l.append(self.image) self.image = sprite_sheet.get_image(233, 0, 140, 210, GREY) self.walking_frames_l.append(self.image) self.image = sprite_sheet.get_image(425, 5, 123, 210, GREY) self.walking_frames_l.append(self.image) self.image = sprite_sheet.get_image(0, 0, 150, 205, GREY) self.image = pygame.transform.flip(self.image, True, False) self.walking_frames_r.append(self.image) self.image = sprite_sheet.get_image(233, 0, 140, 210, GREY) self.image = pygame.transform.flip(self.image, True, False) self.walking_frames_r.append(self.image) self.image = sprite_sheet.get_image(425, 5, 123, 210, GREY) self.image = pygame.transform.flip(self.image, True, False) self.walking_frames_r.append(self.image) self.image = self.walking_frames_r[0] self.rect = self.image.get_rect() self.rect.y = 297 self.rect.x = 100 self.frame = 0 self.moved = 0 def move(self): self.rect.x += self.change_x def walk(self): self.moved += abs(self.change_x) pixels_for_one_step = 60 if self.moved > pixels_for_one_step: self.frame += 1 self.moved = 0 if self.frame >= len(self.walking_frames_r): self.frame = 0 if self.direction =="R": self.image = self.walking_frames_r[self.frame] else: self.image = self.walking_frames_l[self.frame] if self.change_x == 0 and self.direction == "R": self.image = self.walking_frames_r[2] if self.change_x == 0 and self.direction == "L": self.image = self.walking_frames_l[2] def go_left(self): self.change_x = -6 self.direction = "L" def go_right(self): self.direction = "R" self.change_x = 6 def stop(self): self.change_x = 0 self.image = self.walking_frames_r[2] class Bullet(pygame.sprite.Sprite): def __init__(self): super().__init__() self.change_x =0 self.change_y = 0 self.direction = "" sprite_sheet = SpriteSheet("Bullet_2.png") self.image = sprite_sheet.get_image(0, 0, 27, 27, BLACK) self.image = pygame.transform.rotate(self.image, 45) self.rect = self.image.get_rect() self.rect.y = 0 self.rect.x = 0 def moveright(self): self.change_x =2 self.change_y = 2 self.rect.y -= self.change_y self.rect.x -= self.change_x if self.rect.y < -30: self.kill() def moveleft(self): self.change_x =-2 self.change_y = 2 self.rect.y -= self.change_y self.rect.x -= self.change_x if self.rect.y < -30: self.kill() pygame.init() screen_width = 1000 screen_height = 500 screen = pygame.display.set_mode([screen_width, screen_height]) pygame.display.set_caption("Game") clock = pygame.time.Clock() done = False bomb = Bomb() soldier = Soldier() all_sprites = pygame.sprite.Group() bullet_list = pygame.sprite.Group() bomb_list = pygame.sprite.Group() bomb_list.add(bomb) all_sprites.add(bomb) all_sprites.add(soldier) screen_rect = screen.get_rect() pygame.mouse.set_cursor(*pygame.cursors.broken_x) bg = pygame.image.load ("3601933.jpg") while not done: for event in pygame.event.get(): if event.type == pygame.QUIT: done = True if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: soldier.go_left() if event.key == pygame.K_RIGHT: soldier.go_right() if event.key == pygame.K_SPACE: bullet = Bullet() if soldier.direction == "R": bullet.direction = "R" bullet.rect.x = soldier.rect.left -23 bullet.rect.y = soldier.rect.top - 23 else: bullet.image = pygame.transform.flip(bullet.image, True, False) bullet.rect.x = soldier.rect.left +110 bullet.rect.y = soldier.rect.top - 24 bullet.direction = "L" all_sprites.add(bullet) bullet_list.add(bullet) if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT and soldier.change_x < 0: soldier.stop() if event.key == pygame.K_RIGHT and soldier.change_x > 0: soldier.stop() soldier.rect.clamp_ip(screen_rect) screen.blit(bg, [0, 0]) all_sprites.draw(screen) bomb.move() soldier.move() soldier.walk() for bullet in bullet_list: if bullet.direction == "R": bullet.moveright() else: bullet.moveleft() bomb_hit_list = pygame.sprite.spritecollide(bomb, bullet_list, True) for bullet in bomb_hit_list: bomb_list.remove(bomb) all_sprites.remove(bomb) pygame.sprite.spritecollide(soldier, bomb_list, True) clock.tick(60) pygame.display.flip() pygame.quit()
我想删除炸弹。如果炸弹碰到玩家,它的图像就会消失,但它仍然存在。现在,只要子弹碰到(不可见的)炸弹,它也会被删除。
要从 Pygame 内存中永久删除精灵并确保它不再与其他精灵交互,您需要确保正确地将其从所有相关组中删除并正确处理精灵的状态。
从您的代码来看,您似乎正在使用self.kill()移除精灵的方法,这是从其所属的所有精灵组中移除精灵的正确方法。但是,为了确保它完全从内存中消失并且不会干扰游戏逻辑,请确保在移除炸弹后也正确处理碰撞检测。
self.kill()
None
这是代码相关部分的更新版本,以确保炸弹已正确从内存中删除:
对现有代码进行以下修改:
bomb_hit_list = pygame.sprite.spritecollide(bomb, bullet_list, True) for bullet in bomb_hit_list: # Remove bomb from groups and set it to None bomb_list.remove(bomb) all_sprites.remove(bomb) bomb = None # Explicitly set to None to avoid using it later
move
Bomb
class Bomb(pygame.sprite.Sprite): def __init__(self): super().__init__() sprite_sheet = SpriteSheet("Untitled.png") self.image = sprite_sheet.get_image(2, 2, 48, 48, WHITE) self.rect = self.image.get_rect() self.active = True # Flag to indicate if the bomb is active def move(self): if not self.active: # If the bomb is not active, do nothing return self.change_y = 2 self.rect.y += self.change_y if self.rect.y > 500: self.kill() self.active = False # Mark as inactive def kill(self): super().kill() # Call the base class kill method self.active = False # Mark as inactive
在处理炸弹的移动或交互之前,请确保正确检查炸弹的状态。您可以使用该active属性来检查炸弹是否仍应在游戏循环中处理。
active
通过active属性管理炸弹的状态,您可以在炸弹被移除后阻止对其执行任何操作。将炸弹设置为None有助于避免引用可能被删除的精灵,确保游戏逻辑正常运行而不会出现错误。
实施这些更改后,你的炸弹应该可以正确地从内存中移除,而不会影响游戏玩法或产生意外行为。