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

基于AOE2 Parser的Python地图方形树木生成坐标计算求助

解决方案:AOE2 Parser实现网格行道树与交界石头放置

一、明确AOE2坐标对应逻辑

结合你的代码与地图规则,统一坐标逻辑:

  • 瓦片坐标:X从左到右递增(0=最左侧,map_width-1=最右侧);Y从上到下递增(0=最顶部,map_height-1=最底部)
  • 单位放置坐标:瓦片中心位置为(tile_x + 0.5, tile_y + 0.5),你的代码中这部分是正确的

二、实现网格状行道树围方形区域

要围出方形,只需在方形四条边上生成树木,而非遍历整个区域,以下分两种场景实现:

场景1:四边密植树木(每个瓦片都种)

先定义方形边界(根据水域宽度调整偏移量),再分别遍历四条边:

# 定义方形边界(瓦片坐标,避开水域)
square_x_start = largeur_eau + 5
square_x_end = map_manager.map_width - largeur_eau - 5
square_y_start = largeur_eau + 5
square_y_end = map_manager.map_height - largeur_eau - 5

excluded_terrain = [TerrainId.SNOW, TerrainId.SNOW_LIGHT, TerrainId.ICE, TerrainId.ROCK_1, water_arround_arena, TerrainId.BEACH_ICE]
tree_id = OtherInfo.TREE_SNOW_PINE.ID

# 顶部边:y固定为上边界,遍历x范围
for x in range(square_x_start, square_x_end + 1):
    tile = map_manager.get_tile(x, square_y_start)
    if tile.terrain_id not in excluded_terrain:
        unit_manager.add_unit(
            player=P0,
            unit_const=tree_id,
            x=x + 0.5,
            y=square_y_start + 0.5,
            z=0,
            rotation=0,
            animation_frame=0,
        )

# 底部边:y固定为下边界,遍历x范围
for x in range(square_x_start, square_x_end + 1):
    tile = map_manager.get_tile(x, square_y_end)
    if tile.terrain_id not in excluded_terrain:
        unit_manager.add_unit(
            player=P0,
            unit_const=tree_id,
            x=x + 0.5,
            y=square_y_end + 0.5,
            z=0,
            rotation=0,
            animation_frame=0,
        )

# 左侧边:x固定为左边界,遍历y范围(跳过上下边避免重复)
for y in range(square_y_start + 1, square_y_end):
    tile = map_manager.get_tile(square_x_start, y)
    if tile.terrain_id not in excluded_terrain:
        unit_manager.add_unit(
            player=P0,
            unit_const=tree_id,
            x=square_x_start + 0.5,
            y=y + 0.5,
            z=0,
            rotation=0,
            animation_frame=0,
        )

# 右侧边:x固定为右边界,遍历y范围(跳过上下边避免重复)
for y in range(square_y_start + 1, square_y_end):
    tile = map_manager.get_tile(square_x_end, y)
    if tile.terrain_id not in excluded_terrain:
        unit_manager.add_unit(
            player=P0,
            unit_const=tree_id,
            x=square_x_end + 0.5,
            y=y + 0.5,
            z=0,
            rotation=0,
            animation_frame=0,
        )

场景2:四边间隔种树(网格状)

在循环中加入步长参数step,实现间隔种植:

step = 2  # 每2个瓦片种一棵

# 顶部边间隔种树
for x in range(square_x_start, square_x_end + 1, step):
    tile = map_manager.get_tile(x, square_y_start)
    if tile.terrain_id not in excluded_terrain:
        unit_manager.add_unit(
            player=P0,
            unit_const=tree_id,
            x=x + 0.5,
            y=square_y_start + 0.5,
            z=0,
            rotation=0,
            animation_frame=0,
        )

# 底部边间隔种树
for x in range(square_x_start, square_x_end + 1, step):
    tile = map_manager.get_tile(x, square_y_end)
    if tile.terrain_id not in excluded_terrain:
        unit_manager.add_unit(
            player=P0,
            unit_const=tree_id,
            x=x + 0.5,
            y=square_y_end + 0.5,
            z=0,
            rotation=0,
            animation_frame=0,
        )

# 左侧边间隔种树
for y in range(square_y_start + 1, square_y_end, step):
    tile = map_manager.get_tile(square_x_start, y)
    if tile.terrain_id not in excluded_terrain:
        unit_manager.add_unit(
            player=P0,
            unit_const=tree_id,
            x=square_x_start + 0.5,
            y=y + 0.5,
            z=0,
            rotation=0,
            animation_frame=0,
        )

# 右侧边间隔种树
for y in range(square_y_start + 1, square_y_end, step):
    tile = map_manager.get_tile(square_x_end, y)
    if tile.terrain_id not in excluded_terrain:
        unit_manager.add_unit(
            player=P0,
            unit_const=tree_id,
            x=square_x_end + 0.5,
            y=y + 0.5,
            z=0,
            rotation=0,
            animation_frame=0,
        )

三、实现水与陆地交界处放置石头

遍历所有瓦片,检测当前瓦片为陆地且相邻有水域时,放置石头:

# 定义水域地形集合
water_terrains = [water_arround_arena, TerrainId.ICE, TerrainId.BEACH_ICE]
# 定义允许放置石头的陆地地形
allowed_land_terrains = [t for t in TerrainId if t not in excluded_terrain and t not in water_terrains]
stone_id = TerrainId.ROCK_1  # 替换为你需要的石头单位ID

# 遍历所有瓦片(跳过边界避免索引越界)
for x in range(1, map_manager.map_width - 1):
    for y in range(1, map_manager.map_height - 1):
        current_tile = map_manager.get_tile(x, y)
        if current_tile.terrain_id in allowed_land_terrains:
            # 检查上下左右四个相邻瓦片是否有水域
            neighbors = [
                map_manager.get_tile(x+1, y),
                map_manager.get_tile(x-1, y),
                map_manager.get_tile(x, y+1),
                map_manager.get_tile(x, y-1)
            ]
            if any(neighbor.terrain_id in water_terrains for neighbor in neighbors):
                unit_manager.add_unit(
                    player=P0,
                    unit_const=stone_id,
                    x=x + 0.5,
                    y=y + 0.5,
                    z=0,
                    rotation=0,
                    animation_frame=0,
                )

四、注意事项

  • 调整方形边界参数时,需确保数值在0到map_width/map_height范围内,避免索引越界
  • 若需要更精准的石头放置位置,可根据相邻水域的方向微调坐标(比如相邻水域在右侧,石头放在x+0.8, y+0.5)
  • 测试时可缩小遍历范围,避免一次性生成过多单位导致卡顿

内容的提问来源于stack exchange,提问作者Maselia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 12:57:02