【Godot】时间线(技能)节点

news/2024/9/18 6:48:17

4.1

游戏中一般都会有各种各样的技能,或者其他需要按一定的时间顺序去执行的功能。

这里我写出了一个时间线节点,就像是在播放动画一样,按一定的阶段去执行某些功能

#============================================================
#    Timeline
#============================================================
# - author: zhangxuetu
# - datetime: 2023-09-24 23:10:53
# - version: 4.1
#============================================================
class_name _TimeLine
extends Node


## 执行完这个阶段时发出这个信号
signal executed_stage(stage, data)
## 手动停止执行
signal stopped
## 暂停执行
signal paused
## 继续执行
signal resumed
## 执行完成
signal finished


## process 执行方式
enum ProcessExecuteMode {
	PROCESS, ## _process 执行
	PHYSICS, ## _physics_process 执行
}

enum {
	UNEXECUTED, ## 未执行
	EXECUTING, ## 执行中
	PAUSED, ## 暂停中
}


## 时间阶段名称。这关系到 [method execute] 方法中的数据获取的时间数据
@export var stages : Array = []
## process 执行方式。如果设置为 [member PROCESS][member PHYSICS] 以外的值,
## 则当前节点的线程将不会执行
@export var process_execute_mode : ProcessExecuteMode = ProcessExecuteMode.PROCESS


var _last_data : Dictionary
var _point : int = -1:
	set(v):
		if _point != v:
			_point = v
			if _point >= 0 and _point < stages.size():
				self.executed_stage.emit(stages[_point], _last_data)
var _time : float
var _execute_state : int = UNEXECUTED:
	set(v):
		if _execute_state == v:
			return

		_execute_state = v
		match _execute_state:
			UNEXECUTED:
				set_process(false)
				set_physics_process(false)
			EXECUTING:
				if process_execute_mode == ProcessExecuteMode.PROCESS:
					set_process(true)
				elif process_execute_mode == ProcessExecuteMode.PHYSICS:
					set_physics_process(true)
			PAUSED:
				set_process(false)
				set_physics_process(false)


func _ready():
	set_process(false)
	set_physics_process(false)

func _process(delta):
	_exec(delta)

func _physics_process(delta):
	_exec(delta)

func _exec(delta):
	_time -= delta
	while _time <= 0:
		_point += 1
		if _point < stages.size():
			_time += _last_data[stages[_point]]
		else:
			_point = -1
			_execute_state = UNEXECUTED
			self.finished.emit()
			break

func get_time_left():
	return _time

func get_last_data() -> Dictionary:
	return _last_data

func get_last_stage():
	return stages[_point]

## 执行功能。这个数据里需要有 [member stages] 中的 key 的数据,且需要是 [int][float]
## 类型作为判断执行的时间。否则默认时间为 0
func execute(data: Dictionary):
	_last_data = data
	_time = 0
	_point = 0
	if not stages.is_empty():
		_execute_state = EXECUTING
		for stage in stages:
			_last_data[stage] = float(data.get(stage, 0))
		# 执行时会先执行一下
		_time = _last_data[stages[0]]
		_exec(0)

	else:
		printerr("没有设置 stages,必须要设置每个执行的阶段的 key 值!")

## 获取执行状态
func get_execute_state():
	return _execute_state

## 是否正在执行
func is_executing():
	return _execute_state == EXECUTING

## 停止执行
func stop():
	if _execute_state == EXECUTING:
		_execute_state = UNEXECUTED
		self.stopped.emit()

## 暂停执行
func pause():
	if _execute_state == EXECUTING:
		_execute_state = PAUSED

## 恢复执行
func resume():
	if _execute_state == PAUSED:
		_execute_state = EXECUTING
		self.resumed.emit()

## 跳跃到这个阶段
func goto(stage, emit_stage_changed_signal: bool = true):
	if _execute_state == EXECUTING:
		if stages.has(stage):
			_point = stage
			_time = 0
			if emit_stage_changed_signal:
				self.executed_stage.emit()
		else:
			printerr("stages 中没有 ", stage, ". 所有 stage: ", stages)

这里我进行添加整个时间中有哪些阶段,我想一个技能需要有下面几个阶段:

start(开始执行功能,一般用于判断这个条件下是否可以进行执行这个功能,以便进行功能的打断等操作);before 执行功能时的施放动作前摇;execute 具体执行出的功能;after 执行功能后的动画结束;refresh 技能刷新阶段。

这是我的理解,可以自行随意设计。

下面的代码我创建了只有一个 Node2D 作为根节点的场景,进行测试

#============================================================
#    Time Line Test
#============================================================
# - author: zhangxuetu
# - datetime: 2023-09-24 21:51:11
# - version: 4.1
#============================================================
extends Node2D


var timeline = _TimeLine.new()

func _ready():
	timeline.stages = [&"start", &"before", &"execute", &"after", &"refresh"]
	add_child(timeline)

	timeline.executed_stage.connect(_executed_stage)

	timeline.execute({
		"name": "技能名称",
		&"start": 0,
		&"before": 0.4,
		&"execute": 0.2,
		&"after": 0.2,
		&"refresh": 3,
	})


func _executed_stage(stage, data):
	match stage:
		&"start":
			print("   开始执行: ", data["name"])
		&"before":
			print("   播放动作")
			# 临时修改执行时间,延长或缩短时间
			data[&"execute"] = 2
		&"execute":
			print("   实际执行功能,这里写这个阶段要做的事情")
		&"after":
			print("   已经执行完功能,进行后续结束动作")
		&"refresh":
			print("   ", data["name"], " 结束动作完成,开始进行倒计时刷新")

这里我在执行这个技能的时候,传入上面各个阶段所需要的时间的数据,然后在 executed_stage 信号中进行判断各个阶段所需要处理的功能。

这样一个技能节点即可完成,使用时调用 execute 方法即可


http://lihuaxi.xjx100.cn/news/1595770.html

相关文章

关于遥感像元反射率的思考

关于遥感像元反射率的思考 在PROSAIL中模拟的植被反射率是这样的&#xff1a; 模拟了10000个点&#xff0c;其中B2&#xff08;490&#xff0c;蓝色&#xff09;、B3&#xff08;560&#xff0c;绿&#xff09;、B4&#xff08;665&#xff0c;红&#xff09;、B8&#xff08;…

广州华锐互动:VR动物解剖实验室带来哪些便利?

随着科技的不断发展&#xff0c;我们的教育方式也在逐步变化和进步。其中&#xff0c;虚拟现实(VR)技术的应用为我们提供了一种全新的学习方式。尤其是在动物解剖实验中&#xff0c;VR技术不仅能够增强学习的趣味性&#xff0c;还能够提高学习效率和准确性。 由广州华锐互动开发…

Bark Ai 文本转语音 模型缓存位置修改

默认缓存位置在&#xff1a;~/.cache 加入环境变量&#xff1a;XDG_CACHE_HOME&#xff0c;指定缓存位置 修改后新的位置为&#xff1a; D:\Ai\Bark\Bark Cache

One Thread One Loop主从Reactor模型⾼并发服务器

One Thread One Loop主从Reactor模型⾼并发服务器 文章目录 One Thread One Loop主从Reactor模型⾼并发服务器一些补充HTTP服务器Reactor 模型eventfd通用类Any 目标功能模块划分&#xff1a;SERVER模块Buffer模块&#xff1a;编写思路&#xff1a;接口设计&#xff1a;具体实现…

【vue3】可编辑el-table

<template><el-table:data"tableData"style"width: 100%"><el-table-columnprop"date"label"日期"width"180"><template #default"{row,$index}"><input type"text" v-mode…

visual studio code配置anaconda3的python虚拟环境

参考&#xff1a; Visual Studio Code配置anconda3虚拟环境 - 知乎

SSM - Springboot - MyBatis-Plus 全栈体系(二十二)

第四章 SpringMVC 五、SpringMVC 其他扩展 1. 全局异常处理机制 1.1 异常处理两种方式 开发过程中是不可避免地会出现各种异常情况的&#xff0c;例如网络连接异常、数据格式异常、空指针异常等等。异常的出现可能导致程序的运行出现问题&#xff0c;甚至直接导致程序崩溃。…

大语言模型黑盒被打破;Meta 元宇宙硬件亏损可能高于市场共识丨 RTE 开发者日报 Vol.60

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有…