bevy_mod_orbits/
lib.rs

1mod math;
2
3use bevy::prelude::*;
4
5pub mod prelude {
6    pub use super::{Mass, Orbit, OrbitPlugin};
7}
8
9pub struct OrbitPlugin;
10
11impl Plugin for OrbitPlugin {
12    fn build(&self, app: &mut App) {
13        app.add_system_to_stage(
14            CoreStage::PostUpdate,
15            calculate_orbits.before(bevy::transform::transform_propagate_system),
16        );
17    }
18}
19
20#[derive(Component)]
21pub struct Orbit {
22    pub semi_major_axis: f32,
23    pub eccentricity: f32,
24    pub argument_of_periapsis: f32,
25    pub initial_mean_anomaly: f32,
26}
27
28#[derive(Component)]
29pub struct Mass {
30    pub mass: f32,
31}
32
33pub fn calculate_orbits(
34    time: Res<Time>,
35    masses: Query<&Mass>,
36    mut orbits: Query<(&Orbit, &mut Transform, Option<&Parent>)>,
37) {
38    for (orbit, mut transform, maybe_parent) in orbits.iter_mut() {
39        if orbit.semi_major_axis == 0.0 {
40            transform.translation = Vec3::ZERO;
41            continue;
42        }
43
44        let Some(parent) = maybe_parent else {
45            transform.translation = Vec3::ZERO;
46            continue;
47        };
48
49        let Some(parent_mass) = masses.get_component::<Mass>(parent.get()).ok() else {
50            warn!("Parent entity {parent:?} is missing Mass component");
51            continue;
52        };
53
54        let pos = math::calculate_position_at_time(
55            orbit.semi_major_axis,
56            orbit.eccentricity,
57            orbit.argument_of_periapsis,
58            orbit.initial_mean_anomaly,
59            parent_mass.mass,
60            time.elapsed_seconds(),
61        );
62        transform.translation = Vec3::from(pos);
63    }
64}