7
\$\begingroup\$

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.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ I don't fully understand, but since mega man and the platform move together, then maybe it wouldn't be a horrible thing to bind their movement together. (if they move together like one entity, why not program them to be one entity or at least bind them in some fashion?) \$\endgroup\$ Commented Apr 2, 2011 at 22:01
  • \$\begingroup\$ The way I solved the problem of 'falling after a platform' was to not transition into the falling-state until the player has been out of contact with the floor for at least two frames. The player falls; but the animations don't change so the player doesn't notice. This also handles walking down slopes pretty well. \$\endgroup\$
    – Blecki
    Commented Apr 3, 2011 at 4:48
  • \$\begingroup\$ @Blecki - That may or may not work for me - my system is customizable, so it would be a pretty generic change. Anyway, I'm still interested if anyone knows the "correct" game loop ordering. \$\endgroup\$
    – Tesserex
    Commented Apr 3, 2011 at 4:50

2 Answers 2

2
\$\begingroup\$

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.

\$\endgroup\$
5
  • \$\begingroup\$ Thanks. I think that's a novel approach. The game entities are defined externally, and the biggest reason I wanted it to work without some kind of special connection between them is so that any other falling platforms don't need the same special treatment in order to work. But maybe I can use this type of approach to make it easier to make such platforms. \$\endgroup\$
    – Tesserex
    Commented Apr 4, 2011 at 12:30
  • \$\begingroup\$ The only thing that binds the platform and player is a entity component. Thus, you can create other platforms and not attach this entity component to the player. You leave the platform open to extension, that'll make it easier. \$\endgroup\$ Commented Apr 4, 2011 at 21:05
  • \$\begingroup\$ well the one way I've got it to work so far, I used a hitbox to communicate between the two. So it seems at the moment that there's no simple solution that doesn't create at least a small other object in each case. \$\endgroup\$
    – Tesserex
    Commented Apr 5, 2011 at 1:57
  • \$\begingroup\$ Yeah, but is that small object really a problem? It's only being allocated during one frame once. Very small amount in my opinion. \$\endgroup\$ Commented Apr 5, 2011 at 2:29
  • \$\begingroup\$ Right, it works fine. You just have to remember it every time you create such a platform. \$\endgroup\$
    – Tesserex
    Commented Apr 5, 2011 at 2:38
0
\$\begingroup\$

Okay so in its most basic form a game loop looks like this:

while game is running
    act upon user input
    update all game objects
    re-draw everything to the screen

In your case, what should happen is:

  1. Loop begins.
  2. You update all of the objects based on the key presses that have taken place. Platform moves down.
  3. You then update all of the objects based on their velocities, inside that step should be a collision check to not go the full distance or change their velocities to zero when they hit (go through) walls and put them in the right places.
  4. Now draw it all to the screen, the user has never seen any error states so everything looks great; no jitters ever.

And that is how most of the games I write make it work.

Update: If you need more information on how to write a good game loop then look now further than this good guide.

\$\endgroup\$
2
  • \$\begingroup\$ That article seems to be entirely about how to make the game loop time correctly with the hardware speed. But your suggestion seems to suggest my order is correct. The way you have it I think the problem would still exist. I think I have to do some kind of magic binding the two together. \$\endgroup\$
    – Tesserex
    Commented Apr 3, 2011 at 14:55
  • \$\begingroup\$ @Tesserex: I don't understand; if you change the position of the platform before the player does his gravity check then will he not move down and connect with the platform before the next step has occurred? Without looking at your code it just seems that you have an order of operations problem, thus my post. \$\endgroup\$ Commented Apr 4, 2011 at 5:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .