模拟持久按键
Simulate lasting key press
在我的程序中,我想模拟按键。例如,我想说 Press(KeyA, 1000(,其中第一个参数是 KeyCode,第二个参数是以毫塞孔为单位的时间。KeyA 等是 typedef,这些方法非常适合只需按下一次按钮即可。
void PressKey(INPUT &ip, int keycode, int ms)
{
// Press the key
ip.ki.wVk = keycode; // virtual-key code for the key
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
sleep(ms);
// Release the key
ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
SendInput(1, &ip, sizeof(INPUT));
}
int main()
{
// input event
INPUT ip;
INPUT ipMouse;
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0; // hardware scan code for key
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
PressKey(ip, KeyM, 1000);
我以为按下键,然后等到松开它会算作按住按钮,但事实并非如此。我也不想只说一千次 PressKey(ip, KeyM( 以获得与按住按钮 5 秒钟相同的输入。现在有人如何使程序模拟更长的输入吗?
我将回答更一般的问题"如何使用特定输入重播我的游戏运行?
重播输入、用于分析、检查确定性或用于一般 QA 的诀窍是从游戏处理中分离两个元素:
- 对计时器的任何访问
- 从播放器读取任何输入
如果您的游戏编写良好(没有未定义的行为(,并且具有一组给定的输入和关联的计时,则它的行为应始终相同。同时相同的输入会产生相同的输出。
因此,将 TimeGetTime((、std::clock、rdtsc 或任何你用来读取时间的内容包装到你自己的 getTime(( 函数中。同样,将 win32 输入读取和/或扫描码读取包装到您自己的 getInputs(( 中。
运行游戏,但除了使用它们之外,还要将所有输入和时间戳保存到文件中。日志.txt什么的。理想情况下,您的游戏应该每帧只询问一次时间,但是,嘿,我见过每帧查询数千次当前时间的游戏。
现在,修改游戏,使其不是获取实际输入或真实挂钟,而是从日志文件中获取值。如果您的游戏是确定性的,您现在应该能够重播相同的事件序列。
然后,您可以对其进行分析。请注意,由于时间是从文件中读取的,如果游戏在重播时碰巧变慢,则不是问题。你的角色会跳跃相同的长度,落在同一个地方,等等......它只会看起来更慢。这允许您使用最密集的配置文件设置,即使游戏玩得慢 10 倍,它仍然完全相同,您可以有效地测量花费时间的位置。
它还为您准备了 QA 可以保存重播并可以调试的设置。
记录所有这些工作更多,需要注意不要有任何非确定性。
但是,另一方面,如果您遵循原始建议,则输入注入不会完全同时发生。您将失去一些 QA 重现功能。从运行到运行,行为会有所不同。
探查器开销也会影响计时,使测量有时无效。
所以,我的建议:
- 制作一个接近确定性的游戏(很可能总是会有轻微的差异(
- 将所有输入(包括时间(包装在日志记录函数后面
- 将它们全部保存以记录
- 将它们替换为记录的历史记录以重播
具体解决问题的框架: 游戏不是通过 win32 系统提供输入,而是调用您自己的 getInput((,并在重播时获取存储的输入,从而绕过整个 win32 系统。
但是,没有这样的 API 来模拟按键按住。
测试窗口应用程序时,当您按住键盘上的键时,它将收到连续WM_KEYDOWN
消息。
如果你的应用程序是窗口应用程序而不是控制台应用程序,则可以检测低级键盘挂钩中的第一个WM_KEYDOWN
并启动一个 5 秒的计时器,当计时器超时时,发送一条WM_KEYUP
消息,以便模拟按住。您只能呼叫SendInput
一次并发送一条按键消息。
对于控制台应用程序,它无法挂钩,在指定的时间内重复调用 SendInput 是适合您的解决方案。对此有什么顾虑吗?
- 如何使用Google Mock来模拟gettimeofday()
- G锁定铸造到基础上会释放模拟行为
- 有什么好的方法可以让系统调用代理允许在单元测试中进行模拟
- 落砂模拟碰撞检测C++和SFML
- 在gtest.中使用fff.h模拟系统API
- 谷歌模拟和覆盖关键字
- 用C#中的并集模拟C++嵌套结构
- 在同一模拟中使用静脉和静脉_ inet内容时出现运行时错误
- 在模拟器中使用并集来模拟CPU寄存器有多合适
- 我写了一个C++程序来模拟Enigma机器.我没有得到输出
- 如何模拟不同边数的骰子滚动?
- 模拟持久按键
- 使用SIR模型的疾病爆发模拟
- 在 c++ 中模拟输入并在 JAVA 中读取它?
- 转发变量参数列表以模拟 std::thread
- 如何在谷歌模拟中匹配 C 样式数组
- 如何使用兰德随机化模拟点击
- 模拟GPS数据,以便使用Qt与Traccar一起使用
- QKeyPress - 在Qt中模拟按键
- 如何使用不同的谷歌模拟运行相同的谷歌测试用例?