延迟射击的敌人

时间:2017-11-20 17:35:50

标签: python pygame delay

我试图在我的pygame代码中延迟我的一个敌人镜头,这是一个太空入侵者/子弹地狱游戏。不幸的是,我似乎在延迟射击敌人方面遇到了问题。

import pygame
import random
import time
import os
import threading

pygame.time.set_timer ( pygame.USEREVENT , 450 )
event_500ms = pygame.USEREVENT + 1
pygame.time.set_timer(event_500ms, 500)

class Alien2 (pygame.sprite.Sprite):
    def __init__(self):
        # Call the parent class (Sprite) constructor
        super().__init__()

        self.image = pygame.Surface([20, 15])
        self.image = pygame.image.load("alien3.png").convert()
        self.image.set_colorkey(WHITE)


        self.rect = self.image.get_rect()
    def update(self):

        pos = pygame.mouse.get_pos()

        dx = pos[0] - self.rect.x + 18
        dx *= .05
        self.rect.x += dx
def BossPowers():
    bullet3 = Bullet3()
    # Set the bullet so it is where the player is
    bullet3.rect.x = alien2.rect.x + 47
    bullet3.rect.y = alien2.rect.y + 57
    # Add the bullet to the lists
    all_sprites_list.add(bullet3)
    bullet2_list.add(bullet3)

def BossPowers2():
    bullet4 = Bullet4()
    # Set the bullet so it is where the player is
    bullet4.rect.x = alien2.rect.x + 47
    bullet4.rect.y = alien2.rect.y + 57
    # Add the bullet to the lists
    all_sprites_list.add(bullet4)
    bullet2_list.add(bullet4)


def delay():
    #threading.Timer(5.0, delay).start()
    bullet2 = Bullet2()
    # Set the bullet so it is where the player is
    bullet2.rect.x = alien2.rect.x + 47
    bullet2.rect.y = alien2.rect.y + 57
    # Add the bullet to the lists
    all_sprites_list.add(bullet2)
    bullet2_list.add(bullet2)
    BossPowers()
    BossPowers2()

在这里忽略我的意大利面条代码,我已经在这个游戏上工作了一段时间,有时效率低下我的想法

while not done:
    # --- Event Processing
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
    if level % 2 == 0:
        all_sprites_list.add(alien2)
        alien2_list.add(alien2)
        for block in block_list:
            block_list.remove(block)
            all_sprites_list.remove(block)
       #t = threading.Timer(2, delay)
       #t.start()    
        #if event.type == event_500ms:
            #delay()



    if level % 2 == 1:
        block_list.add(block)
        all_sprites_list.add(block) 
好吧所以这是我的问题。 敌舰确实延迟射击......但是只有在船只移动时它才会停止射击。当船停止移动时,它会向它发射一阵溪流,而不是我希望它射击的单个子弹。我需要它来延迟射击,每n秒发射1枚子弹,并且在船舶运动时实际发射。截至目前,敌人几乎无用,好像你只是稍微移动到位,然后就不会开火,而且它很容易击败。 任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:1)

问题是意大利面条代码是意大利面条。 : - )

我自己无法确切地知道你想要什么 - 如果所有的子弹功能产生相同的子弹或者它们实际上是不同的,等等。

有两个问题导致你的主要问题,但是 - 它们可以修复,保持代码的形式相同,但我建议在那里进行一些重写,朝向更多的gnocchi方法(而不是意大利面)

问题的主要来源是你在500ms后注册一个要触发的事件,你对它做出反应并调用你的delay函数。但是,该函数同时调用BossPower函数来触发其他子弹,而不会有任何延迟。

然而,没有,你可以在调用函数来解雇其他子弹之前在延迟内部调用time.sleeppygame.time.delay,因为这会暂停整个游戏。

因此,一种方法是调用延迟来注册其他自定义事件以触发下一个项目符号,然后从函数返回。然后主循环会在找到这些事件时触发下一个子弹。

这让我们看到了这段代码中的第二个大问题:在每个帧中,您获取所有可用事件,但对于所有这些事件,您唯一要做的就是检查pygame.QUIT。巧合的是,每个帧中提取的最后一个事件都由event变量引用,并且在您检查自定义事件的行(if event.type == event_500ms:)中可用。到达同一帧的其他事件被简单地丢弃了。这也意味着您的自定义事件可能会被丢弃。

因此,重要的是,只有在代码中的某一点,您才能获取每个帧的所有事件,并且在同一点上进行任何与事件相关的操作或比较。

现在,Pygame允许使用最少数量的用户定义事件(在默认构建中只有8个,因为他们推荐的是pygame.USEREVENT之前可用的事件)。如果您要为每个要发射的子弹类使用一种事件类型,那么在游戏达到3级之前,您的事件编号就会用尽。

因此,由于触发子弹的代码完全相同,而您只需更改子弹类,您可以生成一系列子弹类,并使用itertools.cycle来获取下一个子弹类型:

...
import itertools


fire_bullet_event = pygame.USEREVENT + 1

...

bullets = itertools.cycle([Bullet2, Bullet3, Bullet4)

def fire_bullet():
    bullet_type = next(bullets)
    bullet2 = bullet_type()

    # Set the bullet so it is where the player is
    bullet2.rect.x = alien2.rect.x + 47
    bullet2.rect.y = alien2.rect.y + 57
    # Add the bullet to the lists
    all_sprites_list.add(bullet2)
    bullet2_list.add(bullet2)

    delay = 500
    # Schedule to call this function again in 500ms. 
    # use an "if" to change the 500 to another number like:
    # if bullet_type == Bullet4:
    #     delay = 2000
    pygame.time.set_timer(fire_bullet_event, delay)


...

# Schedule the first bullet close to entering the loop - 
# it is easier to see than putting it with the game setup code:
pygame.time.set_timer(fire_bullet_event, 500)

while not done:
    # --- Event Processing
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        # all code dealing with events must be inside this `for` loop.
        if event.type == fire_bullet_event:
            fire_bullet()
    if level % 2 == 0:
        all_sprites_list.add(alien2)
        alien2_list.add(alien2)
        for block in block_list:
            block_list.remove(block)
            all_sprites_list.remove(block)

答案 1 :(得分:1)

我通常使用tick返回的增量时间(自上次clock.tick(fps)后经过的时间)并将其传递给精灵的update方法以增加或减少计时器变量。当计时器低于0时,我创建Bullet类的实例,将其添加到精灵组并重置计时器。

import pygame as pg
from pygame.math import Vector2


pg.init()
ALIEN_IMAGE = pg.Surface((20, 15))
ALIEN_IMAGE.fill((40, 200, 90))
BULLET_IMAGE = pg.Surface((5, 5))
BULLET_IMAGE.fill((240, 120, 0))


class Alien(pg.sprite.Sprite):

    def __init__(self, pos, all_sprites, bullets):
        super().__init__()
        self.image = ALIEN_IMAGE
        self.rect = self.image.get_rect(center=pos)
        self.vel = Vector2(1, 0)
        self.pos = Vector2(pos)
        self.bullet_timer = 1  # 1 second.
        self.all_sprites = all_sprites
        self.bullets = bullets

    def update(self, dt):
        self.pos += self.vel
        self.rect.center = self.pos

        # Decrease the countdown timer.
        self.bullet_timer -= dt
        if self.bullet_timer < 0:  # Time is up so create a bullet.
            bullet = Bullet(self.rect.center, Vector2(0, 5))
            # Add the bullet to the sprite groups.
            self.all_sprites.add(bullet)
            self.bullets.add(bullet)
            self.bullet_timer = 1  # Reset timer after firing.


class Bullet(pg.sprite.Sprite):

    def __init__(self, pos, velocity):
        super().__init__()
        self.image = BULLET_IMAGE
        self.rect = self.image.get_rect(center=pos)
        self.vel = velocity
        self.pos = Vector2(pos)

    def update(self, dt):
        self.pos += self.vel
        self.rect.center = self.pos


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()

    all_sprites = pg.sprite.Group()
    bullets = pg.sprite.Group()
    alien =  Alien((0, 30), all_sprites, bullets)
    alien2 = Alien((60, 30), all_sprites, bullets)
    all_sprites.add(alien, alien2)

    done = False

    while not done:
        # dt = delta time (passed time since last clock.tick call).
        dt = clock.tick(30) / 1000  # / 1000 to convert to seconds.

        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True

        all_sprites.update(dt)
        screen.fill((30, 30, 30))
        all_sprites.draw(screen)
        pg.display.flip()


if __name__ == '__main__':
    main()
    pg.quit()