维护提醒

BWIKI 全站将于 9 月 3 日(全天)进行维护,期间无法编辑任何页面或发布新的评论。

全站通知:

模组:制作指南/APIs/Input

来自星露谷物语维基
跳到导航 跳到搜索

模组:目录

输入 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 事件使用此常量,这允许你处理按键按下时不需要区分每种按键的代码。阅读 模组:使用指南/按键绑定 来获取值列表。

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|config model]]中直接使用 SButton 的值,但是大部分情况下推荐使用 KeybindList

KeybindList

SMAPI的KeybindList工具允许您管理任意一组键。一个KeybindList 包含任意数量的 keybind 。每个 keybind 有又包含任意数量的按键代码。例如,keybind list "F2, LeftShift + S" 被识别为“按下”当且仅当 (a) F2被按下 (b) LeftShiftS同时被按下。

您可以直接在您的 [[../Config|your config.json 数据模型]]中使用KeybindList

C#模型   JSON文件
class ModConfig
{
   public KeybindList ToggleKey { get; set; } = KeybindList.Parse("LeftShift + F2");
}
{
   "ToggleKey": "LeftShift + F2"
}

然后您可以直接在代码中检查相应按键是否被按下。例如,可以使用[[../Events|ButtonsChanged事件处理器]]:

private void OnButtonsChanged(object sender, ButtonsChangedEventArgs e)
{
   if (this.Config.ToggleKey.JustPressed())
   {
      // perform desired action
   }
}

KeybindList根据您的使用场景提供了许多方法:

成员 描述
KeybindList.Parse(…)
KeybindList.TryParse(…)
将keybind字符串"F2, LeftShift + S"解析为KeybindList。
IsBound KeybindList是否为空。例如,当keybind为"None"""时会返回false。
Keybinds 列表中的各个keybind。大部分情况下不应直接使用。
GetState() 获取相对于前一时刻的keybind状态。此状态是瞬时的;比如说,当玩家松开一个keybind,并立即按下列表中的另一个keybind,则keybind状态为Held
IsDown() 获取列表中是否存在keybind当前被按下(即,玩家按压或按住不放)。
JustPressed() 获取玩家是否在当前时刻激活了keybind(即,GetState()返回Pressed而不是Held)。
GetKeybindCurrentlyDown() 获取Keybind列表中被按下的keybind。若同时有多个keybind被按下,则仅返回第一个。
ToString() 获取此列表的字符串表示(例如"F2, LeftShift + S")。

警告

  • 不要使用ButtonPressed[[../Events|事件]]来检查keybind,因为此事件在每个按键按下时都会触发一次。若玩家同时按下两个按键,则keybind会被触发两次。请转而使用ButtonsChanged

ICursorPosition

SMAPI的ICursorPosition接口提供了光标在四种坐标系中的位置:

AbsolutePixels表示相对于游戏地图左上角的像素位置,该位置已根据缩放级别调整,但未根据UI缩放调整。 ScreenPixels表示相对于可见屏幕左上角的像素位置,该位置已根据缩放级别调整,但未根据UI缩放调整。 Tile表示光标下的地块位置。 GrabTile表示游戏在执行点击操作时认为光标所在的地块的位置。这会自动考虑手柄模式。如果Tile距离玩家太远,则可能与Tile不同。

this.Helper.Input.GetCursorPosition()方法可以返回上述位置信息;某些输入事件的事件参数也可返回上述位置信息。

像素位置根据UI缩放调整(即,它们是UI无关的)。您需要根据自身需求酌情使用UI相关或UI无关的位置。因此,您可以使用cursorPos.GetScaledAbsolutePixels()cursorPos.GetScaledScreenPixels()来根据当前模式自动调整它们,或者使用Utility.ModifyCoordinatesForUIScale,后者总是获取UI相关的坐标。

另见