Advertisement
disdamoe

Untitled

Jun 20th, 2025
346
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 4.12 KB | None | 0 0
  1. use bevy::{color::palettes::css::DARK_BLUE, prelude::*};
  2. use bevy_rapier3d::prelude::*;
  3.  
  4. use crate::{
  5.     GameState,
  6.     environment::Ground,
  7.     input::{JumpInput, LookInput, MoveInput, Reset},
  8. };
  9.  
  10. pub(crate) struct PlayerPlugin;
  11.  
  12. impl Plugin for PlayerPlugin {
  13.     fn build(&self, app: &mut App) {
  14.         app.add_systems(Startup, spawn_player)
  15.             .register_type::<Player>()
  16.             .add_systems(
  17.                 FixedUpdate,
  18.                 (reset_player, move_player).run_if(in_state(GameState::Playing)),
  19.             );
  20.     }
  21. }
  22.  
  23. fn spawn_player(
  24.     mut commands: Commands,
  25.     mut materials: ResMut<Assets<StandardMaterial>>,
  26.     mut meshes: ResMut<Assets<Mesh>>,
  27. ) {
  28.     let player = Player::default();
  29.     commands.spawn((
  30.         Mesh3d(meshes.add(Cuboid::new(player.girth, player.height, player.girth))),
  31.         MeshMaterial3d(materials.add(StandardMaterial::from_color(DARK_BLUE))),
  32.         Transform::from_xyz(0., player.height / 2., 0.),
  33.         RigidBody::Dynamic,
  34.         Collider::cuboid(player.girth / 2., player.height / 2., player.girth / 2.),
  35.         Restitution {
  36.             coefficient: 0.,
  37.             combine_rule: CoefficientCombineRule::Multiply,
  38.         },
  39.         LockedAxes::ROTATION_LOCKED_X | LockedAxes::ROTATION_LOCKED_Z,
  40.         Velocity::zero(),
  41.         player,
  42.         Name::new("player"),
  43.         ExternalImpulse::default(),
  44.         Ccd::enabled(),
  45.     ));
  46. }
  47.  
  48. // marks player entity
  49. #[derive(Component, Clone, Debug, Reflect)]
  50. #[reflect(Component)]
  51. pub(crate) struct Player {
  52.     pub(crate) height: f32,
  53.     // width and depth
  54.     pub(crate) girth: f32,
  55.     max_speed: Vec2,
  56.     acceleration: Vec2,
  57.     backward_slow: f32,
  58.     grounded_slow: f32,
  59.     jump: f32,
  60. }
  61. impl Default for Player {
  62.     fn default() -> Self {
  63.         Self {
  64.             height: 1.7,
  65.             girth: 0.8,
  66.             max_speed: Vec2::new(7.5, 10.),
  67.             acceleration: Vec2::new(1.5, 2.0),
  68.             backward_slow: 0.5,
  69.             grounded_slow: 0.25,
  70.             jump: 10.,
  71.         }
  72.     }
  73. }
  74. impl Player {
  75.     fn slowing(&self, dir: Vec2, grounded: bool) -> Vec2 {
  76.         let dir = if dir.y > 0. {
  77.             dir.with_y(dir.y * self.backward_slow)
  78.         } else {
  79.             dir
  80.         };
  81.         if !grounded {
  82.             dir * self.grounded_slow
  83.         } else {
  84.             dir
  85.         }
  86.     }
  87. }
  88. fn reset_player(
  89.     mut player: Single<(&mut Transform, &Player, &mut Velocity)>,
  90.     mut reset: ResMut<Reset>,
  91. ) {
  92.     if reset.0 {
  93.         player.0.rotation = Quat::IDENTITY;
  94.         player.0.translation = Vec3::ZERO.with_y(player.1.height);
  95.         *player.2 = Velocity::zero();
  96.         reset.0 = false;
  97.     }
  98. }
  99. fn move_player(
  100.     move_input: Res<MoveInput>,
  101.     mut player: Single<(
  102.         &mut Transform,
  103.         &Player,
  104.         &mut Velocity,
  105.         Entity,
  106.         &mut ExternalImpulse,
  107.     )>,
  108.     look_input: Res<LookInput>,
  109.     mut jump: ResMut<JumpInput>,
  110.     rapier_context: ReadRapierContext,
  111.     ground: Single<Entity, With<Ground>>,
  112. ) {
  113.     player.2.angvel.y = look_input.0.x;
  114.  
  115.     let rapier_context = rapier_context.single().unwrap();
  116.     let grounded = rapier_context
  117.         .contact_pair(player.3, *ground)
  118.         .is_some_and(|view| {
  119.             view.manifolds()
  120.                 .any(|manifold| manifold.normal().dot(Vec3::Y) > 0.)
  121.         });
  122.     if grounded && jump.0 {
  123.         player.4.impulse = Vec3::new(0., player.1.jump, 0.);
  124.         jump.0 = false;
  125.     }
  126.     let Some(input) = move_input.0 else {
  127.         player.2.linvel = player.2.linvel.with_x(0.).with_z(0.);
  128.         return;
  129.     };
  130.     let movement = player.0.compute_affine().matrix3.mul_vec3(
  131.         player
  132.             .1
  133.             .slowing(input * player.1.max_speed, grounded)
  134.             .vec3_y0(),
  135.     );
  136.     player.2.linvel = movement.with_y(player.2.linvel.y);
  137. }
  138.  
  139. pub(crate) trait ToVec3 {
  140.     fn vec3_y0(self) -> Vec3;
  141.     fn vec3_y(self, y: f32) -> Vec3;
  142. }
  143. impl ToVec3 for Vec2 {
  144.     fn vec3_y0(self) -> Vec3 {
  145.         self.vec3_y(0.)
  146.     }
  147.  
  148.     fn vec3_y(self, y: f32) -> Vec3 {
  149.         Vec3::new(self.x, y, self.y)
  150.     }
  151. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement