cyclone2d 0.1.2

A small 2D physics engine from 'Game Physics Engine Development'
Documentation
#![allow(clippy::new_without_default)]

pub use vek2d;
pub mod contact_generators;
mod contact_resolver;
pub mod force_generators;
mod force_registry;
pub mod particle;
pub mod world;

#[cfg(not(feature = "high_precision"))]
use std::f32::MAX as F32_MAX;
#[cfg(feature = "high_precision")]
use std::f64::MAX as F64_MAX;

#[cfg(not(feature = "high_precision"))]
pub type FP = f32;
#[cfg(not(feature = "high_precision"))]
pub const FP_MAX: f32 = F32_MAX;

#[cfg(feature = "high_precision")]
pub type FP = f64;
#[cfg(feature = "high_precision")]
pub const FP_MAX: f64 = F64_MAX;

#[cfg(test)]
mod tests {
    use crate::contact_generators::GroundContact;
    use crate::force_generators::{AnchoredSpring, Drag, Gravity};
    use crate::particle::Particle;
    use crate::vek2d::Vec2d;
    use crate::world::World;

    #[test]
    fn setup() {
        // max_contacts, iterations
        let mut world = World::new(100, 1000, None);

        let mut particle = Particle::new(1.0, 0.3);
        particle.set_position(Vec2d::new(1.0, 100.0));
        let pid1 = world.add_particle(particle).unwrap();
        let ptr1 = world.get_particle_ptr(pid1).unwrap();

        let mut particle = Particle::new(1.0, 0.3);
        particle.set_position(Vec2d::new(1.0, 100.0));
        let pid2 = world.add_particle(particle).unwrap();
        let ptr2 = world.get_particle_ptr(pid2).unwrap();

        let mut particle = Particle::new(1.0, 0.2);
        particle.set_position(Vec2d::new(1.0, 100.0));
        let pid3 = world.add_particle(particle).unwrap();
        let ptr3 = world.get_particle_ptr(pid3).unwrap();

        // Insert force gen
        world.add_force_generator(Gravity::new(ptr1, -9.81));
        world.add_force_generator(Drag::new(ptr1, 1.0, 1.0));

        world.add_force_generator(Gravity::new(ptr2, -9.81));
        world.add_force_generator(Drag::new(ptr2, 1.0, 1.0));

        world.add_force_generator(Gravity::new(ptr3, -9.81));
        world.add_force_generator(Drag::new(ptr3, 1.0, 1.0));

        // Insert contact gen
        world.add_contact_generator(GroundContact::new());

        // RUN
        for _ in 0..10000 {
            world.start_frame();
            world.run_physics(0.01);
        }

        //assert_eq!(bodies[&0].position, bodies[&1].position);
        assert_ne!(
            world.get_particle_position(pid2).unwrap(),
            world.get_particle_position(pid3).unwrap()
        );
        let floor = world.get_particle_position(pid1).unwrap().y().floor();
        assert!(floor >= 0.0 && floor < f64::EPSILON);
    }

    #[test]
    fn test_springs() {
        // max_contacts, iterations
        let mut world = World::new(100, 1000, None);

        let mut particle = Particle::new(1.0, 0.3);
        particle.set_position(Vec2d::new(2.0, 1000.0));
        let pid1 = world.add_particle(particle).unwrap();
        let ptr1 = world.get_particle_ptr(pid1).unwrap();

        // Insert force gen
        world.add_force_generator(AnchoredSpring::new(
            ptr1,
            Vec2d::new(2.0, 100.0),
            1.0,
            100.0,
        ));

        // RUN
        for _ in 0..500 {
            world.start_frame();
            world.run_physics(0.1);
        }

        assert!(
            world.get_particle_position(pid1).unwrap().y() < 201.0
                && world.get_particle_position(pid1).unwrap().y() > 199.0
        );
    }
}