#gamepad-input #input #gamepad #joystick #gamedev

input-actions

将PC和游戏手柄输入绑定到应用程序操作的输入系统

2个版本

0.1.1 2022年4月16日
0.1.0 2021年6月1日

#1513 in 游戏开发

自定义许可证

57KB
1.5K SLoC

input-actions

警告:此crate仍在验证中,非常不稳定,直到v1.0.0。您不能依赖其API在不同版本之间的稳定性,且不应用于生产代码。文档可能在首次重大发布之前任何时候都过时。

input-actions是一个受Unity库Rewired (网站)启发的Rust crate。

此crate利用"gilrs"(它使用"rusty-xinput")来处理游戏手柄输入,这两个crate在设备连接时都会暴露出可能引起垃圾邮件级别的日志记录。建议您忽略或限制"gilrs"和"rusty_xinput"日志目标/模块的日志级别。这正在被跟踪https://gitlab.com/gilrs-project/gilrs/-/issues/105

设置

input-actions使用一种“设置并忘记”的方法来管理系统。只要系统在应用程序的生命周期内保持活动状态,并且其update在常规间隔内被调用,其余部分就相当简单。

let mut input_sys = System::new();
input_sys
	// There is only 1 player/user to send inputs for.
	.add_users(1)
	// These action names are complete up to you.
	// It is recommended that you store the strings as static properties
	// so they can be referenced throughout the consuming crate.
	.add_action("button1", Action::new(Kind::Button))
	.add_action("button2", Action::new(Kind::Button))
	.add_action("axis1", Action::new(Kind::Axis))
	.add_action("axis2", Action::new(Kind::Axis))
	// This specifies that there is 1 layout (the default layout, which is equivalent to `None`).
	.add_layout(LayoutId::default())
	// This adds bindings for each action for a given layout.
	// The group of bindings per layout is called an "action set".
	.add_action_set(
		// This specifies the name of the set. `ActionSetId::default()` is equivalent to `None`.
		ActionSetId::default(),
		ActionSet::default().with(
			// This action set contains 1 layout, the default layout added to the system above.
			LayoutId::default(),
			ActionMap::default()
				.bind(
					"button1",
					vec![
						binding::Source::Keyboard(source::Key::Return).bound(),
						binding::Source::Keyboard(source::Key::NumpadEnter).bound(),
						binding::Source::Gamepad(GamepadKind::DualAxisGamepad,
							binding::Source::Button(source::Button::VirtualConfirm
						)).bound(),
					],
				)
				.bind(
					"button2",
					vec![
						binding::Source::Keyboard(source::Key::Escape).bound(),
						binding::Source::Gamepad(GamepadKind::DualAxisGamepad,
							binding::Source::Button(source::Button::VirtualDeny)
						).bound(),
					],
				)
				.bind(
					"axis1",
					vec![
						binding::Source::Keyboard(source::Key::W).with_modifier(1.0),
						binding::Source::Keyboard(source::Key::S).with_modifier(-1.0),
						binding::Source::Gamepad(GamepadKind::DualAxisGamepad,
							binding::Source::Axis(source::Axis::LThumbstickX)
						).bound(),
					],
				)
				.bind(
					"axis2",
					vec![
						binding::Source::Keyboard(source::Key::A).with_modifier(-1.0),
						binding::Source::Keyboard(source::Key::D).with_modifier(1.0),
						binding::Source::Gamepad(GamepadKind::DualAxisGamepad,
							binding::Source::Axis(source::Axis::LThumbstickY)
						).bound(),
					],
				)
		),
	)
	// In order to use action set bindings, the user needs the action set enabled.
	// This call says "all users should have this action set enabled",
	// though it is equivalent to `mark_action_set_enabled` since there is only 1 user in this example.
	.enable_action_set_for_all(ActionSetId::default());

从那里起,就由您来确定何时以及如何发送系统更新,以便它知道哪些操作处于什么状态。

您应该在更新循环中调用System::update(这将更新所有用户的所有操作的状态)。这主要用于游戏手柄输入轮询和更新需要模拟的操作。

input-actions系统还需要了解鼠标和键盘输入,这可以由任何外部源提供。如果您使用winit,您可以使用winit功能,input-actions = { version = "...", features = ["winit"] },并使用下面的代码发送基于窗口的游戏事件

event_loop.run(move |event, _, _| {
	if let Ok((source, input_event)) = input::winit::parse_winit_event(&event) {
		input_sys.send_event(source, input_event);
	}
}

输入动作系统还支持通过 log 功能进行日志记录: input-actions = { version = "...", features = ["log"] }

依赖关系

~3–6.5MB
~129K SLoC