add char controller

This commit is contained in:
Mitchell Marino 2024-11-10 00:05:32 -06:00
parent c0384b6ada
commit eac5a15091
11 changed files with 211 additions and 136 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -2,9 +2,9 @@
assets:
[
("Player", File ( path: "blueprints/Player.glb" )),
("body.001", File ( path: "materials/body.001.glb" )),
("head.001", File ( path: "materials/head.001.glb" )),
("glasses.001", File ( path: "materials/glasses.001.glb" )),
("head.001", File ( path: "materials/head.001.glb" )),
("body.001", File ( path: "materials/body.001.glb" )),
("Hotel", File ( path: "blueprints/Hotel.glb" )),
("floor", File ( path: "materials/floor.glb" )),
]

View File

@ -17195,22 +17195,22 @@
"type": "object",
"typeInfo": "Enum"
},
"crooks::Player": {
"crooks::setup::Player": {
"additionalProperties": false,
"isComponent": true,
"isResource": false,
"long_name": "crooks::Player",
"long_name": "crooks::setup::Player",
"properties": {},
"required": [],
"short_name": "Player",
"type": "object",
"typeInfo": "Struct"
},
"crooks::PlayerHead": {
"crooks::setup::PlayerHead": {
"additionalProperties": false,
"isComponent": true,
"isResource": false,
"long_name": "crooks::PlayerHead",
"long_name": "crooks::setup::PlayerHead",
"properties": {},
"required": [],
"short_name": "PlayerHead",

View File

@ -1,3 +1,4 @@
/// From the avian3d example
use avian3d::{math::*, prelude::*};
use bevy::{ecs::query::Has, prelude::*, window::PrimaryWindow};

22
src/client.rs Normal file
View File

@ -0,0 +1,22 @@
use bevy::prelude::*;
use lightyear::prelude::ClientConnectEvent;
pub struct MyClientPlugin;
impl Plugin for MyClientPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, handle_events);
}
}
pub fn handle_events(
mut er_client_events: EventReader<ClientConnectEvent>,
// mut er_server_events: EventReader<ServerConnectEvent>,
) {
for client_connect in er_client_events.read() {
println!("Client Connect: {:?}", client_connect.client_id());
}
// for server_connect in er_server_events.read() {
// println!("Server Connect: {:?}", server_connect);
// }
}

View File

@ -1,34 +1,32 @@
use avian3d::math::{Scalar, Vector};
use avian3d::prelude::{Collider, PhysicsDebugPlugin, PhysicsSet};
use avian3d::prelude::PhysicsDebugPlugin;
use avian3d::PhysicsPlugins;
use bevy::core_pipeline::CorePipelinePlugin;
use bevy::gizmos::GizmoPlugin;
use bevy::log::LogPlugin;
use bevy::pbr::PbrPlugin;
use bevy::prelude::*;
use bevy::render::RenderPlugin;
use bevy::sprite::SpritePlugin;
use bevy::state::app::StatesPlugin;
use bevy_dolly::prelude::{Arm, Position, Rig, Rotation, Smooth};
use bevy_dolly::system::Dolly;
use bevy::text::TextPlugin;
use bevy::winit::WinitPlugin;
use bevy_editor_pls::prelude::*;
use blenvy::{BlenvyPlugin, BlueprintInfo, GameWorldTag, HideUntilReady, SpawnBlueprint};
use char_controller::{CharacterControllerBundle, CharacterControllerPlugin};
use blenvy::BlenvyPlugin;
use char_controller::CharacterControllerPlugin;
use clap::Parser;
use client::MyClientPlugin;
use lightyear::prelude::client::ClientPlugins;
use lightyear::prelude::server::ServerPlugins;
use server::MyServerPlugin;
use setup::{Player, PlayerHead, SetupPlugin};
mod char_controller;
pub mod char_controller;
pub mod client;
pub mod protocol;
pub mod server;
pub mod setup;
pub mod shared_net;
#[derive(Component, PartialEq, Eq, Default, Reflect)]
#[reflect(Component)]
pub struct Player;
#[derive(Component, PartialEq, Eq, Default, Reflect)]
#[reflect(Component)]
pub struct PlayerHead;
#[derive(Component, PartialEq, Eq, Default, Reflect)]
#[reflect(Component)]
pub struct MainCamera;
lazy_static::lazy_static! {
pub static ref CONFIG: Cli = {
Cli::parse()
@ -40,11 +38,24 @@ impl Plugin for ClientOrServerPlugin {
fn build(&self, app: &mut App) {
if CONFIG.client {
app.add_plugins(DefaultPlugins)
.add_plugins(ClientPlugins::new(shared_net::client_config()));
.add_plugins(ClientPlugins::new(shared_net::client_config()))
.add_plugins(EditorPlugin::default())
.add_plugins(MyClientPlugin);
}
if CONFIG.server {
app.add_plugins((MinimalPlugins, StatesPlugin, LogPlugin::default()))
.add_plugins(ServerPlugins::new(shared_net::server_config()));
app.add_plugins(
DefaultPlugins.build(), // .disable::<RenderPlugin>()
// .disable::<PbrPlugin>()
// .disable::<CorePipelinePlugin>()
// .disable::<ImagePlugin>()
// .disable::<TextPlugin>()
// .disable::<SpritePlugin>()
// .disable::<WindowPlugin>()
// .disable::<WinitPlugin>()
// .disable::<GizmoPlugin>(),
)
.add_plugins(ServerPlugins::new(shared_net::server_config()))
.add_plugins(MyServerPlugin);
}
}
}
@ -61,125 +72,19 @@ pub struct Cli {
}
fn main() {
App::new()
.register_type::<Player>()
.register_type::<PlayerHead>()
.insert_resource(Msaa::Sample4)
.insert_resource(AmbientLight {
brightness: 200.0,
..default()
})
.add_plugins(ClientOrServerPlugin)
.add_plugins(SetupPlugin)
.add_plugins((
PhysicsPlugins::default(),
PhysicsDebugPlugin::default(),
CharacterControllerPlugin,
))
.add_plugins(ClientOrServerPlugin)
.add_plugins(protocol::ProtocolPlugin)
.add_plugins(EditorPlugin::default())
.add_plugins(BlenvyPlugin::default())
.add_systems(Startup, setup)
.add_systems(Update, setup_player)
.add_systems(
Update,
(update_camera_rig, Dolly::<MainCamera>::update_active),
)
// .add_systems(
// PostUpdate,
// (update_camera_rig, Dolly::<MainCamera>::update_active)
// .after(PhysicsSet::Sync)
// .before(TransformSystem::TransformPropagate),
// )
.run();
}
fn setup(mut commands: Commands) {
commands.spawn((
MainCamera, // The rig component tag
Rig::builder() // The rig itself
.with(Position::new(Vec3::ZERO)) // Start position
// Adds a driver for rotation
.with(Rotation::new(Quat::IDENTITY))
// Interpolation when the translation is updated, also known as smoothing
.with(Smooth::new_position(0.3))
// Interpolation when the rotation is updated (updated via the YawPitch driver)
.with(Smooth::new_rotation(0.3))
// Moves the camera point out in the Z direction and uses the position as the pivot
// .with(Arm::new(Vec3::Z * 4.0))
.build(),
Camera3dBundle::default(), // The camera which is related via the rig tag
));
// commands.spawn(PointLightBundle {
// transform: Transform::from_translation(Vec3::Y * 30.),
// point_light: PointLight {
// intensity: 20_000_000.0,
// shadows_enabled: true,
// range: 100.,
// ..default()
// },
// ..default()
// });
// commands.spawn((
// DirectionalLightBundle {
// transform: Transform::from_translation(Vec3::Y * 10.).with_rotation(Quat::from_euler(
// EulerRot::XYZ,
// 3. * PI / 2.,
// 0.,
// 0.,
// )),
// directional_light: DirectionalLight {
// shadows_enabled: true,
// ..default()
// },
// ..default()
// },
// Name::new("Sun"),
// ));
// commands.spawn(SceneBundle {
// scene: asset_server.load("hotel.glb#Scene0"),
// ..Default::default()
// });
commands.spawn((
BlueprintInfo::from_path("levels/World.glb"),
SpawnBlueprint,
HideUntilReady,
GameWorldTag,
));
}
fn setup_player(
mut commands: Commands,
q_player: Query<Entity, (With<Player>, Without<Collider>)>,
) {
let Ok(player_entity) = q_player.get_single() else {
return;
};
commands.entity(player_entity).insert(
CharacterControllerBundle::new(
Collider::capsule_endpoints(1., Vec3::Y, Vec3::Y * 3.),
Vector::NEG_Y * 9.81 * 2.0,
)
.with_movement(30.0, 0.92, 7.0, (30.0 as Scalar).to_radians()),
);
}
fn update_camera_rig(
q_player_head: Query<&GlobalTransform, (With<PlayerHead>, Without<Rig>)>,
mut rig_q: Query<&mut Rig, Without<PlayerHead>>,
) {
let Ok(player_head_transform) = q_player_head.get_single() else {
return;
};
let (_, rot, pos) = player_head_transform.to_scale_rotation_translation();
let mut rig = rig_q.single_mut();
if let Some(d_rot) = rig.try_driver_mut::<Rotation>() {
d_rot.rotation = rot;
}
if let Some(d_pos) = rig.try_driver_mut::<Position>() {
d_pos.position = pos;
}
}

16
src/server.rs Normal file
View File

@ -0,0 +1,16 @@
use bevy::prelude::*;
use lightyear::prelude::{ClientConnectEvent, ServerConnectEvent};
pub struct MyServerPlugin;
impl Plugin for MyServerPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, handle_events);
}
}
pub fn handle_events(mut er_server_events: EventReader<ServerConnectEvent>) {
for server_connect in er_server_events.read() {
println!("Server Connect: {:?}", server_connect);
}
}

131
src/setup.rs Normal file
View File

@ -0,0 +1,131 @@
use avian3d::{
math::{Scalar, Vector},
prelude::Collider,
};
use bevy::prelude::*;
use bevy_dolly::{prelude::Rig, system::Dolly};
use blenvy::{BlueprintInfo, GameWorldTag, HideUntilReady, SpawnBlueprint};
use crate::char_controller::CharacterControllerBundle;
#[derive(Component, PartialEq, Eq, Default, Reflect)]
#[reflect(Component)]
pub struct Player;
#[derive(Component, PartialEq, Eq, Default, Reflect)]
#[reflect(Component)]
pub struct PlayerHead;
#[derive(Component, PartialEq, Eq, Default, Reflect)]
#[reflect(Component)]
pub struct MainCamera;
pub struct SetupPlugin;
impl Plugin for SetupPlugin {
fn build(&self, app: &mut App) {
app.register_type::<Player>()
.register_type::<PlayerHead>()
.add_systems(Startup, setup)
.add_systems(
Update,
(update_camera_rig, Dolly::<MainCamera>::update_active),
)
// TODO: change to component hooks
.add_systems(Update, setup_player);
}
}
fn setup(mut commands: Commands) {
use bevy_dolly::prelude::*;
commands.spawn((
MainCamera, // The rig component tag
Rig::builder() // The rig itself
.with(Position::new(Vec3::ZERO)) // Start position
// Adds a driver for rotation
.with(Rotation::new(Quat::IDENTITY))
// Interpolation when the translation is updated, also known as smoothing
.with(Smooth::new_position(0.3))
// Interpolation when the rotation is updated (updated via the YawPitch driver)
.with(Smooth::new_rotation(0.3))
// Moves the camera point out in the Z direction and uses the position as the pivot
// .with(Arm::new(Vec3::Z * 4.0))
.build(),
Camera3dBundle::default(), // The camera which is related via the rig tag
));
// commands.spawn(PointLightBundle {
// transform: Transform::from_translation(Vec3::Y * 30.),
// point_light: PointLight {
// intensity: 20_000_000.0,
// shadows_enabled: true,
// range: 100.,
// ..default()
// },
// ..default()
// });
// commands.spawn((
// DirectionalLightBundle {
// transform: Transform::from_translation(Vec3::Y * 10.).with_rotation(Quat::from_euler(
// EulerRot::XYZ,
// 3. * PI / 2.,
// 0.,
// 0.,
// )),
// directional_light: DirectionalLight {
// shadows_enabled: true,
// ..default()
// },
// ..default()
// },
// Name::new("Sun"),
// ));
// commands.spawn(SceneBundle {
// scene: asset_server.load("hotel.glb#Scene0"),
// ..Default::default()
// });
commands.spawn((
BlueprintInfo::from_path("levels/World.glb"),
SpawnBlueprint,
HideUntilReady,
GameWorldTag,
));
}
fn setup_player(
mut commands: Commands,
q_player: Query<Entity, (With<Player>, Without<Collider>)>,
) {
let Ok(player_entity) = q_player.get_single() else {
return;
};
commands.entity(player_entity).insert(
CharacterControllerBundle::new(
Collider::capsule_endpoints(1., Vec3::Y, Vec3::Y * 3.),
Vector::NEG_Y * 9.81 * 2.0,
)
.with_movement(30.0, 0.92, 7.0, (30.0 as Scalar).to_radians()),
);
}
fn update_camera_rig(
q_player_head: Query<&GlobalTransform, (With<PlayerHead>, Without<Rig>)>,
mut rig_q: Query<&mut Rig, Without<PlayerHead>>,
) {
use bevy_dolly::prelude::*;
let Ok(player_head_transform) = q_player_head.get_single() else {
return;
};
let (_, rot, pos) = player_head_transform.to_scale_rotation_translation();
let mut rig = rig_q.single_mut();
if let Some(d_rot) = rig.try_driver_mut::<Rotation>() {
d_rot.rotation = rot;
}
if let Some(d_pos) = rig.try_driver_mut::<Position>() {
d_pos.position = pos;
}
}