You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pygame窗口缩放后Button按钮碰撞hitbox偏移无法正常点击问题求助

问题根源

按钮的碰撞检测逻辑使用的是初始画布(1300*800)的坐标系,但你获取的鼠标位置是缩放后实际窗口的坐标,两者坐标系不匹配;同时你的主代码中连续两次调用pygame.event.get(),会导致事件队列被清空,按钮无法接收点击事件。

可行修改方案

1. 修改主代码

新增原始分辨率常量,统一获取事件队列,计算窗口缩放比例并传递给按钮更新逻辑:

import pygame
import sys
from pygame.locals import *
from buttonClass import Button

running = True
# 新增原始基础分辨率常量
BASE_WIDTH = 1300
BASE_HEIGHT = 800

pygame.init()
mainClock = pygame.time.Clock()
win = pygame.display.set_mode((BASE_WIDTH, BASE_HEIGHT), HWSURFACE|DOUBLEBUF|RESIZABLE)
fakeMenuScreen = win.copy()

# Load background images
bar = pygame.image.load("menuimages/bar.png").convert_alpha()

sprites = pygame.sprite.Group()
singleplayerButton = sprites.add(Button(pygame.Color((0, 0, 0, 0)), 
                   pygame.Color((53, 74, 110, 50)), pygame.Rect(85, 250, 375, 50), lambda x : print('HELLO'), "Singleplayer"))

multiplayerButton = sprites.add(Button(pygame.Color((0, 0, 0, 0)), pygame.Color((53, 74, 110, 50)), 
                   pygame.Rect(85, 320, 375, 50), lambda b: print(f"Button '{b.text}' was clicked"), 'Multiplayer',))

def main_menu():
    global win
    while running == True: 
        # 统一只获取一次事件队列,避免重复调用清空事件
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
          
            if event.type == VIDEORESIZE:
                win = pygame.display.set_mode(event.size, RESIZABLE)
        
        # 计算当前窗口相对原始分辨率的缩放比例
        current_w, current_h = win.get_size()
        scale_x = current_w / BASE_WIDTH
        scale_y = current_h / BASE_HEIGHT
        
        win.blit(pygame.transform.smoothscale(fakeMenuScreen, (current_w, current_h)), (0, 0))

        fakeMenuScreen.blit(bar, (85, 0))  
        # 把事件列表和缩放比例传递给按钮更新方法
        sprites.update(events, scale_x, scale_y)

        sprites.draw(fakeMenuScreen)

        pygame.display.update()

if __name__ == "__main__":
    main_menu()

2. 修改buttonClass.py的update方法

将实际鼠标坐标转换为原始画布坐标后再做碰撞检测:

def update(self, events, scale_x, scale_y):
    # 转换实际鼠标坐标为原始画布坐标系的坐标
    real_x, real_y = pygame.mouse.get_pos()
    original_pos = (real_x / scale_x, real_y / scale_y)
    hit = self.rect.collidepoint(original_pos)

    self.image = self.hov if hit else self.org
    for event in events:
        if event.type == pygame.MOUSEBUTTONDOWN and hit:
                self.callback(self)

修改后缩放窗口时按钮的碰撞检测会和实际显示位置完全匹配。


内容的提问来源于stack exchange,提问作者ahmedquran12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 15:06:03