 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Ethan Guest
|
Posted: Sun Aug 01, 2004 7:57 am Post subject: Accurate Timing |
|
|
I'll start off by admitting my first AHK project is a somewhat frivolous one (recording keystrokes in a game). However, it seems a powerful and useful program, and I've already found a use for it generally that I've added to the ini.
Anyway, back to my game script. It's fairly simple in concept, though it turned out to be somewhat difficult to code (mostly me learning the language and finding out that I'd messed up something because of the lack of complex expressions). The script records key presses of certain keys when recording is turned on, then plays them back when another button is pressed.
The problem (and the reason I needed to write a script at all) lies in the fact that I need to accurately repeat keystrokes that include a lot of precise key holds. Unless I missed it, there seems to be no way to respond to key-up events. As a result what I ended up doing is looping and checking keystate to find the key-up events. The result I've ended up with works... but is not very accurate. Fairly quickly the playback diverges from the original. I've tried setting batchlines to -1 and making the loop as fast as possible without killing performance (just a sleep,0). It still doesn't do it though.
I was wondering if anyone had any suggestions for how to further improve the accuracy of the recording/playback (I'm not sure which is the problem, but I'm assuming it's the recording, since the playback is a fairly simple matter. I suppose problems could occur if the sleep function isn't accurate, since that's what I'm using to delay between key-up/key-down sends, but I don't think this should be a problem). Anyway, AHK is a very handy program, and even if this doesn't work out I'm glad to have learned it (though giving up complex expressions is hard). |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Sun Aug 01, 2004 12:17 pm Post subject: |
|
|
| The only insight I have is that "Sleep 0" will actually sleep for around 20ms or more if the CPU is under load (depending on how many apps are trying to max the CPU simultaneously), which is typical while you're in a game. You might try eliminating the sleeps and instead use "SetBatchLines 10ms" at the top. This should prevent AHK from using any more than 50% of the CPU. |
|
| Back to top |
|
 |
Ethan Guest
|
Posted: Tue Aug 03, 2004 7:47 am Post subject: |
|
|
| I guess what I'm really looking for is a way to respond to key-up and key-down events separately, so perhaps I should add that to the wishlist. At any rate I'll see if there's anything further I can do to improve recording accuracy with what exists in AHK as of now. |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Tue Aug 03, 2004 10:47 am Post subject: |
|
|
Hotkeys that fire upon release are possible, but not directly (a direct feature is on the to-list). To accomplish it indirectly, the key in question must be made a prefix key such as in the following example:
Numpad0 & Numpad1::MsgBox You pressed Numpad1 while holding down Numpad0.
Numpad0::MsgBox You just released Numpad0.
In the above example, Numpad0 has become a prefix key, thus its own action fires upon key-up (but only if you didn't press any other key while holding it down). |
|
| Back to top |
|
 |
Ethan Guest
|
Posted: Wed Aug 04, 2004 1:53 am Post subject: |
|
|
| I really need to respond to both keydown and keyup for the same key, since what I'm trying to generate is essentially the information available on the key history page (a list of key up and key down events and the timing between them for specific keys). I tried enabling and disabling a unused hotkey that used the key in question as a prefix when the key itself fired, but that didn't seem to work very well. Possibly the problem is one that's been resolved (I read the losing shift keys post), so I'll give it a try with the latest version. Otherwise I'll either wait off till there's a more direct way to do it, or just give up and do it via C++. It might be nice to add facilities for accessing the key history programmatically given that it's something the keyboard hook seems to automatically keep track of anyway. Not sure how many other people would use it, since it would mostly duplicate other hotkey and input functionality, but maybe someone would. |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Wed Aug 04, 2004 3:01 am Post subject: |
|
|
You could use the KeyHistory command to display the main window when the script first starts. Then use ControlSend or WinMenuSelectItem to update the window whenever you need it... and use ControlGetText to extract and parse the info you need. Not a very elegant solution of course.
I'm a little surprised that GetKeyState doesn't do the job. It seems the ideal choice since its timing should be accurate to within 10ms on Windows 2k/XP unless the CPU is under heavy load. If your testing shows that it's less accurate than this, perhaps you can post a short test script so that I can try to find out why.
Keep in mind that the timer granularity on Windows 2k/XP is typically 10ms, which means that it is not possible with the features currently in AHK to have any greater precision than 10ms. For example, if two events occur within 75ms apart, the script will see them as either 70ms or 80ms apart instead. The same is true for your playback: Even if you had more precise timings somehow, the playback would suffer from the same lack of precision (though 10ms is very precise when measured in terms of human perception and reaction time). |
|
| Back to top |
|
 |
Ethan Guest
|
Posted: Mon Aug 09, 2004 6:25 am Post subject: |
|
|
I may try the trick you outlined for getting the information from the KeyHistory window, which I'm assuming will be more accurate than what I'm recording, though probably not unless I get ambitious. I've thought it over and I think 10ms should be plenty of accuracy.
All I really need is accuracy comperable or exceeding the framerate of the game in question to make sure everything is the same. Since that's 15ms per frame and up, while there could be problems from a potential 20 second error, I don't think it would cause my replay to diverge from the original as quickly as it does.
I'm starting to suspect the problem is rather one of AutoHotkey not getting the resources it should be due to a very unfriendly multitasking application (the game) which seems to have set it's (windows) priority higher than it should (and also not to yield it's time when it isn't using it). I think the most likely fix/test of this theory would be to up AutoHotkey's main thread priority to high or realtime. I can make sure it's generous about yielding it's time then, because it really doesn't need to do much. Is there any way to do this? The only thread/priority related stuff I could find is for AutoHotkey's internal semi-multitasking. |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Mon Aug 09, 2004 11:46 am Post subject: |
|
|
| Quote: | | I may try the trick you outlined for getting the information from the KeyHistory window, which I'm assuming will be more accurate than what I'm recording |
I do not think it is any more accurate, but it depends on the exact nature of your script (since sometimes, for example, there may be a delay when you press a hotkey caused by an uninterruptible thread). Instead, most likely what is happening is that the accuracy has decreased from 10ms to 20ms due to the CPU being under heavy load. I believe this is because the length of each CPU timeslice is typically 20ms on NT-based operating systems (could be wrong). If true, your timings (and those of the key history window, since it uses the same internal method and clock) could be off by as much as 20ms.
Due to the game being the active window, I think the OS (by default) gives it a slightly higher priority than background processes such as the AHK script.
| Quote: | | ... AutoHotkey not getting the resources it should be due to a very unfriendly multitasking application (the game) which seems to have set it's (windows) priority higher than it should (and also not to yield it's time when it isn't using it). I think the most likely fix/test of this theory would be to up AutoHotkey's main thread priority to high or realtime |
Definitely a possibility. Here is a process setting utility mentioned by Rajat. You can use it to change the priority of the AHK script:
http://www.beyondlogic.org/consulting/processutil/processutil.htm
Example usage: Runwait, e:\dos\utils\process.exe -p autohotkey.exe high,,hide
| Quote: | | I can make sure it's generous about yielding it's time then, because it really doesn't need to do much. Is there any way to do this? |
By default, each script now uses a SetBatchLines of 10ms, which makes it sleep for 10ms after every 10ms of activity. This should make it very cooperative with time-sensitive processes, such as those where the record/playback framerate (such as a game) is crucial. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|