use bevy::{prelude::*, sprite::MaterialMesh2dBundle}; use bevy_xpbd_2d::{math::*, prelude::*}; use examples_common_2d::XpbdExamplePlugin; fn main() { App::new() .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::srgb(0.05, 0.05, 0.1))) .insert_resource(Gravity(Vector::ZERO)) .add_event::() .add_systems(Startup, setup) .add_systems( Update, ( keyboard_input1, keyboard_input2, movement.run_if(has_movement), // don't mutably access the character if there is no movement apply_movement_damping, apply_pressure_plate_colour, update_velocity_text, log_events, ) .chain(), ) .run(); } #[derive(Component, Default, Reflect)] struct Character; #[derive(Component, Default, Reflect)] struct PressurePlate; #[derive(Component, Default, Reflect)] struct CharacterVelocityText; fn setup( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, ) { commands.spawn(( MaterialMesh2dBundle { mesh: meshes.add(Capsule2d::new(12.5, 20.0)).into(), material: materials.add(Color::srgb(0.2, 0.7, 0.9)), transform: Transform::from_xyz(0.0, -100.0, 1.0), ..default() }, Character, RigidBody::Dynamic, Collider::capsule(20.0, 12.5), Name::new("Character"), )); commands.spawn(( SpriteBundle { transform: Transform::from_xyz(0.0, 150.0, 0.0), sprite: Sprite { color: Color::WHITE, custom_size: Some(Vec2::new(100.0, 100.0)), ..default() }, ..default() }, PressurePlate, Sensor, RigidBody::Static, Collider::rectangle(100.0, 100.0), Name::new("Pressure Plate"), )); commands.spawn(( TextBundle::from_section( "Velocity: ", TextStyle { font_size: 16.0, ..default() }, ) .with_style(Style { position_type: PositionType::Absolute, bottom: Val::Px(5.0), left: Val::Px(5.0), ..default() }), CharacterVelocityText, Name::new("Character Velocity Text"), )); commands.spawn(Camera2dBundle::default()); } #[derive(Event, Debug, Reflect)] pub enum MovementAction { Velocity(Vector), Offset(Vector), Stop, } // use velocity fn keyboard_input1( mut movement_event_writer: EventWriter, keyboard_input: Res>, time: Res>, ) { if time.is_paused() { return; } let space = keyboard_input.pressed(KeyCode::Space); if space { movement_event_writer.send(MovementAction::Stop); return; } let left = keyboard_input.any_pressed([KeyCode::KeyA]); let right = keyboard_input.any_pressed([KeyCode::KeyD]); let up = keyboard_input.any_pressed([KeyCode::KeyW]); let down = keyboard_input.any_pressed([KeyCode::KeyS]); let horizontal = right as i8 - left as i8; let vertical = up as i8 - down as i8; let direction = Vector::new(horizontal as Scalar, vertical as Scalar); if direction != Vector::ZERO { movement_event_writer.send(MovementAction::Velocity(direction)); } } // use position offset fn keyboard_input2( mut movement_event_writer: EventWriter, keyboard_input: Res>, time: Res>, ) { if time.is_paused() { return; } let left = keyboard_input.any_pressed([KeyCode::ArrowLeft]); let right = keyboard_input.any_pressed([KeyCode::ArrowRight]); let up = keyboard_input.any_pressed([KeyCode::ArrowUp]); let down = keyboard_input.any_pressed([KeyCode::ArrowDown]); let horizontal = right as i8 - left as i8; let vertical = up as i8 - down as i8; let direction = Vector::new(horizontal as Scalar, vertical as Scalar); if direction != Vector::ZERO { movement_event_writer.send(MovementAction::Offset(direction)); } } fn has_movement(mut reader: EventReader) -> bool { reader.read().next().is_some() } fn movement( time: Res