【问题标题】:How can I accept arrow key presses from user input?如何接受来自用户输入的箭头键按下?
【发布时间】:2016-01-01 06:02:24
【问题描述】:

我正在制作一款 RPG 风格的游戏,并且已经到了制作 HUD 的地步。理想的运行方式是这样的:

每秒输出:18
护甲:9
打开库存
打开地牢门

如何注册箭头键以选择打开库存或打开地牢门?这是我到目前为止的代码:

:HUD

set /p damage=DPS:

set /p armor= Armour:

set /p open=Open the Dungeon door! 

set /p inventory= Open Inventory!

【问题讨论】:

  • 批处理无法处理箭头键按下。您的选择是使用 2、4、6 和 8 来模拟数字键盘上的箭头键,或者对选项进行编号并让用户输入带有 set /p 或 choice 的变量(如果您不使用) Windows XP。
  • thx @SomethingDark 你真的很有帮助:D 我不认为我可以再给你一个勾号 :(
  • 我没有将其作为答案发布,因为我不认为“你不能”是一个体面的答案。
  • 对不起.....@SomethingDark
  • 恐怕我不明白你的问题的目的。假设您有一个方法可以在 Batch 变量中接受箭头键按下,并进一步假设用户按下了 UpArrow 并且您在变量中获得了适当的值。在那之后你想做什么?例如,如果向上/向下箭头键是通过 W/S 字母键模拟的,那么这种模拟如何解决您的问题?

标签: batch-file


【解决方案1】:

这是一个涉及 PowerShell 以解释批处理脚本中的箭头键按下的技巧。

@echo off
setlocal

set /P "=Hit an arrow key: "<NUL

:keyloop
call :getKey
if errorlevel 37 if not errorlevel 41 goto key%errorlevel%
goto keyloop

:key37
echo left
goto :EOF

:key38
echo up
goto :EOF

:key39
echo right
goto :EOF

:key40
echo down
goto :EOF

:getKey
powershell "exit($Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown').VirtualKeyCode)"
exit /b %errorlevel%

在反思下面 Klitos Kyriacou 的评论后,我想到最好让 PowerShell 在内部循环,直到关键代码成为有效值。否则,每次按键都会生成一个新的 PowerShell 实例,如果按下了一堆无效键,则会导致延迟。这是解决此问题的一个变体:

@echo off
setlocal

set "getKeyMacro=powershell -noprofile "^
    while (-not (37..40).contains($x)) {^
        $x = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown').VirtualKeyCode^
    }^
    exit($x)^
""

set /P "=Hit an arrow key: "<NUL
%getKeyMacro%
if errorlevel 37 goto key%ERRORLEVEL%
rem // else user hit Ctrl-C.  Exit gracefully.
echo Bye. & goto :EOF

:key37
echo left
goto :EOF

:key38
echo up
goto :EOF

:key39
echo right
goto :EOF

:key40
echo down
goto :EOF

这是一个缩写版本,它让 PowerShell 将键码转换为人类可读的左、上、右或下字符串。它对于在批处理脚本中触发条件逻辑可能没有那么有用,但可以随心所欲地使用它。

@echo off
setlocal

set "getKeyMacro=powershell -noprofile "^
    while (-not (37..40).contains($x)) {^
        $x = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown').VirtualKeyCode^
    }^
    ('left','up','right','down')[$x - 37]^
""

set /P "=Hit an arrow key: "<NUL
%getKeyMacro%

只是为了好玩,我编写了一个菜单选择脚本,让您使用箭头键进行选择。这也展示了一种制作 Batch + PowerShell 混合嵌合体的巧妙方法。

<# : Batch portion
@echo off & setlocal enabledelayedexpansion

set "menu[0]=Format C:"
set "menu[1]=Send spam to boss"
set "menu[2]=Truncate database *"
set "menu[3]=Randomize user password"
set "menu[4]=Download Dilbert"
set "menu[5]=Hack local AD"

set "selection=0"
set "max=5"

:menu
cls
echo     === MENU ===
echo;
for /L %%I in (0,1,5) do (
    if %%I equ !selection! (
        echo --^> !menu[%%I]! ^<--
    ) else (
        echo     !menu[%%I]!
    )
)
echo;
echo Use the arrow keys and Enter to select.

powershell -noprofile -executionpolicy remotesigned "iex ((gc '%~f0') -join \";\")"
goto :key%errorlevel%

:key13 (enter)
echo You chose !menu[%selection%]!.
goto :EOF

:key39 (right)
:key40 (down)
if %selection% lss %max% set /a selection += 1
goto menu

:key37 (left)
:key38 (up)
if %selection% gtr 0 set /a selection -= 1
goto menu

: PowerShell hybrid chimera #>
while (-not ((37..40 + 13) -contains $x)) {
    $x = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown').VirtualKeyCode
}
exit($x)

这是在 PowerShell 中保留菜单导航的另一个版本。这样做的一个好处是powershell 不会在每次更改菜单选择时重新生成,因此它会在较慢的计算机上响应更快。让 PowerShell 输出菜单还允许更改选择的背景颜色。

<# : Batch portion
@echo off & setlocal enabledelayedexpansion

set "menu[0]=Format C:"
set "menu[1]=Send spam to boss"
set "menu[2]=Truncate database *"
set "menu[3]=Randomize user password"
set "menu[4]=Download Dilbert"
set "menu[5]=Hack local AD"

set "default=0"

powershell -noprofile -executionpolicy remotesigned "iex ((gc '%~f0') -join \"`n\")"
echo You chose !menu[%ERRORLEVEL%]!.

goto :EOF
: end batch / begin PowerShell hybrid chimera #>

$menu = gci env: | ?{ $_.Name -match "^menu\[\d+\]$" } | %{ $_.Value }
[int]$selection = $env:default
$fg = $Host.UI.RawUI.ForegroundColor
$bg = $Host.UI.RawUI.BackgroundColor

function getKey {
    while (-not ((37..40 + 13 + 48..53) -contains $x)) {
        $x = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown').VirtualKeyCode
    }
    $x
}

function menu {
    cls
    write-host "   === MENU ===`n" -f $fg -b $bg

    for ($i=0; $item = $menu[$i]; $i++) {
        if ($i -eq $selection) {
            write-host "  > $item <  " -f $bg -b yellow
        } else {
            write-host " $i`: $item" -f $fg -b $bg
        }
    }

    write-host "`nChoose a number or use the arrow keys and Enter to select." -f $fg -b $bg
    1
}

while (menu) {

    [int]$key = getKey

    switch ($key) {

        37 {}   # left or up
        38 { if ($selection) { $selection-- }; break }

        39 {}   # right or down
        40 { if ($selection -lt ($menu.length - 1)) { $selection++ }; break }

        # number or enter
        default { if ($key -gt 13) {$selection = $key - 48}; [void](menu); exit($selection) }
    }
}

【讨论】:

  • 如果你打算使用 Powershell,那么为什么不在 Powershell 中编写整个脚本呢?它是一种比“批处理”更强大的语言。
  • 因为 OP 正在寻找一种交钥匙解决方案来插入他现有的批处理脚本。如果您有 50% 的精力投入到开发 C# 项目中,并来到这里询问如何执行一项小任务,您会觉得用 Python 重写您的项目的建议很有帮助吗?
猜你喜欢
  • 2014-05-10
  • 2021-09-14
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
相关资源
最近更新 更多