Initial commit
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::input::player::InputFrame;
|
||||
|
||||
use super::player::{FighterInput, BaseInputMap, InputActionState};
|
||||
|
||||
pub fn postprocess_input(input_state: Query<&mut FighterInput>) {
|
||||
for mut player_input in input_state {
|
||||
}
|
||||
}
|
||||
pub fn preprocess_keyboard_input(key: Res<ButtonInput<KeyCode>>, input_map: Res<BaseInputMap>, mut input_state: Query<&mut FighterInput>) {
|
||||
// Keyboard input is only for player 0
|
||||
for mut keeb_input in &mut input_state.iter_mut().take(1) {
|
||||
let mut input_frame = InputFrame::default();
|
||||
for keyboard_elment in &input_map.keyboard {
|
||||
let action_state = if key.just_pressed(keyboard_elment.key) {
|
||||
InputActionState::JustPressed
|
||||
} else if key.just_released(keyboard_elment.key) {
|
||||
InputActionState::JustReleased
|
||||
} else if key.pressed(keyboard_elment.key) {
|
||||
InputActionState::Pressed
|
||||
} else {
|
||||
InputActionState::Released
|
||||
};
|
||||
|
||||
let action_strength = match action_state {
|
||||
InputActionState::JustPressed | InputActionState::Pressed => 1.0f32,
|
||||
InputActionState::JustReleased | InputActionState::Released => 0.0f32,
|
||||
};
|
||||
|
||||
match keyboard_elment.action {
|
||||
super::player::InputMapAction::MovementXDir(sign) => input_frame.movement.x += (sign as f32) * action_strength,
|
||||
super::player::InputMapAction::MovementYDir(sign) => input_frame.movement.y += (sign as f32) * action_strength,
|
||||
super::player::InputMapAction::Jump => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
input_frame.movement = input_frame.movement.normalize_or_zero();
|
||||
input_frame.directional_attack = input_frame.directional_attack.normalize_or_zero();
|
||||
keeb_input.push_input_frame(input_frame);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
pub mod player;
|
||||
pub mod logic;
|
||||
pub mod plugin;
|
||||
@@ -0,0 +1,93 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use arrayvec::ArrayVec;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct InputFrame {
|
||||
pub movement: Vec2,
|
||||
pub directional_attack: Vec2
|
||||
}
|
||||
|
||||
#[derive(Component, Default)]
|
||||
pub struct FighterInput {
|
||||
input_buffer: VecDeque<InputFrame>
|
||||
}
|
||||
|
||||
impl FighterInput {
|
||||
const INPUT_BUFFER_SIZE: usize = 5;
|
||||
pub fn get_last_frame(&self) -> Option<&InputFrame> {
|
||||
self.input_buffer.back()
|
||||
}
|
||||
|
||||
pub fn push_input_frame(&mut self, frame: InputFrame) {
|
||||
while self.input_buffer.len() >= Self::INPUT_BUFFER_SIZE {
|
||||
self.input_buffer.pop_front();
|
||||
}
|
||||
self.input_buffer.push_back(frame);
|
||||
}
|
||||
|
||||
pub fn clear_buffer(&mut self) {
|
||||
while self.input_buffer.len() > 1 {
|
||||
self.input_buffer.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_smash_x_movement(&self, reset_deadzone: f32, threshold: f32, frame_threshold: u32) -> Option<f32> {
|
||||
let iter = self.input_buffer.iter().zip(self.input_buffer.iter().skip(1));
|
||||
|
||||
let mut frames_in_deadzone = 0xFE;
|
||||
for (prev, current) in iter {
|
||||
let x_abs = current.movement.x.abs();
|
||||
if x_abs < reset_deadzone {
|
||||
frames_in_deadzone = 0xFE;
|
||||
} else {
|
||||
let prev_x_abs = prev.movement.x.abs();
|
||||
if prev_x_abs < reset_deadzone || prev.movement.x.signum() != current.movement.x.signum() {
|
||||
frames_in_deadzone = 0;
|
||||
} else {
|
||||
frames_in_deadzone += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if x_abs >= threshold && frames_in_deadzone <= frame_threshold {
|
||||
return Some(x_abs.signum());
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum InputActionState {
|
||||
JustPressed,
|
||||
Pressed,
|
||||
JustReleased,
|
||||
Released
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum InputMapAction {
|
||||
MovementXDir(i32),
|
||||
MovementYDir(i32),
|
||||
Jump
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct KeyboardInputMapElement {
|
||||
pub key: KeyCode,
|
||||
pub action: InputMapAction
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct BaseInputMap {
|
||||
pub keyboard: Vec<KeyboardInputMapElement>
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
#[relationship(relationship_target = ControlledBy)]
|
||||
pub struct Controls(pub Entity);
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
#[relationship_target(relationship = Controls)]
|
||||
pub struct ControlledBy(Entity);
|
||||
@@ -0,0 +1,29 @@
|
||||
use bevy::prelude::*;
|
||||
use crate::fighter::*;
|
||||
use crate::input::player::{ControlledBy, Controls, FighterInput};
|
||||
use crate::input::{
|
||||
logic::{postprocess_input, preprocess_keyboard_input}, player::{BaseInputMap, InputMapAction, KeyboardInputMapElement},
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FighterInputPlugin;
|
||||
|
||||
impl Plugin for FighterInputPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.insert_resource(BaseInputMap {
|
||||
keyboard: vec![
|
||||
// right
|
||||
KeyboardInputMapElement {
|
||||
key: KeyCode::KeyD,
|
||||
action: InputMapAction::MovementXDir(1),
|
||||
},
|
||||
// left
|
||||
KeyboardInputMapElement {
|
||||
key: KeyCode::KeyA,
|
||||
action: InputMapAction::MovementXDir(-1),
|
||||
},
|
||||
],
|
||||
})
|
||||
.add_systems(FixedPreUpdate, (preprocess_keyboard_input, postprocess_input).chain());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user