diff --git a/dodge-the-creeps/godot/Main.tscn b/dodge-the-creeps/godot/Main.tscn index e17eb7a..f551d73 100644 --- a/dodge-the-creeps/godot/Main.tscn +++ b/dodge-the-creeps/godot/Main.tscn @@ -48,6 +48,4 @@ stream = ExtResource("5") [node name="DeathSound" type="AudioStreamPlayer" parent="."] stream = ExtResource("6") -[connection signal="timeout" from="MobTimer" to="." method="on_mob_timer_timeout"] -[connection signal="timeout" from="ScoreTimer" to="." method="on_score_timer_timeout"] [connection signal="timeout" from="StartTimer" to="." method="on_start_timer_timeout"] diff --git a/dodge-the-creeps/rust/src/main_scene.rs b/dodge-the-creeps/rust/src/main_scene.rs index 2f73177..e88455e 100644 --- a/dodge-the-creeps/rust/src/main_scene.rs +++ b/dodge-the-creeps/rust/src/main_scene.rs @@ -53,6 +53,26 @@ impl INode for Main { .signals() .start_game() .connect_obj(&main, Self::new_game); + + // Connect Main.ScoreTimer::timeout -> Main::on_score_timer_timeout. + self.score_timer() + .signals() + .timeout() + .connect_obj(&main, Self::on_score_timer_timeout); + + // Connect Main.MobTimer::timeout -> Main::on_mob_timer_timeout. + self.mob_timer() + .signals() + .timeout() + .connect_obj(&main, Self::on_mob_timer_timeout); + + // Main.StartTimer::timeout -> Main::on_start_timer_timeout is set up in the Editor's Inspector UI, but could be done here as well, + // as follows. Note that signal handlers connected via Rust do not need a #[func] annotation, they can remain entirely visible to Godot. + // + // self.start_timer() + // .signals() + // .timeout() + // .connect_obj(&main, Self::on_start_timer_timeout); } } @@ -60,11 +80,8 @@ impl INode for Main { impl Main { // No #[func] here, this method is directly called from Rust (via type-safe signals). fn game_over(&mut self) { - let mut score_timer = self.base().get_node_as::("ScoreTimer"); - let mut mob_timer = self.base().get_node_as::("MobTimer"); - - score_timer.stop(); - mob_timer.stop(); + self.score_timer().stop(); + self.mob_timer().stop(); self.hud.bind_mut().show_game_over(); @@ -75,12 +92,11 @@ impl Main { // No #[func]. pub fn new_game(&mut self) { let start_position = self.base().get_node_as::("StartPosition"); - let mut start_timer = self.base().get_node_as::("StartTimer"); self.score = 0; self.player.bind_mut().start(start_position.get_position()); - start_timer.start(); + self.start_timer().start(); let hud = self.hud.bind_mut(); hud.update_score(self.score); @@ -89,22 +105,20 @@ impl Main { self.music.play(); } - #[func] - fn on_start_timer_timeout(&self) { - let mut mob_timer = self.base().get_node_as::("MobTimer"); - let mut score_timer = self.base().get_node_as::("ScoreTimer"); - mob_timer.start(); - score_timer.start(); + #[func] // needed because connected in Editor UI (see ready). + fn on_start_timer_timeout(&mut self) { + self.mob_timer().start(); + self.score_timer().start(); } - #[func] + // No #[func], connected in pure Rust. fn on_score_timer_timeout(&mut self) { self.score += 1; self.hud.bind_mut().update_score(self.score); } - #[func] + // No #[func], connected in pure Rust. fn on_mob_timer_timeout(&mut self) { let mut mob_spawn_location = self .base() @@ -134,4 +148,17 @@ impl Main { mob.set_linear_velocity(Vector2::new(range, 0.0).rotated(real::from_f32(direction))); } + + // These timers could also be stored as OnReady fields, but are now fetched via function for demonstration purposes. + fn start_timer(&self) -> Gd { + self.base().get_node_as::("StartTimer") + } + + fn score_timer(&self) -> Gd { + self.base().get_node_as::("ScoreTimer") + } + + fn mob_timer(&self) -> Gd { + self.base().get_node_as::("MobTimer") + } } diff --git a/dodge-the-creeps/rust/src/player.rs b/dodge-the-creeps/rust/src/player.rs index a7c7232..c5e3949 100644 --- a/dodge-the-creeps/rust/src/player.rs +++ b/dodge-the-creeps/rust/src/player.rs @@ -1,4 +1,4 @@ -use godot::classes::{AnimatedSprite2D, Area2D, CollisionShape2D, IArea2D, Input, PhysicsBody2D}; +use godot::classes::{AnimatedSprite2D, Area2D, CollisionShape2D, IArea2D, Input}; use godot::prelude::*; #[derive(GodotClass)] @@ -17,7 +17,7 @@ impl Player { pub fn hit(); #[func] - fn on_player_body_entered(&mut self, _body: Gd) { + fn on_player_body_entered(&mut self, _body: Gd) { self.base_mut().hide(); self.signals().hit().emit(); @@ -55,6 +55,11 @@ impl IArea2D for Player { let viewport = self.base().get_viewport_rect(); self.screen_size = viewport.size; self.base_mut().hide(); + + // Signal setup + self.signals() + .body_entered() + .connect_self(Self::on_player_body_entered); } // `delta` can be f32 or f64; #[godot_api] macro converts transparently.