#框架 #工具 #游戏开发

nodetreederive

node_tree库提供NodeSys

3个版本

0.1.2 2024年4月8日
0.1.1 2024年4月8日
0.1.0 2024年4月8日

#1186#工具

每月 35 次下载
node_tree 中使用

MIT/Apache

11KB

NodeTree

Crates.io License Crates.io Version Documentation

NodeTree是一个通过进程树创建大型可扩展程序和游戏的框架。每个进程都是完全自主的,能够存储自己的状态或数据,并与其他进程进行通信。这些进程被称为节点。

⚠️警告⚠️
这是一个依赖夜间构建版本的库。
此库处于早期开发阶段。请注意可能存在的错误或不安全行为。
此库使用的具体夜间版本是v1.78。

入门!

只需在指向您项目目录的终端中运行cargo add node_tree,或者在cargo.toml文件中添加node_tree = X.X即可。

要开始创建利用NodeTree的Rust程序,我们首先需要创建一个根Node。为了减少样板代码,我们将使用包含的NodeSys derive宏来实现所需的DynamicNodeAbstract特质。然后我们将自己实现Node特质。

#![feature(arbitrary_self_types)]   // Required for now.
use node_tree::prelude::*;


#[derive(Debug, Clone, NodeSys)]
pub struct NodeA {
    base: Rc<NodeBase>   // Required for Nodes.
}

// To make things simple, it is advised to have most node constructors return the node
// instance wrapped inside of this crate's `Hp<T>` pointer.
impl NodeA {
    fn new(name: String) -> Hp<Self> {
        Hp::new(NodeA { base: NodeBase::new(name) })
    }
}

// Example implementation of the Node trait with custom behaviours.
impl Node for NodeA {

    /// Run once the Node is added to the NodeTree.
    fn ready(self: Hp<Self>) -> () {

        // To show off how you could add children nodes.
        if self.depth() < 3 {
            self.add_child(NodeA::new(format!("{}_Node", self.depth() + 1)));
            self.add_child(NodeA::new(format!("{}_Node", self.depth() + 1)));
            self.add_child(NodeA::new(format!("{}_Node", self.depth() + 1)));
        }

        if self.is_root() {
            println!("{:#?}", self.children());
        }
    }

    /// Run once per frame. Provides a delta value in seconds between frames.
    fn process(self: Hp<Self>, delta: f32) -> () {

        // Example of using the delta value to calculate the current framerate.
        println!("{} | {}", self.name(), 1f32 / delta);

        // Using the NodePath, you can reference other nodes in the NodeTree from this node.
        if self.is_root() {
            match self.get_node(NodePath::from_str("1_Node/2_Node1/3_Node2")) {
                Some(node) => println!("{:?}", node),
                None       => ()
            }
        }

        // Nodes can be destroyed. When destroyed, their references from the NodeTree are cleaned up as well.
        // If the root node is destroyed, then the program automatically exits. (There are other ways to
        // terminate the program such as the queue_termination() function on the NodeTree instance).
        if self.children().is_empty() {
            self.free();   // We test the progressive destruction of nodes from the tip of the tree
                           // to the base.
        }
    }

    /// Runs once a Node is removed from the NodeTree, whether that is from the program itself terminating or not.
    fn terminal(self: Hp<Self>) -> () {}   // We do not do anything here for this example.

    /// Returns this node's process mode.
    /// Each process mode controls how the process() function behaves when the NodeTree is paused or not.
    /// (The NodeTree can be paused or unpaused with the pause() or unpause() functions respectively.)
    fn process_mode(self: Hp<Self>) -> ProcessMode {
        ProcessMode::Inherit    // We will return the default value, which inherits the behaviour from
                                // the parent node.
    }
}

最后,为了激活我们的NodeTree,我们必须实例化根Node并将其传递给NodeTree构造函数。

// ...previous implementations

fn main() -> () {

    // Create the tree.
    let root: Hp<NodeA>    = NodeA::new("Root".to_string());
    let tree: Hp<NodeTree> = NodeTree::new(root);

    // Begin operations on the tree.
    tree.start();
    tree.process();   // This will run an indefinite loop until the program exits.
}

特性

  • 🏗️一个易于抽象的框架,不同的进程可以以可扩展的方式相互通信和交互。灵感来自Godot!
  • ⏯️能够暂停和恢复NodeTree,并针对树暂停/恢复时的单个Node行为进行微调。
  • 📡 与其他节点通信的多种方法,例如 owner()parent()get_child()children()get_node()
  • 🔗 一个名为 Hp<T> 的抽象智能指针,它可以隐式克隆以减少语法噪音,并允许低样板。
  • 👪 能够通过 add_child()remove_child() 管理节点。
  • 🌲 允许通过节点的 root() 函数直接引用 NodeTree
  • 📚 TODO:在 NodeTree 上托管一个缓存系统,作为确保 Hp<T> 正确性和提高性能的安全接口!
  • 📜 TODO:包括一个保存和处理单个节点场景的方法,例如方便的视觉宏 Scene!

依赖项

~1.5MB
~36K SLoC