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 {
Sun,
Mercury,
Venus,
Earth,
Moon,
Mars,
Jupiter,
Saturn,
Uranus,
Neptune,
Pluto,
}
#[derive(Bundle)]
pub struct PlanetBundle {
pub planet_type: PlanetType,
pub transform: TransformBundle,
}
pub fn spawn_planets(mut commands: Commands) {
info!("Spawning planets");
let sun_pos = Transform::from_xyz(0.0, 0.0, 0.0);
commands
.spawn(PlanetBundle {
planet_type: PlanetType::Sun,
transform: TransformBundle::from(sun_pos),
})
.insert(Collider::ball(planet!(PlanetType::Sun).size))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType::Sun).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
.spawn(Collider::ball(planet!(PlanetType::Sun).size + 0.3))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
.insert(RigidBody::Fixed);
let mercury_pos = Transform::from_xyz(2322.588, 0.0, 0.0);
commands
.spawn(PlanetBundle {
planet_type: PlanetType::Mercury,
transform: TransformBundle::from(mercury_pos),
})
.insert(Collider::ball(planet!(PlanetType::Mercury).size))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType::Mercury).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
.spawn(Collider::ball(planet!(PlanetType::Mercury).size + 0.3))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
.insert(RigidBody::Fixed);
let venus_pos = Transform::from_xyz(4339.992, 0.0, 0.0);
commands
.spawn(PlanetBundle {
planet_type: PlanetType::Venus,
transform: TransformBundle::from(venus_pos),
})
.insert(Collider::ball(planet!(PlanetType::Venus).size))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType::Venus).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
.spawn(Collider::ball(planet!(PlanetType::Venus).size + 0.3))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
.insert(RigidBody::Fixed);
let earth_pos = Transform::from_xyz(6000.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(6030.828, 0.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(9142.0833, 0.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);
let jupiter_pos = Transform::from_xyz(31222.8, 0.0, 0.0);
commands
.spawn(PlanetBundle {
planet_type: PlanetType::Jupiter,
transform: TransformBundle::from(jupiter_pos),
})
.insert(Collider::ball(planet!(PlanetType::Jupiter).size))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType::Jupiter).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
.spawn(Collider::ball(planet!(PlanetType::Jupiter).size + 0.1))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
.insert(RigidBody::Fixed);
let saturn_pos = Transform::from_xyz(57495.6, 0.0, 0.0);
commands
.spawn(PlanetBundle {
planet_type: PlanetType::Saturn,
transform: TransformBundle::from(saturn_pos),
})
.insert(Collider::ball(planet!(PlanetType::Saturn).size))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType::Saturn).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
.spawn(Collider::ball(planet!(PlanetType::Saturn).size + 0.1))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
.insert(RigidBody::Fixed);
let uranus_pos = Transform::from_xyz(115147.56, 0.0, 0.0);
commands
.spawn(PlanetBundle {
planet_type: PlanetType::Uranus,
transform: TransformBundle::from(uranus_pos),
})
.insert(Collider::ball(planet!(PlanetType::Uranus).size))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType::Uranus).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
.spawn(Collider::ball(planet!(PlanetType::Uranus).size + 0.1))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
.insert(RigidBody::Fixed);
let neptune_pos = Transform::from_xyz(180420.0, 0.0, 0.0);
commands
.spawn(PlanetBundle {
planet_type: PlanetType::Neptune,
transform: TransformBundle::from(neptune_pos),
})
.insert(Collider::ball(planet!(PlanetType::Neptune).size))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType::Neptune).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
.spawn(Collider::ball(planet!(PlanetType::Neptune).size + 0.1))
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(Sensor);
})
.insert(RigidBody::Fixed);
let pluto_pos = Transform::from_xyz(236892.0, 0.0, 0.0);
commands
.spawn(PlanetBundle {
planet_type: PlanetType::Pluto,
transform: TransformBundle::from(pluto_pos),
})
.insert(Collider::ball(planet!(PlanetType::Pluto).size))
.insert(AdditionalMassProperties::Mass(
planet!(PlanetType::Pluto).mass,
))
.insert(ReadMassProperties::default())
.with_children(|children| {
children
.spawn(Collider::ball(planet!(PlanetType::Pluto).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 {
forces.force = Vec2::ZERO;
impulses.impulse = 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
forces.force += direction.xy();
//impulses.impulse += direction.xy();
}
}
}