Bevy Virtual Joystick

Create and use a Virtual Joystick in a UI for bevy Game Engine.
Versions
Aviable and compatible versions
| bevy |
VirtualJoystick |
| 0.10.1 |
1.1.0 |
Features
- Support Mouse and Touch
- Easy usage
- Multiple Joysticks on screen
- Multiple types of joystick behaviour
- Track events on Joystick (Press, Drag and Up)
- Support Axis block (Horizontal, Vertical or Both)
Axis
| Both (Default) |
Horizontal |
Vertical |
 |
 |
 |
Joystick Types
| Fixed |
Floating (Default) |
Dynamic (TODO: Fix movement feel) |
 |
 |
 |
Examples
Features
- inspect: for world inspect with egui inspector
- serialize (default): for serialization support for all types (usable for save and load settings)
virtual_joystick = {
version = "*",
default-features = false,
features = [ "inspect", "serialize" ]
}
Usage
Check out the examples for details.
Add to Cargo.toml
[dependencies]
bevy = "0.10.1"
virtual_joystick = "*"
To solve sizing issue
[patch.crates-io]
android-activity = { git = "https://github.com/MarijnS95/android-activity/", branch = "na-resize"}
The minimal requirement:
use bevy::prelude::*;
use virtual_joystick::*;
#[derive(Default, Reflect, Hash, Clone, PartialEq, Eq)]
enum JoystickControllerID {
#[default]
Joystick1,
Joystick2,
}
#[bevy_main]
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugin(VirtualJoystickPlugin::<JoystickControllerID>::default())
.run()
}
Create Joystick
#[bevy_main]
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugin(VirtualJoystickPlugin)
.add_startup_system(create_scene)
.add_system(update_player)
.run()
}
fn create_scene(mut cmd: Commands, asset_server: Res<AssetServer>) {
cmd.spawn(Camera2dBundle::default());
cmd.spawn_empty().insert(Player(30.));
cmd.spawn(
VirtualJoystickBundle::new(VirtualJoystickNode {
border_image: asset_server.load("Outline.png"),
knob_image: asset_server.load("Knob.png"),
knob_size: Vec2::new(80., 80.),
dead_zone: 0.,
id: JoystickControllerID::Joystick1,
axis: VirtualJoystickAxis::Horizontal,
behaviour: VirtualJoystickType::Fixed,
})
.set_color(TintColor(Color::WHITE))
.set_style(Style {
size: Size::all(Val::Px(150.)),
position_type: PositionType::Absolute,
position: UiRect {
left: Val::Percent(50.),
bottom: Val::Percent(15.),
..default()
},
..default()
}),
)
.insert(VirtualJoystickInteractionArea);
}
Use variable generated by Joystick
fn update_joystick(
mut joystick: EventReader<VirtualJoystickEvent<JoystickControllerID>>,
mut player: Query<(&mut Transform, &Player)>,
time_step: Res<FixedTime>,
) {
let (mut player, player_data) = player.single_mut();
for j in joystick.iter() {
let Vec2 { x, y } = j.axis();
match j.id() {
JoystickControllerID::Joystick1 => {
player.translation.x += x * player_data.0 * time_step.period.as_secs_f32();
player.translation.y += y * player_data.0 * time_step.period.as_secs_f32();
}
}
}
}
Types
enum VirtualJoystickAxis {
Both, Horizontal,
Vertical,
}
enum VirtualJoystickType {
Fixed,
Floating,
Dynamic,
}
struct VirtualJoystickNode {
pub id: S,
pub border_image: Handle<Image>,
pub knob_image: Handle<Image>,
pub knob_size: Vec2,
pub dead_zone: f32,
pub axis: VirtualJoystickAxis,
pub behaviour: VirtualJoystickType,
}
pub enum VirtualJoystickEventType {
Press,
Drag,
Up
}
struct VirtualJoystickEvent {
pub fn id() -> S;
pub fn get_type() -> VirtualJoystickEventType;
pub fn value() -> Vec2;
pub fn direction() -> VirtualJoystickAxis;
pub fn axis() -> Vec2;
pub fn snap_axis(dead_zone: Option<f32>) -> Vec2;
}
struct VirtualJoystickBundle {
pub fn new(joystick: VirtualJoystickNode) -> Self;
pub fn set_node(mut self, node: Node) -> Self;
pub fn set_style(mut self, style: Style) -> Self;
pub fn set_color(mut self, color: TintColor) -> Self;
pub fn set_focus_policy(mut self, focus_policy: FocusPolicy) -> Self;
pub fn set_transform(mut self, transform: Transform) -> Self;
pub fn set_global_transform(mut self, global_transform: GlobalTransform) -> Self;
pub fn set_visibility(mut self, visibility: Visibility) -> Self;
pub fn set_computed_visibility(mut self, computed_visibility: ComputedVisibility) -> Self;
pub fn set_z_index(mut self, z_index: ZIndex) -> Self;
}
Issues
TODOs
- Add more documentation
- Fix movement of Dynamic joystick