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

Auteur Sujet: Besoin d'aide déplacement isométrique  (Lu 2595 fois)

0 Membres et 1 Invité sur ce sujet

2ant

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
Besoin d'aide déplacement isométrique
« le: Mars 14, 2015, 06:22:51 pm »
Bonjour je suis en train d'essayer de faire un rpg en 2d isométrique et je ne sais pas comment faire pour le déplacement d'un personnage.

Mon programme de test :



1:position du curseur dans la fenêtre
2:position du curseur dans le "monde"
3:"case" ou est le curseur
4:position d'affichage du sprite sur la case ou est le curseur

Ce que j'aimerais pouvoir faire est un déplacement simple:

- l'utilisateur clique sur une case
- le mage se délace en direction de spriteo à une vitesse donnée
-on continue le déplacement tant que la distance parcourue (trajet) est inférieure à la lougueur du déplacement ou tant que la position du sprite n'est pas le point d'arrivée

Le code :

#include <SFML/Graphics.hpp>

using namespace std;
using namespace sf;

int loading ( 1 );
int largeurfond = 0;

int main()
{
    sf::RenderWindow window(sf::VideoMode(1280, 720,32), "SFML Test",sf::Style::Close);

    window.setVerticalSyncEnabled(true);

    sf::Font font;
        if (!font.loadFromFile("ff.ttf"))
        {
            // error...
        }
        sf::Text text;
        sf::Text text1;
        sf::Text text2;

        text.setFont(font);
        text.setString("Ligne 1");
        text.setCharacterSize(48);
        text.setColor(sf::Color::White);
        text.setPosition(sf::Vector2f(140, 588));

        text1.setFont(font);
        text1.setString("Ligne 2");
        text1.setCharacterSize(48);
        text1.setColor(sf::Color::White);
        text1.setPosition(sf::Vector2f(140, 618));

        text2.setFont(font);
        text2.setString("Ligne 3");
        text2.setCharacterSize(48);
        text2.setColor(sf::Color::White);
        text2.setPosition(sf::Vector2f(140, 650));

    sf::View view(sf::FloatRect(0, 0, 640, 360));

    sf::Color alpha(250,100,250);
    sf::Color fond (128,225,255);

        sf::Texture background;
            if (!background.loadFromFile("test.png"))
            return -1;
        sf::Sprite back;
            back.setTexture(background);
            largeurfond = background.getSize().x;

        sf::Texture splashscreen;
            if (!splashscreen.loadFromFile("Intro.png"))
            return -1;
        sf::Sprite intro;
            intro.setTexture(splashscreen);

        sf::Image mage;
            if (!mage.loadFromFile("mage.png"))
            return -1;
            mage.createMaskFromColor(alpha);
        sf::Texture maget;
            if (!maget.loadFromImage(mage,sf::IntRect(0, 0, 64, 64)))
            return -1;
        sf::Sprite spritemage;
            spritemage.setTexture(maget);
            spritemage.setPosition(sf::Vector2f(480, 160));

        sf::Image textbox;
            if (!textbox.loadFromFile("chatboxx.png"))
            return -1;
            textbox.createMaskFromColor(alpha);
        sf::Texture boxtex;
            if (!boxtex.loadFromImage(textbox,sf::IntRect(0, 0, 1280, 720)))
            return -1;
        sf::Sprite textbo;
            textbo.setTexture(boxtex);
            textbo.setPosition(sf::Vector2f(0,480));



    sf::Clock clock;
    sf::Clock clock2;


    while (window.isOpen())
    {


        if( loading == 1 )
        {
            sf::Time tt = sf::seconds(5.0);
            sf::Time elapsed = clock.getElapsedTime();

            window.draw(intro);
            window.display();

            if (elapsed >= tt)
                    {
                        loading = 0;
                        clock.restart();
                    }
        }

        if( loading == 0 )
        {
            window.setView(view);

            sf::Vector2i position = sf::Mouse::getPosition(window);

            sf::Vector2f worldPos = window.mapPixelToCoords(position);

            string title ( "SFML Test   ");

            std::string posx = std::to_string ( (int)position.x );
            std::string posy = std::to_string ( (int)position.y );

            std::string worldPosx = std::to_string ( (int)worldPos.x );
            std::string worldPosy = std::to_string ( (int)worldPos.y );

            float mousemapx = ( worldPos.x - 320 );
            float mousemapy = worldPos.y;

            float tilemx = ((mousemapy/32) + (mousemapx/64));
            float tilemy = ((mousemapy/32) - (mousemapx/64));

            int tilecx = (int)floor (tilemx );
            int tilecy = (int)floor (tilemy );

            std::string tilex = std::to_string ( tilecx );
            std::string tiley = std::to_string ( tilecy );

            int spriteox =  (320 + (( tilecx - tilecy )*(64/2))) -32;
            int spriteoy = ((( tilecx + tilecy ) * (32/2))) -32;

            std::string spriteorix = std::to_string ( spriteox );
            std::string spriteoriy = std::to_string ( spriteoy );

            sf::Vector2f spriteo (spriteox,spriteoy);

            title += "Pos Window ";
            title += posx;
            title += " ";
            title += posy;
            title += "    ";
            title += "Pos World ";
            title += worldPosx;
            title += " ";
            title += worldPosy;
            title += "    ";
            title += "Tile ";
            title += tiley;
            title += ":";
            title += tilex;
            title += "    ";
            title += "Spriteorigin ";
            title += spriteorix;
            title += ":";
            title += spriteoriy;


            window.setTitle(title);


            sf::Event event;
            while (window.pollEvent(event))
            {
                switch (event.type)
                {
                    // window closed
                    case sf::Event::Closed:
                        window.close();
                        break;

                    // key pressed
                    case sf::Event::KeyPressed:
                        {
                            if (event.key.code == sf::Keyboard::S)
                                {
                                    view.move(0, -32);
                                }
                            else if (event.key.code == sf::Keyboard::X)
                                {
                                    view.move(0, 32);
                                }
                            else if (event.key.code == sf::Keyboard::W)
                                {
                                    view.move(-64, 0);
                                }
                            else if (event.key.code == sf::Keyboard::C)
                                {
                                    view.move(64, 0);
                                }
                        }
                        break;

                    case sf::Event::MouseButtonPressed:
                        {
                            if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left)
                                {

                                }
                        }
                        break;
                    default:
                        break;
                }


        }

        window.setView(view);


        window.clear(fond);
        window.draw(back);
        window.draw(spritemage);

        window.setView(window.getDefaultView());

        window.draw(textbo);
        window.draw(text);
        window.draw(text1);
        window.draw(text2);

        window.display();
    }
    }

    return 0;
}
 

Comme idées pour l'instant j'ai ça :

Point de départ : coordonnés du mage
sf::Vector2f posmage = spritemage.getposition();
sf::Vector2f depart = posmage;//appellé une seule fois
Point d'arrivée : coordonnées correspondant à la case ou j'ai cliqué
sf::Vector2f spriteo (spriteox,spriteoy);
Trajet parcouru :
float longueur = sqrt (pow((spritox-posmage.x),2)+(pow((spritoy-posmage.y),2));
Longueur du déplacement :
float trajet = sqrt (pow((spritox-depart.x),2)+(pow((spritoy-depart.y),2));//appellé une seule fois
Variable qui me servira plus tard à modifier la vitesse :
int vitesse = 100;

Je suis pas 100%sur de ce que j'ai. Je sais que j'aurais besoin d'utiliser le temps mais je ne sais pas comment faire.

Est ce que quelqu'un peut m'aider à trouvé ( et comprendre ) la solution ou m'orienter vers un tuto pour le même problème?

G.

  • Hero Member
  • *****
  • Messages: 1593
    • Voir le profil
Re : Besoin d'aide déplacement isométrique
« Réponse #1 le: Mars 14, 2015, 10:38:59 pm »
Il te manque des parenthèses là non ?
float longueur = sqrt (pow(((spritox-posmage).x),2)+(pow(((spritoy-posmage).y),2));

Enfin bref : vitesse = distance / temps
Ce qu'il te manque dans ton code c'est la distance de laquelle tu veux déplacer ton sprite dans une direction donnée. Donc tu cherches la distance : distance = vitesse * temps

En code.
Calcule la direction dans laquelle ton sprite doit avancer :
sf::Vector2f direction = spriteox - posmage;
Norme ce vecteur :
sf::Vector2f direction = direction / longueur;
Calcule le déplacement à appliquer à ton sprite :
sf::Vector2f deplacement = direction * vitesse * elapsed.asSeconds();
sprite.move(deplacement);

Ça sera déjà un bon départ si tu cherches à avancer tout droit.

2ant

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
Re : Besoin d'aide déplacement isométrique
« Réponse #2 le: Mars 15, 2015, 02:21:53 pm »
Merci pour tes explications mais j'ai pas compris "norme" ;D

Qu'est ce qui est utile/inutile dans ce que j'ai mis comme idées ?

J'ai enlevé tout ce qui était pas utile dans mon code puis j'ai essayé d'intégré ce que tu as mis.
J'ai eu des erreurs,j'en ai résolues mais il m'en reste 2.

Code :

#include <SFML/Graphics.hpp>

using namespace std;
using namespace sf;

int loading ( 1 );
int largeurfond = 0;

int main()
{
    sf::RenderWindow window(sf::VideoMode(1280, 720,32), "SFML Test",sf::Style::Close);

    window.setVerticalSyncEnabled(true);

    sf::View view(sf::FloatRect(0, 0, 640, 360));

    sf::Color alpha(250,100,250);
    sf::Color fond (128,225,255);

        sf::Texture background;
            if (!background.loadFromFile("test.png"))
            return -1;
        sf::Sprite back;
            back.setTexture(background);
            largeurfond = background.getSize().x;

        sf::Texture splashscreen;
            if (!splashscreen.loadFromFile("Intro.png"))
            return -1;
        sf::Sprite intro;
            intro.setTexture(splashscreen);

        sf::Image mage;
            if (!mage.loadFromFile("mage.png"))
            return -1;
            mage.createMaskFromColor(alpha);
        sf::Texture maget;
            if (!maget.loadFromImage(mage,sf::IntRect(0, 0, 64, 64)))
            return -1;
        sf::Sprite spritemage;
            spritemage.setTexture(maget);
            spritemage.setPosition(sf::Vector2f(480, 160));


    sf::Clock clock;
    sf::Clock clock2;


    while (window.isOpen())
    {


        if( loading == 1 )//image d'intro
        {
            sf::Time tt = sf::seconds(5.0);
            sf::Time elapsed = clock.getElapsedTime();

            window.draw(intro);
            window.display();

            if (elapsed >= tt)
                    {
                        loading = 0;
                        clock.restart();
                    }
        }

        if( loading == 0 )//démarrage de la partie jeu
        {


            window.setView(view);

            sf::Vector2i position = sf::Mouse::getPosition(window);//position de la souris dans la fenêtre

            sf::Vector2f worldPos = window.mapPixelToCoords(position);//position de la souris dans le monde

            string title ( "SFML Test   ");

            std::string posx = std::to_string ( (int)position.x );
            std::string posy = std::to_string ( (int)position.y );

            std::string worldPosx = std::to_string ( (int)worldPos.x );
            std::string worldPosy = std::to_string ( (int)worldPos.y );

            float mousemapx = ( worldPos.x - 320 );
            float mousemapy = worldPos.y;

            float tilemx = ((mousemapy/32) + (mousemapx/64));
            float tilemy = ((mousemapy/32) - (mousemapx/64));

            int tilecx = (int)floor (tilemx );//case ou est la souris
            int tilecy = (int)floor (tilemy );//case ou est la souris

            std::string tilex = std::to_string ( tilecx );
            std::string tiley = std::to_string ( tilecy );

            int spriteox =  (320 + (( tilecx - tilecy )*(64/2))) -32;
            int spriteoy = ((( tilecx + tilecy ) * (32/2))) -32;

            std::string spriteorix = std::to_string ( spriteox );
            std::string spriteoriy = std::to_string ( spriteoy );



            title += "Pos Window ";
            title += posx;
            title += " ";
            title += posy;
            title += "    ";
            title += "Pos World ";
            title += worldPosx;
            title += " ";
            title += worldPosy;
            title += "    ";
            title += "Tile ";
            title += tiley;
            title += ":";
            title += tilex;
            title += "    ";
            title += "Spriteorigin ";
            title += spriteorix;
            title += ":";
            title += spriteoriy;
            window.setTitle(title);

            int vitesse = 100;

            sf::Vector2f spritepos (spriteox,spriteoy);//position d'affichage de sprite pour la case ou est la souris

            sf::Vector2f posmage = spritemage.getPosition();

            float longueur = sqrt ( pow ( (spritepos.x - posmage.x),2 ) + ( pow( (spritepos.y - posmage.y ),2 ) ) );

            sf::Time elapsed2 = clock2.getElapsedTime();

            sf::Vector2f direction = spritepos - posmage;

            sf::Vector2f direction = direction / longueur;

            sf::Vector2f deplacement = direction * vitesse * elapsed2.asSeconds();

            sf::Event event;
            while (window.pollEvent(event))
            {
                switch (event.type)
                {
                    // window closed
                    case sf::Event::Closed:
                        window.close();
                        break;

                    // key pressed
                    case sf::Event::KeyPressed:
                        {
                            if (event.key.code == sf::Keyboard::S)
                                {
                                    view.move(0, -32);
                                }
                            else if (event.key.code == sf::Keyboard::X)
                                {
                                    view.move(0, 32);
                                }
                            else if (event.key.code == sf::Keyboard::W)
                                {
                                    view.move(-64, 0);
                                }
                            else if (event.key.code == sf::Keyboard::C)
                                {
                                    view.move(64, 0);
                                }
                        }
                        break;

                    case sf::Event::MouseButtonPressed:
                        {
                            if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left)
                                {
                                    spritemage.move(deplacement);
                                    clock2.restart();
                                }
                        }
                        break;

                default:
                break;
                }
            }

        window.setView(view);
        window.clear(fond);
        window.draw(back);
        window.draw(spritemage);
    }
    }

    return 0;
}
 

Erreurs :



Je comprend les 2 messages d'erreurs mais je vois pas comment les résoudre.

J'ai encore besoin d'aide.

Je m'excuse mais j'ai vraiment du mal aujourd'hui, j'ai l'impression que mon cerveau est resté au lit.




G.

  • Hero Member
  • *****
  • Messages: 1593
    • Voir le profil
Re : Besoin d'aide déplacement isométrique
« Réponse #3 le: Mars 15, 2015, 08:33:22 pm »
sf::Vector2f direction = spritepos - posmage;
sf::Vector2f direction = direction / longueur;
Bah c'est simplissime et basique, tu déclares 2 fois direction là.  :o
sf::Vector2f direction = spritepos - posmage;
direction = direction / longueur;

Tu peux modifier la longueur d'un vecteur sans en modifier sa direction. Normaliser (j'ai dit normer mais je crois que c'est normaliser ;) ) un vecteur c'est lui donner une longueur de 1. Pour faire ça c'est tout con suffit de le diviser par sa longueur.
Avec un vecteur normé (= de longueur 1) quelque soit la distance entre ton sprite et son point d'arrivée tu auras le même vecteur, et t'as juste à le multiplier par sa vitesse pour obtenir le vecteur de déplacement.

Quant à ta deuxieme erreur, tu peux multiplier un sf::Vector2f par un float mais pas par un int, donc mets ta vitesse en float. ;)

Ensuite, elapsed2 est censé représenter la durée d'une frame. Si tu ne restart pas ta clock2 à chaque frame alors elapsed2 va être de plus en plus grand et ton sprite ira de plus en plus vite !
Tu peux faire directement sf::Time elapsed2 = clock2.restart();
car restart renvoie la valeur de getElapsedTime en plus de reset la clock. ;) (c'est même montré dans le tuto sur la gestion du temps)

J'ai pas tout lu, mais je doute que tu veuilles ton spritemage.move(deplacement); (et le restart qui va avec) uniquement lors d'un évènement clic de souris.