{"id":18118377,"url":"https://github.com/sergioribera/virtual_joystick","last_synced_at":"2025-04-14T16:42:23.671Z","repository":{"id":151762030,"uuid":"624727211","full_name":"SergioRibera/virtual_joystick","owner":"SergioRibera","description":"Bevy virtual Joystick for mobile games (Works with mouse on desktop)","archived":false,"fork":false,"pushed_at":"2024-03-25T06:03:22.000Z","size":293,"stargazers_count":33,"open_issues_count":5,"forks_count":14,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-25T17:42:29.168Z","etag":null,"topics":["bevy","bevy-engine","bevy-plugin","bevy-ui","hacktoberfest","rust","ui","ui-components"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SergioRibera.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":["SergioRibera"]}},"created_at":"2023-04-07T05:45:57.000Z","updated_at":"2024-04-12T19:39:27.000Z","dependencies_parsed_at":null,"dependency_job_id":"20a59cc3-7346-4d22-8629-a66f10b2117c","html_url":"https://github.com/SergioRibera/virtual_joystick","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SergioRibera%2Fvirtual_joystick","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SergioRibera%2Fvirtual_joystick/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SergioRibera%2Fvirtual_joystick/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SergioRibera%2Fvirtual_joystick/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SergioRibera","download_url":"https://codeload.github.com/SergioRibera/virtual_joystick/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248918342,"owners_count":21183170,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bevy","bevy-engine","bevy-plugin","bevy-ui","hacktoberfest","rust","ui","ui-components"],"created_at":"2024-11-01T05:10:58.586Z","updated_at":"2025-04-14T16:42:23.652Z","avatar_url":"https://github.com/SergioRibera.png","language":"Rust","funding_links":["https://github.com/sponsors/SergioRibera"],"categories":[],"sub_categories":[],"readme":"# Bevy Virtual Joystick\n![VJoystick_Fixed_Preview](https://user-images.githubusercontent.com/56278796/230562577-e173e567-5b61-402e-929d-3d3172b0da83.gif)\n\n\u003c/br\u003e\n\u003cp align=\"center\"\u003e\n    \u003cimg alt=\"GitHub Workflow Status\" src=\"https://img.shields.io/github/actions/workflow/status/SergioRibera/virtual_joystick/ci.yml?label=ci\u0026style=flat-square\"\u003e\n    \u003ca href=\"https://crates.io/crates/virtual_joystick\"\u003e\u003cimg alt=\"GitHub release (latest by date)\" src=\"https://img.shields.io/crates/v/virtual_joystick\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nCreate and use a Virtual Joystick in a UI for [bevy](https://bevyengine.org/) Game Engine.\n\n# Versions\nAviable and compatible versions\n\n|  bevy  | VirtualJoystick |\n|--------|-----------------|\n|  0.15  |      2.4.0      |\n|  0.14  |      2.3.0      |\n|  0.13  |      2.2.0      |\n|  0.12  |      2.1.0      |\n|  0.11  |      2.0.1      |\n| 0.10.1 |      1.1.2      |\n\n# Features\n- Support Mouse and Touch\n- Easy usage\n- Multiple Joysticks on screen\n- Multiple types of joystick behaviour\n- Track events on Joystick (Press, Drag and Up)\n- Support Axis block (Horizontal, Vertical or Both)\n\n\u003e **NOTE:** To compile android projects you can use [cargo-apk](https://crates.io/crates/cargo-apk) or the [docker-rust-android](https://github.com/SergioRibera/docker-rust-android) project container where you don't have to install or prepare any sdk, for more details see the readme of the mobile projects\n\n### Axis\n| Both (Default)                                                                                                                 | Horizontal                                                                                                                           | Vertical                                                                                                                           |\n|--------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|\n| ![VJoystick_Fixed_Both](https://user-images.githubusercontent.com/56278796/230561082-fc8ceb4f-0d7d-47f8-b4b8-64cdf3d713b9.gif) | ![VJoystick_Fixed_Horizontal](https://user-images.githubusercontent.com/56278796/230561186-76dba677-f7c6-41b2-9ce7-5a347f5ce480.gif) | ![VJoystick_Fixed_Vertical](https://user-images.githubusercontent.com/56278796/230561212-1b2a66a2-4fc0-456a-bfbe-5d0c89e2cd3d.gif) |\n\n### Joystick Types\n| Fixed                                                                                                                          | Floating (Default)                                                                                                                | Dynamic (TODO: Fix movement feel)                                                                                                |\n|--------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|\n| ![VJoystick_Fixed_Both](https://user-images.githubusercontent.com/56278796/230561082-fc8ceb4f-0d7d-47f8-b4b8-64cdf3d713b9.gif) | ![VJoystick_Floating_Both](https://user-images.githubusercontent.com/56278796/230561292-b9bcc015-17fc-4ef5-9a65-2ce8cc69f073.gif) | ![VJoystick_Dynamic_Both](https://user-images.githubusercontent.com/56278796/230561327-3aeb4c1a-f3ee-49e4-84a9-4872f2c261e3.gif) |\n\n# Examples\n- [Mobile](./examples/simple_mobile)\n- [Desktop](./examples/simple.rs)\n- [Multiple Joysticks Mobile](./examples/multiple_joysticks_mobile)\n- [Multiple Joysticks Desktop](./examples/multiple.rs)\n\n# Features\n- inspect: for world inspect with egui inspector\n- [`serde`](https://serde.rs) (default): for serialization support for all types (usable for save and load settings)\n\n```toml\nvirtual_joystick = {\n    version = \"*\",\n    default-features = false,\n    features = [ \"inspect\", \"serde\" ]\n}\n```\n\n# Usage\nCheck out the [examples](./examples) for details.\n\n```sh\n# to run example\ncargo run --example simple -F=inspect\n```\n\nAdd to Cargo.toml\n```toml\n[dependencies]\nbevy = \"0.12\"\nvirtual_joystick = \"*\" # Add your version\n```\n\nThe minimal requirement:\n```rust\nuse bevy::prelude::*;\n// import crate\nuse virtual_joystick::*;\n\n// ID for joysticks\n#[derive(Default, Reflect, Hash, Clone, PartialEq, Eq)]\nenum JoystickControllerID {\n    #[default]\n    Joystick1,\n    Joystick2,\n}\n\n#[bevy_main]\nfn main() {\n    App::new()\n        .add_plugins(DefaultPlugins)\n        // Add plugin to application\n        .add_plugin(VirtualJoystickPlugin::\u003cJoystickControllerID\u003e::default())\n        .run()\n}\n```\n\nCreate Joystick\n```rust\n#[bevy_main]\nfn main() {\n    App::new()\n        .add_plugins(DefaultPlugins)\n        // Add plugin to application\n        .add_plugin(VirtualJoystickPlugin)\n        // Create system\n        .add_startup_system(create_scene)\n        // update System\n        .add_system(update_player)\n        .run()\n}\n\n\nfn create_scene(mut cmd: Commands, asset_server: Res\u003cAssetServer\u003e) {\n    cmd.spawn(Camera2dBundle::default());\n    cmd.spawn_empty().insert(Player(30.));\n\n    // Spawn Virtual Joystick at horizontal center\n    create_joystick(\n        \u0026mut cmd,\n        asset_server.load(\"Knob.png\"),\n        asset_server.load(\"Outline.png\"),\n        None,\n        None,\n        Some(Color::rgba(1.0, 0.27, 0.0, 0.3))),\n        Vec2::new(75., 75.),\n        Vec2::new(150., 150.),\n        VirtualJoystickNode {\n            dead_zone: 0.,\n            id: \"UniqueJoystick\".to_string(),\n            axis: VirtualJoystickAxis::Both,\n            behaviour: VirtualJoystickType::Floating,\n        },\n        Style {\n            width: Val::Px(150.),\n            height: Val::Px(150.),\n            position_type: PositionType::Absolute,\n            left: Val::Percent(50.),\n            bottom: Val::Percent(15.),\n            ..default()\n        },\n    );\n}\n```\n\nUse variable generated by Joystick\n```rust\nfn update_joystick(\n    mut joystick: EventReader\u003cVirtualJoystickEvent\u003cString\u003e\u003e,\n    mut player: Query\u003c(\u0026mut Transform, \u0026Player)\u003e,\n    time_step: Res\u003cTime\u003e,\n) {\n    // Get player\n    let (mut player, player_data) = player.single_mut();\n\n    // Iter each joystick event\n    for j in joystick.read() {\n        let Vec2 { x, y } = j.axis();\n        // Verify ID of joystick for movement\n        match j.id() {\n            JoystickControllerID::Joystick1 =\u003e {\n                // Move player using joystick axis value\n                player.translation.x += x * player_data.0 * time_step.delta_seconds();\n                player.translation.y += y * player_data.0 * time_step.delta_seconds();\n            }\n        }\n    }\n}\n```\n\n# TODOs\n- [ ] WIP: Add more better documentation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsergioribera%2Fvirtual_joystick","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsergioribera%2Fvirtual_joystick","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsergioribera%2Fvirtual_joystick/lists"}