Skip to content

Commit 1af96e8

Browse files
committed
dodge-the-creeps: use native Rust signals for timers
1 parent 95bb3e5 commit 1af96e8

File tree

3 files changed

+49
-19
lines changed

3 files changed

+49
-19
lines changed

dodge-the-creeps/godot/Main.tscn

-2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,4 @@ stream = ExtResource("5")
4848
[node name="DeathSound" type="AudioStreamPlayer" parent="."]
4949
stream = ExtResource("6")
5050

51-
[connection signal="timeout" from="MobTimer" to="." method="on_mob_timer_timeout"]
52-
[connection signal="timeout" from="ScoreTimer" to="." method="on_score_timer_timeout"]
5351
[connection signal="timeout" from="StartTimer" to="." method="on_start_timer_timeout"]

dodge-the-creeps/rust/src/main_scene.rs

+42-15
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,35 @@ impl INode for Main {
5353
.signals()
5454
.start_game()
5555
.connect_obj(&main, Self::new_game);
56+
57+
// Connect Main.ScoreTimer::timeout -> Main::on_score_timer_timeout.
58+
self.score_timer()
59+
.signals()
60+
.timeout()
61+
.connect_obj(&main, Self::on_score_timer_timeout);
62+
63+
// Connect Main.MobTimer::timeout -> Main::on_mob_timer_timeout.
64+
self.mob_timer()
65+
.signals()
66+
.timeout()
67+
.connect_obj(&main, Self::on_mob_timer_timeout);
68+
69+
// Main.StartTimer::timeout -> Main::on_start_timer_timeout is set up in the Editor's Inspector UI, but could be done here as well,
70+
// as follows. Note that signal handlers connected via Rust do not need a #[func] annotation, they can remain entirely visible to Godot.
71+
//
72+
// self.start_timer()
73+
// .signals()
74+
// .timeout()
75+
// .connect_obj(&main, Self::on_start_timer_timeout);
5676
}
5777
}
5878

5979
#[godot_api]
6080
impl Main {
6181
// No #[func] here, this method is directly called from Rust (via type-safe signals).
6282
fn game_over(&mut self) {
63-
let mut score_timer = self.base().get_node_as::<Timer>("ScoreTimer");
64-
let mut mob_timer = self.base().get_node_as::<Timer>("MobTimer");
65-
66-
score_timer.stop();
67-
mob_timer.stop();
83+
self.score_timer().stop();
84+
self.mob_timer().stop();
6885

6986
self.hud.bind_mut().show_game_over();
7087

@@ -75,12 +92,11 @@ impl Main {
7592
// No #[func].
7693
pub fn new_game(&mut self) {
7794
let start_position = self.base().get_node_as::<Marker2D>("StartPosition");
78-
let mut start_timer = self.base().get_node_as::<Timer>("StartTimer");
7995

8096
self.score = 0;
8197

8298
self.player.bind_mut().start(start_position.get_position());
83-
start_timer.start();
99+
self.start_timer().start();
84100

85101
let hud = self.hud.bind_mut();
86102
hud.update_score(self.score);
@@ -89,22 +105,20 @@ impl Main {
89105
self.music.play();
90106
}
91107

92-
#[func]
93-
fn on_start_timer_timeout(&self) {
94-
let mut mob_timer = self.base().get_node_as::<Timer>("MobTimer");
95-
let mut score_timer = self.base().get_node_as::<Timer>("ScoreTimer");
96-
mob_timer.start();
97-
score_timer.start();
108+
#[func] // needed because connected in Editor UI (see ready).
109+
fn on_start_timer_timeout(&mut self) {
110+
self.mob_timer().start();
111+
self.score_timer().start();
98112
}
99113

100-
#[func]
114+
// No #[func], connected in pure Rust.
101115
fn on_score_timer_timeout(&mut self) {
102116
self.score += 1;
103117

104118
self.hud.bind_mut().update_score(self.score);
105119
}
106120

107-
#[func]
121+
// No #[func], connected in pure Rust.
108122
fn on_mob_timer_timeout(&mut self) {
109123
let mut mob_spawn_location = self
110124
.base()
@@ -134,4 +148,17 @@ impl Main {
134148

135149
mob.set_linear_velocity(Vector2::new(range, 0.0).rotated(real::from_f32(direction)));
136150
}
151+
152+
// These timers could also be stored as OnReady fields, but are now fetched via function for demonstration purposes.
153+
fn start_timer(&self) -> Gd<Timer> {
154+
self.base().get_node_as::<Timer>("StartTimer")
155+
}
156+
157+
fn score_timer(&self) -> Gd<Timer> {
158+
self.base().get_node_as::<Timer>("ScoreTimer")
159+
}
160+
161+
fn mob_timer(&self) -> Gd<Timer> {
162+
self.base().get_node_as::<Timer>("MobTimer")
163+
}
137164
}

dodge-the-creeps/rust/src/player.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use godot::classes::{AnimatedSprite2D, Area2D, CollisionShape2D, IArea2D, Input, PhysicsBody2D};
1+
use godot::classes::{AnimatedSprite2D, Area2D, CollisionShape2D, IArea2D, Input};
22
use godot::prelude::*;
33

44
#[derive(GodotClass)]
@@ -17,7 +17,7 @@ impl Player {
1717
pub fn hit();
1818

1919
#[func]
20-
fn on_player_body_entered(&mut self, _body: Gd<PhysicsBody2D>) {
20+
fn on_player_body_entered(&mut self, _body: Gd<Node2D>) {
2121
self.base_mut().hide();
2222
self.signals().hit().emit();
2323

@@ -55,6 +55,11 @@ impl IArea2D for Player {
5555
let viewport = self.base().get_viewport_rect();
5656
self.screen_size = viewport.size;
5757
self.base_mut().hide();
58+
59+
// Signal setup
60+
self.signals()
61+
.body_entered()
62+
.connect_self(Self::on_player_body_entered);
5863
}
5964

6065
// `delta` can be f32 or f64; #[godot_api] macro converts transparently.

0 commit comments

Comments
 (0)