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

Auteur Sujet: Pathfinding Problem  (Lu 1647 fois)

0 Membres et 1 Invité sur ce sujet

yovano_c

  • Newbie
  • *
  • Messages: 40
    • Voir le profil
    • E-mail
Pathfinding Problem
« le: Octobre 19, 2016, 12:35:34 pm »
Bonjour à tous,
J'ai beau réfléchir depuis maintenant plusieurs jours mais je viens vous demander de l'aide car là je ne sais même pas comment 'bien' implémenter ce que je voudrais faire. Je m'explique:

Je veux juste que mon personnage suive le chemin trouvé par mon système de pathfinding, en utilisant plusieurs choses, j'ai un attribut Speed qui es propre à chaque personnage, et j'ai donc une fonction pour récupéré les coordonnées du milieu de la Tile ( sf::Vector2f getPositionCenter(); ).

Cependant, je ne sais pas vraiment ou me placer dans mon code, ni comment réellement faire ça..

Voilà où j'en suit:

Dans ma gestion d'évènements:
sf::Vector2i localPosition = sf::Mouse::getPosition(mWindow);
sf::Vector2f worldPos = mWindow.mapPixelToCoords(localPosition);

mTileClicked = mMap.getTileWithClick(worldPos);
if (mTileClicked != nullptr)
{
     std::cout << "ID: " << mTileClicked->getId() << " - isWalkable = " << mTileClicked->isWalkable;
     std::cout << " - Position: (" << mTileClicked->getPositionOnMap().x << "," << mTileClicked->getPositionOnMap().y << ")" << std::endl;

     if (mTileClicked->isWalkable && mTileClicked != mPlayer.getCurrentTile() && mTileClicked != mPlayer.getDestinationTile())
     {
          //mPlayer.setTile(mTileClicked);
          //mPlayer.setDestinationTile(mTileClicked);
         mPath = mPathfinder.findPath(mPlayer.getCurrentTile(), mTileClicked);
     }
}


J'avais ensuite penser à implémenter ça dans ma fonction update du player que j'actualise avant chaque affichage que j'appelle du coup de la sorte

mPlayer.update(mElapsed, mPath);

et voilà ma fonction update :

void Player::update(float dt, std::list<MapTile*> path)
{

    if (!path.empty())
    {
        std::cout << path.front()->getId() << std::endl;
    }

    switch (mDirection) {
        case Up: setRect(0); break;
        case Down: setRect(0); break;
        case Left: setRect(0); break;
        case Right: setRect(0); break;
        case DownLeft: setRect(0); break;
        case UpLeft: setRect(0); break;
        case UpRight: setRect(0); break;
        case DownRight: setRect(0); break;
        default: break;
    }
}

Simplement là je segfault en appelant l'update dans la boucle.... je recupere même pas l'id dans la fonction.. c'est vraiment le mPath qui pose problème... déja voici mon premier problème, c'est où me placer dans mon code pour faire bouger mon personnage.... et ensuite j'ai rechercher mais je n'ai que du pseudocode trouver sur internet pour bouger mon personnage mais je ne le comprend pas parfaitement:

if (pathFound)
{
    // A path has been found
    const float unitsPerTick = 8; // Speed in Units per tick
    auto waypoint = waypoint_queue.front(); // The waypoint in use

    Vector2i movementVector = Vector2i(waypoint.x - this->character.getPosition().x,
        waypoint.y - this->character.getPosition().y);

    float moveVecLength = sqrt((movementVector.x * movementVector.x) + (movementVector.y * movementVector.y));

    if (moveVecLength < 0.2)
    {
        /// Move the player by the movement vector
        this->character.setPosition(this->character.getPosition().x + movementVector.x, this->character.getPosition().y + movementVector.y);    
        waypoint_queue.pop_front();
    }
    else {
        /// Normalize the movement vector          
        movementVector.x = movementVector.x / moveVecLength;
        movementVector.y = movementVector.y / moveVecLength;

        /// Scale the movement vector by the units per tick
        movementVector = Vector2i(movementVector.x * unitsPerTick, movementVector.y * unitsPerTick);

        /// Move the character by the new movement vector
        this->character.setPosition(this->character.getPosition().x + movementVector.x, this->character.getPosition().y + movementVector.y);
    }

    if (waypoint_queue.empty())
        pathFound = false;
}

PS: Comme vous pouvez le voir j'ai déjà aussi garder 2 petites variables pour garder l'avancer sur les tiles si ça peut aider, getCurrentTile() et getDestinationTile() avec les setters aussi.. j'ai pour le personnage getSpeed(), et du coup pour chaque tile getPositionCenter() mais je ne sais pas implémenter ça correctement, merci de m'aider :/

yovano_c

  • Newbie
  • *
  • Messages: 40
    • Voir le profil
    • E-mail
Re : Pathfinding Problem
« Réponse #1 le: Octobre 20, 2016, 01:54:38 am »
Je pense que je m'approche de la solution, ça ne marche toujours pas, mais en venant vous dire où j'en suit peut être que quelqu'un sauras m'aider...

Pour commencer, ma fonction getSpeed() sur un player, j'aimerais que ça correspond à la vitesse ou le joueur ira du centre d'une tile au centre de la prochaine, seulement, c'est en isométrique, et les centres des tiles voisines ne sont pas à la même distance, mais c'est pas le plus gros problème.
Ensuite, j'envois donc à la fonction update de mon player, le clock.restart().asSeconds() ...

Voici ma fonction update pour l'instant....

void Player::update(float dt, std::list<MapTile*> *path)
{

    // for (auto& tile: *path)
    // {
    //      std::cout << tile->getId() << " -> ";
    //      path->pop_front();
    // }

    if (!path->empty())
    {
        const float unitsPerTick = this->getSpeed() * dt; // Speed in Units per tick

        std::cout << unitsPerTick << std::endl;
        auto waypoint = path->front();

        sf::Vector2i movementVector = sf::Vector2i(waypoint->getPositionCenter().x - this->getPositionCenter().x,
        waypoint->getPositionCenter().y - this->getPositionCenter().y);

        std::cout << movementVector.x << "," << movementVector.y << std::endl;

        float moveVecLength = sqrt((movementVector.x * movementVector.x) + (movementVector.y * movementVector.y));

        std::cout << "moveVecLength: " << moveVecLength << std::endl;

        if (moveVecLength < unitsPerTick)
        {
            this->move(movementVector.x, movementVector.y);
            this->setCurrentTile(waypoint);
            std::cout << waypoint->getId() << " -> " << std::endl;
            path->pop_front();
        }
        else {
            movementVector.x = movementVector.x / moveVecLength;
            movementVector.y = movementVector.y / moveVecLength;

            movementVector = sf::Vector2i(movementVector.x * unitsPerTick, movementVector.y * unitsPerTick);

            this->move(movementVector.x, movementVector.y);
        }
    } else {
        counterAnimation = 0;
    }

    switch (mDirection) {
        case Up: setRect(0); break;
        case Down: setRect(0); break;
        case Left: setRect(0); break;
        case Right: setRect(0); break;
        case DownLeft: setRect(0); break;
        case UpLeft: setRect(0); break;
        case UpRight: setRect(0); break;
        case DownRight: setRect(0); break;
        default: break;
    }

    if (rand() % 4 == 1)
        this->counterAnimation++;
    if (this->counterAnimation >= (this->nbAnimation - 1))
        this->counterAnimation = 0;
}

Seulement mon personnage fait du surplace, en ayant quand même les animations de deplacements (bras et jambes qui se mettent en route), et j'obtient ceci dans mon terminal avec le std::cout de la fonction (ça tourne en rond quoi...) :

moveVecLength: 31
0.033684
0,31
moveVecLength: 31
0.035512
0,31
moveVecLength: 31
0.033396
0,31
moveVecLength: 31
0.034238
0,31
moveVecLength: 31
0.033816
0,31
moveVecLength: 31
0.03396
0,31
moveVecLength: 31
0.033524
0,31
moveVecLength: 31
0.035762
0,31
moveVecLength: 31
0.03571
0,31
moveVecLength: 31
0.30348
0,31
moveVecLength: 31

Merci beaucoup..