use bevy::app::{Startup, Update};
use bevy::prelude::*;
use bevy::render::render_resource::{Extent3d, TextureDimension, TextureFormat};
use bevy_ineffable::bindings::AnalogInput;
use bevy_ineffable::prelude::*;
const SPEED: f32 = 100.0;
const ROTATE_SPEED: f32 = -2.0;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(IneffablePlugin)
.register_input_action::<PlayerInput>()
.add_systems(Startup, init)
.add_systems(
Update,
(
player_movement,
player_rotation,
player_blushing,
player_teleportation,
),
)
.run();
}
#[derive(Debug, Default, Component)]
pub struct Player;
#[derive(Debug, InputAction)]
pub enum PlayerInput {
#[ineffable(dual_axis)] Movement,
#[ineffable(single_axis)] Rotate,
#[ineffable(continuous)] Blush,
#[ineffable(pulse)] Teleport,
}
pub fn init(
mut commands: Commands,
mut ineffable: IneffableCommands,
mut images: ResMut<Assets<Image>>,
) {
commands.spawn(Camera2dBundle::default());
commands
.spawn(SpriteBundle {
texture: images.add(white_square()),
..default()
})
.insert(Player);
ineffable.set_config(&create_config());
}
#[must_use]
fn create_config() -> InputConfig {
InputConfig::builder()
.bind(
ineff!(PlayerInput::Movement),
DualAxisBinding::builder()
.set_x(
SingleAxisBinding::hold()
.set_negative(KeyCode::A)
.set_positive(KeyCode::D)
.build(),
)
.set_y(
SingleAxisBinding::hold()
.set_negative(KeyCode::S)
.set_positive(KeyCode::W)
.build(),
)
.build(),
)
.bind(
ineff!(PlayerInput::Movement),
DualAxisBinding::builder()
.set_x(
SingleAxisBinding::analog(AnalogInput::GamePad(GamepadAxisType::RightStickX))
.set_sensitivity(5.)
.build(),
)
.set_y(
SingleAxisBinding::analog(AnalogInput::GamePad(GamepadAxisType::RightStickY))
.set_sensitivity(5.)
.build(),
)
.build(),
)
.bind(
ineff!(PlayerInput::Rotate),
SingleAxisBinding::hold()
.set_negative(KeyCode::Left)
.set_positive(KeyCode::Right)
.build(),
)
.bind(
ineff!(PlayerInput::Rotate),
SingleAxisBinding::analog(AnalogInput::GamePad(GamepadAxisType::LeftStickX))
.set_sensitivity(10.)
.build(),
)
.bind(
ineff!(PlayerInput::Blush),
ContinuousBinding::hold(KeyCode::ShiftLeft),
)
.bind(
ineff!(PlayerInput::Teleport),
PulseBinding::just_pressed(KeyCode::Space),
)
.build()
}
fn player_movement(
bindings: Res<Ineffable>,
time: Res<Time>,
mut query: Query<&mut Transform, With<Player>>,
) {
let mut transform = query.single_mut();
let movement_direction = bindings.direction_2d(ineff!(PlayerInput::Movement));
transform.translation.x += movement_direction.x * time.delta_seconds() * SPEED;
transform.translation.y += movement_direction.y * time.delta_seconds() * SPEED;
}
fn player_rotation(
bindings: Res<Ineffable>,
time: Res<Time>,
mut query: Query<&mut Transform, With<Player>>,
) {
let mut transform = query.single_mut();
let rotate_direction = bindings.direction_1d(ineff!(PlayerInput::Rotate));
transform.rotate_z(rotate_direction * time.delta_seconds() * ROTATE_SPEED);
}
fn player_blushing(bindings: Res<Ineffable>, mut query: Query<&mut Sprite, With<Player>>) {
let mut sprite = query.single_mut();
sprite.color = if bindings.is_active(ineff!(PlayerInput::Blush)) {
Color::rgb(0.8, 0.4, 0.4)
} else {
Color::rgb(0.4, 0.8, 0.8)
};
}
fn player_teleportation(bindings: Res<Ineffable>, mut query: Query<&mut Transform, With<Player>>) {
let mut transform = query.single_mut();
if bindings.just_pulsed(ineff!(PlayerInput::Teleport)) {
transform.translation.x += transform.translation.x.signum() * -100.;
transform.translation.y += transform.translation.y.signum() * -100.;
}
}
#[must_use]
fn white_square() -> Image {
Image::new_fill(
Extent3d {
width: 100,
height: 100,
depth_or_array_layers: 1,
},
TextureDimension::D2,
&[255, 255, 255, 255],
TextureFormat::Rgba8Unorm,
)
}