【问题标题】:Pygame: How to wait a certain amount of time to do something after a method has been calledPygame:如何在调用方法后等待一定的时间来做某事
【发布时间】:2020-11-15 21:42:20
【问题描述】:

我大约 6 周前开始学习 python,大约 2 周前开始玩 pygame。我正在阅读一本好书(Python Crash Course),并且正在制作一个简单的游戏作为练习。

在屏幕的左侧,我有一张弓和箭的图片,可以通过按空格键上下移动和“射击”。当箭射出时,图像变为没有箭的未拉弓,因此看起来像是弓弦被松开了。

到目前为止,我已经完成了这一切。不过,我想要的是在射箭后的一定时间内重新加载弓。所以玩家按下空格键,箭被射出,然后大约一秒钟后弓被重新加载,玩家可以再次射击。

特别是,在调用 fire_bow() 方法后,我希望在 2 秒后将 bow_drawn 标志设置回 True。

有人知道我该怎么做吗?我已经阅读了文档,但我似乎找不到任何可以给我想要的效果的东西。特别是我不想暂停程序。理想情况下,我正在想象一种方法,即“等待 1 秒”。

这是我目前的代码,如果有用的话。

import sys

import pygame

from target_practise_settings import Settings
from bow_and_arrow import Bow


class TargetPractise:
    """ Overall class to manage game assets and behaviour. """

    def __init__(self):
        """ Overall class to manage game assets and behavior. """
        pygame.init()
        self.settings = Settings()

        self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
        self.screen_width = self.screen.get_rect().width
        self.screen_height = self.screen.get_rect().height
        pygame.display.set_caption("Target Practise")

        self.bow = Bow(self)

    def run_game(self):
        """ Start the main loop for the game. """
        while True:
            # Watch for keyboard and mouse events.
            self._check_events()

            self.bow.update()

            self._update_screen()

    def _check_events(self):
        """ Respond to keypresses and mouse events. """
        for event in pygame.event.get():

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

            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)

            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)

    def _check_keydown_events(self, event):
        """ Respond to keypresses """
        if event.key == pygame.K_UP:
            self.bow.moving_up = True
        elif event.key == pygame.K_DOWN:
            self.bow.moving_down = True
        elif event.key == pygame.K_q:
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self.bow.fire_bow()

    def _check_keyup_events(self, event):
        """ Respond to key releases """
        if event.key == pygame.K_UP:
            self.bow.moving_up = False
        if event.key == pygame.K_DOWN:
            self.bow.moving_down = False

    def _update_screen(self):
        """ Update images on the screen, and flip to the new screen. """
        # Redraw the screen during each pass through the loop.
        self.screen.fill(self.settings.bg_colour)
        self.bow.blitme()

        # Make the most recently drawn screen visible.
        pygame.display.flip()


if __name__ == '__main__':
    # Make a game instance, and run the game.
    tp = TargetPractise()
    tp.run_game()

还有弓类。

import pygame


class Bow:
    """ A class to manage the bow. """

    def __init__(self, tp_game):
        """ Initialise the bow and its starting position """
        self.screen = tp_game.screen
        self.settings = tp_game.settings
        self.screen_rect = tp_game.screen.get_rect()

        # Load the bow and arrow image
        self.bow_arrow_image = pygame.image.load(
                            'images/FINAL/bow_and_arrow_rotcrop_resize.bmp')

        # Load the bow (no arrow) image and get its rect
        self.bow_image = pygame.image.load(
                                'images/FINAL/bow_no_arrow_rotcrop_resize.bmp')

        self.rect = self.bow_arrow_image.get_rect()

        # Start each new bow at the centre right of the screen
        self.rect.midleft = self.screen_rect.midleft

        # Store a decimal value for the ship's vertical position
        self.y = float(self.rect.y)

        # Movement flags
        self.moving_up = False
        self.moving_down = False

        # Bow drawn flag
        self.bow_drawn = True

    def fire_bow(self):
        self.bow_drawn = False

    def update(self):
        """ Update the bow's position based on the movement flags. """
        # Update the bow's y value, not the rect
        if self.moving_up:
            self.y -= self.settings.bow_speed
        if self.moving_down:
            self.y += self.settings.bow_speed

        # Update rect object from self.y
        self.rect.y = self.y

    def blitme(self):
        """
        Draw the bow at its current location.
        Bow will be drawn depending on the bow_drawn flag
        """
        if self.bow_drawn:
            self.screen.blit(self.bow_arrow_image, self.rect)
        elif not self.bow_drawn:
            self.screen.blit(self.bow_image, (self.rect.x + 75, self.rect.y))

最后是设置。

class Settings:
    """ A class to store all settings for Target Practise """

    def __init__(self):
        """ Initialise the game's settings. """
        # Screen Settings
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_colour = (255, 255, 255)

        # Bow Settings
        self.bow_speed = 1

Bow with arrow

Bow without arrow

非常感谢您阅读本文!

【问题讨论】:

  • sleep 2 ?............

标签: python python-3.x pygame


【解决方案1】:

如果您不想暂停正在使用的唯一线程。您可能应该使用线程。

Python Time Delays

试试这样的:

from threading import Timer

def bow():
    bow_drawn = True

t = Timer(2.0, bow)
t.start() # after 2 seconds, function "bow" will run

【讨论】:

    【解决方案2】:

    我建议使用pygame.time.set_timer() 和 pygames 事件机制。上面的文档是here

    我有一个类似问题 here 的答案,但会在此处包含足够的信息来帮助解决这种特定情况。

    您将计时器设置为在特定时间后到期。当它发生时,它会触发一个您可以在事件循环中查找的事件。这使您可以非常简单地将其添加到现有的事件机制中。

    在发射弓之后,你可以添加这个,它会启动一个计时器,在 2 秒后触发一个事件:

        pygame.time.set_timer(pygame.USEREVENT, 2000)
    

    为了捕捉到这一点,在_check_events() 内的事件循环中,您将拥有类似的内容:

                if event.type == pygame.USEREVENT:
                    # Timer expired. Bow can be fired again
                    self.bow.pull_bow()
    
    

    在 bow 类中,您必须添加 pull_bow() 调用,例如:

    class Bow:
        ...
        def pull_bow(self):
            self.bow_drawn = True
    

    【讨论】:

      【解决方案3】:

      您必须添加一个计时器变量。这是一个简单的整数,在您释放弓后从某个数字开始倒数。当计时器变量达到 0 时,您就知道允许再次触发。

      首先将这个添加到init函数中:

      self.bow_fire_wait = 100
      self.bow_fire_timer = 0
      

      然后将fire_bow函数修改为:

      def fire_bow(self):
          if(self.bow_fire_timer < 0):
              self.bow_drawn = False
              self.bow_fire_timer = self.bow_fire_wait
      

      最后将这一行添加到 blitme 函数的末尾:

      self.bow_fire_timer -= 1
      

      您可以使“self.bow_fire_wait”更大,以增加射击之间的等待时间。那里的值表示要等待的帧数。因此,如果您的速度为 60 fps,self.bow_fire_wait = 60 将等待 1 秒。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-05-08
        相关资源
        最近更新 更多