亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 Pygame 中調整大小期間更新

在 Pygame 中調整大小期間更新

慕容708150 2024-01-15 15:23:40
我正在 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 sysimport pygamepygame.init()size = 320, 240black = 0, 0, 0red = 255, 0, 0screen = 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()
查看完整描述

2 回答

?
FFIVE

TA貢獻1797條經驗 獲得超6個贊

如果您遇到此類問題,最好使用 googleSDL來代替pygame,因為 pygame 是一個相當低級的 SDL 包裝器。

所以這不是 pygame 本身的問題,而是 sdl 和窗口管理器如何交互的問題。

盡管如此,如果您確實需要在調整大小時更新窗口,如果您使用的是 Windows,則可以偵聽WM_SIZEWindows 的實際事件,重繪屏幕,并通過調用 來更新“Windows”窗口RedrawWindow。

這是一個簡單的例子:

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


查看完整回答
反對 回復 2024-01-15
?
森林海

TA貢獻2011條經驗 獲得超2個贊

ctypes如果未指定,則假定參數類型和返回類型為 “c_int指針” 。是一個32位值。LONG_PTR 和 LRESULT 是 64 位操作系統上的 64 位值。好的做法是定義所有使用的函數和。這樣做解決了問題。c_intc_int.argtypes.restype


import ctypes as ct

from ctypes import wintypes as w


import 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.LPARAM

WNDPROC = ct.WINFUNCTYPE(LRESULT, w.HWND, w.UINT, w.WPARAM, w.LPARAM)

WM_SIZE = 0x0005

RDW_INVALIDATE = 0x0001

RDW_ERASE = 0x0004

GWL_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_int

user32.GetWindowLongPtrA.restype = LONG_PTR

user32.GetForegroundWindow.argtypes = ()

user32.GetForegroundWindow.restype = w.HWND

user32.RedrawWindow.argtypes = w.HWND, w.LPRECT, w.HRGN, w.UINT

user32.RedrawWindow.restype = w.BOOL

user32.CallWindowProcA.argtypes = WNDPROC, w.HWND, w.UINT, w.WPARAM, w.LPARAM

user32.CallWindowProcA.restype = LRESULT

user32.SetWindowLongPtrA.argtypes = w.HWND, ct.c_int, LONG_PTR

user32.SetWindowLongPtrA.restype = LONG_PTR


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

    

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



查看完整回答
反對 回復 2024-01-15
  • 2 回答
  • 0 關注
  • 205 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號