【GDScript】做一个常用的功能——节点转向到目标位置

Godot 4.0

使节点不断向鼠标位置旋转

主场景中,拖拽 文件系统 中的 icon.png 文件到场景中,在 icon 节点下边添加一个 Node2D 节点,并添加脚本(如下图所示)。
在这里插入图片描述

然后将下面代码粘贴到 Node2D 节点的脚本里。
在这里我做了一个节点旋转到鼠标位置的代码,你也可以稍作修改,改为旋转到其他节点位置等,在 process 方法里

#==================================================
#	Turn Controller
#==================================================
# @datetime: 2021-9-12 10:58:45
#==================================================
##  转动
class_name TurnController
extends Node2D


##  [code]radian[/code] 为旋转的弧度。连接这个信号调用 [Node2D] 节点的 [method rotate] 方法进行旋转
signal rotated(radian: float)
##  转向完成
signal turn_finished


##  执行方式
enum ExecuteMode {
	MANUAL, ## 需要不断地调用旋转方法进行旋转
	PHYSICS, ## 以 _physics_process 线程进行调用旋转到的节点,只用调用一次旋转方法则会自动旋转到目标位置
	PROCESS, ## 以 _process 线程进行调用旋转到的节点,只用调用一次旋转方法则会自动旋转到目标位置
}

@export var execute_mode : ExecuteMode = ExecuteMode.MANUAL:
	set(v):
		execute_mode = v
		_update_process()
## 根据这个节点作为中心点的方向进行旋转
@export var rotate_by_node : Node2D
## 旋转速度
@export var rotation_speed : float = 3.0
## 偏移的角度(这会决定贴图方向)
@export_range(0, 360.0) var offset_degress : float = 0.0 : 
	set(value):
		offset_degress = value
		_offset_rot = deg_to_rad(offset_degress)

# 偏移的弧度
var _offset_rot : float = 0.0
# 旋转到的节点
var _to : Vector2 = Vector2(0,0)


#==================================================
#   Set/Get
#==================================================
func set_offset_degress(value: float) -> void:
	offset_degress = value
	_offset_rot = deg_to_rad(offset_degress)


#============================================================
#  内置
#============================================================
func _ready() -> void:
	_update_process()
	if is_instance_valid(rotate_by_node):
		_to = rotate_by_node.global_position


func _physics_process(delta: float) -> void:
	central_to(_to, delta)


func _process(delta: float) -> void:
	central_to(_to, delta)


#==================================================
#   自定义方法
#==================================================
# 更新线程
func _update_process() -> void:
	set_process(false)
	set_physics_process(false)
	if execute_mode == ExecuteMode.PROCESS:
		set_process(true)
	elif execute_mode == ExecuteMode.PHYSICS:
		set_physics_process(true)


##  转向到目标位置。(注意这个是手动控制的,需要每帧不断地调用这个方法,然后会旋转到目标方向。)
##[br]
##[br][code]from[/code]  角色位置
##[br][code]to[/code]  目标位置
func to(from: Vector2, to: Vector2, delta: float) -> void:
	to_dir(from.direction_to(to), delta)
	_update_process()


##  中心旋转。以当前 rotate_by_node 位置旋转到目标位置
func central_to(to: Vector2, delta: float) -> void:
	if rotate_by_node:
		_to = to
		to(rotate_by_node.global_position, to, delta)
		_update_process()


##  停止旋转
func stop() -> void:
	set_physics_process(false)
	set_process(false)


##  转向到目标方向
##[br]
##[br][code]dir[/code]  目标方向
func to_dir(dir: Vector2, delta: float):
	var v : Vector2 = rotate_by_node.global_position - get_global_mouse_position()
	var angle : float = v.angle()
	var r : float = rotate_by_node.global_rotation + _offset_rot
	var angle_delta : float = rotation_speed * delta  # 每帧旋转速度
	
	# 旋转到目标位置
	angle = lerp_angle(r, angle, 1.0)
	# 限制上面旋转速度,固定旋转的值在 angle_delta (每帧旋转)速度之内
	angle = clamp(angle, r - angle_delta, r + angle_delta)
	
	if (r != angle):
		rotated.emit(angle)
		
	else:
		set_process(false)
		set_physics_process(false)
		
		turn_finished.emit()



请添加图片描述

按下 F6 试试运行效果吧!


线性差值旋转,速度不是恒定的,会在旋转到目标位置时越来越慢,代码如下

extends Sprite

export var speed = 2

## 旋转角度偏移
var offset_rangle = PI/2

func _physics_process(delta):
	# 旋转到鼠标位置
	var mouse_pos = get_global_mouse_position()
	var a = global_position.direction_to(mouse_pos).rotated(offset_rangle)
	var b = Vector2.RIGHT.rotated(self.global_rotation)
	global_rotation = b.linear_interpolate(a , delta * speed).angle()
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值