pyxel-engine 2.6.8

Core engine for Pyxel, a retro game engine for Python
use std::f32::consts::PI;
use std::sync::{LazyLock, Mutex};

use noise::{NoiseFn, Perlin};
use rand::{RngExt, SeedableRng};
use rand_xoshiro::Xoshiro256StarStar;

use crate::pyxel::Pyxel;

static RNG: LazyLock<Mutex<Xoshiro256StarStar>> = LazyLock::new(|| {
    let mut rng = rand::rng();
    Mutex::new(Xoshiro256StarStar::from_rng(&mut rng))
});

static PERLIN: LazyLock<Mutex<Perlin>> =
    LazyLock::new(|| Mutex::new(Perlin::new(rand::rng().random())));

impl Pyxel {
    pub fn ceil(x: f32) -> i32 {
        f32::ceil(x) as i32
    }

    pub fn floor(x: f32) -> i32 {
        f32::floor(x) as i32
    }

    pub fn sqrt(x: f32) -> f32 {
        f32::sqrt(x)
    }

    pub fn sin(deg: f32) -> f32 {
        f32::sin(deg * PI / 180.0)
    }

    pub fn cos(deg: f32) -> f32 {
        f32::cos(deg * PI / 180.0)
    }

    pub fn atan2(y: f32, x: f32) -> f32 {
        f32::atan2(y, x) * 180.0 / PI
    }

    pub fn rseed(seed: u32) {
        let rng = Xoshiro256StarStar::seed_from_u64(seed as u64);
        *RNG.lock().unwrap() = rng;
    }

    pub fn rndi(a: i32, b: i32) -> i32 {
        let (min, max) = if a < b { (a, b) } else { (b, a) };
        RNG.lock().unwrap().random_range(min..=max)
    }

    pub fn rndf(a: f32, b: f32) -> f32 {
        let (min, max) = if a < b { (a, b) } else { (b, a) };
        RNG.lock().unwrap().random_range(min..=max)
    }

    pub fn nseed(seed: u32) {
        let perlin = Perlin::new(seed);
        *PERLIN.lock().unwrap() = perlin;
    }

    pub fn noise(x: f32, y: f32, z: f32) -> f32 {
        PERLIN.lock().unwrap().get([x as f64, y as f64, z as f64]) as f32
    }
}