猿问

在 Pygame 中调整大小期间更新

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


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 事件只有在用户完成调整窗口大小(即放开边框)后才会推送。screen.get_size() 更新类似。由于我的游戏的图形非常简单,我真的更喜欢它们在用户拖动窗口时调整大小。这在许多其他语言中都是微不足道的,但我在 pygame 中找不到任何参考 - 尽管我无法想象这种基本功能是不可能的。


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


编辑:这是一个最小的工作示例。在 Windows 10、pygame 1.9.4 上运行,以下代码只会在用户完成拖动窗口后绘制更新的矩形。


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()


慕容708150
浏览 124回答 2
2回答

FFIVE

如果您遇到此类问题,最好使用 googleSDL来代替pygame,因为 pygame 是一个相当低级的 SDL 包装器。所以这不是 pygame 本身的问题,而是 sdl 和窗口管理器如何交互的问题。尽管如此,如果您确实需要在调整大小时更新窗口,如果您使用的是 Windows,则可以侦听WM_SIZEWindows 的实际事件,重绘屏幕,并通过调用 来更新“Windows”窗口RedrawWindow。这是一个简单的例子:import pygameimport win32guiimport win32condef 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()

森林海

ctypes如果未指定,则假定参数类型和返回类型为 “c_int指针” 。是一个32位值。LONG_PTR 和 LRESULT 是 64 位操作系统上的 64 位值。好的做法是定义所有使用的函数和。这样做解决了问题。c_intc_int.argtypes.restypeimport ctypes as ctfrom ctypes import wintypes as wimport pygame# LPARAM is typedef'ed as LONG_PTR in winuser.h, so it can be used# for LRESULT and LONG_PTR which are missing from wintypes.LRESULT = LONG_PTR = w.LPARAMWNDPROC = ct.WINFUNCTYPE(LRESULT, w.HWND, w.UINT, w.WPARAM, w.LPARAM)WM_SIZE = 0x0005RDW_INVALIDATE = 0x0001RDW_ERASE = 0x0004GWL_WNDPROC = -4# ctypes.windll.user32 is a cached, shared version of user32.dll.# Get our own copy and meticulously define argtypes/restype according# to MSDN documentation of the C prototypes.user32 = ct.WinDLL('user32')user32.GetWindowLongPtrA.argtypes = w.HWND, ct.c_intuser32.GetWindowLongPtrA.restype = LONG_PTRuser32.GetForegroundWindow.argtypes = ()user32.GetForegroundWindow.restype = w.HWNDuser32.RedrawWindow.argtypes = w.HWND, w.LPRECT, w.HRGN, w.UINTuser32.RedrawWindow.restype = w.BOOLuser32.CallWindowProcA.argtypes = WNDPROC, w.HWND, w.UINT, w.WPARAM, w.LPARAMuser32.CallWindowProcA.restype = LRESULTuser32.SetWindowLongPtrA.argtypes = w.HWND, ct.c_int, LONG_PTRuser32.SetWindowLongPtrA.restype = LONG_PTRdef 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()        old_window_proc = user32.GetWindowLongPtrA(user32.GetForegroundWindow(), GWL_WNDPROC)    def new_window_proc(hwnd, msg, wparam, lparam):        if msg == WM_SIZE:            draw_game()            user32.RedrawWindow(hwnd, None, None, RDW_INVALIDATE | RDW_ERASE)        # LONG_PTR is the same bit width as WNDPROC, but        # need cast to use it here.        return user32.CallWindowProcA(ct.cast(old_window_proc, WNDPROC), hwnd, msg, wparam, lparam)    new_window_proc_cb = WNDPROC(new_window_proc)    # Can't cast a WNDPROC (pointer) to a LONG_PTR directly, but can cast to void*.    # The .value of a c_void_p instance is its integer address.    user32.SetWindowLongPtrA(user32.GetForegroundWindow(), GWL_WNDPROC, ct.cast(new_window_proc_cb, ct.c_void_p).value)    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()
随时随地看视频慕课网APP

相关分类

Python
我要回答