Godot在 Godot 中使用代理模式将一些通用的功能封装起来

Posted 张学徒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Godot在 Godot 中使用代理模式将一些通用的功能封装起来相关的知识,希望对你有一定的参考价值。

Godot 3.4

代理模式:“代理”,顾名思义,将事情代由其他人来管理,这样自己就省事了。代理模式可以将原对象交由代理对象进行管理。

在 Godot 我们可以将一些比较常用的功能做成一个代理,用时创建一个这个对象即可。

比如我们可能有各种各样的节点都需要移动功能,如果是节点类型相同我们可以继承,但是如果不同的话,我们就得一个重写里,但是我们又不想一个个都给它写一遍,那我们就可以写个代理进行控制,需要用到,就给它创建出来就使用了。


创建一个 Move.gd 脚本,代码如下

extends Reference
class_name Move


## 调用的move方法,引用的方法
var move : FuncRef

## 移动方向
var direction := Vector2(0,0)
## 操控的宿主
var host : Node



#================================================
#   内置方法
#================================================
## 构造方法(new 对象时传入的参数)
## @h:操控的对象
## @move_method:操控的move的方法
func _init(h: Node, move_method: String):
	host = h
	# 没有这个方法则报错
	assert(host.has_method(move_method), "没有 %s 方法" % move_method)
	# 等待这个节点加载到场景树中
	if not host.is_inside_tree():
		yield(host, "tree_entered")
	# 连接场景物理帧,在 Reference 类中模拟 Node 类中的 _physics_process 线程
	host.get_tree().connect("physics_frame", self, "_physics_process", [host.get_physics_process_delta_time()])
	# 引用 host 的移动方法
	move = funcref(host, move_method)



#================================================
#   自定义方法
#================================================
## 模拟 Node 中的 _physics_process 物理帧方法
func _physics_process(_delta: float) -> void:
	# 获取用户移动方向(你也可以修改成其他项目设置里的键位映射的键值)
	direction = get_input("ui_left","ui_right","ui_up","ui_down").normalized()
	# 调用move方法,用于传入移动方向,所以创建的对象的方法必须是带有一个参数的方法
	move.call_func(direction)


## 获取用户的输入
## @left 向左移动按键映射
## @right 向右移动按键映射
## @up 向上移动按键映射
## @down 向下移动按键映射
func get_input(left, right, up, down):
	direction.x = Input.get_action_strength(right) - Input.get_action_strength(left)
	direction.y = Input.get_action_strength(down) - Input.get_action_strength(up)
	return direction

新建一个场景,然后保存,再将 文件系统 中的 icon.png 图标拖拽到场景中,给这个 icon 创建一个脚本,脚本名随意,然后在里面写如下代码

extends Sprite


## 移动速度
export var move_speed : int = 300


## 移动代理,操控 self (当前节点) 的 move 方法
var move : Move = Move.new(self, "move")


## 移动
func move(velocity: Vector2):
	position += velocity * move_speed * get_physics_process_delta_time()

运行场景,按下小键盘方向键,即可操纵移动

也可以将节点换成 KinematicBody2D 节点,代码内容只需稍改一下即可

extends KinematicBody2D


## 移动速度
export var move_speed : int = 300


## 移动代理
var move : Move = Move.new(self, "move")


## 移动
func move(velocity: Vector2):
	move_and_slide(velocity * move_speed)
	

这样就可以很方便的对对象进行扩展,很灵活,对象的耦合度也很低。这只是一个比较简单的示例,可能看不出优势,如果是个稍微复杂的功能,也许代理模式就能派上用场了。

你可以举一反三制作出更多功能,欢迎交流。

以上是关于Godot在 Godot 中使用代理模式将一些通用的功能封装起来的主要内容,如果未能解决你的问题,请参考以下文章

godot常用的一些概念组件(整理于官方教程)

Godot状态机设计和使用方式

如何使用带有脚本的 godot fbx 导入器

Godot实用代码1000例

Godot保存当前场景中所有的子节点的属性

Godot保存当前场景中所有的子节点的属性