Which do you think would be more efficient?

Started by ForeverZer0, July 25, 2014, 08:05:56 am

Previous topic - Next topic

ForeverZer0

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
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
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?
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

ArcaneAlchemy

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.
"Wait? Do I look like a waiter?" -Kefka

Blizzard

I think that method #2 would be slower, because of the way how Windows handles event messages.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

ForeverZer0

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.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Blizzard

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.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

ForeverZer0

July 25, 2014, 10:03:43 am #5 Last Edit: July 25, 2014, 01:17:47 pm by ForeverZer0
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 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.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.