Skip to content

Commit

Permalink
Finish initial docs
Browse files Browse the repository at this point in the history
  • Loading branch information
janhohenheim committed Aug 26, 2024
1 parent c565a61 commit 3263745
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 18 deletions.
10 changes: 7 additions & 3 deletions examples/actor_with_collider.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! Shows a minimal example of using `avian_pickup` with Bevy.
//! Here, the actor has a collider as well.

use std::f32::consts::FRAC_PI_2;

use avian3d::prelude::*;
Expand Down Expand Up @@ -26,9 +29,10 @@ fn main() {
util::plugin(util::Example::Generic),
))
.add_systems(Startup, setup)
// Need to read input and rotate camera before physics,
// this is unfortunately the best way to schedule this:
// <https://github.com/bevyengine/bevy/issues/14873>
// Input handling and camera movement need to be executed every frame,
// so we run them in a variable timestep.
// We also want them to happen before the physics system, so we add them
// to the last variable timestep schedule before the fixed timestep systems run.
.add_systems(
RunFixedMainLoop,
(handle_input, rotate_camera).before(run_fixed_main_schedule),
Expand Down
28 changes: 21 additions & 7 deletions examples/manipulate_prop.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! Shows how to move and rotate a prop that is being held.
//! This can be used to implement something like Garry's Mod's physics gun.

use std::f32::consts::FRAC_PI_2;

use avian3d::prelude::*;
Expand Down Expand Up @@ -29,9 +32,10 @@ fn main() {
util::plugin(util::Example::Manipulation),
))
.add_systems(Startup, setup)
// Need to read input and rotate camera before physics,
// this is unfortunately the best way to schedule this:
// <https://github.com/bevyengine/bevy/issues/14873>
// Input handling and camera movement need to be executed every frame,
// so we run them in a variable timestep.
// We also want them to happen before the physics system, so we add them
// to the last variable timestep schedule before the fixed timestep systems run.
.add_systems(
RunFixedMainLoop,
(accumulate_input, handle_pickup_input, rotate_camera)
Expand Down Expand Up @@ -60,6 +64,8 @@ fn setup(
// Add this to set up the camera as the entity that can pick up
// objects.
AvianPickupActor {
// Increase the maximum distance a bit to show off the
// prop changing its distance on scroll.
interaction_distance: 15.0,
..default()
},
Expand Down Expand Up @@ -195,21 +201,24 @@ fn accumulate_input(
/// so we accumulate all input that happened since the last fixed update.
#[derive(Debug, Component, Default)]
struct InputAccumulation {
/// Accumulated mouse scrolling
zoom: i32,
/// Accumulated mouse motion
rotation: Vec2,
/// Was shift pressed during the last frame?
shift: bool,
}

fn move_prop(
time: Res<Time>,
mut actors: Query<(&mut InputAccumulation, &AvianPickupActorState)>,
mut actors: Query<(&mut InputAccumulation, &Transform, &AvianPickupActorState)>,
mut props: Query<(
&mut PreferredPickupDistanceOverride,
&mut PreferredPickupRotation,
)>,
) {
let dt = time.delta_seconds();
for (mut input, state) in &mut actors {
for (mut input, transform, state) in &mut actors {
let AvianPickupActorState::Holding(prop) = state else {
continue;
};
Expand All @@ -224,9 +233,14 @@ fn move_prop(
if !input.shift {
continue;
}

// Make the yaw global
let y_rotation_global = Quat::from_rotation_y(input.rotation.x * dt);
let x_rotation_global = Quat::from_rotation_x(input.rotation.y * dt);
rotation.0 = x_rotation_global * y_rotation_global * rotation.0;

// Make the pitch relative to the actor's orientation
let horizontal_axis = transform.right().into();
let vertical_rotation = Quat::from_axis_angle(horizontal_axis, input.rotation.y * dt);
rotation.0 = vertical_rotation * y_rotation_global * rotation.0;

input.rotation = Vec2::ZERO;
}
Expand Down
11 changes: 7 additions & 4 deletions examples/minimal.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Shows a minimal example of using `avian_pickup` with Bevy.

use std::f32::consts::FRAC_PI_2;

use avian3d::prelude::*;
Expand Down Expand Up @@ -26,17 +28,18 @@ fn main() {
util::plugin(util::Example::Generic),
))
.add_systems(Startup, setup)
// Need to read input and rotate camera before physics,
// this is unfortunately the best way to schedule this:
// <https://github.com/bevyengine/bevy/issues/14873>
// Input handling and camera movement need to be executed every frame,
// so we run them in a variable timestep.
// We also want them to happen before the physics system, so we add them
// to the last variable timestep schedule before the fixed timestep systems run.
.add_systems(
RunFixedMainLoop,
(handle_input, rotate_camera).before(run_fixed_main_schedule),
)
.run();
}

/// Spawn the camera, light, ground, and a box to pick up.
/// Spawn the actor, camera, light, ground, and a box to pick up.
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
Expand Down
8 changes: 8 additions & 0 deletions examples/play_catch.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! A little minigame where you and an NPC play catch with a box.
//! Shows how to use two different actors with Avian Pickup:
//! one is the player, and the other is an NPC.

use std::f32::consts::{FRAC_PI_2, FRAC_PI_6, PI};

use avian3d::prelude::*;
Expand Down Expand Up @@ -26,6 +30,10 @@ fn main() {
))
.add_systems(Startup, setup)
// Pass input to systems runing in the fixed update.
// Input handling and camera movement need to be executed every frame,
// so we run them in a variable timestep.
// We also want them to happen before the physics system, so we add them
// to the last variable timestep schedule before the fixed timestep systems run.
.add_systems(
RunFixedMainLoop,
(
Expand Down
10 changes: 7 additions & 3 deletions examples/prop_playground.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! Shows a minimal example of using `avian_pickup` with Bevy.
//! This one contains a lot of props to play around with.

use std::f32::consts::FRAC_PI_2;

use avian3d::prelude::*;
Expand Down Expand Up @@ -26,9 +29,10 @@ fn main() {
util::plugin(util::Example::Generic),
))
.add_systems(Startup, setup)
// Need to read input and rotate camera before physics,
// this is unfortunately the best way to schedule this:
// <https://github.com/bevyengine/bevy/issues/14873>
// Input handling and camera movement need to be executed every frame,
// so we run them in a variable timestep.
// We also want them to happen before the physics system, so we add them
// to the last variable timestep schedule before the fixed timestep systems run.
.add_systems(
RunFixedMainLoop,
(handle_input, rotate_camera).before(run_fixed_main_schedule),
Expand Down
100 changes: 99 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,107 @@ Additionally, you need some sort of interpolation:
cargo add bevy_transform_interpolation --git https://github.com/Jondolf/bevy_transform_interpolation
```

Finally, add these plugins to your app. Make sure to add Avian Pickup after Avian:

```rust
use bevy::prelude::*;
use avian::prelude::*;
use avian_pickup::prelude::*;
use bevy_transform_interpolation::*;

App::new()
.add_plugins((
DefaultPlugins,
// Add Avian
PhysicsPlugins::default(),
// Add Avian Pickup
AvianPickupPlugin::default(),
// Add interpolation
TransformInterpolationPlugin::interpolate_all(),
))
```

### Usage

TODO
The main two concepts of Avian Pickup are *actors* and *props*. It's simple:

- An *actor* is something that can pick up *props*.
These are spatial entities with an [`AvianPickupActor`](TODO) component.
- An *prop* is an object to be picked up.
These are spatial entities with a regular old [`RigidBody::Dynamic`](TODO) component and associated colliders.

As such, this is the minimum version of these two:

```rust
use bevy::prelude::*;
use avian::prelude::*;
use avian_pickup::prelude::*;

fn setup(mut commands: Commands) {
// Actor
commands.spawn((
SpatialBundle::default(),
AvianPickupActor::default(),
));

// Prop
commands.spawn((
SpatialBundle::default(),
RigidBody::Dynamic,
Collider::sphere(0.5),
));
}
```

In order for an actor to try picking up a prop, you need to send an [`AvianPickupInput`](TODO) event:

```rust
use bevy::prelude::*;
use avian_pickup::prelude::*;

fn handle_input(
mut avian_pickup_input_writer: EventWriter<AvianPickupInput>,
) {
let actor_entity = todo!("Your entity goes here");
avian_pickup_input_writer.send(AvianPickupInput {
action: AvianPickupAction::Pull,
actor: actor_entity,
});
}
```

When using a `AvianPickupAction::Pull` action, the actor will try to pull the nearest prop they're facing towards
them. Once they have picked it up, its [`AvianPickupActorState`](TODO) will reflect that by becoming
[`AvianPickupActorState::Holding(..)`](TODO). Note that [`AvianPickupState`](TODO) is a component that will automatically
get added to every actor.

That's it! You can use other actions to further instruct the actor to manipulate the prop.
The [`AvianPickupActor`](TODO) holds a lot of configuration options to tweak the behavior of the actor.
Many of these can be overridden for a specific prop by using components in the [`props`](TODO) module.
Finally, you can also read the events in the [`output`](TODO) module to react to what's happening.

### First Personal Camera

If you want to use a first person perspective for your player and allow him to be an [`AvianPickupActor`](TODO),
you need to make sure to move the camera *before* the physics update takes place. Usually, all movement code
for physicsal entities in the world should be in the fixed timestep, but the camera is a notable exception.
A player will want to have a camera that works as smoothly as possible and updates every frame. That's why you need to place the camera in the last variable timestep schedule before the physics update. You do this like so:

```rust
use bevy::{
app::RunFixedMainLoop,
prelude::*,
time::run_fixed_main_schedule,
};

App::new()
.add_systems(
RunFixedMainLoop,
move_camera.before(run_fixed_main_schedule),
);

fn move_camera() { todo!() }
```

## Version Compatibility

Expand Down

0 comments on commit 3263745

Please sign in to comment.