Easier joystick, mouse and keyboard input handling in Bevy

Overview

ezinput

GitHub crates.io GitHub Actions GitHub Actions
A powerful input-agnostic library targeting complete support to axis and button handling for the Bevy game engine.

Table of contents

  1. About
  2. Branches
  3. Getting started
  4. Examples

About

Input is relative; the library itself currently implements by default keyboard, mouse and gamepad support, but this is subject to change. Please feel free to contribute to the library by submitting pull requests. Touch support is stil planned, but not yet implemented.

ezinput strives to be simple as possible, while still being powerful and flexible without using any unsafe code.

All bindings are stored in a InputView struct, which is passed as a component to your ECS entity. To allow an input method to be handled, you need to add a service marker component (MouseMarker, KeyboardMarker or GamepadMarker) to the ECS entity. You aren't limited to one marker, since you can use multiple markers to handle multiple input methods. An advantage of this implementation is that input views aren't limited to specific input sources, so you can reutilize the same view for multiple input methods just by adding new input receivers to bindings.

Not everything is documented yet or documented with a high level of detail, so any feedback is appreciated. You can contact me on Discord or here on GitHub!

Limitations

  • Touch support is not implemented yet.
  • Input receivers are limited to implemented input sources only.
  • Input sources are a hard-coded enumeration (it might not be that bad in most cases though).

Branches

Branch Bevy version
master ^0.7
bevy_main git (https://github.com/bevyengine/bevy.git)

Getting started

Add the following to your Cargo.toml (replace ^0.3 with the latest version):

[dependencies]
ezinput = "^0.3"
  • use ezinput::prelude::*;
  • Create an input view by using the input! macro. You can see an example here. https://github.com/eexsty/ezinput/blob/master/src/macros.rs#L5-L45
  • Add the ezinput plugin to your application app.add_plugin(EZInputPlugin::<TheNameOfYourBindingsEnum>::default());
  • Add the input view components alongside markers to your ECS entities.
  • Done! You can handle input by using the InputView component! I recommend taking a look at the examples to get a feel for how to use it.
You might also like...
bevy-hikari is an implementation of voxel cone tracing global illumination with anisotropic mip-mapping in Bevy
bevy-hikari is an implementation of voxel cone tracing global illumination with anisotropic mip-mapping in Bevy

Bevy Voxel Cone Tracing bevy-hikari is an implementation of voxel cone tracing global illumination with anisotropic mip-mapping in Bevy. Bevy Version

A simple extension for `bevy-editor-pls` to support tilemap editing right inside the bevy app.

What is this This is a simple tilemap editor plugin, that hooks right into bevy_editor_pls to work with bevy_ecs_tilemap. It works completely within i

Bevy Simple Portals is a Bevy game engine plugin aimed to create portals.
Bevy Simple Portals is a Bevy game engine plugin aimed to create portals.

Portals for Bevy Bevy Simple Portals is a Bevy game engine plugin aimed to create portals. Those portals are (for now) purely visual and can be used t

Plugins and helpful methods for using sepax2d with Bevy for 2d overlap detection and collision resolution.

bevy_sepax2d Plugins and helpful methods for using sepax2d with Bevy for 2d overlap detection and collision resolution. Compatible Versions bevy bevy_

Pixel-Perfect, 2D Renderer for Bevy that Seamlessly Targets Desktop and Web
Pixel-Perfect, 2D Renderer for Bevy that Seamlessly Targets Desktop and Web

bevy_retro ( Screenshot of Bounty Bros. game made with Bevy Retro and Skip'n Go ) Bevy Retro is a 2D, pixel-perfect renderer for Bevy that can target

Bevy plugin helping with asset loading and organisation

Bevy asset loader This Bevy plugin reduces boilerplate when loading game assets. The crate offers the AssetCollection trait and can automatically load

A quick and dirty Space Invaders type game in Bevy, with attached tutorial.

This article is in-development and will be released in full form soon. It'll appear on Medium (my publisher likes that), with this as a the accompanyi

Simple 2d pinball game for testing of bevy and rapier.
Simple 2d pinball game for testing of bevy and rapier.

Pinball2D Using the Bevy game engine and Rapier physics engine for a simple 2D pinball game. pinball2d.mov Wrote a short piece about how the game was

Plotting library for the Bevy game engine with a focus on esthetics and interactivity
Plotting library for the Bevy game engine with a focus on esthetics and interactivity

Plotting library for the Bevy game engine with a focus on esthetics and interactivity. It can handle both data points (see the "minimal", "markers", a

Comments
  • Not working with wasm

    Not working with wasm

    When I try to run in in WASM, the game freezes when I hit a key and I get this in the console:

    panicked at 'time not implemented on this platform', library/std/src/sys/wasm/../unsupported/time.rs:13:9
    
    Stack:
    
    init/imports.wbg.__wbg_new_693216e109162396@http://127.0.0.1:1334/api/wasm.js:402:11
    console_error_panic_hook::hook::hd43dab39c1b4d728@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[5232]:0x7382b4
    core::ops::function::Fn::call::hbcafa04924ac8fe3@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[30565]:0xa73366
    std::panicking::rust_panic_with_hook::h47a0e203360b6c10@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[10643]:0x91727b
    std::panicking::begin_panic::{{closure}}::h0a2ac8d8166919c8@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[21124]:0xa45a4c
    std::sys_common::backtrace::__rust_end_short_backtrace::h3b68e15c55c8ecfa@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[23824]:0xa5b9fe
    std::panicking::begin_panic::h11967a7fb7837f40@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[21303]:0xa479b4
    std::sys::wasm::time::Instant::now::h98dff29c0747cfdf@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[26731]:0xa68e54
    std::time::Instant::now::he732085a9da86d6b@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[30598]:0xa73471
    ezinput::tick::tick_system::{{closure}}::h42bf63e436677384@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[17445]:0xa0b612
    ezinput::tick::tick_system::update_time::h1f527bc26e94fa5d@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[22037]:0xa4f1d2
    ezinput::tick::tick_system::hc79dab676af0f3c2@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[3500]:0x636d03
    core::ops::function::FnMut::call_mut::had64b42826756baf@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[19870]:0xa35de3
    core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut::he482dc8ace2d5404@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[19871]:0xa35e17
    <Func as bevy_ecs::system::function_system::SystemParamFunction<(),Out,(F0,),()>>::run::call_inner::ha8f523b33f28f7cb@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[18051]:0xa18177
    <Func as bevy_ecs::system::function_system::SystemParamFunction<(),Out,(F0,),()>>::run::hdac9d7adf3a961ed@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[16642]:0x9f7d3d
    <bevy_ecs::system::function_system::FunctionSystem<In,Out,Param,Marker,F> as bevy_ecs::system::system::System>::run_unsafe::h1310d6b28a33e78c@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[20967]:0xa43d92
    <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::h2ee523cac9d87440@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[2286]:0x53c40c
    async_task::raw::RawTask<F,T,S>::run::he95d3c13f0abdc47@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[1486]:0x437f32
    async_task::runnable::Runnable::run::h169f4888c01aafa4@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[26668]:0xa68a84
    async_executor::LocalExecutor::try_tick::h7076019877a16c0d@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[9345]:0x8c7a27
    bevy_tasks::single_threaded_task_pool::TaskPool::scope::h31d7e491347f511d@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[3277]:0x60e5fd
    <bevy_ecs::schedule::executor_parallel::ParallelExecutor as bevy_ecs::schedule::executor::ParallelSystemExecutor>::run_systems::h022b464f80f9a2dc@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[1215]:0x3c83dd
    <bevy_ecs::schedule::stage::SystemStage as bevy_ecs::schedule::stage::Stage>::run::h516f05dc5ca94e48@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[382]:0xfbfdb
    <bevy_ecs::schedule::Schedule as bevy_ecs::schedule::stage::Stage>::run::h68d5a2c1d54d961e@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[5698]:0x772b26
    bevy_app::app::App::update::he2df84884381384b@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[9160]:0x8bab1a
    winit::platform_impl::platform::event_loop::EventLoop<T>::run::{{closure}}::he7bb15fbd04f283f@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[421]:0x176ed3
    winit::platform_impl::platform::event_loop::runner::Shared<T>::handle_event::h57dac68780f61f30@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[2937]:0x5cd29c
    winit::platform_impl::platform::event_loop::runner::Shared<T>::run_until_cleared::h57d424e418c6d456@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[2655]:0x592212
    winit::platform_impl::platform::backend::timeout::AnimationFrameRequest::new::{{closure}}::hdda506bb48b4610c@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[18655]:0xa22f48
    <dyn core::ops::function::FnMut<()>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::he00844d1a1abf775@http://127.0.0.1:1334/api/wasm.wasm:wasm-function[22486]:0xa52949
    __wbg_adapter_51@http://127.0.0.1:1334/api/wasm.js:243:6
    real@http://127.0.0.1:1334/api/wasm.js:200:32
    
    
    wasm.js:414:9
    
    opened by idanarye 6
  • just_pressed does not work correctly

    just_pressed does not work correctly

    How to reproduce:

    1. Copy the setup from examples/singleplayer.rs
    2. Replace the code in check_input with this
    use EnumeratedBinding::*;
    use EnumeratedMovementBinding::*;
    
    if let Some(vertical) = query.single().axis(&Movement(Vertical)).first() {
        if vertical.press.just_pressed() {
            println!("just pressed");
        }
    }
    

    Issues:

    1. This code will print "just pressed" more than once when a key for the Vertical axis is pressed.
    2. If the key is held down and auto-repeat is enabled in the OS (it's enabled for me in Windows 10) it will print every frame once auto-repeat starts.

    I believe that 1. is caused by using a fixed value of 75ms in src/press_state.rs instead of something like deltaTime

    // just_pressed
    if let Some(instant) = started_pressing_instant {
        instant.elapsed().as_millis() <= 75
    } else {
        true
    }
    

    but I don't know what would cause 2. (the auto-repeat issue)

    opened by dis-da-moe 3
  • Close #2 - update Bevy version to 0.7

    Close #2 - update Bevy version to 0.7

    Looks like it works just like that - no code changes required.

    I did not change the crate's version - that's your job to decide (e.g. - should the macro crate's version change too?)

    opened by idanarye 1
Owner
Pedro Henrique
🌠 Self-taught backend developer, freelancer, and computer science enthusiast. 15yo
Pedro Henrique
Adds support for wasm/wat assets in Bevy, and enables easier scripting

bevy_wasm_scripting Adds support for wasm/wat assets in Bevy, and enables easy scripting. This is enabled through the wasmer crate. Prepare for public

null 9 Dec 20, 2022
A simple example showcasing how to use Bevy to display a square with acceleration (controllable with your keyboard) that wraps around the screen!

Bevy Wrapping Square example A simple example showcasing how to use Bevy to display a square with acceleration (controllable with your keyboard) that

Luciano Mammino 3 Oct 23, 2022
A 2d top-down shooter written in Bevy, capable of handling 100K enemies

Bevy 2D Shooter This is a 2d top-down shooter written in Rust using the Bevy game engine. It's capable of handling 100K enemies and uses a kd-tree to

Bones-ai 41 Jul 21, 2024
A simple-to-use input manager for the Bevy game engine that empowers players and makes accessibility easy.

Bevy Ineffable A simple-to-use input manager for the Bevy game engine that empowers players and makes accessibility easy. Core tenets Make accessibili

Jazarro 10 Mar 2, 2024
Bevy plugin for a simple single-line text input widget.

bevy_simple_text_input An unambitious single-line text input widget for bevy_ui. Usage See examples/basic.rs. Alternatives If you need more features,

Rob Parrett 9 Oct 3, 2023
Controls the RGB on the keyboard for the Legion 5 Pro from Lenovo. Mostly used for learning a bit of rust.

L5P Keyboard RGB Control Program A fun little experiment. Probably contains bugs. ⚠️ Use at your own risk, the developer is not responsible for any da

null 114 Jan 2, 2023
Turn your keyboard into a typewriter! 📇

Turn your keyboard into a typewriter! ?? daktilo-demo.mp4 daktilo ("typewriter" in Turkish, pronounced "duck-til-oh", derived from the Ancient Greek w

Orhun Parmaksız 583 Oct 8, 2023
Simple rust asset handling derive macro for enums, and a proc-macro learning resource!

asset-derive Summary • Todos • Docs Summary Simple Rust asset loading derive macro for Enums, and a resource for learning proc-macros! Please feel fre

Shadorain 5 Feb 9, 2023
Minecraft using Bevy and Bevy-Meshem

minecraft_bevy Minecraft_bevy was built to showcase bevy_meshem. After a week of developing it has: Chunk loading / unloading each chunk's mesh is bei

Adam 7 Oct 4, 2023
Minecraft-esque voxel engine prototype made with the bevy game engine. Pending bevy 0.6 release to undergo a full rewrite.

vx_bevy A voxel engine prototype made using the Bevy game engine. Goals and features Very basic worldgen Animated chunk loading (ala cube world) Optim

Lucas Arriesse 125 Dec 31, 2022