add char controller
This commit is contained in:
parent
c0384b6ada
commit
eac5a15091
BIN
art/crooks.blend
BIN
art/crooks.blend
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -2,9 +2,9 @@
|
|||||||
assets:
|
assets:
|
||||||
[
|
[
|
||||||
("Player", File ( path: "blueprints/Player.glb" )),
|
("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" )),
|
("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" )),
|
("Hotel", File ( path: "blueprints/Hotel.glb" )),
|
||||||
("floor", File ( path: "materials/floor.glb" )),
|
("floor", File ( path: "materials/floor.glb" )),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -17195,22 +17195,22 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"typeInfo": "Enum"
|
"typeInfo": "Enum"
|
||||||
},
|
},
|
||||||
"crooks::Player": {
|
"crooks::setup::Player": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"isComponent": true,
|
"isComponent": true,
|
||||||
"isResource": false,
|
"isResource": false,
|
||||||
"long_name": "crooks::Player",
|
"long_name": "crooks::setup::Player",
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"required": [],
|
"required": [],
|
||||||
"short_name": "Player",
|
"short_name": "Player",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"typeInfo": "Struct"
|
"typeInfo": "Struct"
|
||||||
},
|
},
|
||||||
"crooks::PlayerHead": {
|
"crooks::setup::PlayerHead": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"isComponent": true,
|
"isComponent": true,
|
||||||
"isResource": false,
|
"isResource": false,
|
||||||
"long_name": "crooks::PlayerHead",
|
"long_name": "crooks::setup::PlayerHead",
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"required": [],
|
"required": [],
|
||||||
"short_name": "PlayerHead",
|
"short_name": "PlayerHead",
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
/// From the avian3d example
|
||||||
use avian3d::{math::*, prelude::*};
|
use avian3d::{math::*, prelude::*};
|
||||||
use bevy::{ecs::query::Has, prelude::*, window::PrimaryWindow};
|
use bevy::{ecs::query::Has, prelude::*, window::PrimaryWindow};
|
||||||
|
|
||||||
|
|||||||
22
src/client.rs
Normal file
22
src/client.rs
Normal 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);
|
||||||
|
// }
|
||||||
|
}
|
||||||
165
src/main.rs
165
src/main.rs
@ -1,34 +1,32 @@
|
|||||||
use avian3d::math::{Scalar, Vector};
|
use avian3d::prelude::PhysicsDebugPlugin;
|
||||||
use avian3d::prelude::{Collider, PhysicsDebugPlugin, PhysicsSet};
|
|
||||||
use avian3d::PhysicsPlugins;
|
use avian3d::PhysicsPlugins;
|
||||||
|
use bevy::core_pipeline::CorePipelinePlugin;
|
||||||
|
use bevy::gizmos::GizmoPlugin;
|
||||||
use bevy::log::LogPlugin;
|
use bevy::log::LogPlugin;
|
||||||
|
use bevy::pbr::PbrPlugin;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
use bevy::render::RenderPlugin;
|
||||||
|
use bevy::sprite::SpritePlugin;
|
||||||
use bevy::state::app::StatesPlugin;
|
use bevy::state::app::StatesPlugin;
|
||||||
use bevy_dolly::prelude::{Arm, Position, Rig, Rotation, Smooth};
|
use bevy::text::TextPlugin;
|
||||||
use bevy_dolly::system::Dolly;
|
use bevy::winit::WinitPlugin;
|
||||||
use bevy_editor_pls::prelude::*;
|
use bevy_editor_pls::prelude::*;
|
||||||
use blenvy::{BlenvyPlugin, BlueprintInfo, GameWorldTag, HideUntilReady, SpawnBlueprint};
|
use blenvy::BlenvyPlugin;
|
||||||
use char_controller::{CharacterControllerBundle, CharacterControllerPlugin};
|
use char_controller::CharacterControllerPlugin;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use client::MyClientPlugin;
|
||||||
use lightyear::prelude::client::ClientPlugins;
|
use lightyear::prelude::client::ClientPlugins;
|
||||||
use lightyear::prelude::server::ServerPlugins;
|
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 protocol;
|
||||||
|
pub mod server;
|
||||||
|
pub mod setup;
|
||||||
pub mod shared_net;
|
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! {
|
lazy_static::lazy_static! {
|
||||||
pub static ref CONFIG: Cli = {
|
pub static ref CONFIG: Cli = {
|
||||||
Cli::parse()
|
Cli::parse()
|
||||||
@ -40,11 +38,24 @@ impl Plugin for ClientOrServerPlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
if CONFIG.client {
|
if CONFIG.client {
|
||||||
app.add_plugins(DefaultPlugins)
|
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 {
|
if CONFIG.server {
|
||||||
app.add_plugins((MinimalPlugins, StatesPlugin, LogPlugin::default()))
|
app.add_plugins(
|
||||||
.add_plugins(ServerPlugins::new(shared_net::server_config()));
|
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() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.register_type::<Player>()
|
|
||||||
.register_type::<PlayerHead>()
|
|
||||||
.insert_resource(Msaa::Sample4)
|
.insert_resource(Msaa::Sample4)
|
||||||
.insert_resource(AmbientLight {
|
.insert_resource(AmbientLight {
|
||||||
brightness: 200.0,
|
brightness: 200.0,
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
|
.add_plugins(ClientOrServerPlugin)
|
||||||
|
.add_plugins(SetupPlugin)
|
||||||
.add_plugins((
|
.add_plugins((
|
||||||
PhysicsPlugins::default(),
|
PhysicsPlugins::default(),
|
||||||
PhysicsDebugPlugin::default(),
|
PhysicsDebugPlugin::default(),
|
||||||
CharacterControllerPlugin,
|
CharacterControllerPlugin,
|
||||||
))
|
))
|
||||||
.add_plugins(ClientOrServerPlugin)
|
|
||||||
.add_plugins(protocol::ProtocolPlugin)
|
.add_plugins(protocol::ProtocolPlugin)
|
||||||
.add_plugins(EditorPlugin::default())
|
|
||||||
.add_plugins(BlenvyPlugin::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();
|
.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
16
src/server.rs
Normal 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
131
src/setup.rs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user