Moving objects sitting on horizontally moving platforms

The topmost platform in this picture moves left and right. For some reason, however, when I move my little Megaman onto the platform, he does not move with it, instead remaining static. I thought I may be able to solve it by continuing to call the physics handling event for as long as the player remains on the platform, and using it to apply some impulse that'll move the player alongside the platform, but there does not seem to be a way to accomplish this - at least, I haven't been able to find anything while looking through the tutorials, the examples and the API doc. It only covers one-and-done type collision deals which doesn't help me at all.

While looking through the wider web, I did find a possible solution. That's with the use of the Friction value. If I give both the player and the platform friction, then that will make the platform carry the player properly. But that comes with its own problems: even with friction as low as 1, it makes the player move slower while on the platform that they'd otherwise be (right now, moving left and right on the bottom platforms and in the air gives a Speed value of 319, but moving left and right while on the platform lowers it to 223). And also, having any friction at all will make the player cling onto the side of the platform if they hit it from the side and move towards it in the air. I think this could maybe be solved by setting Friction to 1 while the player is stationary but setting it to 0 when in the air or holding left and right. Problem there is that there doesn't seem to be a way to change Friction during runtime either! There's no orxObject_SetFriction nor anything like it.

I feel like there's a really easy solution to all this and I'm just not seeing it for some reason.

Comments

  • That's a really interesting problem. @iarwain might have some tips. Otherwise I can play around with some settings and see I can get something acceptable working.

  • edited September 2019

    I wish there'd be an easy solution but instead there are multiple slightly more complex ones.

    What you're facing is a very common issue that occurs even in some high profile AAA games, especially when there are very few platforming elements in a shooter game, for example. It'll usually manifest itself as jitter for the carried object (I just experienced it earlier this week while playing Borderlands The Pre-Sequel).

    Unfortunately, that type of movement requires a different set of rules than those usually set for most platformers.

    Here are a few leads for potential solutions:

    • the solution you mentioned yourself: modifying the friction coefficients on the fly (I can provide accessors for that in orx). However you'll more than likely encounter corner cases and not get the exact result you'd expect, like slight sliding, potential jitter or weird control feeling during the transitions.
    • add some sort of parenting between the platform and the carried object through the mean of physics joints (weld or prismatic depending on your needs), you can already add/remove joints on the fly between two bodies using orxBody functions. This might also have corner cases and is probably a bit more complex to get right.
    • add some parenting at the engine level (as opposed to the physics simulation mentioned earlier), using orxObject_Attach/orxObject_Detach. This should be easier than the joints solution, however the engine and the physics might fight each other and you might have to temporarily disable collisions between both or something to that effect.
    • have some custom code on the platform that'll apply the movement delta to objects it carries upon detection. That's basically the same as previous one but this time it's not orx doing the update but your own code, and it might be easier to arbitrate any potential disagreement with the physics simulation.

    I've worked on high profile commercial games that had platforming elements in the past, and usually the solution we ended up using was #3 when the engine allowed it or something close to #4. Keep in mind they were all 3D games with more complex physics simulation than what Box2D offers and some of them had their physics engine built around this kind of cases.

    That being said, I find the body collision approach for platformers hard to tweak when making a 2D platformer with physics engines such as Box2D. I think that, for most situation, using raycasts without any solid collision body makes all those situations much more easy to apprehend, including easy support for 1-way platforms/walls, platform parenting (the current issue), control over sliding on slopes without affecting the reactivity of the character itself, better grounding vs air detection, etc...

    If you're interested in this approach, Loki wrote a quick test to experiment with this idea a few years ago that's quite easy to analyze and gives a good insight on what can be achieved with this approach.
    If you compile his project, I recommend running the debug version and setting

    [Physics]
    ShowDebug = true
    

    which will display all the raycasts that are made based on the current movement/location of the character.

    You can find his project at https://bitbucket.org/loki666/boxbot

  • Quick update, I've just pushed new body part accessors for Friction, Restitution and Density. However, as per Box2D itself, you can't change the friction nor the restitution for contacts that already exist.

    So in your case, changing the friction of the part after the contact was created from the collision with the platform might not work as you'd expect.

  • @iarwain I really appreciate the gesture but unfortunately, I wasn't able to test if SetPartFriction worked or not because it's making the code unable to compile. I keep getting an undefined reference to __imp_orxBody_SetPartFriction error no matter what I try.

    Also huge thanks for the link to that project, I'll be sure to study it thoroughly. Using raycasts likely is the better solution.

  • edited September 2019

    @SuperVehicle001 the undefined reference means that your project isn't using the header files that match the compiled library.
    Did you create your project using init? If so, you should only need to compile orx for the flavors you're using and both headers and libraries should be picked up via the ORX environment variable.

  • @iarwain That's what I was missing. Recompiled Orx and now the code compiles, and you were right with what you said earlier - the friction change works but is very inconsistent. I'll definitely be keeping the "platforming using raycasts" project around in case I can't make it work out somehow.

  • Glad the update worked. Good luck with the platforming aspect, let us know how it goes!

Sign In or Register to comment.