use bevy::prelude::*; use bevy_rapier2d::prelude::*; use serde::{Deserialize, Serialize}; use crate::{config::StkConfig, module::component::PartType, planet}; #[derive(Component, Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)] pub enum PlanetType { Earth, Moon, Mars, } #[derive(Bundle)] pub struct PlanetBundle { pub planet_type: PlanetType, pub transform: TransformBundle, } pub fn spawn_planets(mut commands: Commands) { info!("Spawning planets"); let earth_pos = Transform::from_xyz(0.0, 0.0, 0.0); commands .spawn(PlanetBundle { planet_type: PlanetType::Earth, transform: TransformBundle::from(earth_pos), }) .insert(Collider::ball(planet!(PlanetType::Earth).size)) .insert(AdditionalMassProperties::Mass( planet!(PlanetType::Earth).mass, )) .insert(ReadMassProperties::default()) .with_children(|children| { children .spawn(Collider::ball(planet!(PlanetType::Earth).size + 0.3)) .insert(ActiveEvents::COLLISION_EVENTS) .insert(Sensor); }) .insert(RigidBody::Fixed); let moon_pos = Transform::from_xyz(50.0, 20.0, 0.0); commands .spawn(PlanetBundle { planet_type: PlanetType::Moon, transform: TransformBundle::from(moon_pos), }) .insert(Collider::ball(planet!(PlanetType::Moon).size)) .insert(AdditionalMassProperties::Mass( planet!(PlanetType::Moon).mass, )) .insert(ReadMassProperties::default()) .with_children(|children| { children .spawn(Collider::ball(planet!(PlanetType::Moon).size + 0.1)) .insert(ActiveEvents::COLLISION_EVENTS) .insert(Sensor); }) .insert(RigidBody::Fixed); let mars_pos = Transform::from_xyz(-50.0, 300.0, 0.0); commands .spawn(PlanetBundle { planet_type: PlanetType::Mars, transform: TransformBundle::from(mars_pos), }) .insert(Collider::ball(planet!(PlanetType::Mars).size)) .insert(AdditionalMassProperties::Mass( planet!(PlanetType::Mars).mass, )) .insert(ReadMassProperties::default()) .with_children(|children| { children .spawn(Collider::ball(planet!(PlanetType::Mars).size + 0.1)) .insert(ActiveEvents::COLLISION_EVENTS) .insert(Sensor); }) .insert(RigidBody::Fixed); } pub fn gravity_update( mut part_query: Query< ( &Transform, &ReadMassProperties, &mut ExternalForce, &mut ExternalImpulse, ), With, >, planet_query: Query<(&Transform, &ReadMassProperties), With>, server_config: Res, ) { for (part_transform, part_mp, mut forces, mut impulses) in &mut part_query { impulses.impulse = Vec2::ZERO; forces.force = Vec2::ZERO; forces.torque = 0.; let part_mp = part_mp.get(); let part_mass = part_mp.mass; let part_translate = part_transform.translation; for (planet_transform, planet_mp) in &planet_query { let planet_mp = planet_mp.get(); let planet_mass = planet_mp.mass; let planet_translate = planet_transform.translation; let distance = planet_translate.distance(part_translate); // gravity equation let force = server_config.world.gravity * ((part_mass * planet_mass) / (distance * distance)); // gravity vector let direction = (planet_translate - part_translate).normalize() * force; // apply gravity vector as impulse to body impulses.impulse += direction.xy(); } } }