You posted 2 ways you approached the problem.Sure thing, I'll scavenge my old code and post here soon. It'll probably be delayed a little, I am removing Ubuntu from all my machines due to those Amazon features. It's taking me quite some time...
Did you consider the 3rd option that was posted?
Because things such as physics happen on a routine basis. If I can’t jump while in the air I might either need to do a verify of an “isOnGround” flag or ask the physics engine if I am on the ground in order to know if I am able to jump again when the button is pressed.
Since the physics routine is called on each frame at a specific time within that frame, maybe it would be best to just use that call for all the information related to input?
I mean instead of a player spamming input into a keyboard and having the in-game character invoke a million physics queries, perhaps it would be better to just stick to the main game loop and buffer things such as, “isOnGround”, etc. Perhaps physics can be made more efficient by dividing it into a PrePhysics(), Physics(), and PostPhysics() set of calls. Yes? Something that would not be possible if characters handle their own input routines.
And I really hate repeating myself, but that is just the overall framework point-of-view. It ignores the obvious (which I already mentioned) problem in which a character knows what physics is. The character does not control the game. The game controls the character.
Compared to simple callbacks, your system is a shift in the right direction, but not the best way for the example you provided in which you can hold keys etc.This last one is specially preferable since it is easier to create different input types like press and hold. With callbacks I usually messed my entire code up to do simple evaluations in order to call the correct callback...
If you play a modern fighting game such as Persona 4 Arena or BlazBlue: Chronophantasma in training mode, the keys you have pressed are shown on the bottom and span the entire screen length.
Why? Because they handle input the way I described. As a log.
And with inputs as a log you can easily detect the correct input codes for an attack (and I am using a fighting game here as an example because it is the best example of input complicated enough to be suitable for any other type of game).
With an input log, as described by my previous post, you can easily look back and see if a move should be converted to a combo-button hit-button release attack or a button-hit-combo-button release attack. And if neither of those, then if the last button hit was A, do a standard weak attack.
With input becoming exponentially more complex you need the same rate of branch-explosions in order to handle every order of every case.
Look at my example and think about parsing it.
“A was just hit. Look back. Last 3 inputs were 236 (for those not in the game, that’s D, FD, F (for those not in the game, that’s Down, Forward-Down, Forward (for those not in the game, that’s a Ryu fireball (for those not in the game, Ryu is a character from Street Fighter, and he has a fireball, which is done by pressing 236-Y)))), and 236A makes a valid attack. Look back. If B was pressed just before that, it is a super attack. Look back. If B was pressed, held for 2 seconds, and then released, the 236A attack becomes overpowered, but only if the player’s gauge is maxed.
See how this could start to suck trying to parse event-by-event in real-time?
Keeping a log and parsing it at a specific time during the frame is the only way to go.
L. Spiro