Archive for the ‘GameDev’ Category
Game Engine Input
It’s funny how things have come full circle in the Windows game development world – when it comes to processing player input of course. It used to be back in the day (I think around 2000 or so) that a game engine would use DirectInput to manage user input, but that has now been deprecated in favour of using plain old native Win32 messages.
(Though you still need to use DirectInput for Joysticks that require it, and XInput for newer devices – such as XBox360 gamepads. There’s an article on how to use both side by side.)
I came to this realisation when working on my own engine recently, as I was planning on coding up a nice primarily DirectInput based system, and only using the native windows functions to handle the mouse input when windowed. However after reading an article or two and looking at some of my old projects I decided against it and just used simple windows message handling to get the job done.
Some of the reasons to no longer used DirectInput are:
- That it isn’t really all that direct at all, it just spawns another thread that listens for the input related windows messages and processes them for you.
- It also doesn’t play nice with the user’s input related settings in the control panel, such as the key repeat rate, and mouse speed and acceleration settings.
- And it doesn’t handle international keyboards as well as the alternative.
Additionally it turns out that not only is using the native windows messages easier to code up, but the code is also shorter and it makes the other architecture cleaner and more elegant to boot.
Technical Details
To use the windows messages as input all you need to do is to process all of the relevant messages:
- WM_KEYDOWN, WM_KEYUP – For the regular keystrokes
- WM_SYSKEYDOWN, WM_SYSKEYUP – For the ALT key, can be processed by the same functions as the regular keystrokes.
- WM_MOUSEMOVE – For the mouse movement
- WM_MOUSEWHEEL – For the mouse wheel (Only on Windows XP and above)
- WM_*BUTTONDOWN, WM_*BUTTONUP – (Where * is L, R, M, X) For mouse buttons
- WM_CAPTURECHANGED – Needed to properly handle some aspects of the mouse in windowed mode.
(There is also another way of getting far more precise mouse values using the more generic input messages, but I did not need this for the project so I did not use it. However developers of first person shooters or other twitch games should investigate this method.)
Then pack the data into your own custom structure so that you don’t have to have the windows message handling values all through your code, and then dispatch the data structure to your game state controller for handling.
Implementation Notes
Now there are a few things to watch out for when creating this system, mainly dealing with the processing of mouse based input, and especially when operating in windowed mode.
Mouse Position
You should cache the mouse position as it is received from the WM_MOUSEMOVE message and only dispatch the new mouse position once per frame in an update function or similar. The reason for this is that the mouse update rate is far higher than the frame rate and movements in the mouse can generate many such messages which flood the system. This is especially bad when expensive computations are performed on the movement of the mouse (such as camera orientation/position) as they will suck up all of the CPU time doing the processing.
When switching the mouse from reporting absolute to relative coordinates there are several things that need to happen. The mouse needs to be captured, the cursor hidden, the current coordinates stored for later, and then set to the centre coordinates of the window. I found that sometimes the mouse cursor show count is greater than one, so I repeatedly call the ShowCursor(FALSE) function to make sure it is hidden. Otherwise the user can still see the mouse as it is wildly moving about the centre of the window. Then at the end when switching back into absolute coordinates don’t forget to restore the previous position of the mouse.
Mouse Wheel
For every mouse that I have encountered the value reported is a multiple of 120 units, with 120 (or WHEEL_DELTA in the code) units representing a single “click” or movement of the mouse wheel. As the Microsoft documentation explains this is so that in future we might have mice that scroll at a finer granularity. Therefore I made sure in the processing that I first accumulated the incoming value and then only reported the movement if it moved more than 120 units.
Additionally I discovered that (at least) in debug mode when I scrolled the mouse wheel I would sometimes get multiples of 120 showing up as the incoming delta. Where as I had not seen this behaviour before at work or otherwise. Therefore it is possible to return more than one “click” or significant movement of the scroll wheel in a single message.
Mouse Buttons
When the user presses down on a mouse button within your client area the mouse should be captured by your application. This is so that you will get a mouse button up message when the button is released while the mouse is no longer above your client window. (That’s also why the WM_CAPTURECHANGED message is listed above.)
Keyboard
One tip for dealing with the keyboard is to only report the first instance of a key down message. You can detect this by checking the status flags on the incoming message (Bit 30 of the wparam parameters I believe, but check the documentation). This blocks the key repeat feature of the messages from going to the rest of your application so you’ll only get one key down event. Hence enable it for the general game but disable it when the user is typing into a text input field, as you’ll want to allow the default system key repeat settings to take effect.
That’s it for now. Hopefully this has helped someone that was in a similar situation to me before.
Game Engine Update
This is an update on the game development project I am working on as a hobby. Initially the goal was to make an engine and a small game an enter it into the TSumea AI programming challenge. However I wasn’t able to complete the entry in time as I really bit off far more than I could chew.
It came down to the fact that developing an engine, a game, and an interesting AI simulation is far more for one person to do in three weeks of hard coding. There are some questions to consider as to why I didn’t have an entry ready.
- Maybe I could have used an existing open source engine – but none of them gelled with me nicely.
- Maybe I could have started developing the game and engine back in September (when the challenge started) – but there were work deadlines to make.
Regardless, the final result is that I didn’t get the engine or game completed. Not only that, but from all the people that suggested interest in the challenge there was only one final entry. How disappointing.
But still I have developed something that looks like an engine.
In three weeks “working” about 12 to 16 hours a day of programming/research I have managed to create a nice engine, with (what I hope is) a good architecture underneath it. I even spent a weekend working out mathematical and physics formulae (for collision detection and response) on my Tablet PC, and I can honestly say that I haven’t done that much mathematics since University.
(I have to note that it’s quite nice to scribble out mathematics on a tablet. As you can use normal handwriting with the correct mathematical symbols and all on a grid ruled background. Also you can move stuff around and erase with ease if you make a mistake.)
For the time spent on the project I have had a blast. It reminded me of the good old Uni days staying up till the early hours in the morning coding, and yes I did that this time as well. I learnt to use some interesting bits of the Boost library, experimented with better ways of writing game architecture code, and re-learnt a whole bunch of mathematics and phyics.
However the engine and game is not complete, and since I stopped working on it on the 15th I haven’t done much to it since. (I’ve been playing games instead!) But I’ll start working on it again now and see if I can create a decent game out of it. Also I have a couple of articles that are in various stages or preparation and will post them when they are done.
Have a happy new year too!
Writing a new Game Engine
Since I’ve got some free time now I’ve decided to write a nice and simple 3D engine, again. The main reason for this is to enter a small programming competition, but I’m taking care with the engine design and architecture so that I may use it in the future. Also it will be a nice addition to my portfolio.
My last attempt at making a game engine was over 7 years ago, back when I was learning all of this programming and mathematics stuff. Looking back over the code now I shudder at all of the simple and naive mistakes I made, and the faulty assumptions I was working with. Granted at the time the engine did have some spiffy features like a scriptable Quake3-like shader engine among other things. But in the same vein I made some serious snafu’s, like building my own container classes that could actually return null references! Though overall the learning experience of writing such a large amount of code for a project was the best thing that came out of it. (I’ll post the source code sometime so that people can learn from my mistakes.)
However this time around I’m putting in my years of experience and building this engine right. I’m using existing libraries whenever possible (go STL, ATL/WTL, and other acronyms) and thinking about what I actually need and implementing only that rather than spending a lot of time developing features I won’t use. Hopefully this will mean a reduced development time and a better finished product.
I’m going to update this blog on my progress and post some demos and screen shots of the project as it’s progressing.