使用Pygame开发伪3D游戏引擎时持续出现blit目标位置无效错误
解决Pygame中「Invalid destination position for blit」错误的方案
我帮你排查了代码里的几个问题,这个错误主要是由语法疏漏、逻辑错误和绘制逻辑缺失导致的,咱们一步步来修复:
问题根源拆解
- 未定义变量导致图片加载失败:在
OBJECT.update()里你用了image变量加载图片,但这个变量根本没定义,应该用初始化时保存的图片路径才行。 - 相机Z轴逻辑崩了:初始化时
camera.z是0,你写的self.z = (self.z*camera.z) + camera.zv会让对象的Z值始终等于camera.zv,一旦camera.zv为0,对象Z值就变成0,后续缩放会生成0尺寸的无效表面。 - 无效的缩放尺寸:当Z值≤0时,
pygame.transform.scale会创建尺寸≤0的表面,这种表面根本没法用blit绘制,直接触发错误。 - 绘制逻辑没连上:你的
engine.draw()需要传图像和位置参数,但main.py里直接空调用,而且OBJECT类也没把自己的图像和位置传给绘制函数,等于根本没在屏幕上画东西。 - 拼写错误:
CAMERA类里的pygame.transfrom.scale少了个字母r,应该是pygame.transform.scale,虽然这个可能没触发当前错误,但肯定会导致相机初始化失败。
修正后的完整代码
engine.py
import pygame, time, math, random, os random.seed(time.time()) BLACK = ( 0, 0, 0) WHITE = ( 255, 255, 255) GREEN = ( 0, 255, 0) RED = ( 255, 0, 0) BLUE = ( 0, 0, 255) PI = 3.141592653 size = (1200, 600) clock = pygame.time.Clock() screen = pygame.display.set_mode(size) pygame.display.set_caption("ENGINE") # 全局存储所有需要绘制的游戏对象 game_objects = [] class CAMERA(object): def __init__(self, image, iresize0, iresize1, xpos, ypos, zpos): self.x = xpos self.y = ypos self.z = zpos self.xv = 0 self.yv = 0 self.zv = 0 if not image == "": self.image = pygame.image.load(os.path.join(image)) # 修正拼写错误:transfrom → transform self.image = pygame.transform.scale(self.image, (iresize0, iresize1)) self.image.convert() # 初始z设为1,避免乘以0导致后续计算异常 camera = CAMERA("", 0, 0, 0, 0, 1) class OBJECT(object): def __init__(self, image, xpos, ypos, zpos): self.x = xpos self.y = ypos self.z = zpos self.img_path = image # 保存图片路径,后续更新时复用 self.image = pygame.image.load(os.path.join(image)) self.image.convert() game_objects.append(self) # 加入全局列表,方便统一绘制 def update(self): global camera # 调整相机Z轴逻辑:累加速度值,模拟缩放效果 camera.z += camera.zv # 限制相机z最小值,避免缩放比例过小或为0 if camera.z <= 0.1: camera.z = 0.1 # 计算缩放比例(这里用简单的透视逻辑,你可以根据需求调整) scale = camera.z / 10 if scale < 0.1: scale = 0.1 # 优化:基于原始图片缩放(不用每次都重新加载,这里先保持你的逻辑,后续可以改成保存原始图) self.image = pygame.image.load(os.path.join(self.img_path)) new_size = (int(self.image.get_width() * scale), int(self.image.get_height() * scale)) self.image = pygame.transform.scale(self.image, new_size) self.image.convert() def draw(): global screen, game_objects # 遍历所有对象,计算居中位置后绘制 for obj in game_objects: # 让对象在屏幕居中,同时加上自身的x/y偏移 draw_x = (size[0] - obj.image.get_width()) // 2 + obj.x draw_y = (size[1] - obj.image.get_height()) // 2 + obj.y screen.blit(obj.image, (draw_x, draw_y)) def events(): event_outcome = None # 处理所有事件,避免遗漏 for event in pygame.event.get(): if event.type == pygame.QUIT: event_outcome = 'quit' if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: event_outcome = 'left' if event.key == pygame.K_RIGHT: event_outcome = 'right' if event.key == pygame.K_UP: event_outcome = 'up' if event.key == pygame.K_DOWN: event_outcome = 'down' # 其他按键逻辑保持不变 if event.type == pygame.KEYUP: event_outcome = 'keyup' return event_outcome def refresh(backcolor): global clock, screen pygame.display.flip() clock.tick(60) screen.fill(backcolor) def end(): pygame.quit()
main.py
import engine # 初始x/y设为0,方便看居中效果,你可以随时调整 cool = engine.OBJECT("data/cool.png", 0, 0, 10) while True: # 只调用一次events(),避免多次调用导致事件丢失 current_event = engine.events() if current_event == "up": # 调小Z轴速度,避免缩放太快 engine.camera.zv = 0.1 if current_event == "keyup": engine.camera.zv = 0 if current_event == "quit": engine.end() break # 退出循环,防止程序崩溃 cool.update() engine.draw() engine.refresh(engine.WHITE)
关键修正说明
- 修复变量问题:给
OBJECT加了img_path属性,保存初始化时的图片路径,更新时用这个路径加载。 - 救回相机Z轴:把相机初始Z值设为1,改成累加速度的逻辑,还加了最小值限制,确保缩放比例始终有效。
- 避免无效表面:限制缩放比例不小于0.1,保证生成的图片尺寸大于0。
- 补上绘制逻辑:新增全局对象列表,
draw()函数自动遍历所有对象并计算合理的绘制位置,再也不会出现blit位置无效的问题。 - 优化事件处理:只调用一次
events(),避免事件被跳过;退出时加break,防止退出Pygame后继续循环。 - 修正拼写错误:把
transfrom改成transform,避免相机初始化报错。
这样修改后,你的伪3D游戏引擎基础逻辑就能正常运行了,不会再触发「Invalid destination position for blit」错误~
内容的提问来源于stack exchange,提问作者Slipknot1
相关产品推荐
相关产品推荐

