Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Physique de saut  (Lu 8426 fois)

0 Membres et 1 Invité sur ce sujet

TheArrow

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Physique de saut
« le: Avril 07, 2016, 11:58:51 am »
Salut à tous, je viens vers vous car comme mon titre l'indique j'ai un soucis avec la physique d'un saut 2D.
J'aime bien comprendre quand j'utilise quelques choses donc j'ai commencé à me remémorer mes cours sur la loi de newton.

https://www.kartable.fr/terminale-s/physique-chimie/specifique/chapitres-33/applications-des-lois-de-newton/cours/applications-des-lois-de-newton/22620

Dans ce cours, pour les équations horaires du mouvement on obtient ce système :

OG⎯→{ x(t)=0
          {  y(t)=v0⋅cos(α)⋅t
          { z(t)=−12⋅g⋅t2+v0⋅sin(α)⋅t


Dans le jeu la fonction y(t) correspond à l'axe x et z(t) correspond à l'axe y.
J'ai donc simuler un petit saut, voici le code:

void Game::play()
{
        gState = GAME_STATE::G_RUNNING;
       
        Map map;
        map.load(".\\Data\\Map\\level.map", "tile");

        Character player(sf::Vector2f(0, 0), "player");
        player.setCenter();

        int v_init = 2;
        int angle_init = Utils::pi / 3;
        float t = 0;


        while (getWindow().isOpen() && gState == GAME_STATE::G_RUNNING)
        {
                sf::Event event;
                while (getWindow().pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                                getWindow().close();
                }

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
                {
                        gState = GAME_STATE::G_PAUSED;
                        break;
                }
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                {
                        getView().move(3, 0);
                }

                sf::Vector2f jump;

                jump.x = cos(angle_init) * v_init * t;
                jump.y = -0.5 * Utils::g*pow(t, 2) + v_init*sin(angle_init)*t;

                getView().move(jump);
                t += 0.001;


                getWindow().clear(sf::Color::Black);

                getWindow().setView(getView());
                getWindow().draw(map);

                getWindow().setView(getWindow().getDefaultView());
                getWindow().draw(player);

                getWindow().display();
        }
}

Le soucis c'est que mon personnage monte bien mais il ne redescend jamais ou alors il redescendra dans quelques décennie.

Je ne vois pas trop d'ou peut venir ce soucis, j'ai mis l'incrémentation de t avec des valeurs très petite pour avoir le temps de bien voir la trajectoire.

Si quelqu'un pourrait m'aiguiller sur ce sujet, merci d'avance !

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Physique de saut
« Réponse #1 le: Avril 07, 2016, 12:53:58 pm »
Citer
t += 0.001;
A moins que ton temps entre deux frames soit calé à 1 ms par un procédé qui n'est pas montré dans ce code, il faudra prendre le temps réel plutôt qu'une valeur arbitraire potentiellement très éloignée de la réalité. Utilise sf::Clock par exemple.
Laurent Gomila - SFML developer

TheArrow

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Re : Physique de saut
« Réponse #2 le: Avril 07, 2016, 01:17:11 pm »
J'ai mis le framerate à 60 avec la méthode de RenderWindow, du coup j'ai essayé de mettre 1/60 = 0.016 mais c'est pareil.


kimci86

  • Full Member
  • ***
  • Messages: 128
    • Voir le profil
Re : Physique de saut
« Réponse #3 le: Avril 07, 2016, 01:22:30 pm »
Il me semble que le problème vient surtout de la façon dont tu positionnes ta View.
Tu appelles la méthode move alors que les formules te donnent un position.
Tu dois choisir : soit utiliser la méthode move et indiquer effectivement un déplacement, soit utiliser setCenter avec une position.

TheArrow

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Re : Physique de saut
« Réponse #4 le: Avril 07, 2016, 01:32:48 pm »
J'ai essayé en déplacement le sprite avec setPosition mais le soucis reste le même.
Ca vient surement de mes paramètres utilisés dans la formule mais je trouve pas.

G.

  • Hero Member
  • *****
  • Messages: 1593
    • Voir le profil
Re : Physique de saut
« Réponse #5 le: Avril 07, 2016, 02:21:01 pm »
C'est combien g ?

Avec g = 10 ça monte jusqu'à y = 0.15, donc un sixième de pixel si t'as une vue où 1 unité = 1 pixel donc en gros tu devrais rien voir monter puis descendre tout le temps. (enfin l'inverse, car dans SFML y augmente vers le bas)
Et si g est négatif ça fait que monter (ou descendre) après t = 0

Ensuite déplacer la vue avec move avec ces valeurs là comme tu le fais c'est très douteux. Quand tu dis que tu déplace le sprite (sprite qui ne bouge jamais dans ton code d'ailleurs) avec setPosition tu parles de la vue ?

TheArrow

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Re : Physique de saut
« Réponse #6 le: Avril 07, 2016, 02:31:10 pm »
g = 9.81

Sinon oui pour le fait que ça descend je n'ai pas édité mon code mais j'avais simplement ajouter "-" devant jump.y vu que c'est inversé.

void Game::play()
{
        gState = GAME_STATE::G_RUNNING;
       
        Map map;
        map.load(".\\Data\\Map\\level.map", "tile");

        Character player(sf::Vector2f(0, 0), "player");
        player.setCenter();

        float v_init = 0.15;
        int angle_init = Utils::pi/3;
        float t = 0;

        while (getWindow().isOpen() && gState == GAME_STATE::G_RUNNING)
        {
                sf::Event event;
                while (getWindow().pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                                getWindow().close();
                }

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
                {
                        gState = GAME_STATE::G_PAUSED;
                        break;
                }
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                {
                        getView().move(3, 0);
                }

                sf::Vector2f jump, lastPos, newPos;

                jump.x = cos(angle_init) * v_init * t;
                jump.y = -(-Utils::g*pow(t, 2)/2000 + v_init*sin(angle_init)*t);

                lastPos = player.getPosition();

                newPos = lastPos + jump;
                player.setPosition(newPos);
                t += 0.2;


                getWindow().clear(sf::Color::Black);

                getWindow().setView(getView());
                getWindow().draw(map);

                getWindow().setView(getWindow().getDefaultView());
                getWindow().draw(player);

                getWindow().display();
        }
}
 

Voici le code modifié, ou je déplace le sprite avec setPosition mais plus la vue.
Ça fait bien une parabole depuis que j'ai diminué la vitesse initiale à 0.15 et t avec une incrémentation de 0.2.

Ce qui me pose maintenant soucis c'est que j'aimerais bien savoir comment avoir mathématiquement la bonne valeur de t et de v_init, sans faire ça au pif x)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Physique de saut
« Réponse #7 le: Avril 07, 2016, 03:04:41 pm »
Tu fais toujours un move, sauf que maintenant il est déguisé (getPosition() + jump). Il faut juste faire setPosition(jump).
Laurent Gomila - SFML developer

TheArrow

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Re : Physique de saut
« Réponse #8 le: Avril 07, 2016, 03:10:37 pm »
Je ne comprends pas trop là, je dois obligatoirement ajouter la position actuelle en plus de celle du saut, sinon là mon sprite commence son saut aux coordonnées 0;0, il ne prends pas en compte le placement avant le saut.

nicox11

  • Jr. Member
  • **
  • Messages: 51
    • Voir le profil
Re : Physique de saut
« Réponse #9 le: Avril 07, 2016, 04:22:39 pm »
La loi de newton te donne la position "absolue" (je vais me faire tapper dessus par les vrais physiciens mais tant pis !) en fonction de temps. Elle ne dépends en aucun cas de la position précédente. De cette fait, comme le dit Laurent, il suffit de positionner ton sprite aux valeurs calculées par tes formules.

TheArrow

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Re : Physique de saut
« Réponse #10 le: Avril 07, 2016, 04:27:03 pm »
Oui j'ai bien compris mais quand mon personnage saute il se trouve à des coordonnées x,y dans mon monde 2D et donc les positions du sauts calculées doivent être ajoutées aux positions pour que le saut soit dans la continuité du mouvement non ?

Pour preuve, si je fais setPosition(jump), mon personnage fait bien l'hyperbole mais en partant de 0,0 vu que je calcule les coordonnées du saut sans me baser sur sa position, tandis que si j'y ajoute la position actuelle le saut se fait en partant de là ou il a commencé.


« Modifié: Avril 07, 2016, 04:29:50 pm par TheArrow »

nicox11

  • Jr. Member
  • **
  • Messages: 51
    • Voir le profil
Re : Physique de saut
« Réponse #11 le: Avril 07, 2016, 04:33:58 pm »
Citer
Oui j'ai bien compris mais quand mon personnage saute il se trouve à des coordonnées x,y dans mon monde 2D et donc les positions du sauts calculées doivent être ajoutées aux positions pour que le saut soit dans la continuité du mouvement non ?

Pas avec les formules que tu utilises en tout cas. Tu utilises le temps depuis le début de ton programme. Alors en effet à t=0, ton programme va faire ce que tu demandes. Par contre si tu attends un peu avant de faire le saut, tu vas te rendre compte du problème. Il faut que tu procède par incrément de temps.

Pour la valeur de v_init, on ne peut pas deviner ce que tu veux faire.

Je suppose que tu veux faire un jeu où tu as la possibilité de sauter, si oui voici un bon début de réponse (en anglais mais c'est case obligatoire dans le developpement !) :
http://gamedev.stackexchange.com/questions/29617/how-to-make-a-character-jump
« Modifié: Avril 07, 2016, 04:43:31 pm par nicox11 »

G.

  • Hero Member
  • *****
  • Messages: 1593
    • Voir le profil
Re : Physique de saut
« Réponse #12 le: Avril 07, 2016, 04:36:12 pm »
Ouais mais là ton lastPos, c'est le lastPos + jump au t d'avant, auquel tu ajoutes encore le nouveau t, et ainsi de suite.
En gros ta position à t=0.6 c'est lastPos + jump(t=0) + jump(t=0.2) + jump(t=0.4) + jump(t=0.6)
Au lieu d'être juste lastPos + jump(t=0.6)

Ta formule là elle calcule la position dans un saut à partir du point de départ du saut, pas à partir de la position dans le saut à un t inférieur.

PS: c'est pour un jeu de plateforme ?
« Modifié: Avril 07, 2016, 04:37:54 pm par G. »

TheArrow

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Re : Physique de saut
« Réponse #13 le: Avril 07, 2016, 04:43:24 pm »
Ah oui je vois merci du coup je dois simplement ajouter la position de départ (t = 0) du saut à chaque fois !
En faite c'est comme si le saut recommencé à chaque fois du coup.

Ça fonctionne parfaitement, merci beaucoup pour votre aide !

Oui c'est pour un jeu de plateforme.


Voici le code final pour ceux qui aurait le même soucis :

void Game::play()
{
        gState = GAME_STATE::G_RUNNING;
       
        Map map;
        map.load(".\\Data\\Map\\level.map", "tile");

        Character player(sf::Vector2f(0, 0), "player");
        player.setCenter();

        float v_init = 2;
        float angle_init = Utils::pi/3;
        float t = 0;

        sf::Vector2f lastPos = player.getPosition();

        while (getWindow().isOpen() && gState == GAME_STATE::G_RUNNING)
        {
                sf::Event event;
                while (getWindow().pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                                getWindow().close();
                }

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
                {
                        gState = GAME_STATE::G_PAUSED;
                        break;
                }
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                {
                        getView().move(3, 0);
                }

                sf::Vector2f jump, newPos;

                jump.x = cos(angle_init) * v_init * t;
                jump.y = -(-Utils::g*pow(t, 2)/2000 + v_init*sin(angle_init)*t);


                newPos = lastPos + jump;

                player.setPosition(newPos);
                t += 10;


                getWindow().clear(sf::Color::Black);

                getWindow().setView(getView());
                getWindow().draw(map);

                getWindow().setView(getWindow().getDefaultView());
                getWindow().draw(player);

                getWindow().display();
        }
}
 
« Modifié: Avril 07, 2016, 04:46:55 pm par TheArrow »

G.

  • Hero Member
  • *****
  • Messages: 1593
    • Voir le profil
Re : Physique de saut
« Réponse #14 le: Avril 07, 2016, 04:50:54 pm »
En général on n'utilise pas de formule aussi rigide pour faire un simple jeu de plateforme. On part plutot sur du
position = position + vitesse * delta
vitesse = vitesse + acceleration * delta
mais c'est complètement autre chose