如何在PyGame中创建可扩展的条形Sprite?
用PyGame实现UI元素的九宫格缩放(边框不变,中间拉伸)
可以的,PyGame完全能实现这种UI适配效果,核心是用九宫格切片绘制法——这是行业内保留边框样式、适配任意尺寸的标准方案,能精准保留你素材的像素化边框和角落。
核心逻辑
把原始素材切割成9个区域:4个固定尺寸的角落、4条可拉伸的边、1个可自由缩放的中间区域。绘制时,角落和边保持原始像素大小,仅拉伸中间区域填充空白,以此适配目标尺寸。
具体实现代码
假设你的原始素材名为bar_asset.png,先根据素材实际像素确定边框宽度(示例中设为4像素,你可自行调整):
1. 加载素材并切割区域
import pygame pygame.init() # 加载带透明通道的原始素材 original_bar = pygame.image.load("bar_asset.png").convert_alpha() orig_width, orig_height = original_bar.get_size() # 定义边框宽度(根据你的素材实际值修改) border_size = 4 # 切割9个区域 # 四个角落(固定尺寸) top_left = original_bar.subsurface((0, 0), (border_size, border_size)) top_right = original_bar.subsurface((orig_width - border_size, 0), (border_size, border_size)) bottom_left = original_bar.subsurface((0, orig_height - border_size), (border_size, border_size)) bottom_right = original_bar.subsurface((orig_width - border_size, orig_height - border_size), (border_size, border_size)) # 四条边(仅单一维度拉伸) top_edge = original_bar.subsurface((border_size, 0), (orig_width - 2*border_size, border_size)) bottom_edge = original_bar.subsurface((border_size, orig_height - border_size), (orig_width - 2*border_size, border_size)) left_edge = original_bar.subsurface((0, border_size), (border_size, orig_height - 2*border_size)) right_edge = original_bar.subsurface((orig_width - border_size, border_size), (border_size, orig_height - 2*border_size)) # 中间区域(可双向拉伸) middle_area = original_bar.subsurface((border_size, border_size), (orig_width - 2*border_size, orig_height - 2*border_size))
2. 封装绘制函数
def draw_scaled_bar(target_surface, pos_x, pos_y, target_width, target_height): # 创建适配目标尺寸的透明表面 scaled_bar = pygame.Surface((target_width, target_height), pygame.SRCALPHA) # 绘制固定角落 scaled_bar.blit(top_left, (0, 0)) scaled_bar.blit(top_right, (target_width - border_size, 0)) scaled_bar.blit(bottom_left, (0, target_height - border_size)) scaled_bar.blit(bottom_right, (target_width - border_size, target_height - border_size)) # 拉伸并绘制上下边 scaled_top = pygame.transform.scale(top_edge, (target_width - 2*border_size, border_size)) scaled_bottom = pygame.transform.scale(bottom_edge, (target_width - 2*border_size, border_size)) scaled_bar.blit(scaled_top, (border_size, 0)) scaled_bar.blit(scaled_bottom, (border_size, target_height - border_size)) # 拉伸并绘制左右边 scaled_left = pygame.transform.scale(left_edge, (border_size, target_height - 2*border_size)) scaled_right = pygame.transform.scale(right_edge, (border_size, target_height - 2*border_size)) scaled_bar.blit(scaled_left, (0, border_size)) scaled_bar.blit(scaled_right, (target_width - border_size, border_size)) # 拉伸并绘制中间填充区域 scaled_middle = pygame.transform.scale(middle_area, (target_width - 2*border_size, target_height - 2*border_size)) scaled_bar.blit(scaled_middle, (border_size, border_size)) # 将最终绘制好的bar放到目标表面上 target_surface.blit(scaled_bar, (pos_x, pos_y))
3. 主循环调用示例
screen = pygame.display.set_mode((800, 600)) clock = pygame.time.Clock() running = True while running: screen.fill((30, 30, 30)) # 绘制一个宽300、高50的适配bar draw_scaled_bar(screen, 250, 275, 300, 50) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False pygame.display.flip() clock.tick(60) pygame.quit()
关键提示
- 如果你要保留像素风格,务必用
pygame.transform.scale(最近邻插值),别用smoothscale,避免边框模糊。 - 边框尺寸一定要精确对应素材的实际像素,否则切割区域会错位。
内容的提问来源于stack exchange,提问作者kokoko
相关产品推荐
相关产品推荐

