Saturday, July 1, 2017

collision detection - Correct order of operations in a platformer game loop


I've run into an issue with my Mega Man engine, and the structure of my game loop is making it very difficult to fix. With Rush Jet, or any falling platform, Mega Man needs to stay attached to the platform as it falls. Right now the best I can do (without resorting to workarounds like magic forcefields that pull him down) has it so that he falls for a single frame when the platform first starts falling. But even this requires the falling platform to pull him down during the collision check. Without this extra step, he constantly "jitters" in falling as the platform descends.


The order of events in my game loop is making this happen. It goes like this:



  1. Mega Man and Rush Jet are flying horizontally for a while.

  2. Thinking phase: Player presses down - the platform decides to set its velocity to downward.

  3. Action phase: Platform moves down, player has no awareness of this.

  4. Reaction phase: The two are not colliding, so no "binding force" check can occur.

  5. Next frame, Mega Man falls. A frame later, gravity catches up and he lands on the platform again, resetting his y velocity to 0.



You can see there the basic order of my loop:



  1. Thinking phase, where you analyze collisions from the previous frame, and any other variables, to decide on state transitions and other adjustments.

  2. Action phase - everyone moves according to their velocity.

  3. Reaction phase - collision checks, adjust positions to fix them. This also handles effects like moving platforms, eg. push the player by some amount. The changes to his velocity are applied in the next frame, during the action phase.


I've tried reordering these steps and various other changes, but they all make the whole thing much worse, with all sorts of bugs. If I need to make sweeping changes to my engine to get these things right, I'd rather know what the "proper" way is before wasting any time.


I know one possible solution would be for the movement step to look at who was touching the platform in the previous frame and pull him then, so they actually move together. That seems too complex though, reaching between components like that. My engine code already feels way more complicated than the original game could have been, suggesting that I'm doing something wrong.


So is there a proper sequence of events? There's another question on here about moving things along with a platform, but that doesn't address the order of events issue which causes my problem. Also, if anyone actually knows the way the classic Mega Man games did it, that would obviously be a huge help.


Find as much of my code as you want at https://github.com/Tesserex/C--MegaMan-Engine/tree/master/Mega%20Man. The CollisionComponent and MovementComponent may be the most useful.




Answer



I know this answer doesn't fit with the title of this question, but I think it could solve your problem.


I looked at your code base and you have an aggregative component design for composing game entities. I'm guessing the rush jet has it's own game entity and list of components ("rush jet" is what I'll be calling this moving platform, yes I know nothing about mega man games). If this is the case, you should try to pass the rush jet a player game entity and set up some kind of bridge (not the best term to use).


For this "bridge", I would have the rush jet not take input from the keyboard. Instead, the player would take input and in your message system (the one for the game components in an entity) you could have another game component tied to the rush jet that would also intercept the movement message. Thus, the player and the platform would both be moved together. Once the rush jet is gone, the game component that serves as a bridge between the rush jet and player would be disposed of and removed.


I think this is a plausible alternative. The movement occurs in your game loop and then the collision checks occur to make sure the rush jet and the player are within bounds. I also believe it is perfectly fine for the rush jet to be dependent upon the player in this way. It's not the most sublime solution, but it'll probably work.


PS: I like your code base. The code isn't the best, but it's nice.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...