Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Pathfinding Problem  (Read 1074 times)

0 Members and 1 Guest are viewing this topic.

yovano_c

  • Newbie
  • *
  • Posts: 40
    • View Profile
    • Email
Pathfinding Problem
« on: October 21, 2016, 06:44:36 pm »
Hello,

I've been working on that issue since a lot of time... and I think today that I'm close to the solution, but I need your help.

I explain:

I just want to my player follow the path that my pathfinding system just found when he clicks on a tile, on an isometric map. But I want to use the speed attribute of my player class, which is represent the time to get through one tile... from middle of a tile to middle of the other, I have getPositionCenter() method from my tile class to get the middle of this. But, the center of the neighbors tiles are not at the same distance because of the isometric system.

I don't really know how to implements this in my code, and don't know exactly how to do it so...

PS: I also have like you can see on screenshots below I kept 2 variables to keep track of the path following if it can help: getCurrentTile() and getDestinationTile(), with setters too. I have getSpeed() of course for the player, and getPositionCenter() for Tile and Player class.


I send each frame the mClock.restart().asSeconds() and the path to my update() function to my Player class like that:

When a left click is done:

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.setDestinationTile(mTileClicked);
        mPathfinder.findPath(mPlayer.getCurrentTile(), mTileClicked);
    }
}


then on update part, before drawing:

mElapsed = mClockUpdate.restart();
mPlayer.update(mElapsed.asSeconds(), &mPathfinder.path);


My player update function:

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

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

        std::cout << "Units per tick: " << unitsPerTick << std::endl;

        auto waypoint = path->front();

        std::cout << "Player Position: X:" << this->getPositionCenter().x << ", Y:" << this->getPositionCenter().y << std::endl;
        std::cout << "Tile Position: X:" << waypoint->getPositionCenter().x << ", Y:" << waypoint->getPositionCenter().y << std::endl;


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

        auto movementVector = waypoint->getPositionCenter() - this->getPositionCenter();

        std::cout << "Movement Vector 1: X:" << movementVector.x << ", Y:" << movementVector.y << std::endl;

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

        std::cout << "Movement Vector Length: " << moveVecLength << std::endl;

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

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

            std::cout << "Movement Vector 2: X:" << movementVector.x << ", Y:" << movementVector.y << std::endl;

            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;
}

And I obtain that to the console with my std::cout, and my player move really slowly (0.0X each time), but the
std::cout << waypoint->getId() << " -> ";
appear on the console so it's good for that, and if I move of only one tile, it's stopped when the player reach the center, but it's very slow, thanks....


ID: 426 - isWalkable = 1 - Position: (6,30)
Path found in 78 µs
Units per tick: 0.033536
Player Position: X:1088.03, Y:735.983
Tile Position: X:1088, Y:736
Movement Vector 1: X:-0.03479, Y:0.017395
Movement Vector Length: 0.0388964
Movement Vector 2: X:-0.0299955, Y:0.0149978
Units per tick: 0.035656
Player Position: X:1088, Y:735.998
Tile Position: X:1088, Y:736
Movement Vector 1: X:-0.00476074, Y:0.00238037
Movement Vector Length: 0.00532267
316 -> Units per tick: 0.035542
Player Position: X:1088, Y:736
Tile Position: X:1024, Y:768
Movement Vector 1: X:-64, Y:32
Movement Vector Length: 71.5542
Movement Vector 2: X:-0.0317897, Y:0.0158949
Units per tick: 0.035124
Player Position: X:1087.97, Y:736.016
Tile Position: X:1024, Y:768
Movement Vector 1: X:-63.9683, Y:31.9841
Movement Vector Length: 71.5187
Movement Vector 2: X:-0.0314159, Y:0.0157079

Thanks
« Last Edit: October 21, 2016, 08:48:46 pm by yovano_c »