为“太空侵略者”做子弹

时间:2019-12-19 12:59:50

标签: python pygame

我正在尝试使用我的太空侵略者版本制造飞船的弹丸。我认为目前唯一不起作用的是显示所有射弹,因为我不知道如何,这就是为什么我尝试使用不起作用的blit的原因。我也想延迟每个弹丸之间的时间,但是我不确定该怎么做。 到目前为止,这是我完成的最先进的屏幕相关程序。

import pygame
pygame.init()

class Player():
    def __init__(self):
        self.originalImage = pygame.image.load("ship.png")
        self.image = self.originalImage
        self.xposition = 480
        self.yposition = 450
        self.speed = 1

class Projectile():
    def __init__(self):
        self.originalImage = pygame.image.load("shot.png")
        self.image = self.originalImage
        self.xposition = player.xposition
        self.yposition = player.yposition
        self.speed = 1


size = width, height = 960, 540
screen = pygame.display.set_mode(size)
background = 0, 0, 0
player = Player()
projectile = Projectile()
projectiles = []
keys = pygame.key.get_pressed()

while True:
    screen.fill(background)

    for projectile in projectiles:
        if projectile.yposition < height:
            projectile.yposition -= projectile.speed
        else:
            projectiles.pop(projectiles.index(projectile))

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    if (keys[pygame.K_RIGHT] or keys[pygame.K_d]) == True:
        player.xposition += player.speed
    if (keys[pygame.K_LEFT] or keys[pygame.K_a]) == True:
        player.xposition -= player.speed
    if (keys[pygame.K_SPACE] or keys[pygame.K_w] or keys[pygame.K_UP]) == True:
        projectiles.append(projectile)

    for projectile in projectiles:
        screen.blit(projectile.image, (projectile.xposition, projectile.yposition))

    screen.blit(player.image, ((player.xposition, player.yposition)))
    pygame.display.flip()

我在注释后编辑了代码,但仍然没有任何动作...

2 个答案:

答案 0 :(得分:1)

问题出在哪里

  • 什么都没有动,因为pygame.key.get_pressed()在游戏循环之外,也就是说,您仅在启动时检查键的状态。

  • 每次拍摄都必须创建一个新的Projectile实例,否则只能拍摄一次。

  • 要使弹丸正确显示,必须先将玩家的精灵变白,然后再将弹丸消散,否则玩家的精灵会覆盖住它们。

  • 要编码两次射击之间的延迟,请将射击冷却时间存储在一个变量(最好是player属性)中,您每次射击时都会将其设置为某个正值,并且每回合递减。

  • 您使用sys.exit(),但尚未导入sys,这会使您的游戏在退出时崩溃。或者,您可以改为raise SystemExit,它与sys.exit()完全相同,并且不需要任何导入。

这是更正的代码:

import pygame
pygame.init()

class Player():
    def __init__(self):
        self.originalImage = pygame.image.load("ship.png")
        self.image = self.originalImage
        self.xposition = 480
        self.yposition = 450
        self.speed = 1
        self.attack_cooldown = 0   # variable to store shooting cooldown

class Projectile():
    def __init__(self):
        self.originalImage = pygame.image.load("shot.png")
        self.image = self.originalImage
        self.xposition = player.xposition
        self.yposition = player.yposition
        self.speed = 1


size = width, height = 960, 540
screen = pygame.display.set_mode(size)
background = 0, 0, 0
player = Player()
projectiles = []

while True:
    screen.fill(background)

    # decrement the current shooting cooldown
    if player.attack_cooldown > 0:
        player.attack_cooldown -= 1

    for projectile in projectiles:
        if projectile.yposition < height:
            projectile.yposition -= projectile.speed
        else:
            projectiles.pop(projectiles.index(projectile))

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            raise SystemExit   # does the same thing as sys.exit() but you don't need to import sys

    keys = pygame.key.get_pressed()   # put this in the game loop

    if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
        player.xposition += player.speed
    if keys[pygame.K_LEFT] or keys[pygame.K_a]:
        player.xposition -= player.speed
    if keys[pygame.K_SPACE] or keys[pygame.K_w] or keys[pygame.K_UP]:
        if player.attack_cooldown == 0:   # shoot only when not on cooldown
            projectiles.append(Projectile())   # shoot a new projectile instead of the one you already shot
            player.attack_cooldown = 100   # add shooting cooldown, the number can be any positive integer you want

    # blit the player first
    screen.blit(player.image, ((player.xposition, player.yposition)))
    for projectile in projectiles:
        screen.blit(projectile.image, (projectile.xposition, projectile.yposition))

    pygame.display.flip()

答案 1 :(得分:1)

我建议使用pygame.sprite.Sprite。从Projectile派生SpriteSprite应该具有属性.image.rect。添加一个方法,当其超出范围时,将移动Projectilekill() s。例如:

class Projectile(pygame.sprite.Sprite):

    def __init__(self):
        super().__init__() 
        self.originalImage = pygame.image.load("shot.png")
        self.image = self.originalImage
        self.rect = self.image.get_rect(center = (player.xposition, player.yposition))
        self.speed = 1

    def move(self):
        self.rect.y -= self.speed
        if self.rect.y < 0:
            self.kill()

创建一个pygame.sprite.Group来容纳弹丸:

projectiles = pygame.sprite.Group()

.draw()可以绘制Group中的精灵。

projectiles.draw(screen)

每次玩家发射子弹时,都必须创建一个新的子弹实例并将其添加到子弹组中。我建议我们为此使用键盘事件:

for event in pygame.event.get():
    # [...]

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_SPACE or event.key == pygame.K_w or event.key == pygame.K_UP: 
            projectiles.add(Projectile())

键(keys = pygame.key.get_pressed())的状态必须在主应用程序循环中评估。应用程序的速度可以由pygame.time.Clock()控制:

import pygame
pygame.init()

class Player(pygame.sprite.Sprite):
    def __init__(self):
        self.originalImage = pygame.image.load("ship.png")
        self.image = self.originalImage
        self.rect = self.image.get_rect(center = (480, 450))
        self.speed = 1

class Projectile(pygame.sprite.Sprite):

    def __init__(self):
        super().__init__() 
        self.originalImage = pygame.image.load("shot.png")
        elf.image = self.originalImage
        self.rect = self.image.get_rect(center = player.rect.center)
        self.speed = 1

    def move(self):
        self.rect.y -= self.speed
        if self.rect.y < 0:
            self.kill()


size = width, height = 960, 540
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
background = 0, 0, 0
player = Player()
projectiles = pygame.sprite.Group()

run = True
while run:
    clock.tick(120)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN:
           if event.key == pygame.K_SPACE or event.key == pygame.K_w or event.key == pygame.K_UP: 
              projectiles.add(Projectile())

    keys = pygame.key.get_pressed()
    if (keys[pygame.K_RIGHT] or keys[pygame.K_d]) == True:
        player.rect.x += player.speed
    if (keys[pygame.K_LEFT] or keys[pygame.K_a]) == True:
        player.rect.x -= player.speed

    for projectile in projectiles:
        projectile.move()

    screen.fill(background)
    projectiles.draw(screen)
    screen.blit(player.image, player.rect.topleft)
    pygame.display.flip()