Easier joystick, mouse and keyboard input handling in Bevy

Last update: Jun 11, 2022

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.

GitHub

https://github.com/eexsty/ezinput
You might also like...

An asset that provides 2d collision detector and kinematics, build from scratch in bevy

Busturi A physics engine An asset that provides 2d collision detector and kinematics, build from scratch in bevy How to use Add PhysicsPlugin to the p

Jun 2, 2022

Integration layer between Bevy, puffin and tracing libraries

bevy_puffin This crate integrates the puffin library into Bevy. It provides PuffinTracePlugin to use as a replacement for the Bevy's default LogPlugin

Jun 15, 2022

An adventure survival voxel game written using Bevy and Rust.

An adventure survival voxel game written using Bevy and Rust.

Jun 4, 2022

A Bevy plugin for loading the LDtk 2D tile map format.

A Bevy plugin for loading the LDtk 2D tile map format.

bevy_ldtk ( Tileset from "Cavernas" by Adam Saltsman ) A Bevy plugin for loading LDtk tile maps. Usage use bevy::prelude::*; use bevy_ldtk::*; fn mai

Jun 3, 2022

Basic first-person fly camera for the Bevy game engine

bevy_flycam A basic first-person fly camera for Bevy 0.4 Controls WASD to move horizontally SPACE to ascend LSHIFT to descend ESC to grab/release curs

Jun 20, 2022

An ergonomic physics API for bevy games.

Heron An ergonomic physics API for 2d and 3d bevy games. (powered by rapier) How it looks like fn main() { App::build() .add_plugins(DefaultPlug

Jun 16, 2022

Inspector plugin for the bevy game engine

Inspector plugin for the bevy game engine

bevy-inspector-egui This crate provides the ability to annotate structs with a #[derive(Inspectable)], which opens a debug interface using egui where

Jun 22, 2022

A plugin for Egui integration into Bevy

A plugin for Egui integration into Bevy

bevy_egui This crate provides a Egui integration for the Bevy game engine. Features: Desktop and web (bevy_webgl2) platforms support Clipboard (web su

Jun 21, 2022

Crossterm plugin for the bevy game engine

Crossterm plugin for the bevy game engine

What is bevy_crossterm? bevy_crossterm is a Bevy plugin that uses crossterm as a renderer. It provides custom components and events which allow users

Jun 13, 2022
Comments
  • 1. 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/[email protected]://127.0.0.1:1334/api/wasm.js:402:11
    console_error_panic_hook::hook::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[5232]:0x7382b4
    core::ops::function::Fn::call::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[30565]:0xa73366
    std::panicking::rust_panic_with_hook::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[10643]:0x91727b
    std::panicking::begin_panic::{{closure}}::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[21124]:0xa45a4c
    std::sys_common::backtrace::__rust_end_short_backtrace::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[23824]:0xa5b9fe
    std::panicking::begin_panic::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[21303]:0xa479b4
    std::sys::wasm::time::Instant::now::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[26731]:0xa68e54
    std::time::Instant::now::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[30598]:0xa73471
    ezinput::tick::tick_system::{{closure}}::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[17445]:0xa0b612
    ezinput::tick::tick_system::update_time::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[22037]:0xa4f1d2
    ezinput::tick::tick_system::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[3500]:0x636d03
    core::ops::function::FnMut::call_mut::[email protected]://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::[email protected]://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::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[18051]:0xa18177
    <Func as bevy_ecs::system::function_system::SystemParamFunction<(),Out,(F0,),()>>::run::[email protected]://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::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[20967]:0xa43d92
    <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[2286]:0x53c40c
    async_task::raw::RawTask<F,T,S>::run::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[1486]:0x437f32
    async_task::runnable::Runnable::run::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[26668]:0xa68a84
    async_executor::LocalExecutor::try_tick::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[9345]:0x8c7a27
    bevy_tasks::single_threaded_task_pool::TaskPool::scope::[email protected]://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::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[1215]:0x3c83dd
    <bevy_ecs::schedule::stage::SystemStage as bevy_ecs::schedule::stage::Stage>::run::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[382]:0xfbfdb
    <bevy_ecs::schedule::Schedule as bevy_ecs::schedule::stage::Stage>::run::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[5698]:0x772b26
    bevy_app::app::App::update::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[9160]:0x8bab1a
    winit::platform_impl::platform::event_loop::EventLoop<T>::run::{{closure}}::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[421]:0x176ed3
    winit::platform_impl::platform::event_loop::runner::Shared<T>::handle_event::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[2937]:0x5cd29c
    winit::platform_impl::platform::event_loop::runner::Shared<T>::run_until_cleared::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[2655]:0x592212
    winit::platform_impl::platform::backend::timeout::AnimationFrameRequest::new::{{closure}}::[email protected]://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::[email protected]://127.0.0.1:1334/api/wasm.wasm:wasm-function[22486]:0xa52949
    [email protected]://127.0.0.1:1334/api/wasm.js:243:6
    [email protected]://127.0.0.1:1334/api/wasm.js:200:32
    
    
    wasm.js:414:9
    
    Reviewed by idanarye at 2022-03-09 16:53
  • 2. 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)

    Reviewed by dis-da-moe at 2022-06-05 14:08
  • 3. 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?)

    Reviewed by idanarye at 2022-05-09 13:38
Minecraft-esque voxel engine prototype made with the bevy game engine. Pending bevy 0.6 release to undergo a full rewrite.
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

Jun 18, 2022
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

Jun 8, 2022
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

Jun 21, 2022
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

Jun 19, 2022
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

Feb 5, 2022
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

Apr 15, 2022
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

Jun 2, 2022
Helper functions and structs for working with 2D space in Bevy.

About Baffled by quaternions? Want to accelerate an object in 2D? Wish that there was a simple way to work with grids? Just want to know if two axis-a

May 9, 2022
Rapidly iterate and build Bevy UI's with existing web-based technologies
Rapidly iterate and build Bevy UI's with existing web-based technologies

bevy_webview WIP   Rapidly iterate and build Bevy UI's with existing web-based technologies It is currently very early days of this plugin - only Linu

Jun 19, 2022
2d collision test for game-development in rust (with optional integration and example for bevy)

impacted 2d collision test for game-development in rust (with optional integration and example for bevy) This provides a low-level "narrow-phase" coll

May 6, 2022