~starkingdoms/starkingdoms

ref: 6e23340819969670c3897611192b04cd7c479168 starkingdoms/server/src/planet.rs -rw-r--r-- 4.2 KiB
6e233408 — c0repwn3r orbits 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::collections::HashMap;
use nalgebra::{Vector2, vector};
use rapier2d_f64::prelude::{RigidBodyHandle, RigidBodySet, ColliderBuilder, RigidBodyBuilder, ColliderSet};
use starkingdoms_protocol::planet::PlanetType;

use crate::{SCALE, manager::ClientHandlerMessage};
use crate::orbit::constants::{EARTH_MASS, EARTH_RADIUS, MOON_APOAPSIS, MOON_MASS, MOON_PERIAPSIS, MOON_RADIUS};
use crate::orbit::orbit::{calculate_point_on_orbit, calculate_world_position_of_orbit};

//const GRAVITY: f64 = 0.001;
pub const GRAVITY: f64 = 12.6674;

#[derive(Clone)]
pub struct Planet {
    pub planet_type: PlanetType,
    pub body_handle: RigidBodyHandle,
    pub position: (f64, f64),
    pub radius: f64,
    pub mass: f64
}

impl Planet {
    pub fn gravity(&self, position: (f64, f64), mass: f64) -> (f64, f64) {
        let distance = ((position.0 - self.position.0).powi(2) + (position.1 - self.position.1).powi(2)).sqrt();
        let force = GRAVITY * ((self.mass * mass) / (distance * distance));
        let mut direction = Vector2::new(self.position.0 - position.0, self.position.1 - position.1);
        direction.set_magnitude(force);
        (direction.x, direction.y)
    }
}

#[derive(Default, Clone)]
pub struct Planets {
    pub planets: HashMap<String, Planet>,
}

impl Planets {
    pub fn get_planet(&self, planet_id: &str) -> Option<&Planet> {
        self.planets.get(planet_id)
    }

    pub fn get_planet_mut(&mut self, planet_id: &str) -> Option<&mut Planet> {
        self.planets.get_mut(planet_id)
    }

    pub fn make_planet(planets: &mut HashMap<String, Planet>, planet_id: &str, planet_type: PlanetType, mass: f64, radius: f64, position: (f64, f64), rigid_body_set: &mut RigidBodySet, collider_set: &mut ColliderSet) {
        let collider = ColliderBuilder::ball(radius / SCALE)
            .build();
        let body = RigidBodyBuilder::kinematic_position_based()
            .translation(vector![position.0 / SCALE, position.1 / SCALE])
            .dominance_group(127)
            .additional_mass(0.0);
        let body_handle = rigid_body_set.insert(body);

        collider_set.insert_with_parent(collider, body_handle, rigid_body_set);

        planets.insert(planet_id.to_string(), Planet {
            planet_type,
            body_handle,
            position,
            radius,
            mass,
        });
    }

    pub fn new(rigid_body_set: &mut RigidBodySet, collider_set: &mut ColliderSet) -> Planets {
        let mut planets = HashMap::new();
        
        Planets::make_planet(
            &mut planets,
            "earth",
            PlanetType::Earth,
            EARTH_MASS,
            EARTH_RADIUS,
            (100.0, 100.0),
            rigid_body_set,
            collider_set,
        );

        let moon_start_point = calculate_world_position_of_orbit(calculate_point_on_orbit(MOON_PERIAPSIS, MOON_APOAPSIS, 0.0), vector![planets.get("earth").unwrap().position.0, planets.get("earth").unwrap().position.1]);

        Planets::make_planet(
            &mut planets,
            "moon",
            PlanetType::Moon,
            MOON_MASS,
            MOON_RADIUS,
            (moon_start_point[0], moon_start_point[1]),
            rigid_body_set,
            collider_set
        );

        Planets { planets }
    }

    pub fn to_protocol(&self) -> ClientHandlerMessage {
        let mut planets = vec![];

        for (_, planet) in self.planets.clone() {
            // TODO: Adjust codegen to use f64
            planets.push(starkingdoms_protocol::planet::Planet {
                planet_type: planet.planet_type.into(),
                x: (planet.position.0 * SCALE) as f32,
                y: (planet.position.1 * SCALE) as f32,
                radius: planet.radius as f32, // DO NOT * SCALE
                special_fields: Default::default(),
            });
        }

        ClientHandlerMessage::PlanetData {
            planets
        }
    }

    pub fn gravity(&self, position: (f64, f64), mass: f64) -> (f64, f64) {
        let mut direction = Vector2::zeros();
        for (_, planet) in self.planets.clone() {
            let planet_grav = planet.gravity(position, mass);
            direction.x += planet_grav.0;
            direction.y += planet_grav.1;
        }
        (direction.x, direction.y)
    }
}