【问题标题】:Pygame Surface updates non-sequentiallyPygame Surface 不按顺序更新
【发布时间】:2018-11-09 23:37:30
【问题描述】:

我正在尝试实现一个简单的 Pygame 脚本,它应该:

  1. 首先,检查用户何时按下Space键;
  2. Space 按键上, 显示一些文字;那么
  3. 暂停 2 秒然后将屏幕更新到其原始状态。

请注意,以上所有事件都必须依次发生,并且不能乱序

我遇到的问题是程序先暂停,然后在屏幕更新到原始状态之前显示文本仅出现一瞬间(或根本不出现)。

程序似乎跳过了第 2 步,并在显示文本之前继续第 3 步中的暂停。我的代码如下:

import pygame
import sys
from pygame.locals import *

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

pygame.init()
wS = pygame.display.set_mode((500, 500), 0, 32)


# Method works as intended by itself
def create_text(x, y, phrase, color):
    """
    Create and displays text onto the globally-defined `wS` Surface
    (params in docstring omitted)
    """
    # Assume that the font file exists and is successfully found
    font_obj = pygame.font.Font("./roboto_mono.ttf", 32)
    text_surface_obj = font_obj.render(phrase, True, color)
    text_rect_obj = text_surface_obj.get_rect()
    text_rect_obj.center = (x, y)
    wS.blit(text_surface_obj, text_rect_obj)


while True:
    wS.fill(BLACK)
    for event in pygame.event.get():
        if event.type == KEYDOWN and event.key == K_SPACE:

            # Snippet containing unexpected behavior
            create_text(250, 250, "Hello world!", WHITE)
            pygame.display.update()
            pygame.time.delay(2000)
            # Snippet end

        if event.type == QUIT:
            pygame.quit()
            sys.exit(0)
    pygame.display.update()

提前致谢!

【问题讨论】:

  • 尝试删除pygame.time.delay(2000)下的两行。看起来它们是不必要的,可能会导致问题。
  • @skrx 一旦我删除了delay() 方法调用下面的两行,我确实看到Hello World! 文本被blitted;但是,它只会显示瞬间(一帧?),而不是预期的 2 秒。
  • 这很奇怪。程序的执行应该在delay 调用之后停止。顺便说一句,我一开始就很难重现这个错误。我想我在很短的时间内看过一次,但无法再次复制它。也许重组程序并使用其中一个timers 会更好。

标签: python python-3.x pygame


【解决方案1】:

由于某种原因,该程序对我有用,我唯一更改的是字体。这与@Omega0x013 所做的相同,但您的帧速率不受限制。它有效,因为 FPS.tick() 返回自上次调用以来的时间量,如果您不指定帧速率,则它不会保存程序。

import pygame
import sys
from pygame.locals import *
displayText = False
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

pygame.init()
wS = pygame.display.set_mode((500, 500), 0, 32)


# Method works as intended by itself
def create_text(x, y, phrase, color):
    """
    Create and displays text onto the globally-defined `wS` Surface
    (params in docstring omitted)
    """
    # Assume that the font file exists and is successfully found

    font_obj = pygame.font.Font(None,30)
    text_surface_obj = font_obj.render(phrase, True, color)
    text_rect_obj = text_surface_obj.get_rect()
    text_rect_obj.center = (x, y)
    wS.blit(text_surface_obj, text_rect_obj)

FPS = pygame.time.Clock()
while True:
    wS.fill(BLACK)
    for event in pygame.event.get():
        if event.type == KEYDOWN and event.key == K_SPACE:
            totalTime = 0
            FPS.tick()
            displayText = True

        if event.type == QUIT:
            pygame.quit()
            sys.exit(0)
    if displayText:
        totalTime += FPS.tick()
        create_text(250, 250, "Hello world!", WHITE)
        if totalTime >= 2000:
            displayText = False
    pygame.display.update()

【讨论】:

  • 哇,这个解决方案非常适合我的使用。谢谢! (另外,如果将FPS.tick() 调用从事件循环中移除,不应该没问题吗?)
  • Fps.Tick() 返回自上次调用以来的时间量。如果我按空格然后 5 秒后我再次按空格并调用 FPS.tick() 它将返回 5 秒,这意味着屏幕将立即变黑,通过将其保持在事件循环中,每当我按空格时,时间都会重置.
【解决方案2】:

你应该试试这个:

import pygame
import sys
from pygame.locals import *

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

pygame.init()
wS = pygame.display.set_mode((500, 500), 0, 32)
clock = pygame.time.Clock()

showing = False
timer = 0
# Method works as intended by itself
def create_text(x, y, phrase, color):
    """
    Create and displays text onto the globally-defined `wS` Surface
    (params in docstring omitted)
    """
    # Assume that the font file exists and is successfully found
    font_obj = pygame.font.Font("./roboto_mono.ttf", 32)
    text_surface_obj = font_obj.render(phrase, True, color)
    text_rect_obj = text_surface_obj.get_rect()
    text_rect_obj.center = (x, y)
    wS.blit(text_surface_obj, text_rect_obj)


while True:
    wS.fill(BLACK)
    for event in pygame.event.get():
        if event.type == KEYDOWN and event.key == K_SPACE:
            showing = True
            timer = 0

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

    if showing:
        timer += 1
        create_text(250, 250, "Hello world!", WHITE)

    if timer == 20:
        timer = 0
        showing = False

    pygame.display.update()
    clock.tick(100)

每次你按空格键时,它都会显示文本 2 秒,计数 2000 毫秒,然后不显示。

【讨论】:

  • 缩进有点不对劲,你可能想解决这个问题。另外,我知道这没有在问题中指定,但pygame.Clock.tick() 具有帧速率有限的缺点。我会更倾向于不涉及此类限制的解决方案。
  • 如果我将最后 2 个 if 子句取消缩进到与 for event 循环相同的级别,则此解决方案有效;我赞成你的回答。但我也在寻找一种更优雅的解决方案,它不依赖于pygame.Clock.tick()
  • 我同意 pygame.Clock.tick() @Jerrybibo 有一些限制,但它使得它所花费的时间恒定且可精确测量两秒。
猜你喜欢
  • 1970-01-01
  • 2012-05-21
  • 2017-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多