【问题标题】:Do something every x (milli)seconds in pygame在pygame中每隔x(毫秒)秒做一些事情
【发布时间】:2013-09-27 17:50:11
【问题描述】:

我正在学习 Python 和 Pygame,我做的第一件事是一个简单的 Snake 游戏。我正在努力让蛇每 0.25 秒移动一次。这是我的代码循环部分:

while True:
    check_for_quit()

    clear_screen()

    draw_snake()
    draw_food()

    check_for_direction_change()

    move_snake() #How do I make it so that this loop runs at normal speed, but move_snake() only executes once every 0.25 seconds?

    pygame.display.update()

我希望所有其他函数都能正常运行,但 move_snake() 仅每 0.25 秒发生一次。我查了一下,找到了一些答案,但对于编写第一个 Python 脚本的人来说,它们似乎都太复杂了。

是否可以实际获得一个示例来说明我的代码应该是什么样子,而不仅仅是告诉我需要使用哪个函数?谢谢!

【问题讨论】:

  • 不要使用睡眠它会停止整个游戏而不仅仅是蛇

标签: python function pygame milliseconds seconds


【解决方案1】:

使用Clock module of Pygame 跟踪时间。具体来说,Clock 类的 tick 方法将向您报告自您上次调用 tick 以来的毫秒数。因此,您可以在游戏循环中每次迭代的开始(或结束)调用一次tick,并将其返回值存储在名为dt 的变量中。然后使用dt 更新您的时间相关游戏状态变量。

time_elapsed_since_last_action = 0
clock = pygame.time.Clock()

while True: # game loop
    # the following method returns the time since its last call in milliseconds
    # it is good practice to store it in a variable called 'dt'
    dt = clock.tick() 

    time_elapsed_since_last_action += dt
    # dt is measured in milliseconds, therefore 250 ms = 0.25 seconds
    if time_elapsed_since_last_action > 250:
        snake.action() # move the snake here
        time_elapsed_since_last_action = 0 # reset it to 0 so you can count again

【讨论】:

    【解决方案2】:

    有几种方法,例如跟踪系统时间或使用Clock 和计数滴答声。

    但最简单的方法是使用事件队列并每 x ms 创建一个事件,使用pygame.time.set_timer()

    pygame.time.set_timer()

    在事件队列上重复创建一个事件

    set_timer(eventid, milliseconds) -> None

    将事件类型设置为每隔给定的毫秒数出现在事件队列中。在经过一定时间之前,第一个事件不会出现。

    每个事件类型都可以附加一个单独的计时器。最好使用 pygame.USEREVENT 和 pygame.NUMEVENTS 之间的值。

    要禁用事件的计时器,请将毫秒参数设置为 0。

    这是一个运行中的小示例,其中蛇每 250 毫秒移动一次:

    import pygame
    pygame.init()
    screen = pygame.display.set_mode((300, 300))
    player, dir, size = pygame.Rect(100,100,20,20), (0, 0), 20
    MOVEEVENT, t, trail = pygame.USEREVENT+1, 250, []
    pygame.time.set_timer(MOVEEVENT, t)
    while True:
        keys = pygame.key.get_pressed()
        if keys[pygame.K_w]: dir = 0, -1
        if keys[pygame.K_a]: dir = -1, 0
        if keys[pygame.K_s]: dir = 0, 1
        if keys[pygame.K_d]: dir = 1, 0
    
        if pygame.event.get(pygame.QUIT): break
        for e in pygame.event.get():
            if e.type == MOVEEVENT: # is called every 't' milliseconds
                trail.append(player.inflate((-10, -10)))
                trail = trail[-5:]
                player.move_ip(*[v*size for v in dir])
    
        screen.fill((0,120,0))
        for t in trail:
            pygame.draw.rect(screen, (255,0,0), t)
        pygame.draw.rect(screen, (255,0,0), player)
        pygame.display.flip()
    

    【讨论】:

    • 很好的示例程序!
    • 有没有办法让程序每 1250 毫秒从 command_list 读取一个新命令? Move_North ... Move_East ... Move_South ?
    • @user1839239 当然可以。您可以创建一些常量,如MOVE_EAST = (1, 0) 等,然后创建命令列表,如command_list = [MOVE_EAST, MOVE_NORTH, ....],并在事件处理程序中执行dir = command_list.pop(0) 之类的操作,以获取player.move_ip... 行之前的下一个命令。
    • 听起来不错!你能写一个小例子程序来说明你的想法吗?我是菜鸟!
    猜你喜欢
    • 1970-01-01
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    • 1970-01-01
    • 2014-06-15
    相关资源
    最近更新 更多