Input and User Commands

I just finished implementing the system for handling user input and commands, and I must say that I'm liking how it's turned out. Some of it was planned, some of it I had no choice, and some of it felt like a hack but turned out nice.

The first thing I had to deal with was user input on Windows. Since I'm using the Win32 API, I decided to get my input from WndProc and that the best thing to do would be to queue up all input as it came in, then have the game poll the input queue whenever it wanted user input. So currently, my game loop infinitely runs, and each time around, the game logic allocates energy to objects and gives turns to objects with enough energy. When the player has enough energy for a turn, the game logic polls the input queue. If there is no input waiting, the game logic exits out, and the loop continue until the user HAS pressed a key.

The game logic then takes action based on the key pressed, and code for all sorts of commands gets called. Sometimes the command doesn't actually use the player's turn, so the game logic continues to poll for more input, until the user actually does something that uses up their turn. Energy is taken from the player, and the whole process starts over again.

I really like how Dungeon Crawl takes multiple turns to do certain things, like putting on and taking off armor, eating, etc. To make this work under my system I hacked in a sort of internal command queue to the game logic. If a user command takes multiple turns, fake user input along with helper parameters are placed in an internal queue that gets polled just before the real user input. The internal queue gets consumed first, and things happen automatically without the need for the user to explicitly tell the game to do them.

For example: If you try to put on a helm when you already have one on, the game simply queues up an order to take off the current helm then to put on the new one. If you try to put on heavy armor, the game queues up the command internally along with a timer parameter that keeps track of how many turns are left until the 'putting on' is complete. I really love the realism this provides without causing the user pain.

Eventually I'll need to add in an alerting system that aborts internal commands if certain bad things happen, like a monster comes around. It shouldn't be too difficult, as all I'll have to do is clear the internal queue and only accept user input. But a cool side effect of this whole system is that I'll be able to record and replay entire games simply by feeding the keystrokes the original user made into the input queue! I never ever call getc() or anything of the sort - it all comes from the queue. I'm just now starting to think about the possibilities. A replay could easily be advanced to a certain numeric turn. This could be any arbitrary turn, or one chosen from a recorded list of 'notable moments of the game', like the first encounter with a unique, or the player's HP dropped to 1, or the player arrived at such 'n such town. The user could step through the turns, or let it run at a given speed and watch it like a move. Players could learn tactics from observing others or share battle stories as an actual short clip of the game.

I really am making some good progress with things, and there are a lot of fun game elements that I'm going to be able to start to put into the game.