You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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(比如遍历列表时删除元素会导致跳过某些物体),建议把逻辑拆分清楚:

  1. 先处理所有物体的移动、AI行为
  2. 再处理碰撞检测和生命值变化,收集要移除的物体
  3. 批量移除死亡/销毁的物体
  4. 最后排序并绘制

调整后的代码片段大概是这样:

#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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 15:09:31