【问题标题】:Pygame the best way to slow down the framerate of a certain animation without pausing the program?Pygame是在不暂停程序的情况下减慢某个动画的帧速率的最佳方法?
【发布时间】:2019-04-07 14:54:15
【问题描述】:

我在为精灵的不同帧设置动画时遇到了问题。我的程序以 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 来控制何时更改显示帧。在动画开始时,您使用pygame.time.get_ticks 获得当前时间,稍后在每个循环中您获得时间(也使用pygame.time.get_ticks)并计算差异。如果它是预期值,那么您更改帧并保持当前时间与下一个循环中的时间进行比较。
  • 你也可以使用pygame.time.set_timer每隔几秒/毫秒创建自己的事件。然后你可以使用这个事件来改变动画中的帧。
  • self.deadself.visible 有什么作用?难道不应该在爆炸之后而不是在开始时改变状态吗?

标签: animation pygame wait python-3.7


【解决方案1】:

您可以使用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 &gt; 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()

【讨论】:

  • 对于解决方案 1,我明白你的意思,但我不确定我将如何实施这个“change_frame_in_animation()”
  • 你必须得到下一帧并blit它——所以可能self.explosionc = (self.explosionc + 1) % 6win.blit(Expl[self.explosionc],(self.x,self.y))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-04
  • 2018-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多