Pygame Surface缩放异常:缩小带网格Surface后线条显示错误
问题
在Pygame中绘制带网格的Surface时,原显示正常,但缩小尺寸后出现线条绘制异常的bug。原本以为在指定尺寸的虚拟Surface上绘制内容后,缩放时内部所有元素会同步缩放,但实际并非如此。
代码如下:
import pygame WIDTH = 640 HEIGHT = 320 TILE_SIZE = 32 pygame.init() # 16:9 比例 screen = pygame.display.set_mode((192, 108), pygame.RESIZABLE) s = pygame.Surface([WIDTH, HEIGHT]) pygame.display.set_caption("Grid") def draw_grid(): s.fill((255, 255, 255)) for v in range((WIDTH // TILE_SIZE) + 1): # 垂直线 pygame.draw.line(s, (0, 0, 0), (TILE_SIZE * v, 0), (TILE_SIZE * v, HEIGHT)) # 水平线 for h in range((HEIGHT // TILE_SIZE) + 1): pygame.draw.line(s, (0, 0, 0), (0, TILE_SIZE * h), (WIDTH, TILE_SIZE * h)) def draw_bg(): temp_frame = pygame.transform.scale(s, (192, 108)) # 此处出现bug screen.blit(temp_frame , (0, 0)) # screen.blit(s, (0, 0)) 可以正常显示 while True: draw_grid() draw_bg() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() pygame.display.flip()
尝试修改draw_grid函数中的WIDTH和HEIGHT变量,但问题未解决。
解决方案
这个问题源于pygame.transform.scale默认的缩放算法会让细线条在非整数倍缩小后丢失或变形,以下是几种可行的解决方法:
方法1:使用平滑缩放替代普通缩放
用pygame.transform.smoothscale替换scale,它的算法会更好地保留线条细节,修改draw_bg函数:
def draw_bg(): temp_frame = pygame.transform.smoothscale(s, (192, 108)) screen.blit(temp_frame , (0, 0))
方法2:直接在目标尺寸上绘制网格
跳过缩放步骤,直接根据屏幕尺寸计算网格参数,在最终显示的Surface(或screen)上绘制,从根源避免缩放失真。修改后的完整代码:
import pygame SCREEN_WIDTH = 192 SCREEN_HEIGHT = 108 ORIG_TILE_SIZE = 32 ORIG_WIDTH = 640 ORIG_HEIGHT = 320 pygame.init() screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.RESIZABLE) pygame.display.set_caption("Grid") def draw_grid(): screen.fill((255, 255, 255)) # 计算适配屏幕的网格单元尺寸 scaled_tile_w = SCREEN_WIDTH / (ORIG_WIDTH // ORIG_TILE_SIZE) scaled_tile_h = SCREEN_HEIGHT / (ORIG_HEIGHT // ORIG_TILE_SIZE) # 绘制垂直线 for v in range(int(ORIG_WIDTH // ORIG_TILE_SIZE) + 1): pygame.draw.line(screen, (0, 0, 0), (scaled_tile_w * v, 0), (scaled_tile_w * v, SCREEN_HEIGHT)) # 绘制水平线 for h in range(int(ORIG_HEIGHT // ORIG_TILE_SIZE) + 1): pygame.draw.line(screen, (0, 0, 0), (0, scaled_tile_h * h), (SCREEN_WIDTH, scaled_tile_h * h)) while True: draw_grid() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() # 窗口 resize 时更新尺寸 if event.type == pygame.VIDEORESIZE: SCREEN_WIDTH, SCREEN_HEIGHT = event.size screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.RESIZABLE) pygame.display.flip()
方法3:加粗原始线条
在绘制原始网格时给线条增加宽度,让缩放后线条不容易消失,修改draw_grid中的画线代码:
pygame.draw.line(s, (0, 0, 0), (TILE_SIZE * v, 0), (TILE_SIZE * v, HEIGHT), width=2) pygame.draw.line(s, (0, 0, 0), (0, TILE_SIZE * h), (WIDTH, TILE_SIZE * h), width=2)
内容的提问来源于stack exchange,提问作者r'ouster
相关产品推荐
相关产品推荐

