简体   繁体   English

如何在pygame中创建冷却功能?

[英]How to create a cooldown function in pygame?

I'm making a game where I want the character only to be able to shoot every 0.4 seconds or so. 我正在做一个游戏,我希望角色只能每0.4秒左右拍摄一次。 Currently, the character can spam bullets and it looks like a long strip of bullets coming out of the character. 目前,角色可以向子弹发送垃圾邮件,并且看起来像一条长条子弹从角色中冒出来。 How can I make the charcacter wait until the next bullet comes out. 如何让角色等待下一个项目符号出来。

I think this would work with pygame.time.get_clicks() but I don't really know how. 我认为这可以与pygame.time.get_clicks()但我真的不知道如何。

I tried doing this but then no bullets comes out. 我尝试这样做,但是没有子弹出来。 How can I make it work? 我该如何运作?

def fire():
    last = pygame.time.get_ticks()
    cooldown = 300
    for bullet in bullets:
        if bullet.y < 500 and bullet.y > 0:
            bullet.y -= bullet.vel
        else:
            bullets.pop(bullets.index(bullet))
    if keys[pygame.K_SPACE]:
        now = pygame.time.get_ticks()
        if now - last >= cooldown:
            bullets.append(projectile((man.x + man.width // 2), (man.y - 7), 7, 3, (255, 0, 0)))

Here is the entire code if anybody wants it (I made it a rectangle instead of a picture sprite so anyone could try it. 如果有人需要,这里是完整的代码(我将其制作为矩形而不是图片精灵,因此任何人都可以尝试。


pygame.init()

win = pygame.display.set_mode((500, 500))

class player():
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 4
        self.left = False
        self.right = False

    def draw(self, win):
        pygame.draw.rect(win, (0, 200, 0), (man.x, man.y, man.height, man.width))
        if self.left:
            pygame.draw.rect(win, (0, 200, 0), (man.x, man.y, man.height, man.width))
        elif self.right:
            pygame.draw.rect(win, (0, 200, 0), (man.x, man.y, man.height, man.width))

class projectile():
    def __init__(self, x, y, width, height, color):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color
        self.vel = 7

    def draw(self, win):
        pygame.draw.rect(win, self.color, (self.x, self.y, self.height, self. width))


def move():
    if keys[pygame.K_LEFT] and man.x > man.vel:
        man.x -= man.vel
        man.left = True
        man.right = False

    elif keys[pygame.K_RIGHT] and man.x < 500 - man.width - man.vel:
        man.x += man.vel
        man.left = False
        man.right = True


def fire():
    last = pygame.time.get_ticks() # remove this if you want to try it working
    cooldown = 400 # remove this if you want to try it working
    for bullet in bullets:
        if bullet.y < 500 and bullet.y > 0:
            bullet.y -= bullet.vel
        else:
            bullets.pop(bullets.index(bullet))
    if keys[pygame.K_SPACE]:
        now = pygame.time.get_ticks() # remove this if you want to try it working
        if now - last >= cooldown: # remove this if you want to try it working
            bullets.append(projectile((man.x + man.width // 2), (man.y - 7), 7, 3, (255, 0, 0)))


def re_draw():
    win.fill((0, 0, 0))
    man.draw(win)
    for bullet in bullets:
        bullet.draw(win)
    pygame.display.update()


man = player(400, 400, 64, 64)
bullets = []
run = True
shoot_loop = 0
clock = pygame.time.Clock()


while run:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    keys = pygame.key.get_pressed()
    fire()
    move()
    clock.tick(60)
    re_draw()

pygame.quit()

I think the problem with this is that you set last every time, even if firing was unsuccessful. 我认为这样做的问题是,即使发射失败,您也要每次都设置last一次。 Moving the line 移动线

last = pygame.time.get_ticks()

inside the 在 - 的里面

if now - last >= cooldown:

should solve this problem. 应该解决这个问题。 This way last stores the time of last successful fire, not last attempt. 这样last存储的时间是最后一次成功射击的时间,而不是最后一次尝试的时间。

As @gregk says, the error is that you set last = pygame.time.get_ticks() inside the fire function, which is called each iteration of the main loop. 正如@gregk所说,错误是您在fire函数中设置了last = pygame.time.get_ticks() ,该函数被称为主循环的每次迭代。
You are saying to the program that the time of the last shot is always the time of the last iteration, even if there was not a shot. 您对程序说的是,即使没有镜头,最后一次射击的时间也总是最后一次迭代的时间。 Hence now - last >= cooldown will never be True, since last is always updated to the later time. 因此, now - last >= cooldown永远不会为True,因为last总是更新到以后的时间。

This can be solved in many ways, but the key point is how to track the flowing time. 这可以通过许多方法解决,但是关键是如何跟踪流动时间。 You don't have to update last each iteration. 您不必在每次迭代时都更新last一个。

A close approach to your current code (to avoid to edit a lot of stuff) is the following. 下面是您当前代码的一种接近方法(避免编辑大量内容)。 Edit your fire() function this way: 通过以下方式编辑fire()函数:

def fire():
    global cooldown_tracker
    cooldown_tracker += clock.get_time()
    if cooldown_tracker > 400:
        cooldown_tracker = 0

    for bullet in bullets:
        if bullet.y < 500 and bullet.y > 0:
            bullet.y -= bullet.vel
        else:
            bullets.pop(bullets.index(bullet))

    if keys[pygame.K_SPACE] and cooldown_tracker == 0:
        bullets.append(projectile((man.x + man.width // 2), (man.y - 7), 7, 3, (255, 0, 0)))

And add 并添加

cooldown_tracker = 0

before the main loop (just before while run ). 在主循环之前( while run之前)。
In this solution, rather than pygame.time.get_ticks() I use the clock object you already have. 在此解决方案中,我不是使用pygame.time.get_ticks()而是使用您已经拥有的clock对象。

I use a cooldown_tracker variable, each iteration (when the fire() function is called) the time of the last iteration is added to the tracker, and if this time is greater than 400 ms, the tracker is reset to 0. A bullet is added to the list (a shot) only if the tracker is 0, meaning that the cooldown time has elapsed. 我使用cooldown_tracker变量,每次迭代(调用fire()函数时)将最后一次迭代的时间添加到跟踪器中,如果该时间大于400毫秒,则将跟踪器重置为0。仅在跟踪器为0时才添加到列表(快照),这意味着冷却时间已经过去。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM