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<PartType>,
>,
planet_query: Query<(&Transform, &ReadMassProperties), With<PlanetType>>,
server_config: Res<StkConfig>,
) {
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();
}
}
}