用cv2.imread做Pygame关卡编辑器如何避免逐像素画rect优化性能
性能问题优化方案
问题核心原因
你当前的性能瓶颈来自两个完全可以避免的冗余操作:
- 每帧都遍历所有像素调用
pygame.draw.rect绘制,单次循环几万次绘制调用,CPU占用直接拉满 - 不必要的cv2像素格式转换开销,没有用Pygame原生的Surface批量渲染能力
具体优化方案
1. 预生成地图缓存(核心优化)
地图是静态数据,只需要在程序启动时生成一次完整的地图Surface,主循环直接调用blit渲染即可,把每帧几万次绘制操作变成1次。
2. 替换不必要的cv2依赖
直接用Pygame原生的pygame.image.load加载图片,不需要手动做像素格式转换,性能更高逻辑更简单。
3. 预生成碰撞数据
如果需要做瓦片碰撞检测,提前在初始化阶段遍历一次像素生成碰撞Rect列表,后续碰撞检测直接用这个预生成的列表即可,不需要每帧处理像素。
优化后代码(无cv2版本,性能提升百倍以上)
import sys import pygame pygame.init() screen = pygame.display.set_mode((388, 404)) # 初始化地图缓存Surface map_surface = pygame.Surface((388, 404)) map_img = pygame.image.load('Map1.png').convert() img_width, img_height = map_img.get_size() tile_size = 32 # 仅初始化时生成一次地图Surface和碰撞列表 collision_rects = [] for y in range(img_height): for x in range(img_width): r, g, b, *a = map_img.get_at((x, y)) if r > 240 and g > 240 and b > 240: color = (255,255,255) else: color = (0,0,0) # 绘制到缓存的map_surface pygame.draw.rect(map_surface, color, pygame.Rect(x*tile_size, y*tile_size, tile_size, tile_size)) # 可选择仅把需要碰撞的瓦片加入列表,减少后续碰撞检测开销 if color == (0,0,0): collision_rects.append(pygame.Rect(x*tile_size, y*tile_size, tile_size, tile_size)) clock = pygame.time.Clock() while True: screen.fill((15, 15, 15)) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() # 直接渲染预生成的地图,仅1次调用 screen.blit(map_surface, (0,0)) pygame.display.update() clock.tick(120)
保留cv2的快速转换方案
如果你必须使用cv2读取图片,可以用下面的方法快速转成Pygame Surface,不需要逐像素处理:
import cv2 import numpy as np # cv2读取图片转Pygame Surface cv_img = cv2.imread('Map1.png') # 转BGR到RGB格式 cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) # 直接转成Pygame Surface,毫秒级操作 pygame_img = pygame.image.frombuffer(cv_img.tobytes(), cv_img.shape[1::-1], "RGB")
内容的提问来源于stack exchange,提问作者Saw
相关产品推荐
相关产品推荐

