Pygame中按Y轴层级绘制队列对象的实现求助
Pygame中按Y轴层级绘制队列对象的实现求助
兄弟,我完全懂你想要的效果——就是让游戏里的所有物体按照世界Y坐标的高低来决定绘制顺序,保证位置更靠下(Y值更大)的物体先画,位置更靠上(Y值更小)的物体后画,这样视觉上就会有正确的遮挡关系:比如当玩家的Y坐标比物体低(更靠屏幕上方)时,物体先绘制,玩家后绘制,自然就会显示在物体上面,对吧?
你当前的问题很明确:现在代码里是直接遍历objects列表绘制,完全没考虑Y轴排序,绘制顺序全看列表里的添加顺序,肯定达不到你要的层级效果。你之前试的drawing_y变量思路走偏了,完全没必要搞那一套。
核心解决方案:绘制前按Y轴排序
Pygame的绘制逻辑是后画的物体会覆盖先画的,所以我们只需要在绘制前把所有物体按Y坐标从小到大排序,让位置靠下的先画,位置靠上的后画,就能完美实现你要的遮挡效果。
直接修改你代码里的绘制部分就行:
原代码:
#ALL THE OBJECTS IN THE LIST (INCLUDE ME) for object in objects: object.draw(screen,camera_x,camera_y)
改成:
#ALL THE OBJECTS IN THE LIST (INCLUDE ME) # 按物体的Y坐标从小到大排序,Y值大的(靠下)先画,Y值小的(靠上)后画 # 如果你的物体有高度属性,建议用 obj.y + obj.height 排序(按底部Y坐标),遮挡更准确 sorted_objects = sorted(objects, key=lambda obj: obj.y) for obj in sorted_objects: obj.draw(screen,camera_x,camera_y)
额外的优化建议(避免踩坑)
看你代码里在绘制循环里还混着处理碰撞、移动、删除物体的逻辑,这很容易出bug(比如遍历列表时删除元素会导致跳过某些物体),建议把逻辑拆分清楚:
- 先处理所有物体的移动、AI行为
- 再处理碰撞检测和生命值变化,收集要移除的物体
- 批量移除死亡/销毁的物体
- 最后排序并绘制
调整后的代码片段大概是这样:
#Main Game if window=='game': camera_x =max(2,min((camera_x-(camera_x-player.x)/30)-0.2,SIZE_W-2)) camera_y =max(2,min((camera_y-(camera_y-player.y)/30)-0.1,SIZE_H-2)) draw_map(lvl_1) # 第一步:处理物体移动和AI逻辑 for obj in objects: if obj.type=='enemy': obj.move(player.x,player.y,obj.speed) obj.sees_player = abs(obj.x-player.x)<3 and abs(obj.y-player.y)<3 # 第二步:处理碰撞和生命值,收集要移除的物体 to_remove = [] for obj in objects: # 玩家砍树逻辑 if obj.type=='tree' and player.image_cross_rect.colliderect(obj.rect): obj.hp -= player.skills['attack'] if obj.hp <= 0: to_remove.append(obj) # 敌人攻击玩家逻辑 elif obj.type=='enemy': if player.rect.colliderect(obj.rect): player.hp -= obj.attack if obj.hp <= 0: to_remove.append(obj) # 第三步:批量移除要销毁的物体(避免遍历中修改列表) for obj in to_remove: if obj in objects: objects.remove(obj) # 第四步:排序后绘制所有物体 sorted_objects = sorted(objects, key=lambda obj: obj.y) for obj in sorted_objects: obj.draw(screen,camera_x,camera_y) # 后续的UI、玩家控制等逻辑 player.control() watch.show_time(screen) inventory.draw(screen,(WIDTH-inventory.ile*inventory.scale)/2,HEIGHT-inventory.image.get_height()-10) player.draw_ui(screen)
小提示
如果你的物体(比如树木)有明显的高度,建议用obj.y + obj.height作为排序的key,也就是按物体的底部Y坐标排序,这样遮挡关系会更自然,不会出现“玩家明明在树的底部,却被树的顶部挡住”的奇怪情况。
备注:内容来源于stack exchange,提问作者Andrzej Tsaruk
相关产品推荐
相关产品推荐

