问题
解决方案
基于网格或图块的移动意味着角色的位置受到限制。他们只能站在一个特定的瓷砖上 - 永远不会在两个瓷砖之间。
角色设定
以下是我们将用于播放器的节点:
- Area2D(“播放器”):使用Area2D意味着我们可以检测到重叠(用于拾取物体或与敌人碰撞)。
- Sprite:您可以在此处使用精灵表(我们将在下面设置动画)。
- CollisionShape2D:不要让hitbox太大。由于玩家将站在瓷砖的中心,因此重叠将从中心开始。
- RayCast2D:用于检查是否可以在给定方向上移动。
- Tween:用于从瓷砖到瓷砖的插值运动。
- AnimationPlayer:用于播放角色的行走动画。
将一些输入操作添加到输入映射。在此示例中,我们将使用“上”、“下”、“左”和“右”。
基本动作
我们将从设置逐块移动开始,不使用任何动画或插值。
extends Area2D
var tile_size = 64
var inputs = {"right": Vector2.RIGHT,
"left": Vector2.LEFT,
"up": Vector2.UP,
"down": Vector2.DOWN}
tile_size应设置为匹配您的瓷砖的大小。在较大的项目中,这可以在实例化播放器时由您的主场景设置。在下面的示例中,我们使用 64x64 瓷砖。
字典将inputs输入动作名称映射到方向向量。确保您在此处和输入映射中的名称拼写相同(大写计数!)。
func _ready():
position = position.snapped(Vector2.ONE * tile_size)
position += Vector2.ONE * tile_size/2
snapped()允许我们将位置“四舍五入”到最近的瓷砖增量,并添加半瓷砖数量确保玩家在瓷砖上居中。
func _unhandled_input(event):
for dir in inputs.keys():
if event.is_action_pressed(dir):
move(dir)
func move(dir):
position += inputs[dir] * tile_size
这是实际的运动代码。当输入事件发生时,我们检查四个方向以查看哪个匹配,然后将其传递给以move()更改位置。
碰撞
现在我们可以添加一些障碍。你可以加StaticBody2Ds 手动添加一些障碍物(启用捕捉以确保它们与网格对齐)或使用 TileMap(定义了碰撞),如下例所示。
我们将使用RayCast2D以确定是否允许移动到下一个图块。
onready var ray = $RayCast2D
func move(dir):
ray.cast_to = inputs[dir] * tile_size
ray.force_raycast_update()
if !ray.is_colliding():
position += inputs[dir] * tile_size
更改光线投射的cast_to属性时,物理引擎不会重新计算其碰撞,直到下一个物理帧。force_raycast_update()让您立即更新光线的状态。如果它没有碰撞,那么我们允许移动。
另一种常见的方法是使用 4 个单独的光线投射,每个方向一个。
动画运动
最后,我们可以在瓷砖之间插入位置,给运动带来平滑的感觉。我们将使用Tween节点为position属性设置动画。
onready var tween = $Tween
export var speed = 3
添加引用Tween节点和一个变量来设置我们的移动速度。
func _unhandled_input(event):
if tween.is_active():
return
for dir in inputs.keys():
if event.is_action_pressed(dir):
move(dir)
在补间运行时,我们将忽略任何输入。
func move(dir):
ray.cast_to = dir * tile_size
ray.force_raycast_update()
if !ray.is_colliding():
# position += dir * tile_size
move_tween(dir)
删除直接position更改并调用函数来激活补间:
func move_tween(dir):
tween.interpolate_property(self, "position",
position, position + dir * tile_size,
1.0/speed, Tween.TRANS_SINE, Tween.EASE_IN_OUT)
tween.start()
尝试不同的补间过渡以获得不同的运动效果。
您可以下载此示例的完整项目:grid_based_movement.zip