@dloizides/game-input

中文文档
1.14.0发布于 2026/11/11MITTypeScriptESM + CJS零依赖近 30 天下载 3164

框架-不可知游戏输入原始. v1 船安全,玩家可切换的概率(Vibration API包装,局部Storage-gated,零道克). 取自Aurora;在EisaiPollis游戏中消费.

中文使用文档
文档目录11 节
  1. 没有捆绑的引导
  2. 安装
  3. 使用量
  4. 语义图案词汇
  5. API 密码
  6. 许可证
  7. 帆布菜单:行走钩(NAV-1)
  8. 标签调试器( T) createTabPager (中文(简体) )
  9. 控制器滚动( O) MenuNav.stick (中文(简体) )
  10. 动作提示 (1.11.0)
  11. 动作芯片( O) createActionPrompts 页:1

@dloizides/游戏输入

框架-不可知游戏输入原始. v1 船安全, 玩家可切换的意外 - 一个薄薄的包裹 在网络振动 API 上, 当禁用、 不支持或屏蔽时, 无法静默地操作, 所以呼叫站点可以 火花和他们的SFX/视觉反馈一起无条件.

零运行时间依赖关系. 异态性(不需要DOM lib)—— navigator 和储存是结构性的 注射式),因此它在浏览器游戏,React Industrial shells,以及测试中都起作用.

范围说明: 键盘/游戏板的正常化是有意的 没有 (原始内容存档于2018-03-25). in v1. 被审核的游戏 (Aurora, Morphe) 执行输入,其设计根本不同——没有共同的逻辑 提炼出来 当出现真正的第2种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同种同相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相.

没有捆绑的引导

createSteerInput 用于连续移动(飞行、驱动); createMenuNav 还行菜单. dist/index.mjs 没有导入, 因此一个普通页面可以在没有导入地图的情况下直接加载 :

<script type="module">
  import { createSteerInput, STANDARD_BUTTON } from 'https://cdn.jsdelivr.net/npm/@dloizides/[email protected]/dist/index.mjs';

  const steer = createSteerInput({ surface: canvas, enabled: () => playing });

  function frame() {
    const { x, y, back, pressed, touch } = steer.read();
    move(x, y);
    if (back) exitPlay();
    if (pressed.includes(STANDARD_BUTTON.south)) act();
    drawStick(touch);
    requestAnimationFrame(frame);
  }
  requestAnimationFrame(frame);
</script>

打电话 read() 每帧一次: back 财务报告和审定财务报表 pressed 被读取所消耗。 给 surface 支助科 touch-action: none。从 enabled ,而菜单或对话框则拥有输入;然后按键保留在页面上. touch 带着客户端 px 加上方向盘中的媒体点,用于绘制一根棒.

安装

npm install @dloizides/game-input

使用量

import { createHaptics, HAPTIC_PATTERNS } from '@dloizides/game-input';

// One controller per game; the storage key namespaces the player's preference.
const haptics = createHaptics({ storageKey: 'aurora.haptics' });

// Fire unconditionally — disabled/unsupported just no-ops.
haptics.vibrate(HAPTIC_PATTERNS.tap);      // menu navigation / selection
haptics.vibrate(HAPTIC_PATTERNS.success);  // level cleared
haptics.vibrate([0, 14, 24, 14]);          // or your own pattern

// Settings toggle — returns the new state, fires a confirming tick when enabling.
function onHapticsToggle(): boolean {
  return haptics.toggle();
}
haptics.isEnabled();

语义图案词汇

HAPTIC_PATTERNS 是由意图键入的一组共享的调谐振动模式,所以每款游戏使用相同的 感觉而不是重新选择魔法持续时间:

意图图案使用
tap10菜单导航 / 选择/ 撤销/ 重新启动
select12拾取工具/图/项目
lock18东西锁定位置
bump24动作被屏蔽
navigate16门户/翻页
success[0,40,50,90]级别/分组已清除
error[0,14,24,14]致命/破坏性事件
loss[0,40,50,40]玩家丢失/ 掉落
reveal[0,14,20,18,26,24]谜题解析/ 退出打开

API 密码

  • createHaptics(options?) → Haptics —— 说 { isEnabled, setEnabled, toggle, vibrate }无震动 用户手势前 : navigator.userActivation.hasBeenActive 现在在哪里, 否则第一个 pointerdown 编号 : keydown 编号 : touchstart 打开 options.activationTarget (默认) globalThis) (中文(简体) ).
    • options.storageKey (默认) game.haptics) ——上下优惠的本地Storage键.
    • options.enableConfirmation (违约a) 15毫秒勾选;通过 null ——开启时被发射.
    • options.navigator 编号 : options.storage ——注入测试/RN;默认为 globalThis。 。 。 .
  • HAPTIC_PATTERNS, (中文(简体) ), DEFAULT_HAPTICS_STORAGE_KEY, (中文(简体) ), DEFAULT_ENABLE_CONFIRMATION。 。 。 .
  • createGamepadPoller({ getPads, requestFrame, cancelFrame, onAction }) → { start, stop } - 民意调查 第一次连接 W3C 标准 Gamepad 每个帧和调用 onAction(PadAction)。通过 () => navigator.getGamepads(), (中文(简体) ), requestAnimationFrame, (中文(简体) ), cancelAnimationFrame 在浏览器中.
    • 按位置排列的按钮: 南- confirm东 东 back西部地区 view北边 mood, (中文(简体) ), L/R 肩 → pagePrev编号 :pageNext (仅形成边缘).
    • D-pad或左接棒(0.5个死区)- up编号 :down编号 :left编号 :right:起火一次,重复后为380ms后,再每110ms后.
  • stepPad(prev, next, repeat, now) - 传票人背后的纯每帧减少器; IDLE_REPEAT, (中文(简体) ), PAD_ACTIONS, (中文(简体) ), STANDARD_BUTTON。 。 。 .

许可证

麻省理工学院

帆布菜单:行走钩(NAV-1)

一个在画布上绘制菜单的游戏( 没有 DOM 按钮) 发布其菜单状态, 所以共享的行走者 in @dloizides/game-e2e (单位:千美元)expectHookMenuWalkable)可以证明每件物品都可以被箭头和花板所达到:

import { installMenuWalkHook } from '@dloizides/game-input';

installMenuWalkHook({
  screen: () => menu.screenId,          // e.g. 'title', 'settings'
  items: () => menu.items.map((i) => i.id),
  focused: () => menu.focusedId ?? null,
});

标签调试器( T)createTabPager(中文(简体) )

const pager = createTabPager({ host: dialogEl, ignore: '.h-rail' });
const onPad = (a: PadAction): void => { if (!pager.pad(a)) menuNav.pad(a); };

host 必须保持挂载; 里面的一切可能都重新卸载。 标签需要 role="tab" 内置 a role="tablist", (中文(简体) ), aria-selected,并选择它们的点击处理器;面板是标签的 aria-controls 目标或第一个 role="tabpanel"。箭头和 D-pad 沿着标签行移动焦点,而不切换标签(手动激活); Enter/Space/ 点击,肩部按钮或刷出按钮.

控制器滚动( O)MenuNav.stick(中文(简体) )

const poller = createGamepadPoller({ getPads, requestFrame, cancelFrame, onAction: (a) => menuNav.pad(a), onScroll: (y, now) => menuNav.stick(y, now) });
// own poll loop: menuNav.stick(pad.axes[RIGHT_STICK_Y] ?? 0, now) every frame

右接棒滚动了焦点控件的滚动容器(也就是菜单中第一个可滚动的,包含一个标签面板),并带有一个死区和平方速度曲线;当将焦点控件滚动出视线时,焦点移动到视图中的第一个控件. 向上/向下(d-pad,左棒,箭头键)向上滚动半个视图,而不是在下个控件距离超过一步时,在滚动列表后移动焦点,或缺失(文本页),并仅在容器到尾后才进行包装. 焦点移动将新控件滚动到视图 block: nearest,顺利,除非 prefers-reduced-motion。 。 。 .

动作提示 (1.11.0)

import { createBindings, createInputDeviceTracker, glyphSvg, PadFamily, promptFor } from '@dloizides/game-input';

const binds = createBindings({ actions: ['jump'], keys: { jump: 'Space' }, pad: { jump: 0 }, storageKey: 'surge.binds' });
const tracker = createInputDeviceTracker({ target: window, getPads: () => navigator.getGamepads() });
const prompt = promptFor(binds, 'jump', tracker.current());
const icon = prompt.glyph === null ? '' : glyphSvg(prompt.glyph, tracker.current().family ?? PadFamily.Generic);

打电话 tracker.poll() 每帧一次。 样式格言 --gi-fg 财务报告和审定财务报表 --gi-bg。隐藏的快取(触碰或对该设备没有约束力)不会造成任何结果.

动作芯片( O)createActionPrompts页:1

import { createActionPrompts } from '@dloizides/game-input';

const prompts = createActionPrompts({ bindings: () => binds, onBindingsChanged: (repaint) => binds.onChange(repaint) });
prompts.tag(jumpButton, 'jump');
prompts.tagFixed(pauseButton, 'pause', { key: 'Esc', pad: 'Menu' });
prompts.untag(jumpButton);

每个被标记的控件都得到 data-gi-action (单位:千美元) .gi-chip (单位:千美元)data-kind="key"|"pad"保持一个格子跨度和 .gi-text[data-gi-prompt]. 芯片跟随最后使用的装置和当前绑定,隐藏在触摸上,如果控制器重新发回,则重新附加. 纸被调查 requestAnimationFrame; 通过 schedule: null 调查你自己,或者你自己 tracker属性和类名称为选项(默认为 ACTION_CHIP_DOM) (中文(简体) ).

版本与发布记录

@dloizides/game-input 共发布 21 个版本,首次发布于 2026/06/17;过去 12 个月发布了 21 个版本。

版本发布日期距今
1.14.0latest2026/11/111 天前
1.13.02026/11/0210 天前
1.12.12026/10/2419 天前
1.12.02026/10/2319 天前
1.11.12026/10/2320 天前
1.11.02026/10/2320 天前

关于 @dloizides/game-input 的常见问题

@dloizides/game-input 是什么?

框架-不可知游戏输入原始. v1 船安全,玩家可切换的概率(Vibration API包装,局部Storage-gated,零道克). 取自Aurora;在EisaiPollis游戏中消费.

如何安装 @dloizides/game-input?

在项目目录运行 npm install @dloizides/game-input,或使用 pnpm add / yarn add / bun add。

@dloizides/game-input 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dloizides/game-input 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@dloizides/game-input 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@dloizides/game-input 可以商用吗?

@dloizides/game-input 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@dloizides/game-input 的下载量有多少?

根据 npm 官方下载统计,@dloizides/game-input 在 2026/10/13 – 2026/11/11 这 30 天内被下载 3,164 次,日均约 105 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@dloizides/game-input 还在维护吗?

最新版本 1.14.0 发布于 2026/11/11(1 天前);至今共发布 21 个版本,其中过去 12 个月发布了 21 个;首次发布于 2026/06/17。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。