C'est un peu du bidouillage ce saut, mais si ça te va y'a pas de pb
Voici un exemple pour illustrer ce dont on parlait (pseudo code bien sûr, et pas testé):
PERSO *p;
const float G = 0.5f; //Gravité
p->vy = 0; //vy => vitesse y, y => position y
while (1)
{
//1) Gestion du saut
if (keys->pressed.button1) //Début de saut
p->vy = -10; //Il va monter (vitesse de -10)
//2) Collisions
if (MoteurCollisions(p) & TC_BAS) //On touche en bas?
p->vy = 0; //Retour à une vitesse nulle sur le sol
//3) Physique
p->vy += G; //Ajoute la gravité
p->y += p->vy; //Ajoute la vitesse à la position
[...]
}
Et c'est là que la gestion physique est intéressante:
p->vy += G;
p->y += p->vy;
Lorsqu'on saute, on va prendre une vitesse de -10, qui sera additionnée à 'y', c'est-à-dire que ton perso va monter de 10 pixels à chaque fois. Mais à cause de la gravité, on ajoute 0.5 à ces -10, qui vont devenir -9.5, -9, -8.5 ... -0.5, 0, 0.5, 1, 1.5, ..., ainsi son saut va être de plus en plus atténué jusqu'à ce qu'il ne monte plus du tout, et même après il redescendra lorsque sa vitesse y ('vy') sera positive
Résultat tu as un vrai et beau saut qui marche dans tous les cas et le code est assez compact. Maintenant si tu veux gérer les cas spéciaux, c'est simplement une atténuation du saut (poussée vers le bas) si tu lâches la touche pendant la montée du saut. Ainsi:
//Premier coup, au sol
if (keys->pressed.button1 && p->auSol)
p->vy = -10, debutSaut = 1;
//Si on laisse appuyé
if (keys->held.button1 && debutSaut == 1) {
//Le saut continue en de bonnes conditions
}
else if (debutSaut >= 0) {
//Atténuation => gravité suppl, et plus possible d'appuyer par la suite
p->vy += G;
debutSaut = 0;
}
//Dès qu'on a dépassé le sommet du saut, la touche n'a plus d'effet sur la descente
if (p->vy >= 0)
debutSaut = -1;