Godot带重力网格移动:角色分步执行移动实现求助
问题描述
我正在制作一款**网格(Grid-based)**移动类2D游戏,核心设定如下:
- 角色跳跃受重力影响
- 角色不响应实时键盘输入,玩家点击「GO」按钮后,角色会按预设指令列表分步执行动作
- 已实现重力对角色的影响,但不知道如何实现基于网格的分步移动,求实现思路或修改建议
当前变量moviendose会在玩家按下GO时设为true,现有代码如下:
extends KinematicBody2D var moviendose = false var lista_habilidades_jugador = [] onready var tweene = $AnimatedSprite const GRAVITY = 9.8 var velocity = Vector2.ZERO const def_habilidades = { "Habilidad1": Vector2(16,0), "Habilidad2": Vector2(-16,0), "Habilidad3": Vector2(0,(-GRAVITY*16)) } func _physics_process(delta): velocity.y += GRAVITY if lista_habilidades_jugador.size() == 0: moviendose = false if moviendose == true: movimiento() velocity = move_and_slide(velocity) func movimiento(): for mov in lista_habilidades_jugador: if mov == "Habilidad1": velocity = velocity.move_toward(def_habilidades[mov] , 5) tweene.flip_h = false tweene.play("correr") if mov == "Habilidad2": velocity = lerp(velocity + def_habilidades[mov], Vector2.ZERO,20) tweene.flip_h = true if mov == "Habilidad3": velocity = velocity + def_habilidades[mov] self.lista_habilidades_jugador.pop_front()

分步移动实现思路与代码修改建议
你现在的代码问题很明显:movimiento()里直接循环所有指令,一帧就把所有动作跑完了,根本没给角色分步移动的时间。要实现网格分步移动,得改成先执行单个指令,等角色到达目标网格点后,再执行下一个指令的逻辑,具体改法如下:
核心逻辑调整方向
- 记录当前要到达的网格目标位置,而非直接叠加速度
- 每帧检查角色是否抵达目标,达标后再从指令列表取下一个动作
- 所有移动都要确保角色最终对齐网格,避免位置偏移
具体修改步骤
添加网格相关变量
先定义网格尺寸(和你现有技能的向量匹配),以及记录目标位置、移动状态的变量:const GRID_SIZE = 16 # 网格单元格大小,和技能向量的16对应 var target_position = Vector2.ZERO # 当前要移动到的网格坐标 var is_moving_to_target = false # 是否正在执行当前移动动作初始化目标位置
在角色初始化时,把初始位置对齐到网格上:func _ready(): target_position = position.snapped(Vector2(GRID_SIZE, GRID_SIZE))重写
movimiento()函数
不再一次性循环所有指令,改为每次只处理一个,直到到达目标再取下一个:func movimiento(): # 没有正在执行的动作,且还有指令待执行时,取出第一个指令 if not is_moving_to_target and lista_habilidades_jugador.size() > 0: var current_mov = lista_habilidades_jugador[0] var move_offset = def_habilidades[current_mov] # 计算目标位置并对齐网格 target_position = (position + move_offset).snapped(Vector2(GRID_SIZE, GRID_SIZE)) # 设置对应动画 match current_mov: "Habilidad1": tweene.flip_h = false tweene.play("correr") "Habilidad2": tweene.flip_h = true tweene.play("correr") "Habilidad3": tweene.play("saltar") # 替换成你的跳跃动画名称 is_moving_to_target = true # 正在移动时,逐步靠近目标 if is_moving_to_target: var direction = (target_position - position).normalized() velocity = direction * 60 # 可根据需求调整移动速度 # 检查是否到达目标(距离小于阈值时判定完成) if position.distance_to(target_position) < 2: # 精确对齐到目标位置 position = target_position velocity = Vector2.ZERO is_moving_to_target = false # 移除已完成的指令 lista_habilidades_jugador.pop_front() # 切换回 idle 动画 tweene.play("idle")优化重力处理逻辑
区分角色状态,避免水平移动时被重力干扰(如果你的游戏设定移动时角色在地面):func _physics_process(delta): # 仅当角色不在地面,或正在执行跳跃指令时,应用重力 if not is_on_floor() or (is_moving_to_target and lista_habilidades_jugador[0] == "Habilidad3"): velocity.y += GRAVITY * delta * 60 # 乘以delta确保帧率无关 if lista_habilidades_jugador.size() == 0: moviendose = false if moviendose == true: movimiento() velocity = move_and_slide(velocity, Vector2.UP)
额外提示
- 网格移动的核心是位置对齐,所有目标位置计算都要用
snapped()方法确保贴合网格 - 跳跃动作可以单独优化:比如在角色落地(
is_on_floor()为true)时,再判定跳跃完成并执行下一个指令 - 也可以用Godot的
Tween节点实现更丝滑的网格移动过渡,替代手动计算速度的方式
内容的提问来源于stack exchange,提问作者Johan SlZAR
相关产品推荐
相关产品推荐

