heron/lib.rs
1#![deny(future_incompatible, nonstandard_style)]
2#![warn(missing_docs, rust_2018_idioms, clippy::pedantic)]
3#![allow(clippy::needless_pass_by_value, clippy::needless_doctest_main)]
4#![cfg(any(dim2, dim3))]
5
6//! An ergonomic physics API for 2d and 3d [bevy] games. (powered by [rapier])
7//!
8//! [bevy]: https://bevyengine.org
9//!
10//! [rapier]: https://rapier.rs
11//!
12//! # Get started
13//!
14//! ## Add the dependency and choose to work with either 2d or 3d
15//!
16//! Add the library to `Cargo.toml`.
17//!
18//! For a 3d game:
19//! ```toml
20//! heron = { version = "3", features = ["3d"] }
21//! ```
22//!
23//! For as 2d game:
24//! ```toml
25//! heron = { version = "3", features = ["2d"] }
26//! ```
27//!
28//! ### Feature flags
29//!
30//! One must choose to use either `2d` or `3d`. If none of theses two features is enabled, the plugin won't be available.
31//!
32//!
33//! * `3d` Enable simulation on the 3 axes `x`, `y`, and `z`. Incompatible with the feature `2d`.
34//! * `2d` Enable simulation only on the first 2 axes `x` and `y`. Incompatible with the feature `3d`, therefore require to disable the default features.
35//! * `debug-2d` Render 2d collision shapes
36//! * `debug-3d` Render 3d collision shapes
37//! * `collision-from-mesh` Add the [`PendingConvexCollision`] component to generate convex hull collision shapes from a mesh
38//! * `enhanced-determinism` Enable rapier's [enhanced-determinism](https://rapier.rs/docs/user_guides/rust/determinism)
39//!
40//!
41//! ## Install the plugin
42//!
43//! The [`PhysicsPlugin`] should be installed to enable physics and collision detection.
44//!
45//! ```no_run
46//! use bevy::prelude::*;
47//! use heron::prelude::*;
48//!
49//! fn main() {
50//! App::new()
51//! .add_plugins(DefaultPlugins)
52//! .add_plugin(PhysicsPlugin::default())
53//! // ... Add your resources and systems
54//! .run();
55//! }
56//! ```
57//!
58//! ## Create rigid bodies
59//!
60//! To create a rigid body, add the [`RigidBody`] to the entity and add a collision shapes with the
61//! [`CollisionShape`] component.
62//!
63//! The position and rotation are defined by the bevy [`GlobalTransform`] component.
64//!
65//! [`GlobalTransform`]: bevy::prelude::GlobalTransform
66//!
67//! ```
68//! # use bevy::prelude::*;
69//! # use heron::prelude::*;
70//! fn spawn(mut commands: Commands) {
71//! commands
72//!
73//! // Spawn any bundle of your choice. Only make sure there is a `GlobalTransform`
74//! .spawn_bundle(SpriteBundle::default())
75//!
76//! // Make it a rigid body
77//! .insert(RigidBody::Dynamic)
78//!
79//! // Attach a collision shape
80//! .insert(CollisionShape::Sphere { radius: 10.0 })
81//!
82//! // Optionally add other useful components...
83//! .insert(Velocity::from_linear(Vec3::X * 2.0))
84//! .insert(Acceleration::from_linear(Vec3::X * 1.0))
85//! .insert(PhysicMaterial { friction: 1.0, density: 10.0, ..Default::default() })
86//! .insert(RotationConstraints::lock());
87//! }
88//! ```
89//!
90//! ## Move rigid bodies programmatically
91//!
92//! When creating games, it is often useful to interact with the physics engine and move bodies
93//! programmatically. For this, you have two options: Updating the [`Transform`] or applying a
94//! [`Velocity`].
95//!
96//! [`Transform`]: bevy::prelude::Transform
97//!
98//! ### Option 1: Update the Transform
99//!
100//! For positional kinematic bodies ([`RigidBody::KinematicPositionBased`]), if the transform is
101//! updated, the body is moved and get an automatically calculated velocity. Physics rules will be
102//! applied normally. Updating the transform is a good way to move a kinematic body.
103//!
104//! For other types of bodies, if the transform is updated, the rigid body will be *teleported* to
105//! the new position/rotation, **ignoring physic rules**.
106//!
107//! ### Option 2: Use the Velocity component
108//!
109//! For [`RigidBody::Dynamic`] and [`RigidBody::KinematicVelocityBased`] bodies **only**, one can
110//! add a [`Velocity`] component to the entity, that will move the body over time. Physics rules
111//! will be applied normally.
112//!
113//! Note that the velocity component is updated by heron to always reflects the current velocity.
114//!
115//! Defining/updating the velocity is a good way to interact with dynamic bodies.
116//!
117//! ## See also
118//!
119//! * How to define a [`RigidBody`]
120//! * How to add a [`CollisionShape`]
121//! * How to define [`CollisionLayers`]
122//! * How to define the world's [`Gravity`]
123//! * How to define the world's [`PhysicsTime`]
124//! * How to define the [`PhysicMaterial`]
125//! * How to get the current [`Collisions`]
126//! * How to listen to [`CollisionEvent`]
127//! * How to define [`RotationConstraints`]
128//! * How to define [`CustomCollisionShape`] for [`heron_rapier`]
129
130use bevy::app::{App, Plugin};
131
132pub use heron_core::*;
133pub use heron_macros::*;
134use heron_rapier::RapierPlugin;
135
136/// Physics behavior powered by [rapier](https://rapier.rs)
137///
138/// Allow access to the underlying physics world directly
139pub mod rapier_plugin {
140 pub use heron_rapier::*;
141}
142
143/// Re-exports of the most commons/useful types
144pub mod prelude {
145 pub use heron_macros::*;
146
147 #[allow(deprecated)]
148 pub use crate::{
149 stage, Acceleration, AxisAngle, CollisionEvent, CollisionLayers, CollisionShape,
150 Collisions, Damping, Gravity, PhysicMaterial, PhysicsLayer, PhysicsPlugin, PhysicsSystem,
151 PhysicsTime, RigidBody, RotationConstraints, Velocity,
152 };
153}
154
155/// Plugin to install to enable collision detection and physics behavior.
156#[must_use]
157#[derive(Debug, Copy, Clone, Default)]
158pub struct PhysicsPlugin {
159 #[cfg(debug)]
160 debug: heron_debug::DebugPlugin,
161}
162
163impl Plugin for PhysicsPlugin {
164 fn build(&self, app: &mut App) {
165 app.add_plugin(RapierPlugin);
166
167 #[cfg(debug)]
168 app.add_plugin(self.debug);
169 }
170}