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}