2个版本
0.5.9 | 2024年6月20日 |
---|---|
0.5.8 | 2024年4月27日 |
0.4.0 |
|
0.3.1 |
|
0.1.0 |
|
#383 在 游戏开发
每月 62 次下载
1MB
7K SLoC
包含 (Windows DLL, 1MB) tester/Bin/gdnative_tweener.dll
gdnative_tweener是..
- Godot 3.5内置的tween/lerp对象的替代品: Tween | SceneTreeTween
- 灵感来自Unity包 DoTween
警告!
- 此包尚未经过彻底测试,可能包含破坏游戏的错误。尽管如此,我每天都在所有项目中使用它,并承诺尽快修复任何报告的错误,至少到2025年7月。
- 此包大部分没有文档,这个readme就是所有内容,并且由于作者是唯一已知的用户,它可能仍然保持如此。但接受添加文档的PR。
- 此包需要Rust nightly版本,并使用如autotraits和negative impls等不稳定功能。
摘要
用法
当使用Godot的内置 SceneTreeTween
时,节点颜色缓动需要执行以下操作
fn tween_color(owner: Ref<Node2D>, color: Color, duration: f64) -> Result<SceneTreeTween> {
let owner_tref = unsafe {
owner.assume_safe_if_sane()
.ok_or_else(|| Error("Owner is not sane, cannot create tween."))?
};
let tween =
owner_tref.create_tween()
.ok_or_else(|| Error("Could not create tween."))?;
let tween_tref = unsafe {
tween.assume_safe()
};
tween_tref.tween_property(owner, "modulate", color, duration);
return tween;
}
这相当多的样板代码,你可能经常这样做,具体取决于你的游戏中有多少动画。此库的目的是以更直观的方式实现相同的功能。以下是使用 gdnative_tweener
缓动节点颜色的方法
use gdnative_tweener::prelude::*;
fn tween_ref_wrapper_color(owner: Ref<Node2D>, color: Color, duration: f64) -> Result<TweenID<TweenProperty_Color>> {
owner.do_color(color, duration)
.register()
}
// `do_color` is implemented on any of &T|Ref<T>|TRef<T>, where T: SubClass<CanvasItem>, this is because CanvasItem is the class that defines the property `modulate`, which `do_color` acts on.
fn tween_any_subclass_of_canvas_item(ref_sprite: Ref<Sprite>, tref_tilemap: TRef<TileMap>, control: &Control) -> Result<()> {
let color = Color::from_rgb(0.8, 0.0, 0.8); // purple :3
let duration = 0.69;
let tween_id_of_ref = ref_sprite.do_color(color, duration).register()?;
let tween_id_of_tref = tref_tilemap.do_color(color, duration).register()?;
let tween_id = control.do_color(color, duration).register()?;
Ok(())
}
请注意,与DoTween不同,我们需要在最后调用register()。代码register()
尝试访问TweensController自动加载,将其插入到内部列表中。它还返回一个Result<TweenID>,您可以使用它来稍后访问缓动,检查缓动是否存活,其状态等。如果自动加载不可访问(这可能发生在它不存在或已经被别处借用的情况下),则操作将失败。
gdnative_tweener
提供了多种方法来配置您缓动的行为,尽管没有文档说明,但名称相当直观,类似于DoTween
。您应该在注册缓动之前进行所有配置,注册后修改缓动可能会影响性能,因为这需要获取TweensController自动加载的锁。我不建议在主线程之外尝试注册/访问缓动。
以下是一些示例
let owner: Ref<Node2D> = ..;
let mut tween = owner.do_move_x(2000.0, 5.0);
// To mimic TweenProperty::as_relative()
let origin = 0.0; // since relative tweens don't have a starting point, the origin parameter is necessary for the tween to compare how much it needs to move between each frame
tween = tween.as_relative(origin);
// To mimic TweenProperty::from_current(), no need to do anything, that's the default behavior,
// instead, if you want to set a specific starting point:
tween = tween.starting_at(500.0);
// To mimic TweenProperty::set_delay(f64);
tween = tween.with_delay(10.0);
// SpeedBased is also implemented:
let speed = 100.0; // Speed is always in units per second, 100. speed means position:x increases by 100 each second.
tween = tween.as_speed_based(speed);
您可以将所有这些方法链接起来
let tween_id =
node.do_global_position(Vector2::new(1920., 1080.), 5.0)
.with_delay(10.0)
.starting_at(Vector2::new(0., 0.))
.looped(10)
.when_finished(node, "print", vec!["Tween finished!".to_variant()])
.register()?;
属性缓动只是DoProperty特质的包装。代码do_property
自动将节点绑定到缓动,就像Node::create_tween一样,这意味着当节点被删除时,缓动将自动“死亡”。
DoProperty使用call_deferred("set_indexed")
,因此属性路径也是有效的
// Tween only the Z position
let tween = owner.do_property("position:z", 20., 10.);
DoProperty接受泛型值,只要它们实现了_Lerp + FromVariant + ToVariant
let my_custom_property = "..";
let my_custom_end_val = CustomStruct {..};
let duration = 5.0;
// the only difference is that the method is called do_property_var()
let tween = owner.do_property_var(my_custom_property, my_custom_end_val, duration);
您还可以缓动方法
// Imagine you have a method like this...
#[method]
fn _set_fill(&self, #[base] owner: &Range, value: f64) {
owner.set_value(value);
}
// You can tween it like this
let start = 0.;
let end = 1.;
let duration = 8.;
let tween = owner.do_method("_set_fill", start, end, duration);
如果您只需要在延迟后调用一次方法,您可以使用
#[method]
fn _start_game(&mut self, player_name: String, difficulty: Difficulty) {
...
}
let player_name = "Houtamelo";
let difficulty = Difficulty::GameDeveloper;
let delay = 24.;
let tween = owner.do_callback("_start_game", vec![player_name.to_variant(), difficulty.to_variant()], delay);
永远不要忘记注册您的缓动!否则它们将被丢弃
let id = tween.register()?;
我们还有序列,它们的工作方式与DoTween非常相似
let mut sequence = Sequence::new();
sequence.append(owner.do_move_x(640.0, 5.0));
sequence.join(owner.do_fade(1.0, 4.0));
sequence.append(owner.do_global_move(Vector2::new(124., 256.));
sequence.insert(8.0, owner.do_scale(Vector2::new(10., 10.));
let id = sequence.register()?;
需要终止一个缓动吗?
let id: TweenID<TweenCallback> = ..;
id.kill();
// Same for sequences
let sequence_id: SequenceID = ..;
sequence_id.kill();
需要立即完成一个缓动吗?
tween_id.complete();
sequence_id.complete();
了解...
gdnative_tweener
以任何方式与Godot的内置缓动交互,它是一个独立的NativeScript,在它的_process(f64)
和_physics_process(f64)
虚拟方法中处理已注册的缓动。- 缓动执行的每个交互都是以“延迟”方式完成的...(“set_property_deferred”,“call_deferred”)
设置
设置过程假设您已经熟悉GDNative的工作方式。
第1步
将gdnative_tweener
添加到您的项目依赖项中:运行cargo add gdnative_tweener
或将以下行添加到您的Cargo.toml中:gdnative_tweener = "0.3"
您很可能会想使用最新版本,因为它将包含最新的错误修复。
第2步
在您的库的初始化(在gdnative模板中:rust/src/lib.rs
)中注册TweenController
类
fn init(handle: InitHandle) {
handle.add_class::<gdnative_tweener::prelude::TweensController>();
}
第3步
在您的 Godot 项目中,为 TweensController
类创建一个 NativeScript
:![图片](https://img.gs/czjpqfbdkz/full/https://github.com/Houtamelo/gdnative_tweener/assets/88971943/da0f6b81-c76f-4b75-b56d-4059a2d8246a "图片" width="504" height="431")
步骤 4
将 TweensController
类添加到项目的自动加载中,节点命名为 "tweens_controller":![图片](https://img.gs/czjpqfbdkz/full/https://github.com/Houtamelo/gdnative_tweener/assets/88971943/83bd22ef-fe9a-4380-a738-a958f0492a5b "图片" width="800" height="135")
警告:节点名称必须是 "tweens_controller",否则在尝试注册缓动时将收到错误。
帮助
在 GitHub 上创建一个问题或向我发送 Discord 消息:houtamelo
依赖关系
~13–21MB
~321K SLoC