Pygame在不暂停程序的情况下减慢某个动画的帧速率的最佳方法?



我在为精灵的不同帧制作动画时遇到了问题。我的程序以 60 FPS 的速度运行,我的一些精灵没有足够的帧来看起来很流畅,并有足够的时间让用户看到。例如,我的爆炸精灵中有 6 帧。虽然游戏以 60FPS 的速度运行,但这意味着整个动画仅在 1/10 秒内可见。

我已经尝试了以下功能:Pygame.wait 和 Pygame.delay 以及 "//" 楼层函数。Pygame.wait/delay都完全暂停了程序,这意味着仅仅为了看到爆炸,用户就必须停止他们正在做的任何事情,我不想复制帧来达到30或60帧,这似乎效率低下。

爆炸阵列:

Expl = [pygame.image.load("EX1.png"),pygame.image.load("EX2.png"),pygame.image.load("EX3.png"),pygame.image.load("EX4.png"),pygame.image.load("EX5.png"),pygame.image.load("EX6.png")]

发生地点:

if self.explosionc + 1 >= 6:
self.explosionc = 0
elif self.vel > 0:
win.blit(Expl[self.explosionc // 5],(self.x,self.y))
self.explosionc +=1

玩家类,如果你需要那么多信息

class Player(pygame.sprite.Sprite):
def __init__(self,x,y,width,height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 5
self.health = 10
self.visible = True
self.explosions = False
self.explosionc = 0
self.hitbox = (self.x + 5,self.y + 10,60,60)
self.canshoot = True
self.dead = False
def draw(self,win):
global bgvel
if self.y > 600:
win.blit(EFTNA,(self.x,self.y))
for enemy in enemies:
enemy.vel = 2
#bgvel = 1
elif self.y <= 600 and self.y > 400:
win.blit(EFTAL,(self.x,self.y))
for enemy in enemies:
enemy.vel = 3
#bgvel = 2
elif self.y <= 400 and self.y > 350:
win.blit(EFTAM,(self.x,self.y))
for enemy in enemies:
enemy.vel = 4
#bgvel = 3
elif self.y <= 450:
win.blit(EFTAH,(self.x,self.y))
for enemy in enemies:
enemy.vel = 5
#bgvel = 4
self.hitbox = (self.x + 5,self.y + 10,60,60)
#pygame.draw.rect(win,(255,0,0),self.hitbox,2)
if self.y + self.height > HEIGHT:
self.y -= self.vel
if self.x < 0:
self.x += self.vel
if self.x + self.width > WIDTH:
self.x -= self.vel
if self.explosions == True:
print("I exploded")
self.canshoot = False
self.dead = True
index = self.explosionc//10
if self.vel > 0:
win.blit(Expl[index % 6],(self.x,self.y))
self.explosionc += 1
#if self.explosionc >= 6*10:
#    self.explosionc = 0
self.visible = False
def hit(self):
if self.health > 0:
self.health -=1
else:
self.explosions = True

我希望程序在每一帧之间等待一定的时间,而不会暂停整个程序。我听说"地板"是一个很好的方法,但它似乎没有效果,因为它要么使人眼完全看不见,要么没有效果。

您可以使用pygame.time.get_ticks()来使用时间来控制显示帧的时间长度

start_time = pygame.time.get_ticks()
while running:
current_time = pygame.time.get_ticks()
if current_time - start_time >= expected_delay_in_ms:
change_frame_in_animation()
start_time = current_time

我在while running之前创建start_time,但您必须在开始动画时创建它。


您还可以使用pygame.time.set_timer()每隔几毫秒创建自己的事件。然后,您可以使用此事件更改动画中的帧

pygame.time.set_timer(pygame.USEREVENT+1, expected_delay_in_ms)
while running:
for event in pygame.event.get():
if event.type = pygame.USEREVENT+1:
change_frame_in_animation()

我在while running之前使用pygame.time.set_timer(),但您必须在开始动画时使用它。


编辑:使用您有问题的新代码可能是(但我无法测试它)

self.__init__我定义

self.frame_delay = 200 # 200 milliseconds

当玩家死亡时,我设置self.start_delay = 0- 它应该立即显示第一帧。

def hit(self):
if self.health > 0:
self.health -= 1
else:
self.explosions = True
self.start_delay = 0 # or pygame.time.get_ticks()

draw我使用self.start_delaycurrent_timeself.frame_delay进行比较

if self.explosions == True:
current_time = pygame.time.get_ticks()
if current_time - self.start_delay >= self.frame_delay:
self.start_delay = current_time
print("I exploded")
self.canshoot = False
self.dead = True
self.explosionc = (self.explosionc + 1) % 6
if self.vel > 0: # ???
win.blit(Expl[self.explosionc],(self.x,self.y))
self.visible = False

我计算下一帧

self.explosionc = (self.explosionc + 1) % 6

我不知道你为什么使用if self.vel > 0:

完整代码

class Player(pygame.sprite.Sprite):
def __init__(self,x,y,width,height):
self.x = x
self.y = y
self.width = width
self.height = height
self.vel = 5
self.health = 10
self.visible = True
self.explosions = False
self.explosionc = 0
self.hitbox = (self.x + 5,self.y + 10,60,60)
self.canshoot = True
self.dead = False
self.frame_delay = 200 # 200 milliseconds

def draw(self,win):
global bgvel
if self.y > 600:
win.blit(EFTNA,(self.x,self.y))
for enemy in enemies:
enemy.vel = 2
#bgvel = 1
elif self.y <= 600 and self.y > 400:
win.blit(EFTAL,(self.x,self.y))
for enemy in enemies:
enemy.vel = 3
#bgvel = 2
elif self.y <= 400 and self.y > 350:
win.blit(EFTAM,(self.x,self.y))
for enemy in enemies:
enemy.vel = 4
#bgvel = 3
elif self.y <= 450:
win.blit(EFTAH,(self.x,self.y))
for enemy in enemies:
enemy.vel = 5
#bgvel = 4
self.hitbox = (self.x + 5,self.y + 10,60,60)
#pygame.draw.rect(win,(255,0,0),self.hitbox,2)
if self.y + self.height > HEIGHT:
self.y -= self.vel
if self.x < 0:
self.x += self.vel
if self.x + self.width > WIDTH:
self.x -= self.vel
if self.explosions == True:
current_time = pygame.time.get_ticks()
if current_time - self.start_delay >= self.frame_delay:
self.start_delay = current_time
print("I exploded")
self.canshoot = False
self.dead = True
self.explosionc = (self.explosionc + 1) % 6
if self.vel > 0: # ???
win.blit(Expl[self.explosionc],(self.x,self.y))
self.visible = False
def hit(self):
if self.health > 0:
self.health -= 1
else:
self.explosions = True
self.start_delay = 0 # or pygame.time.get_ticks()

最新更新