【Godot_4.3】2d俯视角下的move_and_slide()

关键词:Godot,4.3,2d,俯视角,move_and_slide(),角色,移动



在Godot的2d俯视角项目中,想要拥有【一面不可移动的墙】和【一名玩家】,要怎么做呢?

1、墙

①墙是静止的,所以用StaticBody2D,并添加形状(和颜色)。操作很简单,这里不过多赘述。

在这里插入图片描述

2、玩家

①添加玩家,用CharacterBody2D,并添加形状、图片(Sprite2d)。

在这里插入图片描述

②玩家代码,如下图所示。其中最重要的是“move_and_slide()”,以下是说明:

(1)一般情况下角色移动时计算不需要乘以delta,引擎会根据物理步骤(即每秒钟的物理更新次数)自动将速度转换为移动距离(例子:土豆兄弟)

(2)特殊情况才要乘以delta,比如2d平台跳跃游戏里的垂直速度(velocity.y)受重力影响,通常需要额外的时间增量(delta)来确保帧率独立(例子:马里奥)
在这里插入图片描述


最终效果

玩家被墙挡住,无法继续前进。
至此,本篇结束。
在这里插入图片描述

<think>我们之前讨论了使用`Input.get_vector()`简化2D视角角色移动的方法,现在用户希望在检测输入并更新方向的基础上添加平滑旋转功能。根据用户引用[3]中的代码片段,我们看到通过插值或角度限制可以实现平滑的旋转效果。在Godot中,我们可以利用`lerp_angle()`或`Quaternion.slerp()`等方法实现平滑旋转。以下是实现步骤:1.**获取输入向量**:使用`Input.get_vector()`获取归一化移动方向2.**计算目标旋转角度**:`target_rotation=input_vector.angle()`3.**应用平滑旋转**:通过插值函数逐步改变当前旋转角度具体实现代码如下:```gdscriptextendsCharacterBody2D@exportvarspeed:float=300.0@exportvarrotation_speed:float=5.0#旋转速度系数varcurrent_rotation:float=0.0#当前旋转角度(弧度)func_physics_process(delta):#获取输入向量varinput_vector=Input.get_vector("ui_left","ui_right","ui_up","ui_down")#设置速度velocity=input_vector*speedmove_and_slide()#当有输入时更新旋转ifinput_vector!=Vector2.ZERO:#计算目标角度(弧度)vartarget_rotation=input_vector.angle()#使用角度插值实现平滑旋转current_rotation=lerp_angle(current_rotation,target_rotation,rotation_speed*delta)#应用旋转rotation=current_rotation```###关键参数说明:-`rotation_speed`:控制旋转平滑度的系数,值越大旋转越快-推荐范围:$1\leq\text{rotation\_speed}\leq20$-`lerp_angle()`:Godot内置的角度线性插值函数-函数定义:`lerp_angle(from,to,weight)`-特性:自动处理角度环绕问题(如从$350^\circ$到$10^\circ$的过渡)###数学原理:旋转插值公式:$$\theta_{\text{current}}=(1-\alpha)\theta_{\text{current}}+\alpha\theta_{\text{target}}$$其中$\alpha=\text{rotation\_speed}\times\delta$,$\delta$为帧时间增量###进阶优化:1.**添加旋转加速度**:```gdscript@exportvarrotation_acceleration:float=0.1varrotation_velocity:float=0.0func_physics_process(delta):#...速度计算...ifinput_vector!=Vector2.ZERO:vartarget_rotation=input_vector.angle()varangle_diff=wrapf(target_rotation-current_rotation,-PI,PI)rotation_velocity+=rotation_acceleration*angle_diff*deltarotation_velocity=lerp(rotation_velocity,0.0,0.1)#阻尼current_rotation+=rotation_velocity*deltarotation=current_rotation```2.**使用四元数旋转**(3D场景):```gdscriptvarcurrent_quat=Quaternion(transform.basis)vartarget_quat=Quaternion(Basis().looking_at(input_vector,Vector3.UP))current_quat=current_quat.slerp(target_quat,rotation_speed*delta)transform.basis=Basis(current_quat)```###注意事项:-在角色没有输入时保持当前朝向-使用`wrapf()`处理角度跳跃问题-对于2D游戏,优先使用`lerp_angle`避免万向锁问题[^3]§§相关问题§§1.如何实现角色旋转时的动画过渡效果?2.Godot中如何优化角度计算的性能?3.如何处理3D角色的平滑朝向更新?4.如何为旋转添加最大角速度限制?</think> ### 在检测输入基础上实现平滑旋转的方法 在检测输入并更新方向的基础上添加平滑旋转功能,关键在于使用**角度插值**技术。以下是完整的实现方案(基于Godot引擎): ```gdscript extends CharacterBody2D @export var speed: float = 300.0 @export var rotation_speed: float = 5.0 # 旋转平滑度系数 (推荐值: 3-10) var target_rotation: float = 0.0 # 目标旋转角度 func _physics_process(delta): # 获取输入向量 var input_vector = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") # 设置速度 velocity = input_vector * speed move_and_slide() # 当有输入时更新旋转目标 if input_vector != Vector2.ZERO: # 计算输入向量的角度 (弧度制) target_rotation = input_vector.angle() # 使用角度插值实现平滑旋转 rotation = lerp_angle(rotation, target_rotation, rotation_speed * delta) ``` ### 关键实现原理 1. **目标角度计算**: - 使用向量角度计算:$\theta = \atan2(v_y, v_x)$ - `input_vector.angle()`返回输入方向的弧度值(范围$-\pi$到$\pi$) 2. **平滑插值函数**: - `lerp_angle(from, to, weight)`是Godot专门的角度插值函数 - 数学表达式: $$\theta_{\text{current}} = (1-\alpha)\theta_{\text{current}} + \alpha\theta_{\text{target}}$$ 其中$\alpha = \text{rotation\_speed} \times \delta$ 3. **旋转速度系数**: - 值越大旋转越快(线性响应) - 推荐范围:$3 \leq \text{rotation\_speed} \leq 10$ - 可通过`@export_range(1, 20)`在编辑器中调整 ### 高级优化方案 1. **添加旋转缓冲**: ```gdscript var rotation_buffer: float = 0.0 func _physics_process(delta): # ...其他代码... var angle_diff = wrapf(target_rotation - rotation, -PI, PI) rotation_buffer += angle_diff * rotation_speed * delta rotation += rotation_buffer rotation_buffer *= 0.9 # 阻尼系数 ``` 2. **速度敏感的旋转速率**: ```gdscript func _physics_process(delta): # ...其他代码... var dynamic_speed = rotation_speed * clamp(velocity.length() / speed, 0.1, 1.0) rotation = lerp_angle(rotation, target_rotation, dynamic_speed * delta) ``` 3. **四元数旋转(3D场景)**: ```gdscript # 在3D中更推荐使用四元数插值 var current_quat := Quaternion(transform.basis) var target_quat := Quaternion(Basis().looking_at(input_vector, Vector3.UP)) transform.basis = Basis(current_quat.slerp(target_quat, rotation_speed * delta)) ``` ### 注意事项 1. **角度范围处理**: - 使用`wrapf()`确保角度差值在$(-\pi, \pi]$范围内 - 避免从$179^\circ$到$-179^\circ$的突变旋转 2. **性能优化**: - 当$|\Delta\theta| < 0.01$时可跳过插值计算 - 使用`@onready`缓存频繁访问的节点 3. **移动停止时的行为**: ```gdscript if input_vector == Vector2.ZERO: rotation_buffer *= 0.95 # 缓慢停止旋转 ``` 这种方法通过角度插值实现了自然的方向过渡效果,避免了突然的旋转跳跃,符合人眼对运动的预期[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值