我试图在我的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枚子弹,并且在船舶运动时实际发射。截至目前,敌人几乎无用,好像你只是稍微移动到位,然后就不会开火,而且它很容易击败。
任何帮助表示赞赏!
答案 0 :(得分:1)
问题是意大利面条代码是意大利面条。 : - )
我自己无法确切地知道你想要什么 - 如果所有的子弹功能产生相同的子弹或者它们实际上是不同的,等等。
有两个问题导致你的主要问题,但是 - 它们可以修复,保持代码的形式相同,但我建议在那里进行一些重写,朝向更多的gnocchi方法(而不是意大利面)
问题的主要来源是你在500ms后注册一个要触发的事件,你对它做出反应并调用你的delay
函数。但是,该函数同时调用BossPower
函数来触发其他子弹,而不会有任何延迟。
然而,没有,你可以在调用函数来解雇其他子弹之前在延迟内部调用time.sleep
或pygame.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()