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

如何为Python简易2D网格游戏实现视野判定函数?

网格游戏视野函数实现思路

我正在用Python开发一款无图形界面的简易网格游戏来练手,核心设定如下:

  • 最大10×10的2D网格,角色处于其中某个方块
  • 网格内每个方块的任意侧边可设置墙体,角色无法穿过或透视墙体
  • 当前用嵌套字典存储方块数据(示例见下方),也可改为列表嵌套等更易用的结构

需要实现一个视野函数:根据角色坐标与周边方块的墙体信息,返回其他方块的完全可见、部分可见(约一半区域可见,视线被墙体阻挡)或不可见状态。

方块数据结构示例(原嵌套字典)

{"square 1": {"items": [], "description": "This square has walls on the west and south sides", "coordinates": [0, 0], "walls": ["west", "south"]}}

推荐数据结构优化(可选)

把嵌套字典改成二维列表,直接通过坐标索引访问方块,效率更高:

# 10x10网格,grid[y][x]对应坐标(x,y)的方块
grid = [[
    {"walls": {"west", "south"}, "items": [], "description": "This square has walls on the west and south sides"}
    for _ in range(10)
] for _ in range(10)]

核心实现思路

1. 基于网格步进的视线检测

不用复杂的浮点射线,用简化的方块角落视线追踪:

  • 把每个方块的四个角落作为视线检测的终点(比如坐标(x,y)的方块,四个角落虚拟坐标为(x-0.5, y-0.5)、(x+0.5, y-0.5)、(x-0.5, y+0.5)、(x+0.5, y+0.5))
  • 从角色所在方块的中心,向目标方块的四个角落分别发射"视线",每进入一个新方块,就检查与前一个方块之间是否有墙体阻挡

2. 辅助函数:墙体检测

先写一个判断相邻方块间是否有墙体的函数:

def has_wall_between(coord1, coord2, grid):
    """
    coord1: 元组(x1, y1),coord2: 元组(x2, y2),必须是相邻坐标
    返回两个方块之间是否存在墙体
    """
    x1, y1 = coord1
    x2, y2 = coord2
    # 东边相邻(x1+1 = x2,y1=y2)
    if x2 == x1 + 1 and y1 == y2:
        return 'east' in grid[y1][x1]['walls'] or 'west' in grid[y2][x2]['walls']
    # 西边相邻(x1-1 = x2,y1=y2)
    elif x2 == x1 - 1 and y1 == y2:
        return 'west' in grid[y1][x1]['walls'] or 'east' in grid[y2][x2]['walls']
    # 南边相邻(y1+1 = y2,x1=x2)
    elif y2 == y1 + 1 and x1 == x2:
        return 'south' in grid[y1][x1]['walls'] or 'north' in grid[y2][x2]['walls']
    # 北边相邻(y1-1 = y2,x1=x2)
    elif y2 == y1 - 1 and x1 == x2:
        return 'north' in grid[y1][x1]['walls'] or 'south' in grid[y2][x2]['walls']
    return False

3. 视线可达性判断

写一个函数,判断从角色坐标到目标角落的视线是否被阻挡:

def is_sight_clear(role_coord, target_corner, grid):
    """
    role_coord: 角色所在方块坐标(x, y)
    target_corner: 目标方块的角落虚拟坐标(比如(0.5, 0.5))
    返回视线是否清晰无阻挡
    """
    rx, ry = role_coord
    # 角色位置转为中心虚拟坐标
    start_x, start_y = rx + 0.5, ry + 0.5
    tx, ty = target_corner

    # 计算步进方向
    dx = 1 if tx > start_x else -1 if tx < start_x else 0
    dy = 1 if ty > start_y else -1 if ty < start_y else 0

    current_x, current_y = start_x, start_y
    current_grid_x, current_grid_y = rx, ry

    while True:
        # 计算到下一个网格边界的距离
        step_x = float('inf')
        if dx != 0:
            next_x = current_grid_x + dx
            step_x = (next_x + 0.5 - current_x) if dx > 0 else (current_x - (next_x + 0.5))
        
        step_y = float('inf')
        if dy != 0:
            next_y = current_grid_y + dy
            step_y = (next_y + 0.5 - current_y) if dy > 0 else (current_y - (next_y + 0.5))
        
        # 先碰到x或y边界,检查对应方向的墙体
        if step_x <= step_y:
            if has_wall_between((current_grid_x, current_grid_y), (next_x, current_grid_y), grid):
                return False
            current_x += step_x * dx
            current_grid_x = next_x
        else:
            if has_wall_between((current_grid_x, current_grid_y), (current_grid_x, next_y), grid):
                return False
            current_y += step_y * dy
            current_grid_y = next_y
        
        # 到达目标方块区域
        if current_grid_x == int(tx) and current_grid_y == int(ty):
            return True

4. 计算方块可见状态

遍历所有方块,统计能到达的角落数量,标记状态:

def calculate_vision(role_coord, grid):
    vision_status = {}
    rx, ry = role_coord
    grid_size = 10

    for y in range(grid_size):
        for x in range(grid_size):
            if (x, y) == (rx, ry):
                continue  # 跳过自身方块
            # 当前方块的四个角落虚拟坐标
            corners = [
                (x - 0.5, y - 0.5),
                (x + 0.5, y - 0.5),
                (x - 0.5, y + 0.5),
                (x + 0.5, y + 0.5)
            ]
            clear_count = 0
            for corner in corners:
                if is_sight_clear((rx, ry), corner, grid):
                    clear_count += 1
            # 根据可见角落数量判定状态
            if clear_count == 4:
                vision_status[(x, y)] = '完全可见'
            elif 1 <= clear_count <= 3:
                vision_status[(x, y)] = '部分可见'
            else:
                vision_status[(x, y)] = '不可见'
    return vision_status

补充说明

  • 相邻方块特殊处理:如果和角色方块共用墙体,视线只能到达部分角落,会被标记为部分可见;无墙体则完全可见
  • 可根据需求调整部分可见的判定阈值(比如改为2个及以上角落可见才算部分可见)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 12:48:15