模组:制作指南/APIs/Input
阅读
2024-10-15更新
最新编辑:sizau
阅读:
更新日期:2024-10-15
最新编辑:sizau
← 模组:目录
输入 API 允许您检查和抑制控制器/键盘/鼠标状态。
APIs
检查按键状态
- IsDown
-
您可以通过调用 IsDown(button) 方法来检查当前是否按下了任何控制器/键盘/鼠标按钮。 例如:
bool isShiftPressed = this.Helper.Input.IsDown(SButton.LeftShift) || this.Helper.Input.IsDown(SButton.RightShift);
- GetState
-
要进行更精细的控制,您可以检查相对于上一次游戏 tick 的按键状态:
SButtonState state = this.Helper.Input.GetState(SButton.LeftShift); bool isDown = (state == SButtonState.Pressed || state == SButtonState.Held);
可用的按键状态:
上一次 tick 当前 tick 最终状态 up up None up down Pressed down down Held down up Released
不完整的翻译 本文或部分尚未完全翻译成中文。
欢迎您通过编辑帮助其建设。 |
检查光标位置
GetCursorPosition() 方法提供了三种坐标体系下的光标位置。
例如:
// 在光标位置绘制文本
ICursorPosition cursorPos = this.Helper.Input.GetCursorPosition();
Game1.spriteBatch.DrawString(Game1.smallFont, "some text", cursorPos.ScreenPixels, Color.Black);
抑制输入
你可以通过抑制输入来阻止游戏对控制器/键盘/鼠标的响应。这种抑制会在玩家松开按键前持续生效。这种抑制不会阻止其他mod对输入的处理。
方法 | 效果 |
---|---|
Suppress
|
抑制给定的 SButton 值。 |
SuppressActiveKeybinds
|
对于给定的KeybindList,抑制其中的每个按键输入。 |
IsSuppressed
|
检查给定的 SButton 值是否正在受到抑制。 |
例如:
// 使游戏忽略LeftShift按键的动作
this.Helper.Input.Suppress(SButton.LeftShift);
// 鼠标单击也可以被抑制
this.Helper.Input.Suppress(SButton.MouseLeft);
// 检查某个按键是否被抑制
bool suppressed = this.Helper.Input.IsSuppressed(SButton.LeftShift);
副作用:
- ButtonReleased 事件 会在输入被抑制后的下一个 tick 触发。
- 在按键被抑制期间,类似 helper.Input.IsDown(button) 和 helper.Input.GetState(button) 的方法会表明按键的状态是 released,即使该按键在现实中处于被按下的状态。你可以使用 helper.Input.IsSuppressed(button) 来检查按键是否处于这种情况(它会一直返回 true 直到按键在现实中被松开):
bool isPhysicallyDown = helper.Input.IsDown(button) || helper.Input.IsSuppressed(button);
数据结构
SButton
SMAPI 的 SButton 是一个涵盖了每种控制器, 键盘和鼠标的按键的常量。SMAPI 事件使用此常量,这允许你处理按键按下时不需要区分每种按键的代码。阅读 Modding:Player Guide/Key Bindings 来获取值列表。
SMAPI 提供了把任意其他常量转换为 SButton 的扩展:
SButton key = Keys.A.ToSButton(); // SButton.A
SButton button = Buttons.A.ToSButton(); // SButton.ControllerA
SButton input = new InputButton(true).ToSButton(); // SButton.MouseLeft
你也可以将 SButton 转换为其他常量。这将使用到 TryGet 的途径,因为 SButton 是其他常量的一个超集(比方说,你不能把 SButton.ControllerA 转换成一个 keyboard 值):
SButton value = SButton.A;
if (value.TryGetKeyboard(out Keys key))
...;
if (value.TryGetController(out Buttons button))
...;
if (value.TryGetStardewInput(out InputButton input))
...;
最后两个扩展帮助你检查按键在游戏中如何布局:
SButton button = SButton.MouseLeft;
if (button.IsUseToolButton())
// 使用工具
else if (button.IsActionButton())
// 执行动作
你可以在config model中直接使用 SButton 的值,但是大部分情况下推荐使用 KeybindList。
KeybindList
SMAPI's KeybindList utility lets you manage an arbitrary set of keybindings. A keybind list has any number of keybinds, each of which has any number of button codes. For example, the keybind list "F2, LeftShift + S"
would be pressed if (a) F2 is pressed, or (b) both LeftShift and S are pressed.
You can use a KeybindList directly in your config.json model:
C# model | JSON file | |
---|---|---|
class ModConfig
{
public KeybindList ToggleKey { get; set; } = KeybindList.Parse("LeftShift + F2");
}
|
→ | {
"ToggleKey": "LeftShift + F2"
}
|
And you can then check whether it's pressed directly in your code. For example, in a ButtonsChanged event handler:
private void OnButtonsChanged(object sender, ButtonsChangedEventArgs e)
{
if (this.Config.ToggleKey.JustPressed())
{
// perform desired action
}
}
The KeybindList provides a number of methods depending on your use case:
member | description |
---|---|
KeybindList.Parse(…) KeybindList.TryParse(…)
|
Parse a keybind string like "F2, LeftShift + S" into a keybind list.
|
IsBound
|
Whether the keybind list has any keys bound. For example, this would be false for the strings "None" or "" .
|
Keybinds
|
The individual keybinds. In most cases you shouldn't use these directly. |
GetState()
|
Get the overall keybind state relative to the previous tick. This state is transitive across keybinds; e.g., if the player releases one keybind and immediately presses another within the list, the overall state is Held. |
IsDown()
|
Get whether any keybind in the list is currently down (i.e., the player pressed or is holding down the keys). |
JustPressed()
|
Get whether the player just activated the keybind during the current tick (i.e., GetState() returns Pressed instead of Held).
|
GetKeybindCurrentlyDown()
|
Get the individual Keybind in the list which is currently down, if any. If there are multiple keybinds down, the first one is returned. |
ToString()
|
Get a string representation of the input binding (e.g., "F2, LeftShift + S" ).
|
Caveats:
- Don't use the ButtonPressed event to check keybinds, since it's raised once for each button pressed. If the player presses two keys at once, your keybind would be activated twice. Use ButtonsChanged instead.
ICursorPosition
SMAPI's ICursorPosition provides the cursor position in four coordinate systems:
- AbsolutePixels is the pixel position relative to the top-left corner of the in-game map, adjusted for zoom but not UI scaling.
- ScreenPixels is the pixel position relative to the top-left corner of the visible screen, adjusted for zoom but not UI scaling.
- Tile is the tile position under the cursor.
- GrabTile is the tile position that the game considers under the cursor for the purposes of clicking actions. This automatically accounts for controller mode. This may be different than Tile if that's too far from the player.
This is returned by the this.Helper.Input.GetCursorPosition() method and in the event args for some input events.
The pixel positions are not adjusted for UI scaling (i.e., they're non-UI mode). Whether you need UI or non-UI positions depends how you're using them, so you can use cursorPos.GetScaledAbsolutePixels() or cursorPos.GetScaledScreenPixels() to adjust them automatically for the current mode or Utility.ModifyCoordinatesForUIScale to always get UI mode coordinates.
另见
- Input events
- Modding:Player Guide/Key Bindings 中有一个可用的 SButton 值列表