在 Pygame 调整大小时更新

Update during resize in Pygame

我正在 pygame 中开发基于网格的游戏,并希望 window 可以调整大小。我使用以下初始化代码完成此操作:

pygame.display.set_mode((740, 440), pygame.RESIZABLE)

以及我的事件处理程序中的以下内容:

elif event.type == pygame.VIDEORESIZE:
     game.screen = pygame.display.set_mode((event.w, event.h),
                                            pygame.RESIZABLE)
     # Code to re-size other important surfaces

我遇到的问题是,似乎 pygame.VIDEORESIZE 事件仅在用户 完成 调整 window 大小后才会推送,即让去边境。 screen.get_size() 更新类似。由于我的游戏图形非常简单,我真的更喜欢它们在用户拖动 window 时调整大小。这在许多其他语言中是微不足道的,但我在 pygame 中找不到任何参考 - 虽然我无法想象这个基本的功能是不可能的。

在 pygame 中调整屏幕大小时如何更新我的游戏?

编辑:这是一个最小的工作示例。 运行 on Windows 10, pygame 1.9.4,下面的代码只会在用户拖动完 window.

后绘制更新的矩形
import sys
import pygame

pygame.init()

size = 320, 240
black = 0, 0, 0
red = 255, 0, 0

screen = pygame.display.set_mode(size, pygame.RESIZABLE)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.VIDEORESIZE:
            pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE)

    screen.fill(black)
    pygame.draw.rect(screen, red, (10,10,screen.get_width(),screen.get_height()))
    pygame.display.flip()

如果您 运行 遇到这种问题,使用 SDL 而不是 pygame 总是值得 google,因为 pygame 是一个漂亮 low-level SDL 包装器。

所以这不是 pygame 本身的问题,而是 sdl 和您的 window 经理如何互动的问题,例如参见 this SDL bug report

尽管如此,如果您确实需要在调整大小时更新 window,如果您正在使用 Windows,您可以监听 [=36= 的实际 WM_SIZE 事件],重新绘制屏幕,​​并通过调用 RedrawWindow.

更新“Windows”-window

这是一个简单的例子:

import pygame
import win32gui
import win32con

def wndProc(oldWndProc, draw_callback, hWnd, message, wParam, lParam):
    if message == win32con.WM_SIZE:
        draw_callback()
        win32gui.RedrawWindow(hWnd, None, None, win32con.RDW_INVALIDATE | win32con.RDW_ERASE)
    return win32gui.CallWindowProc(oldWndProc, hWnd, message, wParam, lParam)

def main():
    pygame.init()

    screen = pygame.display.set_mode((320, 240), pygame.RESIZABLE | pygame.DOUBLEBUF)

    def draw_game():
        screen.fill(pygame.Color('black'))
        pygame.draw.rect(screen, pygame.Color('red'), pygame.Rect(0,0,screen.get_width(),screen.get_height()).inflate(-10, -10))
        pygame.display.flip()
    
    oldWndProc = win32gui.SetWindowLong(win32gui.GetForegroundWindow(), win32con.GWL_WNDPROC, lambda *args: wndProc(oldWndProc, draw_game, *args))

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return
            elif event.type == pygame.VIDEORESIZE:
                pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE| pygame.DOUBLEBUF)
        draw_game()
        
if __name__ == '__main__':
    main()

默认行为:

RedrawWindow: