如何修改代码实现六边形瓦片地图中CharacterBody2D的移动?
六边形瓦片地图角色移动实现(Godot 2D)
现有代码是四方向移动逻辑,六边形地图需要适配6个移动方向,下面分两种常见场景给出修改方案:
方案1:格子锁定式移动(战棋类常用)
这种方式下角色会从当前格子直接移动到相邻的可通行格子,适合回合制或战棋游戏。
修改后的代码
extends CharacterBody2D @export var move_duration: float = 0.3 # 移动到相邻格子的耗时(秒) @export var tilemap: TileMap # 拖入场景中的六边形瓦片地图 var target_pos: Vector2? = null # 目标格子的世界位置 func _input(event): # 只有在未移动时响应输入 if target_pos == null: # 适配 odd-r 类型(点向上)的六边形方向偏移 var dir_offsets = { "hex_up": Vector2(0, -1), "hex_up_right": Vector2(1, -1), "hex_down_right": Vector2(1, 0), "hex_down": Vector2(0, 1), "hex_down_left": Vector2(-1, 0), "hex_up_left": Vector2(-1, -1) } for action, offset in dir_offsets: if event.is_action_pressed(action): # 获取当前角色所在的格子坐标 var current_tile = tilemap.local_to_map(position) # 计算目标格子坐标 var target_tile = current_tile + offset # 检查目标格子是否可通行(可根据你的地图规则修改) if tilemap.get_cellv(target_tile) != -1: # 转换格子坐标为世界位置(加上瓦片中心偏移) target_pos = tilemap.map_to_local(target_tile) + tilemap.tile_size / 2 break func _physics_process(delta): if target_pos != null: # 计算移动方向和速度 var move_dir = (target_pos - position).normalized() velocity = move_dir * (tilemap.tile_size.x / move_duration) move_and_slide() # 到达目标位置后重置状态 if position.distance_to(target_pos) < 2: position = target_pos target_pos = null velocity = Vector2.ZERO
配置步骤
- 打开项目设置 -> 输入映射,添加6个动作:
hex_up、hex_up_right、hex_down_right、hex_down、hex_down_left、hex_up_left,分别绑定对应的按键(比如W、E、D、S、A、Q)。 - 在场景中选中角色节点,将你的六边形TileMap拖入检查器的
tilemap变量槽中。 - 可通行判断逻辑可根据需求修改,比如改用图层标记、自定义瓦片属性等。
方案2:自由式六边形方向移动(动作类常用)
这种方式保留类似四方向的自由移动,但限制移动方向为六边形的6个轴向,适合动作类六边形地图游戏。
修改后的代码
extends CharacterBody2D @export var speed: int = 35 # 适配 odd-r 类型(点向上)的6个方向向量 var hex_dirs = [ Vector2(0, -1), Vector2(1, -1), Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(-1, -1) ] func handleInput(): var move_dir = Vector2.ZERO # 检测6个方向的输入 if Input.is_action_pressed("hex_up"): move_dir += hex_dirs[0] if Input.is_action_pressed("hex_up_right"): move_dir += hex_dirs[1] if Input.is_action_pressed("hex_down_right"): move_dir += hex_dirs[2] if Input.is_action_pressed("hex_down"): move_dir += hex_dirs[3] if Input.is_action_pressed("hex_down_left"): move_dir += hex_dirs[4] if Input.is_action_pressed("hex_up_left"): move_dir += hex_dirs[5] # 归一化方向,避免多方向同时按下时速度过快 if move_dir.length() > 0: move_dir = move_dir.normalized() velocity = move_dir * speed func _physics_process(delta): handleInput() move_and_slide()
注意事项
- 如果你的六边形地图是边向上类型(Offset为odd-q/even-q),需要替换
hex_dirs为以下向量:var hex_dirs = [ Vector2(1, 0), Vector2(0, -1), Vector2(-1, -1), Vector2(-1, 0), Vector2(0, 1), Vector2(1, 1) ] - 同样需要先配置好6个方向的输入映射。
内容的提问来源于stack exchange,提问作者codingbyDEC
相关产品推荐
相关产品推荐

