ggez-goodies
ggez-goodies copied to clipboard
switching between input bindings and raw input events
What's a good way of switching between input events and the raw key codes. Say if I wanted an input dialogue to let a player input their name? I'm happy to work on this but wanted some input before going ahead and making something up that would just get rejected.
I'd just capture ggez
's raw events and optionally handle them before feeding them into the InputState
. If you're using ggez 0.4, then the Event::TextInput
event might be useful to you, since IIRC it handles localization and such as well.
that sounds useful, my only thing was that I'd need to rewrite some parts of SceneStack
to allow the keyevents to goto the Scene
as I'd only want it for specific Scenes
, and I didn't want to go tearing up the existing code if there was a better way.
fn key_down_event(
&mut self,
_ctx: &mut Context,
keycode: event::KeyCode,
_keymods: event::KeyMods,
_repeat: bool,
) {
if let Some(ev) = self.input_binding.resolve(keycode) {
self.scene_stack.input(ev, true);
self.scene_stack.world.input.update_effect(ev, true);
}
}
so I think I might of copied this from your ludum dare entry, but scenes only take the InputBindings
So I've been puzzling over this and I think I've come up with a solution which doesn't require changes to ggez goodies (apart from stuff for 0.5). I took a look at amethyst state as you suggested in the push/pop ticket and that gave me the idea
instead of only sending binded events through the scene as I was doing (like below)
//input.rs
pub type InputBinding = input::InputBinding<Axis, Button>;
pub type InputEvent = input::InputEffect<Axis, Button>;
pub type InputState = input::InputState<Axis, Button>;
/// main.rs
impl event::EventHandler for MainState {
fn key_down_event(
&mut self,
_ctx: &mut Context,
keycode: event::KeyCode,
_keymods: event::KeyMods,
_repeat: bool,
) {
if let Some(ev) = self.input_binding.resolve(keycode) {
self.scene_stack.input(ev, true);
self.scene_stack.world.input.update_effect(ev, true);
}
}
You can instead have the Input event as an enum of the binded InputEvent
and have a RawInputEvent
as well, this way you passing either a binded event or the raw event to you scene through input
//input.rs
#[derive(Debug)]
pub struct RawInputEvent {
pub keycode: KeyCode,
}
pub type InputBinding = input::InputBinding<Axis, Button>;
pub type BindedInputEvent = input::InputEffect<Axis, Button>;
pub type InputState = input::InputState<Axis, Button>;
pub enum InputEvent {
Binded(BindedInputEvent),
Raw(RawInputEvent),
}
//main.rs
impl event::EventHandler for MainState {
fn key_down_event(
&mut self,
ctx: &mut Context,
keycode: event::KeyCode,
keymods: event::KeyMods,
repeat: bool,
) {
self.scene_stack.input(
input::InputEvent::Raw(input::RawInputEvent { keycode }),
true,
);
// this feels a bit ugly as we're calling input twice, but i think it might be ok
if let Some(ev) = self.input_binding.resolve(keycode) {
self.scene_stack.input(input::InputEvent::Binded(ev), true);
self.scene_stack.world.input.update_effect(ev, true);
}
}
and then the game scene can match
between the enum types to either ignore the raw input and just use binded events or use the events. etc
impl Scene<Game, InputEvent> for MyScene {
fn input(&mut self, gameworld: &mut Game, event: InputEvent, started: bool) {
match event {
InputEvent::Raw(raw_input) => ...,
InputEvent::Binded(ev) => ...,
}
}
once I'm done making sure this works and makes sense I can try and write up an example.
That's a pretty good idea! I wonder if it would be easier to have two different input callbacks rather than matching on an enum though? I usually only ever want one type of event or the other, seldom both...
yeah the other way is for Scene
and SceneStack
both to have the key_up_event/key_down_event/text_event mouse gamepad etc
methods from 0.5 and have empty implementations so only scenes that want to use them can override them as they wish.
Noticed a similar issue whilst attempting LD 46, https://github.com/not-fl3/good-web-game/blob/master/src/goodies/scene.rs in good web game they've removed the input binding from the scene stack.
I ended up copy-pasting and adjusting their codes as I just cared about mouse clicks, for a text based game, and didn't want to have to setup a bunch of boiler plate input bindings that I wasn't going to use.
So I think there is a use case for using a scene stack separately from input bindings and just pulling in whatever you need, might be a better approach?