From aaec4f3c3fa5a0895fce09a2dfb39054d1de212a Mon Sep 17 00:00:00 2001 From: Mike Hsu Date: Sun, 3 Mar 2024 22:04:58 -0800 Subject: [PATCH] make generic system param example more realistic --- examples/ecs/generic_system.rs | 95 ++++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 26 deletions(-) diff --git a/examples/ecs/generic_system.rs b/examples/ecs/generic_system.rs index f55bc440ce..783b8d57d9 100644 --- a/examples/ecs/generic_system.rs +++ b/examples/ecs/generic_system.rs @@ -11,7 +11,6 @@ use bevy::prelude::*; use system_param_in_associated_type::*; -use system_with_generic_system_param::*; #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, States)] enum AppState { @@ -42,8 +41,6 @@ fn main() { ( print_text_system, transition_to_in_game_system.run_if(in_state(AppState::MainMenu)), - system_with_generic::>, - system_with_generic::>, system::, ), ) @@ -67,8 +64,6 @@ fn setup_system(mut commands: Commands) { LevelUnload, )); - commands.insert_resource(ResourceA(1)); - commands.insert_resource(ResourceB(2)); commands.insert_resource(ResourceC { data: 3 }); } @@ -97,42 +92,90 @@ fn cleanup_system(mut commands: Commands, query: Query { - fn calculate_something(&mut self) { - // dbg!(self.0); - self.0 = 5; + struct DamagePlugin; + impl Plugin for DamagePlugin { + fn build(&self, app: &mut App) { + app.add_systems(Startup, setup_damage).add_systems( + Update, + ( + apply_damage::, + apply_damage::, + ), + ); } } + #[derive(Component)] + struct Player; + + #[derive(Component)] + struct Enemy; + + #[derive(Component)] + struct Health(f32); + #[derive(Resource)] - pub struct ResourceB(pub usize); - impl MyTrait for ResMut<'_, ResourceB> { - fn calculate_something(&mut self) { - // dbg!(self.0); - self.0 = 10; + struct EnemySettings { + /// damage done by player to enemy + take_damage: f32, + /// damage done by enemy to player + do_damage: f32, + } + + pub trait GetDamage { + fn apply_damage(&mut self) {} + } + + #[derive(SystemParam)] + struct PlayerDamageParams<'w, 's> { + player: Query<'w, 's, &'static mut Health, With>, + enemy_settings: Res<'w, EnemySettings>, + } + impl<'w, 's> GetDamage for PlayerDamageParams<'w, 's> { + fn apply_damage(&mut self) { + let mut player_health = self.player.single_mut(); + player_health.0 += self.enemy_settings.do_damage; } } - pub fn system_with_generic(mut param: SystemParamItem) + #[derive(SystemParam)] + struct EnemyDamageParams<'w, 's> { + enemies: Query<'w, 's, &'static mut Health, With>, + enemy_settings: Res<'w, EnemySettings>, + } + impl<'w, 's> GetDamage for EnemyDamageParams<'w, 's> { + fn apply_damage(&mut self) { + for mut enemy_health in self.enemies.iter_mut() { + enemy_health.0 -= self.enemy_settings.take_damage; + } + } + } + + // Note that the param passed into a system is `SystemParam::Item` and not just `SystemParam`. + fn apply_damage(mut param: S::Item<'_, '_>) where - for<'w, 's> S::Item<'w, 's>: MyTrait, + for<'w, 's> S::Item<'w, 's>: GetDamage, { - param.calculate_something(); + param.apply_damage(); + } + + fn setup_damage(mut commands: Commands) { + commands.insert_resource(EnemySettings { + do_damage: 1.0, + take_damage: 2.0, + }); } } -// TODO: change this to be assets? +// TODO: change this to use assets? +// You may want to be have the SystemParam be specified in an associated type. mod system_param_in_associated_type { use super::*; use bevy::ecs::system::{lifetimeless::SRes, StaticSystemParam, SystemParam, SystemParamItem};