Chaos Project

Game Development => Sea of Code => Topic started by: ForeverZer0 on July 25, 2014, 08:05:56 am

Title: Which do you think would be more efficient?
Post by: ForeverZer0 on July 25, 2014, 08:05:56 am
I haven't run any benchmarks or anything yet, so I am kind of just asking this out of my ass, but here goes.
I am working on the Input module for Rpg.NET, so keep in mind this is not being performed in Ruby, so there are some things that can be done that are not possible with a script. Here is my debate, which of these two directions to take it:

Direction 1 : GetKeyboardState (http://msdn.microsoft.com/en-us/library/windows/desktop/ms646299(v=vs.85).aspx)
This was my original thought. Every time Input.update is called, invoke GetKeyboardState, enumerate the buffer the key states were copied to, and internally calculate and set flags in arrays to store which keys are triggered, released, repeated, etc. This is more or less just the same formula as Custom Controls in ToA, but written in C#.

After thinking about it, I really don't care for this approach. It is perfectly acceptable as a Ruby script, since the options there are more limited, but I am not a fan of the the need to enumerate 256 keys every time the update method is called, and perform a bunch of checks on each key to determine what to do about each.

Direction 2 : WindowProc (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx)
I already have a WndProc function in place that receives any message posted to the window, including key presses, key releases, mouse buttons, mouse wheel, mouse move, and just about anything else you could imagine that has an effect on the window.

My theory is, instead of checking the state of the keyboard every frame, I can simply update the states of the keys as the messages arrive, and do nothing in the meantime. That means no enumerating 256 every frame, and it has the obvious advantage of being an "all-in-one" method that can allow me to seamlessly integrate mouse input, as well as other anything else I want to implement.


My question is, are there any disadvantages of the second approach over the first?
Title: Re: Which do you think would be more efficient?
Post by: ArcaneAlchemy on July 25, 2014, 08:23:41 am
It sounds like even if method #2 would have an input latency, it would by far counter the need to enumerate so many key states in method #1. I'm saying this not knowing if method 2 would even create an input latency in the first place, but it sounds like it would and be extremely minimal.
Title: Re: Which do you think would be more efficient?
Post by: Blizzard on July 25, 2014, 08:28:09 am
I think that method #2 would be slower, because of the way how Windows handles event messages.
Title: Re: Which do you think would be more efficient?
Post by: ForeverZer0 on July 25, 2014, 08:47:29 am
Quote from: Blizzard on July 25, 2014, 08:28:09 am
I think that method #2 would be slower, because of the way how Windows handles event messages.


How so?
Correct me if I am mistaken, but these messages come through the WndProc first, before the application even receives them, and they are passing by whether I am looking at them or not, so where would the slow down come from?

My thinking is that basically by filtering the message before calling the "base.WndProc", I am just peeking at them before the message is posted to the application. I thought it is the same as when installing a hook, you can decide to process the message yourself, and not invoke CallNextHook, meaning the application never receives the message. I thought is was a cleaner solution than installing a keyboard hook.
Title: Re: Which do you think would be more efficient?
Post by: Blizzard on July 25, 2014, 09:37:02 am
The slowdown comes from the fact that messages aren't sent immediately to other windows to be processed. Windows itself decides the priority and hence it can delay your events. On the other hand when you use manual calls that don't depend on the event system (such as direct Win32API calls, however slow they may be), they will be executed immediately. You can't rely on Windows to send you events with no delay. This is the very reason why the cursor highlight lags behind in games and such if the CPU is overloaded. It's a latency between the moment where a cursor position is actually received from the hardware and the moment the game window actually receives it is simply increased. Even using direct Win32API calls gives you input positions with a latency. Try it out on ANY game. Or just run RMXP and use Win32API cursor position API calls to move a sprite around where you cursor is and you will notice a latency. Now imagine how much additional latency you can possibly get if you let Windows decide when it's actually gonna send you the events.
Title: Re: Which do you think would be more efficient?
Post by: ForeverZer0 on July 25, 2014, 10:03:43 am
I see. But if the window is not going to receive the input until the message is posted anyways, does it make any difference whatsoever if it was a few CPU cycles behind? As far as I understand, whatever input that changed will be processed before the game actually receives it anyway, and it will accurately reflect the input from the previous update to the current one, without all the extra calculations and overhead.


EDIT:
Unfortunately, after creating a working version of the entire thing, including detecting mouse movement, double-clicks, mouse wheel, and keyboard input, it's just too much overhead intercepting the messages. I scrapped the thing and have decided to use SetWindowsHookEx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx) to install hooks to monitor input, following the same principle, but without the expensive call. I've only ever installed used it for installing global hooks, but I don't think it will be impossible figuring out how to install it only for the scope of the RGSS Player.