4.1.beta2
给不规则的 TileMap 划分子区域块部分代码
## 生成房间内部数据
func generate_room_inside_data():GLog.info("生成房间内部数据")# 划分房间的各个矩形块for room_coords in room_coords_to_data:var room_data = room_coords_to_data[room_coords] as Dictionaryvar edge_coords_set = room_data["edge_coords_set"] as HashSet# 获取外部的空白点,用于排除筛选出内部空白点var outer_empty_coords_set = room_data["outer_empty_coords_set"] as HashSet# 找到内部第一个空白起始点var start_coords = null var edge_coors_list = edge_coords_set.to_array() edge_coors_list.shuffle()for edge_coords in edge_coors_list:for direction in FOUR_DIRECTIONS:var tmp_coords = edge_coords + directionif (not edge_coords_set.has(tmp_coords)and not outer_empty_coords_set.has(tmp_coords)and tile_map.get_cell_source_id(TILE_LAYER.WALL, tmp_coords) == SOURCE_ID.NONE):start_coords = tmp_coordsbreakif typeof(start_coords) == TYPE_VECTOR2I:breakassert(typeof(start_coords) == TYPE_VECTOR2I, "没有找到可用的点,代码逻辑有误!")# 广度搜索所有内部通路var inside_empty_coords_set = HashSet.new()var room_rect = room_data["rect"] as Rect2ivar visited = {}var tmp_coordsvar last_coords_list = [start_coords]while not last_coords_list.is_empty():var next_coords_list = []for coords in last_coords_list:for direction in FOUR_DIRECTIONS:tmp_coords = coords + directionif (not visited.has(tmp_coords)and room_rect.has_point(tmp_coords)and tile_map.get_cell_source_id(TILE_LAYER.WALL, tmp_coords) == SOURCE_ID.NONE):visited[tmp_coords] = nullnext_coords_list.append(tmp_coords)inside_empty_coords_set.append(tmp_coords)last_coords_list = next_coords_listnext_coords_list = []# 记录内部空白瓦片数据room_data["inside_empty_coords_set"] = inside_empty_coords_set# 根据内部空白点,获取每个拐角处的整个矩形var inside_empty_corner_coords_list = Array()for coords in inside_empty_coords_set:if is_empty_corners(coords, tile_map):inside_empty_corner_coords_list.append(coords)# 对房间进行局部矩形细分var added_coords_set = HashSet.new()var block_rect_list = []for empty_coords in inside_empty_corner_coords_list:# TEST 测试显示角落点#tile_map.set_cell(TILE_LAYER.TEST, coords, 0, Vector2i(0,0), ALTERNATIVE_TILE_ID.ASTAR_PATH)# 添加过这个小块矩形四个点包含这个坐标时则跳过if added_coords_set.has(empty_coords):# FIXME 会有两边都有形,但中间有个障碍物,导致左右坐标全部被占# 进而导致另外两个矩形无法生成出来continue# 拐角只有两个方向var empty_coords_directions = get_around_empty_coords_directions(empty_coords, tile_map)for dir_idx in empty_coords_directions.size():# 朝这个拐角的另一方向移动,直到对面墙角,作为矩形一边的线var direction = empty_coords_directions[dir_idx] var moved_line_coords_list = [empty_coords]var current_coords = empty_coordswhile true:current_coords = current_coords + directionif (tile_map.get_cell_source_id(TILE_LAYER.WALL, current_coords) == SOURCE_ID.NONEand tile_map.get_cell_source_id(TILE_LAYER.ENV, current_coords) == SOURCE_ID.NONE):moved_line_coords_list.append(current_coords)else:break# 超过这个移动步数长度才认为是矩形const MAX_STEP = 2if moved_line_coords_list.size() >= MAX_STEP:# 矩形左上角的坐标点var move_start_coords = moved_line_coords_list[0]var arrive_coords# 使用移动的路径线的点,进行平移推进,找到这个局部的矩形var move_direction = empty_coords_directions[1 if dir_idx == 0 else 0]while true:MathUtil.offset_origin_array(moved_line_coords_list, move_direction)for line_coords in moved_line_coords_list:# 如果移动到的位置有点不是空白区域点,则到达一个墙壁if not inside_empty_coords_set.has(line_coords):arrive_coords = moved_line_coords_list[moved_line_coords_list.size() - 1]# 回退一步arrive_coords -= move_directionbreakif arrive_coords is Vector2i:break# 这个小块区域大小var size = (arrive_coords - move_start_coords).abs()# 获取左上角位置var left_top_coords = move_start_coordsif left_top_coords.x > arrive_coords.x:left_top_coords.x = arrive_coords.xif left_top_coords.y > arrive_coords.y:left_top_coords.y = arrive_coords.y var block_rect = Rect2i(left_top_coords, size)# 必须超过步数大小(大小为 0 代表只有一行或一列)if size.x >= MAX_STEP-1 and size.y >= MAX_STEP-1:block_rect_list.append(block_rect)# 记录小块区域的四周坐标点,后续不再对其进行这个操作added_coords_set.append(block_rect.position) # 左上角added_coords_set.append(block_rect.end) # 右下角added_coords_set.append(Vector2i(block_rect.position.x, block_rect.end.y)) # 左下角 added_coords_set.append(Vector2i(block_rect.end.x, block_rect.position.y)) # 右上角room_data["block_rect_list"] = block_rect_list# TEST 测试显示小块划分区域的矩形#for block_rect in block_rect_list:#FuncUtil.for_rect_around(block_rect, func(coords: Vector2i):#tile_map.set_cell(TILE_LAYER.TEST, coords, 0, Vector2i(0,0), ALTERNATIVE_TILE_ID.ASTAR_PATH)#)