Pygame:如何在方法被调用后等待一定的时间来做某事

2024-06-16 17:17:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我大约6周前开始学习python,大约2周前开始玩pygame。我正在努力完成一本好书(Python速成课程),作为练习,我正在制作一个简单的游戏

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

到目前为止,我已经把这些都做好了。不过我想要的是在箭发射后的一定时间内重新装填弓。因此,玩家按下空格键,射出箭头,然后在大约一秒钟后重新装好弓,玩家可以再次射出

特别是,在调用fire_bow()方法后,2秒钟后,我希望bow_draw标志设置为True

有人知道我怎么做吗?我已经阅读了文档,但似乎找不到任何能给我带来预期效果的东西。特别是我不想暂停节目。理想情况下,我正在想象一种方法,说“等一秒钟”

这是我目前为止的代码,如果它有用的话

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

非常感谢你阅读这篇文章


Tags: andthetorectimageselfeventgame
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

你可以使“自我。弓火等待”变大,以增加射击之间的等待时间。其中的值表示要等待的帧数。因此,如果您的速度为60 fps,self.bow_fire_wait = 60将等待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

我建议使用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

相关问题 更多 >