Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use bevy::{color::palettes::css::DARK_BLUE, prelude::*};
- use bevy_rapier3d::prelude::*;
- use crate::{
- GameState,
- environment::Ground,
- input::{JumpInput, LookInput, MoveInput, Reset},
- };
- pub(crate) struct PlayerPlugin;
- impl Plugin for PlayerPlugin {
- fn build(&self, app: &mut App) {
- app.add_systems(Startup, spawn_player)
- .register_type::<Player>()
- .add_systems(
- FixedUpdate,
- (reset_player, move_player).run_if(in_state(GameState::Playing)),
- );
- }
- }
- fn spawn_player(
- mut commands: Commands,
- mut materials: ResMut<Assets<StandardMaterial>>,
- mut meshes: ResMut<Assets<Mesh>>,
- ) {
- let player = Player::default();
- commands.spawn((
- Mesh3d(meshes.add(Cuboid::new(player.girth, player.height, player.girth))),
- MeshMaterial3d(materials.add(StandardMaterial::from_color(DARK_BLUE))),
- Transform::from_xyz(0., player.height / 2., 0.),
- RigidBody::Dynamic,
- Collider::cuboid(player.girth / 2., player.height / 2., player.girth / 2.),
- Restitution {
- coefficient: 0.,
- combine_rule: CoefficientCombineRule::Multiply,
- },
- LockedAxes::ROTATION_LOCKED_X | LockedAxes::ROTATION_LOCKED_Z,
- Velocity::zero(),
- player,
- Name::new("player"),
- ExternalImpulse::default(),
- Ccd::enabled(),
- ));
- }
- // marks player entity
- #[derive(Component, Clone, Debug, Reflect)]
- #[reflect(Component)]
- pub(crate) struct Player {
- pub(crate) height: f32,
- // width and depth
- pub(crate) girth: f32,
- max_speed: Vec2,
- acceleration: Vec2,
- backward_slow: f32,
- grounded_slow: f32,
- jump: f32,
- }
- impl Default for Player {
- fn default() -> Self {
- Self {
- height: 1.7,
- girth: 0.8,
- max_speed: Vec2::new(7.5, 10.),
- acceleration: Vec2::new(1.5, 2.0),
- backward_slow: 0.5,
- grounded_slow: 0.25,
- jump: 10.,
- }
- }
- }
- impl Player {
- fn slowing(&self, dir: Vec2, grounded: bool) -> Vec2 {
- let dir = if dir.y > 0. {
- dir.with_y(dir.y * self.backward_slow)
- } else {
- dir
- };
- if !grounded {
- dir * self.grounded_slow
- } else {
- dir
- }
- }
- }
- fn reset_player(
- mut player: Single<(&mut Transform, &Player, &mut Velocity)>,
- mut reset: ResMut<Reset>,
- ) {
- if reset.0 {
- player.0.rotation = Quat::IDENTITY;
- player.0.translation = Vec3::ZERO.with_y(player.1.height);
- *player.2 = Velocity::zero();
- reset.0 = false;
- }
- }
- fn move_player(
- move_input: Res<MoveInput>,
- mut player: Single<(
- &mut Transform,
- &Player,
- &mut Velocity,
- Entity,
- &mut ExternalImpulse,
- )>,
- look_input: Res<LookInput>,
- mut jump: ResMut<JumpInput>,
- rapier_context: ReadRapierContext,
- ground: Single<Entity, With<Ground>>,
- ) {
- player.2.angvel.y = look_input.0.x;
- let rapier_context = rapier_context.single().unwrap();
- let grounded = rapier_context
- .contact_pair(player.3, *ground)
- .is_some_and(|view| {
- view.manifolds()
- .any(|manifold| manifold.normal().dot(Vec3::Y) > 0.)
- });
- if grounded && jump.0 {
- player.4.impulse = Vec3::new(0., player.1.jump, 0.);
- jump.0 = false;
- }
- let Some(input) = move_input.0 else {
- player.2.linvel = player.2.linvel.with_x(0.).with_z(0.);
- return;
- };
- let movement = player.0.compute_affine().matrix3.mul_vec3(
- player
- .1
- .slowing(input * player.1.max_speed, grounded)
- .vec3_y0(),
- );
- player.2.linvel = movement.with_y(player.2.linvel.y);
- }
- pub(crate) trait ToVec3 {
- fn vec3_y0(self) -> Vec3;
- fn vec3_y(self, y: f32) -> Vec3;
- }
- impl ToVec3 for Vec2 {
- fn vec3_y0(self) -> Vec3 {
- self.vec3_y(0.)
- }
- fn vec3_y(self, y: f32) -> Vec3 {
- Vec3::new(self.x, y, self.y)
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement