Skip to content

The sticky situation part 1

19/09/2011

The part of the code I re-written the most is definitively the collisions handling. Collisions handling is the program that makes hitting a wall, walking on a platform, pushing a crate, jumping, dying, bouncing… working properly in a game.

Hopefully, most of those actions are working good in my game. The only thing that I can’t get rid of is the “sticky situation”. It’s a well known situation for those using Box2D. I didn’t find any “perfect solution” to this. Only workarounds that could be featured in “There I fixed it” website.

So, I want to share with you my efforts (and misery) to make the best hit box for the hero of the game. So people won’t do the same mistakes I did and, maybe, a Box2D prophet will read this and show me the light.


Attempt #1

Hit-box 1

Old stuff

This is my first very naive approach to the hero hit-box. As you can see, the hero is a simple round body. The ground and wall collisions are handled by those thin rectangles, called “sensors”, that are placed on the actual wall and ground physics bodies.

The sensors are not part of the physics world. They’re just here to send informations when something touch them.

The ground sensor prevent the hero from jumping when in mid-air. If the hero touches the sensors it means that he’s “grounded” so he has the permission to jump. As soon as he’s not touching it anymore, the permission is revoked. Simple and effective.

So why is the wall sensors are for? Is a big physics box not enough? NO! When the hero is jumping and moving against a wall, all we get is the infamous “sticky situation”! Meaning that the hero stays sticked to the wall until you release the left or right direction. This is something that makes me crazy about Box2D. Why don’t he just slides along the wall onto the floor?

Well, this is because of how velocity is handled in Box2D. As long as the hero has a velocity pushing him in a direction, he will stay sticked to any vertical surfaces. So that’s why I used sensors on the walls as well. They simply cancel the hero’s velocity so he can fall gently.

This was good enough. Simple and effective. Until I started to make more levels.


Attempt #2

Hit Box 2

Not that bad

Making sensors on every surfaces was a pain and was quadrupling the physics bodies in the scene. So I had an idea. Why not putting the sensors on the hero directly? A tutorial on iForce2D (an excellent website about using Box2D) was saying like “Yeah, this is the way to go”.

So I came up with this. The same round body but with the sensors all around. The head sensor is for when the hero is walking upside-down but it does exactly the same as the foot sensor.

I almost believed this was the final attempt. Until the hero got stuck on a cliff. Yeah, the exposed surfaces of the rounded body was sticking to the cliff… Gosh…


Attempt #3

Hit box 3

Not good enough

Well, let’s make a square body then! If it was that simple… So what we have here, it’s that the corner of the main body are stil exposed to collisions without the sensor colliding.

So why not making the sensors the size of the main body? Because the collisions, especially at high speed, are not that precise. Box2D somewhat simulates the collisions but not at every frames. So, the result is that sometimes, the foot sensor hits the wall so the player can wall jump. Even if it’s cool, it’s not what I want. Or worst, the wall sensor hits the ground so the hero can’t move anymore. Bummer!

But, hey, at least, he’s not stuck on cliff anymore!

Conclusion

What I learned here is that I will never ever use a physics engine for a platformer again. There are plenty of “fake” physics that are just enough for this kind of games. But now, I’m too far into the development to restart from scratch. And, honestly, it’s so much fun to play with Box2D. It is far more easy to make physics based puzzles for exemple. So, I will “stick” with it.

I have different hypothesis to fix this sticky situation (which is actually the only issue I have with Box2D). I will try to make different bodies for ground and walls so the sensors will detect which material they’re colliding with and thus, will prevent confusions.

Feel free to share your experiences! I’m very curious to know how you struggled and maybe succeeded with this issue.

And thanks for reading my bad english.

Read part 2.

Advertisements
19 Comments leave one →
  1. 19/09/2011 22:54

    So as I said on Twitter : that’s just a quick / ugly / non flexible / antiethic / whatever spontaneous hack idea, but what about watching the velocity and zeroing it when it goes under a certain threshold ?

  2. 19/09/2011 22:59

    @LiaSae
    En fait le jeu fonctionne plutôt bien. Le problème vient des situations ou le coin du body du héros touche un mur. Là, il reste collé. Je ne peux pas faire les sensors plus grand car, comme expliqué dans le post, il arrive que les sensors latéraux touchent le sol et là le perso reste bloqué. Il faudrait que je fasse des boites différentes pour le sol et les murs pour leurs donner des propriétés différentes. Ce qui va m’obliger à faire des trapèzes, plutôt que des boites (sinon il vont se chevaucher dans les coins).

  3. 19/09/2011 23:07

    Je réagissais principalement à cette phrase-ci : “As long as the hero has a velocity pushing him in a direction, he will stay sticked to any vertical surfaces.”
    Mais peut-être qu’elle signifiait que tant que la flèche est enfoncée, une accélération est appliquée et l’empêche donc de glisser ? Dans ce cas une solution serait de détecter la collision avec le mur (via un ContactListener) et de désactiver temporairement l’accélération par les touches (enfin je suppose).

    Il me semble que j’ai rencontré le problème du peu que j’ai manipulé Box2D (le portage Flash très exactement) … C’était un proto minuscule et un bon gros “hop on jette tout et on recommence” a fait l’affaire, mais je me doute bien que ce n’est guère envisageable ici !

    • 19/09/2011 23:10

      A propos de la détection de collision avec le mur : il n’y a pas besoin de sensor pour ça, les contacts sont reportés même pour les bodies classiques (et j’ai eu l’occasion de constater qu’au moins dans Box2DFlash, un Sensor ne reporte pas les coordonnées des points de contacts et est donc une très mauvaise idée pour certaines tâches !).

    • 19/09/2011 23:13

      Oui c’est exactement ça. Le sensor du mur annule la vélocité du héros. Voir mon comment précédent 🙂

      • 19/09/2011 23:18

        Donc le souci c’est quand un coin touche un coin au final …
        Idée stupide : ajouter des sensors anti murs sur les coins mais ne réagissant pas au sol ?

      • 19/09/2011 23:25

        En fait, étant donné que les murs et le sol sont en fait une même boite, les sensors ne font pas la différence. Je crois que la solution est celle que j’ai donné dans mon premier commentaire. Il faut que je fasse des bodies distinct pour les murs et pour les sols. Et pour ne pas qu’ils se chevauchent, il faut qu’ils aient la forme de trapèze (pour qu’ils s’emboitent sans se toucher). Malheureusement, mon éditeur de niveau ne fait pas de trapèzes… Il va donc falloir que je fasse un programme qui transforme les boites en trapèzes. Youpi!

      • 19/09/2011 23:27

        Ensuite, je pourrais faire des sensors qui font toute la longueur et la largeur du héros et hop! Plus de problèmes!

  4. 19/09/2011 23:35

    (Lia a eu un problème de connexion, on sait pas quand elle va revenir)

    • 19/09/2011 23:41

      OK!

    • 19/09/2011 23:48

      (Elle revient pour 5 minutes grâce aux merveilles d’Ethernet, toujours fiable quand le Wifi fait défaut, merci à meteo d’avoir transmis :p)
      Effectivement, séparer le sol et les murs ne peut être qu’une bonne idée s’ils doivent provoquer des comportement différents. Même si le sol n’est pas toujours à la même hauteur, ça semble logique de séparer les deux.
      A ce moment-là :
      – en cas de contact avec le sol on autorise le saut (ou l’inverse, en cas d’absence, on interdit)
      – en cas de contact avec un mur on désactive le mouvement vers ce mur
      – et sauf si le level design est particulièrement alambiqué ou que j’oublie un cas, je ne suis pas sûre qu’il y ait besoin de trapèzes 😉
      Je laisse donc là la conversation pour ce soir, en espérant avoir aidé à ma modeste échelle.

      • 20/09/2011 00:01

        En effet le level design est assez alambiqué et de plus, il est possible d’inverser la gravité (je te suggère de regarder ma chaîne YouTube pour voir de quoi je parle). Ce qui veut dire que le plafond doit avoir les même propriétés que le sol. Et que oui, il est nécessaire de faire des trapèzes.
        Bonne nuit Amandine et merci pour ta contribution qui m’a permis de mener ma réflexion plus loin 🙂

  5. 20/09/2011 10:45

    WOW! Awesome, this is a very great game! Good job guys!

  6. 20/09/2011 12:40

    Hi there!

    Very interesting topic!

    I already got the same issue and questions (does a platform game need a physics engine?) when I was working on our prototype of Seasons After Fall.

    I was using Box2D too, and I choose to modify the Box2D code to allow some bodies to not have their velocity set by the Box2D engine (in b2Island.cpp mainly), but set by my code instead.
    So I was able to handle the velocity exactly the way I wanted.

    My code was listening to collision with the ground (using edge bodies), and maintained a normal to the “ground”, rejecting some contacts will “wall”.

    For the rest, the states were handled by a state machine.
    For example, when there was at least 1 “ground contact” (i.e. a contact that has a normal contained in a given range), then I was in the standing state, if the velocity was not null on x-axis, then the state machine was able to go to the “run” state, and when I was in a run or stand state, I was able to give the velocity an impulse and go to the “jump” state, etc.

    • 20/09/2011 12:49

      Hey Guillaume, thanks for sharing your experience!
      This is a very interesting insight. But what are edge bodies?
      It doesn’t seem to exist in the port I’m using (for Corona SDK). Can you tell me more about that?

      • 20/09/2011 12:55

        haha, in fact I made a typing mistake, it’s not a body, it’s a shape: the b2EdgeShape shape.

        It consist on a succession of line segments, so it was perfect to make the ground shapes.

        Maybe you don’t have this shape on your port of the library, it’s was not in the Box2D library from the beginning, but it appears in 2009, I don’t know the exact version of the c++ lib.

      • 20/09/2011 14:10

        Ok now I see what you’re talking about.
        Actually I’m using a state machine more or less like you described it.
        I’m not skilled enough to modify Box2D but I will start by having different bodies for walls and floors (right now, the levels are built with big boxes).
        So it will be easier to manage who collides what.

Trackbacks

  1. The sticky situation part 2 «

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: