godot-plateformer/addons/reedscene/scene/ReedScene.gd

166 lines
5.3 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@tool
@icon("uid://p0oxphym6oqg")
'''
此类为一个level的最小单元其可以承载任意多的prop和act
你可以这样理解一个level大关卡带有n个小关卡n = scene的数量
Scene 必须带有:
1.Act Manager
2.复数个Prop
其中: ActManager下带有复数个Act其主要用于记录各个Prop的不同state当Act切换时Prop对应的状态也会切换。
ActManager的主要作用就是管理这些Act的切换。
Prop可以简单的理解为场景中的非地形碰撞的与玩家可交互的道具AI等。
所有的Prop会自带一个PropComponent其核心功能是负责管理Prop自身的state和state的切换
举例一个门从State1 -> State2state1是关闭状态state2是打开状态那么
1. 我们在State1中定义门是关的State2中定义门是开的。简单的实现比如我们去设置门的坐标
2. 我们会做一个State1 -> State2的流转函数其定义了State1->State2的具体行为比如播放一个门打开的动画。
对于任意的添加到Scene的Prop如果其自身的最上层子节点集中不含有PropComponentScene会默认的给他发一个PropComponent
注意我并不推荐在Prop上直接挂载PropComponent通过Scene来添加更为合适。
对于SceneScene通过PropComponent上的ID通过ID获取到PropComponent所挂载的组件这也是为什么我强制要求
PropComponent必须是处于Prop的最上层子节点集。
Scene自身也有SceneIDSceneID是实现跨Scene修改的核心SceneID是插件内置的系统主动生成的且理论上不允许修改
对于每个Scene来说SceneID是唯一且绝对的这个涉及到后续的异步加载问题虽然2D游戏可能没有这些问题。
比如说我们可以让玩家在Scene1的时候触发Scene9的一个ActChange发射一个火焰流星雨但是实际上这个东西是可以被在Scene的玩家所
观察的。
'''
class_name ReedScene extends Node2D
## ==============================
## Const Config
## ==============================
##Act管理器的命名
const ACT_MANAGER_NAME := "ActManager"
##Prop的根节点命名
const PROPS_ROOT_NAME := "Props"
##场景管理器的根节点命名
const SCENE_MANAGER_NAME := "SceneManager"
## ==============================
## Export Config
## ==============================
@export var props_root_path: NodePath = ^"Props"
@export var auto_attach_prop_component := true
@export var debug_log := true
## ==============================
## Internal State
## ==============================
var _act_manager: ActManager
var _props_root: Node
var _prop_map: Dictionary = {} # prop_id -> PropComponent
## ==============================
##
## ==============================
func _enter_tree() -> void:
if Engine.is_editor_hint():
_editor_ensure_scene_nodes() ##进入场景树自动添加ActManager,PropsRoot,和SceneManager
## ==============================
## Resolve References
## ==============================
func _resolve_act_manager() -> void:
_act_manager = get_node_or_null("ActManager")
if _act_manager == null:
push_error("[ReedScene] ActManager not found.")
return
func _resolve_props_root() -> void:
_props_root = get_node_or_null(props_root_path)
if _props_root == null:
push_error("[ReedScene] Props root not found: %s" % props_root_path)
## ==============================
## Prop Collection
## ==============================
func _collect_props() -> void:
_prop_map.clear()
if _props_root == null:
return
for prop in _props_root.get_children():
if not prop is Node:
continue
var prop_comp := _find_prop_component(prop)
if prop_comp == null:
continue
var prop_id := prop_comp.prop_id
if prop_id < 0:
push_warning("[ReedScene] Prop has invaild ID: %s" % prop.name)
continue
if _prop_map.has(prop_id):
push_error("[ReedScene] Duplicate Prop ID: %s" % prop_id)
continue
_prop_map[prop_id] = prop_comp
if debug_log:
print("[ReedScene] Registered Prop:", prop_id)
func _find_prop_component(prop: Node) -> PropComponent:
for child in prop.get_children():
if child is PropComponent:
return child
return null
## ==============================
## Act Binding
## ==============================
func _bind_act_events() -> void:
if _act_manager == null:
return
_act_manager.act_changed.connect(_on_act_changed)
func _on_act_changed(from_act: int, to_act: int) -> void:
if debug_log:
print("[ReedScene] Act changed:", from_act, "->", to_act)
for prop_comp in _prop_map.values():
prop_comp.on_act_changed(from_act, to_act)
##进入场景树自动添加ActManager,PropsRoot,和SceneManager
func _editor_ensure_scene_nodes() -> void:
_editor_ensure_node(SCENE_MANAGER_NAME, SceneManager)
_editor_ensure_node(ACT_MANAGER_NAME, ActManager)
_editor_ensure_node(PROPS_ROOT_NAME, PropManager)
##添加命名和节点
func _editor_ensure_node(name: String, type: Variant) -> Node:
var node := get_node_or_null(name)
if node != null:
return node
node = type.new()
node.name = name
add_child(node)
node.owner = get_tree().edited_scene_root
if debug_log:
print("[ReedScene][Editor] Created node:", name)
return node
func _ready() -> void:
_resolve_act_manager()
_resolve_props_root()
_collect_props()
_bind_act_events()