use bevy::prelude::*;
use leafwing_input_manager::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(InputManagerPlugin::<ArpgAction>::default())
.add_systems(Startup, spawn_player)
.add_systems(Update, cast_fireball)
.add_systems(Update, player_dash)
.add_event::<PlayerWalk>()
.add_systems(Update, player_walks)
.run();
}
#[derive(Actionlike, PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)]
enum ArpgAction {
Up,
Down,
Left,
Right,
Ability1,
Ability2,
Ability3,
Ability4,
Ultimate,
}
impl ArpgAction {
const DIRECTIONS: [Self; 4] = [
ArpgAction::Up,
ArpgAction::Down,
ArpgAction::Left,
ArpgAction::Right,
];
fn direction(self) -> Option<Dir2> {
match self {
ArpgAction::Up => Some(Dir2::Y),
ArpgAction::Down => Some(Dir2::NEG_Y),
ArpgAction::Left => Some(Dir2::NEG_X),
ArpgAction::Right => Some(Dir2::X),
_ => None,
}
}
}
#[derive(Component)]
pub struct Player;
#[derive(Bundle)]
struct PlayerBundle {
player: Player,
input_manager: InputManagerBundle<ArpgAction>,
}
impl PlayerBundle {
fn default_input_map() -> InputMap<ArpgAction> {
use ArpgAction::*;
let mut input_map = InputMap::default();
input_map.insert(Up, KeyCode::ArrowUp);
input_map.insert(Up, GamepadButtonType::DPadUp);
input_map.insert(Down, KeyCode::ArrowDown);
input_map.insert(Down, GamepadButtonType::DPadDown);
input_map.insert(Left, KeyCode::ArrowLeft);
input_map.insert(Left, GamepadButtonType::DPadLeft);
input_map.insert(Right, KeyCode::ArrowRight);
input_map.insert(Right, GamepadButtonType::DPadRight);
input_map.insert(Ability1, KeyCode::KeyQ);
input_map.insert(Ability1, GamepadButtonType::West);
input_map.insert(Ability1, MouseButton::Left);
input_map.insert(Ability2, KeyCode::KeyW);
input_map.insert(Ability2, GamepadButtonType::North);
input_map.insert(Ability2, MouseButton::Right);
input_map.insert(Ability3, KeyCode::KeyE);
input_map.insert(Ability3, GamepadButtonType::East);
input_map.insert(Ability4, KeyCode::Space);
input_map.insert(Ability4, GamepadButtonType::South);
input_map.insert(Ultimate, KeyCode::KeyR);
input_map.insert(Ultimate, GamepadButtonType::LeftTrigger2);
input_map
}
}
fn spawn_player(mut commands: Commands) {
commands.spawn(PlayerBundle {
player: Player,
input_manager: InputManagerBundle::with_map(PlayerBundle::default_input_map()),
});
}
fn cast_fireball(query: Query<&ActionState<ArpgAction>, With<Player>>) {
let action_state = query.single();
if action_state.just_pressed(&ArpgAction::Ability1) {
println!("Fwoosh!");
}
}
fn player_dash(query: Query<&ActionState<ArpgAction>, With<Player>>) {
let action_state = query.single();
if action_state.just_pressed(&ArpgAction::Ability4) {
let mut direction_vector = Vec2::ZERO;
for input_direction in ArpgAction::DIRECTIONS {
if action_state.pressed(&input_direction) {
if let Some(direction) = input_direction.direction() {
direction_vector += *direction;
}
}
}
let net_direction = Dir2::new(direction_vector);
if let Ok(direction) = net_direction {
println!("Dashing in {direction:?}");
}
}
}
#[derive(Event)]
pub struct PlayerWalk {
pub direction: Dir2,
}
fn player_walks(
query: Query<&ActionState<ArpgAction>, With<Player>>,
mut event_writer: EventWriter<PlayerWalk>,
) {
let action_state = query.single();
let mut direction_vector = Vec2::ZERO;
for input_direction in ArpgAction::DIRECTIONS {
if action_state.pressed(&input_direction) {
if let Some(direction) = input_direction.direction() {
direction_vector += *direction;
}
}
}
let net_direction = Dir2::new(direction_vector);
if let Ok(direction) = net_direction {
event_writer.send(PlayerWalk { direction });
}
}