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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
#![deny(future_incompatible, nonstandard_style)] #![warn(missing_docs, rust_2018_idioms, clippy::pedantic)] //! Core components and resources to use Heron use bevy_ecs::Entity; use bevy_math::Vec3; pub use gravity::Gravity; pub use velocity::{AxisAngle, Velocity}; mod gravity; pub mod utils; mod velocity; /// Components that defines a body subject to physics and collision /// /// # Example /// /// ``` /// # use bevy::prelude::*; /// # use heron_core::*; /// fn spawn(commands: &mut Commands, mut materials: ResMut<Assets<ColorMaterial>>) { /// commands.spawn(todo!("Spawn your sprite/mesh, incl. at least a GlobalTransform")) /// .with(Body::Sphere { radius: 1.0 }); /// } /// ``` #[derive(Debug, Clone)] pub enum Body { /// A sphere (or circle in 2d) shape defined by its radius Sphere { /// Radius of the sphere radius: f32, }, /// A capsule shape Capsule { /// Distance from the center of the capsule to the center of an hemisphere. half_segment: f32, /// Radius of the hemispheres radius: f32, }, /// A cuboid/rectangular shape Cuboid { /// The **half** extends on each axis. (x = half width, y = half height, z = half depth) /// /// In 2d the `z` axis is ignored half_extends: Vec3, }, } /// Component that defines the *type* of rigid body. /// /// # Example /// /// ``` /// # use bevy::prelude::*; /// # use heron_core::*; /// fn spawn(commands: &mut Commands, mut materials: ResMut<Assets<ColorMaterial>>) { /// commands.spawn(todo!("Spawn your sprite/mesh, incl. at least a GlobalTransform")) /// .with(Body::Sphere { radius: 1.0 }) // Make a body (is dynamic by default) /// .with(BodyType::Static); // Make it static (so that it doesn't move and is not affected by forces like gravity) /// } /// ``` #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum BodyType { /// A dynamic body is normally affected by physic forces and affect the other bodies too. /// /// This is the most "natural" type in the sense that, in the real life, everything is dynamic. Dynamic, /// A static body is not affected by physic forces and doesn't move. But it does affect the other bodies. /// /// This effectively behaves like a dynamic body with infinite mass and zero velocity. /// /// It is especially useful to model terrain and static obstacles. Static, /// A sensor is not affected by physics forces and doesn't affect other bodies either. /// Other bodies will be able to penetrate the sensor. /// /// A sensor is useful when we are only interested in collision events. /// One may for example add a sensor to detect when the player reach a certain area. Sensor, } impl Default for BodyType { fn default() -> Self { Self::Dynamic } } /// An event fired when the collision state between two entities changed /// /// # Example /// /// ``` /// # use bevy::prelude::*; /// # use heron_core::*; /// fn detect_collisions(mut reader: Local<EventReader<CollisionEvent>>, events: Res<Events<CollisionEvent>>) { /// for event in reader.iter(&events) { /// match event { /// CollisionEvent::Started(entity1, entity2) => println!("Entity {:?} and {:?} started to collide", entity1, entity2), /// CollisionEvent::Stopped(entity1, entity2) => println!("Entity {:?} and {:?} stopped to collide", entity1, entity2), /// } /// } /// } #[derive(Debug, Copy, Clone, PartialEq)] pub enum CollisionEvent { /// The two entities started to collide Started(Entity, Entity), /// The two entities no longer collide Stopped(Entity, Entity), } /// Component that define the [Coefficient of Restitution] /// /// [Coefficient of Restitution]: https://en.wikipedia.org/wiki/Coefficient_of_restitution #[derive(Debug, Copy, Clone, PartialEq)] pub struct Restitution(f32); impl Restitution { /// Perfectly inelastic coefficient, all kinematic energy is lost on collision. (Do not bounce at all) pub const PERFECTLY_INELASTIC: Restitution = Restitution(0.0); /// Perfectly elastic coefficient, all kinematic energy is restated in movement. (Very bouncy) pub const PERFECTLY_ELASTIC: Restitution = Restitution(1.0); /// Create a new restitution from a coefficient value. #[must_use] pub fn new(coefficient: f32) -> Self { Self(coefficient) } } impl Default for Restitution { fn default() -> Self { Self::PERFECTLY_INELASTIC } } impl From<f32> for Restitution { fn from(value: f32) -> Self { Self(value) } } impl From<Restitution> for f32 { fn from(Restitution(value): Restitution) -> Self { value } }