Пигментный Спрайт Не Рисование - PullRequest
2 голосов
/ 18 апреля 2020

Итак, я создаю эту игру со стрельбой по астероидам, и у меня есть класс под названием Laser. Поскольку мне нужно создать много лазеров, я создал группу спрайтов для этого класса и добавил 25 спрайтов. Я делаю так, что всякий раз, когда пользователь нажимает пробел, последний лазер (мне удалось организовать его, используя список спрайтов) в группе поднимается по экрану с помощью Vector2D, а остальные лазеры «спрятаны» под космическим кораблем. спрайт. Вот код для класса Laser:

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

изображение лазера, появляющегося на screen

Но есть несколько вещей, которые я хочу, которые не удовлетворяют приведенному выше коду. Прежде всего, я хочу, чтобы лазер стрелял и двигался по экрану (я знаю, что движение - это перекрашивание пикселей). Кроме того, я хочу, чтобы он go находился в разных позициях, потому что он будет зависеть от того, куда пользователь перемещает свой спрайт космического корабля и из которого стреляет. Я пытался найти решение для этого в течение нескольких часов и специально создал учетную запись переполнения стека для этого вопроса, любая помощь будет принята с благодарностью. :)

РЕДАКТИРОВАТЬ: лазер запускается, но теперь мне нужно выяснить, как игрок может запустить несколько лазеров. Под этим я подразумеваю, что игрок должен нажать пробел, подождать несколько секунд, затем снова нажать пробел, и на экране должны появиться 2 лазера. В настоящее время, если игрок делает это, лазер, который был на экране, стирается, а затем перемещается, так что похоже, что новый лазер исходит от космического корабля. Это смущает игрока, поскольку лазер, который только что поднялся, «исчезает».

1 Ответ

1 голос
/ 18 апреля 2020

Прежде всего, у вас есть все лазеры в группе Sprite, но вы получаете все лазеры из группы и помещаете их в список, затем l oop просматриваете список, чтобы обновить и нарисовать их, затем нарисуйте их. снова через группу спрайтов, в которой нет необходимости, лучше иметь все спрайты в группе спрайтов и вызывать lasers.update() и 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()

когда вы нажимаете пробел, он будет продолжать двигаться тем же лазером, пока не достигнет вершины и не будет удален. Если это то, что вы хотите, это не идеально, но это подойдет. В противном случае вы можете захотеть счетчик, который отсчитывает лазеры.

Так что я думаю, что это решает вторую часть вашего вопроса. Что касается лазера, не показывающего, когда вы нажимаете пробел, если вы очищаете свой код и используете спрайт-группу или список, а не оба, тогда он должен работать, если нет, опубликовать весь ваш код, чтобы я мог его воссоздать.

...