pyxel/
math.rs

1use std::f64::consts::PI;
2use std::sync::{LazyLock, Mutex};
3
4use noise::{NoiseFn, Perlin};
5use rand::{Rng, SeedableRng};
6use rand_xoshiro::Xoshiro256StarStar;
7
8use crate::pyxel::Pyxel;
9
10static RNG: LazyLock<Mutex<Xoshiro256StarStar>> = LazyLock::new(|| {
11    let seed = pyxel_platform::elapsed_time();
12    Mutex::new(Xoshiro256StarStar::seed_from_u64(seed as u64))
13});
14
15static PERLIN: LazyLock<Mutex<Perlin>> = LazyLock::new(|| {
16    let seed = pyxel_platform::elapsed_time();
17    Mutex::new(Perlin::new(seed))
18});
19
20impl Pyxel {
21    pub fn ceil(x: f64) -> i32 {
22        f64::ceil(x) as i32
23    }
24
25    pub fn floor(x: f64) -> i32 {
26        f64::floor(x) as i32
27    }
28
29    pub fn sgn(x: f64) -> i32 {
30        if x > 0.0 {
31            1
32        } else if x < 0.0 {
33            -1
34        } else {
35            0
36        }
37    }
38
39    pub fn sqrt(x: f64) -> f64 {
40        f64::sqrt(x)
41    }
42
43    pub fn sin(deg: f64) -> f64 {
44        f64::sin(deg * PI / 180.0)
45    }
46
47    pub fn cos(deg: f64) -> f64 {
48        f64::cos(deg * PI / 180.0)
49    }
50
51    pub fn atan2(y: f64, x: f64) -> f64 {
52        f64::atan2(y, x) * 180.0 / PI
53    }
54
55    pub fn rseed(seed: u32) {
56        let rng = Xoshiro256StarStar::seed_from_u64(seed as u64);
57        *RNG.lock().unwrap() = rng;
58    }
59
60    pub fn rndi(a: i32, b: i32) -> i32 {
61        let (a, b) = if a < b { (a, b) } else { (b, a) };
62        RNG.lock().unwrap().random_range(a..=b)
63    }
64
65    pub fn rndf(a: f64, b: f64) -> f64 {
66        let (a, b) = if a < b { (a, b) } else { (b, a) };
67        RNG.lock().unwrap().random_range(a..=b)
68    }
69
70    pub fn nseed(seed: u32) {
71        let perlin = Perlin::new(seed);
72        *PERLIN.lock().unwrap() = perlin;
73    }
74
75    pub fn noise(x: f64, y: f64, z: f64) -> f64 {
76        PERLIN.lock().unwrap().get([x, y, z])
77    }
78}