首页 > 解决方案 > Pygame Sprite 不绘图

问题描述

所以我正在创建这个小行星射击游戏,并且我有一个名为 Laser 的课程。因为我需要创建很多激光,所以我为这个类创建了一个 Sprite Group 并添加了 25 个 sprite。我正在这样做,每当用户按下空格键时,组中的最后一个激光(我设法使用精灵列表组织它)使用 Vector2D 穿过屏幕,其余的激光被“隐藏”在宇宙飞船下精灵。这是激光类的代码:

import pygame


class Laser(pygame.sprite.Sprite):
    def __init__(self, pos):
        super().__init__()
        self.image = pygame.image.load("laser.png")
        self.scale = 0.05
        self.image = pygame.transform.smoothscale(
            self.image,
            (int(self.image.get_rect().width * self.scale),
             int(self.image.get_rect().height * self.scale)),
        )
        self.rect = self.image.get_rect()
        # Getting the rectangle around the image lets you move it.
        self.rect.center = pos
        self.speed = pygame.math.Vector2(0, -5)
        self.speed.rotate_ip(0)
        self.track = 0

    def update(self, pos):
        if self.track == 0:
            self.rect.move_ip(pos)

    def move(self):
        self.rect.move_ip(self.speed)
        self.track = self.track + 1
        # self.track makes it so that the program knows not to call the update function for this Laser object.

main.py 中涉及激光拍摄和创建的代码片段(包括所有代码会太多):

global lasers
    player.collect((width/2, height), spriteNum)
    for i in range(0, 25):
        lasers.add(Laser((width/2, height)))
    init()
    while True:
        screen.fill([255, 255, 255])
        bigger_img = pygame.transform.scale(background.image, (width, height))
        screen.blit(bigger_img, (0, 0))
        playerPosition = player.update()
        lasers_list = lasers.sprites()
        for i in range(0, len(lasers_list)):
            lasers_list[i].update(playerPosition)
            screen.blit(lasers_list[i].image, lasers_list[i].rect)
            if lasers_list[i].rect.top < 0:
                lasers.remove(lasers_list[i])
        enemies.update(speed)
        clock.tick(60)
        last_laser = lasers.sprites()[len(lasers_list) - 1]
        player_hit = pygame.sprite.spritecollide(player, enemies, False)
        screen.blit(player.image, player.rect)
        enemies.draw(screen)
        lasers.draw(screen)
        screen.blit(last_laser.image, last_laser.rect)
        pygame.display.flip()
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    player.speed[0] = 5
                if event.key == pygame.K_LEFT:
                    player.speed[0] = -5
                if event.key == pygame.K_UP:
                    player.speed[1] = -5
                if event.key == pygame.K_DOWN:
                    player.speed[1] = 5
                if (event.key == pygame.K_SPACE):
                    if  (len(lasers_list) - 1) > -1:
                        last_laser.move()
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT:
                    player.speed[0] = 0
                if event.key == pygame.K_LEFT:
                    player.speed[0] = 0
                if event.key == pygame.K_UP:
                    player.speed[1] = 0
                if event.key == pygame.K_DOWN:
                    player.speed[1] = 0
                if event.key == pygame.K_SPACE:
                    abcd = "0"
                    #nothing, I don't feel like I need anything here since no lasers would be launched if the spacebar was up. 

好的,所以如果我从这里更改代码,last_laser 就会出现:

                if (event.key == pygame.K_SPACE):
                    if  (len(lasers_list) - 1) > -1:
                        last_laser.move()

对此:

                if (event.key == pygame.K_SPACE):
                    last_laser.rect.center = (400, 400)
                    # Some arbitrary x and y values (400, 400).
                    last_laser.track += 1

激光显示在屏幕上的图片

但是有很多我想要的东西对上面的代码不满意。首先,我希望激光射出并像在屏幕上移动一样(我知道移动是像素的重新着色)。此外,我希望它去到不同的位置,因为它将依赖于用户将他/她的宇宙飞船精灵移动到哪里以及从哪里射击。几个小时以来,我一直在努力寻找解决方案,并专门为这个问题制作了一个堆栈溢出帐户,任何帮助将不胜感激。:)

编辑:激光正在发射,但现在我需要弄清楚玩家如何发射多个激光。我的意思是玩家应该能够按空格键,等待几秒钟,然后再次按空格键,屏幕上应该会出现 2 道激光。目前,如果玩家这样做,屏幕上的激光将被擦除然后重新定位,因此看起来新的激光来自宇宙飞船。这让玩家感到困惑,因为刚刚上升的激光“消失了”。

标签: pythonpygamespritegame-development

解决方案


首先,你有一个 Sprite 组中的所有激光,但是你从组中获取所有激光并将它们放入一个列表中,然后循环遍历列表以更新和绘制它们,然后通过精灵组再次绘制它们,这是不必要的,而是将所有精灵放在 Sprite 组中并调用 lasers.update()and lasers.draw(screen),或者将它们放在列表中并执行您现在正在做的事情,除了这里

for i in range(0, 25):
    lasers.add(Laser((width/2, height)))

变成

for i in range(0, 25):
     lasers_list.append(Laser((width/2, height)))

还有很多线条可以缩短,看起来更干净

last_laser = lasers.sprites()[len(lasers_list) - 1]
last_laser = lasers.sprites()[-1] #-1 gets the last in list

if (len(lasers_list) - 1) > -1:
if len(lasers_list) > 0:

self.track = self.track + 1
self.track += 1

也会移动

screen.blit(lasers_list[i].image, lasers_list[i].rect)
    if lasers_list[i].rect.top < 0:
        lasers.remove(lasers_list[i])

到激光类中的更新功能

def update(self, pos):
    if self.track == 0:
        self.rect.move_ip(pos)
    screen.blit(lasers_list[i].image, lasers_list[i].rect)
        if self.rect.top < 0:
            self.kill() #deletes from sprite group

在激光类的更新功能中,我会添加

def update(self, pos):
    if self.track == 0:
        self.rect.move_ip(pos)
    else:  #if not moving with ship
        self.move() # so it moves on its own
    screen.blit(lasers_list[i].image, lasers_list[i].rect)
        if self.rect.top < 0:
            self.kill() #deletes from sprite group

因为这个

 if (event.key == pygame.K_SPACE):
     if len(lasers_list) > 0:
         last_laser.move()

当你按下空格键时,它会继续移动相同的激光,直到它到达顶部并被移除。如果这就是你想要的,它并不完美,但它会做到的。否则,您可能需要一个计数器,用于对激光进行倒计时。

所以我认为这解决了你问题的第二部分。至于按下空格时激光不显示,如果您清理代码并使用精灵组或列表,而不是两者,那么它应该可以工作,如果没有,请发布您的所有代码,以便我可以重新创建它。


推荐阅读