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

Author Topic: Other methods on moving sprite from one point to another point?  (Read 10364 times)

0 Members and 1 Guest are viewing this topic.

magneonx

  • Full Member
  • ***
  • Posts: 141
    • MSN Messenger - magnumneon04@hotmail.com
    • View Profile
Hello it seems my post has been confusing readers( I might even deter others from helping me). SO I edited the orignal post.

I no longer want movement through vector normalization, I am not totally verbose in math, what I mean is, going from point to another point using vectors. Because it works great at first, but there are instances that makes the AI Path Finding don't look nice in the game I am making.

What I want now is moving horizontally and vertically without even normalizing the vector. Is there anyway I could do it? Also, I don't have any means to detect whether the next tile in question is on left, right, top, bottom of the sprite. I heavily rely on delta of sprite position to target position( by subtracting sprite position to target position) to give me the sign whether to move the sprite horizontal or vertical.

 Just try to imagine you are moving sprite using keyboard, but this time the input is the position of the next tile. Usually in keyboard you move your sprite at ( -10 , 0 ) if you wanna go left etc. This time it's different it has a mind of its own the only input it needs is the position of its next adjacent tile.

for example:
My Sprite is on position( 60.0f , 60.0f )
the generated path is:
60.0f , 120.0f // go down
60.0f , 180.0f // go down once more
120.0f , 180.0f // go right

I have to go to the path 120.0f, 180.0f. That's my input for my sprite on how it going to move around. I just gave it coordinates were to go. My question is, How can I go from (60.0f , 60.0f) to (60.0f , 120.0f) at the first loop up until the last tile at( 120.0f , 180.0f )? I don't like normalizing vectors anymore, my code actually works using that but there are times it cuts corners when my sprite was trapped between 2 tiles when I issued a new order (I haven't fixed that yet but as soon as I finish this one).

I hope it really clear things up.
This problem has been bothering me eversince, I could not sleep and my sleeping pattern is heavily disrupted by this one.
« Last Edit: August 13, 2013, 08:59:43 pm by magneonx »

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Other methods on moving sprite from one point to another point?
« Reply #1 on: August 11, 2013, 08:49:43 pm »
Well, if you don't want diagonal movement, then why are you doing things like normalizing vectors?   The "problem" is simply that you wrote code that moves the sprite in any arbitrary 2D direction, even though that wasn't what you wanted.

Here's my quick attempt at moving your code around so it does strictly horizontal/vertical movement instead:

            delta.x = targetPosition.x - spritePosition.x;
            delta.y = targetPosition.y - spritePosition.y;

            float distMoved = e * velocity;
            float movex = 0.f, movey = 0.f;
            if(delta.x > delta.y) { //move horizontally
                        movex     = spritePosition.x + ( delta.x * distMoved );
                        if( abs( targetPosition.x - spritePosition.x ) <= 1) {
                            spritePosition.x  = targetPosition.x;
                            c++;
                        }
            } else { //move vertically
                        movey     = spritePosition.y + ( delta.y * distMoved );
                        if( abs( targetPosition.y - spritePosition.y ) <= 1) {
                            spritePosition.y  = targetPosition.y;
                            c++;
                        }
            }

            movableObjects->setSpritePosition( movex , movey );
 

However, you left a lot of code out of your post and your description of what you want is pretty unclear, so I have no idea if this even close to a solution.  If this isn't enough, try giving us some more detail.  A picture of the kind of path you want it to find might help.
« Last Edit: August 11, 2013, 08:51:45 pm by Ixrec »

magneonx

  • Full Member
  • ***
  • Posts: 141
    • MSN Messenger - magnumneon04@hotmail.com
    • View Profile
Re: Other methods on moving sprite from one point to another point?
« Reply #2 on: August 12, 2013, 06:06:22 pm »
Thanks Ixrec! Yes at first I do want a smooth traversing of the tiles in my vector, a behavior by which the sprite just move not from to tile to tile, it should move flawless irrespective of the tile it is on but making the generated path the guide to go from point a to point b. I am sorry if I make my post totally unclear.

And yes, my sprite just happens to exhibit an unwanted behavior which I fail to predict. I know what vector normalization does. I just realize some few mistakes, I think this is due to a lack of understanding on the matter, I not quite particular to this subject yet but I am trying harder.

And yes, your code is what I wanted! Thank you very much for showing me how to move just vertical or diagonal this is a great help truly!

magneonx

  • Full Member
  • ***
  • Posts: 141
    • MSN Messenger - magnumneon04@hotmail.com
    • View Profile
Re: Other methods on moving sprite from one point to another point?
« Reply #3 on: August 13, 2013, 04:48:23 pm »
Hello again! I think I really need help. All right, I am a bit struggling to do it, the thing is, to make my point clear, I actually want a movement from tile to tile. As I have mentioned earlier, I have an AI Path Finding set, it is working and there is no question about it. I have path generated already. I just have to move my sprite from tile to tile. So by now, everyone must know that I use a GRID to find the shortest path.

My first attempt was simple, I have considered to put a point on to the tile that my sprite have to move on. That point is where the sprite will go. That is, if it reaches that point, my vector of generated path will throw the next target tile, thus the point, and I have to move my sprite there. So I have decided to use normalizing the vector, I just found out that it moves cool and it simplifies the path it doesn't look like its bounded by the grid but only guided by it! It works very well.

It's great until then if my sprite is near on the wall and I try to move it around that I just realize that normalizing vector is not a great idea. Well, it does evade the wall, but you know, it still hits the wall, it even cuts across the wall not by much, not an array of walls in the grid, but only single wall on a tile. I could fix this by making my wall sprite smaller or have rounded corners but seriously? I know that is not an elegant solution. Sorry if I didn't make things clear right away.

Now what I want is to move the sprite tile by tile.
I have different units on game so they need to have different speed. How am I suppose to do it? I do not move my sprite by keyboard nor mouse, it just move on its own.

If you don't still understand and sorry if I can't perfectly express myself in English. Here is a video.


Thank you :D

Lee R

  • Jr. Member
  • **
  • Posts: 86
    • View Profile
Re: Other methods on moving sprite from one point to another point?
« Reply #4 on: August 13, 2013, 08:07:54 pm »
Unfortunately, I think it is still quite hard to decipher what you are actually asking for. 'what I want is to move the sprite tile by tile' is not very descriptive.

You said earlier that the code provided Ixrec is "what I wanted". I note that his code contains several bugs; for instance, when checking the major axis, the absolute value of each axis should be taken. Also, his approach is not exempt from normalization, which in 1D amounts to taking the sign of the major axis.

Here is an attempt to resolve said bugs (although it may well contain several new bugs, because we have no way of testing against your codebase. Also because I couldn't resist flattening your control flow :P). I have introduced a new parameter, 'axisLocked', which when true will lock movement to the current major axis as in Ixrec's code, otherwise it will allow arbitrary movement, as in your original code.

void PathFinder::moveToDestination( float dt, bool axisLocked = false )
{
    if ( !_isPathFound ) {
        return;
    }

    if ( (c + 1) < path.size() ) {
        spriteNextTile = path[c + 1];
    }

    const float tilesize = static_cast<float>( tileset->getTilesize() );

    targetPosition.x = spriteNextTile->getTileGridPositionX() * tilesize;
    targetPosition.y = spriteNextTile->getTileGridPositionY() * tilesize;

    spritePosition.x = movableObjects->getSpritePositionX();
    spritePosition.y = movableObjects->getSpritePositionY();

    delta = targetPosition - spritePosition;

    // distance considered 'close enough' to target position.
    const float tolerance = 1.0f;

    // actual distance to target position.
    const float distance = length( delta );

    // amount of movement this time step.
    const float displacement = movableObjects->getVelocity() * dt;

    // direction of movement.
    sf::Vector2f direction( 0.0f, 0.0f );

    if ( axisLocked )
    {
        // movment restricted to major axis.
        if( std::abs(delta.x) > std::abs(delta.y) )
        {
            // horizontal movement.
            direction.x = (delta.x < 0.0f) ? -1.0f : 1.0f;
        }
        else
        {
            // vertical movement.
            direction.y = (delta.y < 0.0f) ? -1.0f : 1.0f;
        }
    }
    else
    {
        // movement in arbitrary direction.
        direction = normalize( delta );
    }

    if ( distance <= tolerance || distance <= displacement )
    {
        // target position reached.
        spritePosition = targetPosition;
        if ( ++c >= path.size() - 1 )
        {
            // end of path reached.
            _isPathFound = false;
            c = 0;
            reset();
        }
    }
    else
    {
        // advance towards target position.
        spritePosition += direction * displacement;
    }

    movableObjects->setSpritePosition( spritePosition.x, spritePosition.y );
}
 

Really though, this is no better than looking into a crystal ball. I could well be that you have competing forces which need resolving, or any other number of possibilities. AI code is notoriously fiddly, often leading straight to tweakers hell.

magneonx

  • Full Member
  • ***
  • Posts: 141
    • MSN Messenger - magnumneon04@hotmail.com
    • View Profile
Re: Other methods on moving sprite from one point to another point?
« Reply #5 on: August 13, 2013, 08:51:12 pm »
Hello thanks for replying! I have edited my post, see if it helps to understand my undertaking as of this moment.

magneonx

  • Full Member
  • ***
  • Posts: 141
    • MSN Messenger - magnumneon04@hotmail.com
    • View Profile
Re: Other methods on moving sprite from one point to another point?
« Reply #6 on: August 13, 2013, 08:57:21 pm »
Really though, this is no better than looking into a crystal ball. I could well be that you have competing forces which need resolving, or any other number of possibilities. AI code is notoriously fiddly, often leading straight to tweakers hell.

Couldn't agree on this I am starting to realize this. I felt so much accomplishment when I have done AI Path Finding, I understood it very well and all that. After I implemented AI Path Finding, I asked myself "now what". I got the path but my sprite is still idle.

Thanks for the code I'll try it. But I just don't understand what axis does? I not so sure if I understand it? Can you explain a little bit more? Why do I have a need to lock on an axis? Is that your way to tell if the sprite is going up or down?

Lee R

  • Jr. Member
  • **
  • Posts: 86
    • View Profile
Re: Other methods on moving sprite from one point to another point?
« Reply #7 on: August 13, 2013, 09:19:29 pm »
Yes, that is how it decides in which direction the sprite should move. It also restricts the sprite's movement to up, down, left and right. If moving up, the direction vector will be [0.0f, -1.0f], or [0.0f, 1.0f] if down, [-1.0f, 0.0f] if left or [1.0f, 0.0f] if right. Therefore, only one axis of the direction vector will affect movement. Consider:

Speed = 10
Direction = [1.0f, 0.0f] = right
Movement = Direction * Speed = [1.0 * 10, 0.0 * 10] = [10.0f, 0.0f] = move right 10 units.

EDIT: Just to be clear, the code I provided will calculate the direction of movement on it's own. The 'lockAxis' parameter simply specifies whether to allow arbitrary movement in any direction (when lockAxis = false), or to restrict movement such that it will only choose to move up, down, left or right (when lockAxis = true).
« Last Edit: August 13, 2013, 09:45:04 pm by Lee R »

magneonx

  • Full Member
  • ***
  • Posts: 141
    • MSN Messenger - magnumneon04@hotmail.com
    • View Profile
Re: Other methods on moving sprite from one point to another point?
« Reply #8 on: August 13, 2013, 09:56:52 pm »
Ah I see, it seems that if I set to false, I can put my sprite everywhere and I can make my sprite move and that it is guided by the tile path? For short, I can make my sprite move not tile to tile but only relative to it?

magneonx

  • Full Member
  • ***
  • Posts: 141
    • MSN Messenger - magnumneon04@hotmail.com
    • View Profile
Re: Other methods on moving sprite from one point to another point?
« Reply #9 on: August 13, 2013, 09:58:54 pm »
I also have question, how do you imperatively define length()? Is that subtracting the current position to target position to get the remaining distance?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Other methods on moving sprite from one point to another point?
« Reply #10 on: August 13, 2013, 10:02:08 pm »
It's the magnitude of a vector: square root of the components squared and added.
std::sqrt(v.x*v.x + v.y*v.y);

By the way, you can edit your post.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Lee R

  • Jr. Member
  • **
  • Posts: 86
    • View Profile
Re: Other methods on moving sprite from one point to another point?
« Reply #11 on: August 13, 2013, 10:09:20 pm »
Quote from: magneonx
Ah I see, it seems that if I set to false, I can put my sprite everywhere and I can make my sprite move and that it is guided by the tile path? For short, I can make my sprite move not tile to tile but only relative to it?

Exactly.

Quote from: magneonx
I also have question, how do you imperatively define length()? Is that subtracting the current position to target position to get the remaining distance?

Length is defined as the magnitude of a vector (as Nexus has already taught us :P). It can be used to calculate the distance between two vectors in exactly the way you describe (i.e. 'distance = length(b - a);' where 'a' and 'b' are vectors) The C++ incantation goes thusly:

template<typename T>
inline T length(const sf::Vector2<T>& v)
{
        return std::sqrt(v.x * v.x + v.y * v.y);
}
 

The normalize function is then as follows:
template<typename T>
inline sf::Vector2<T> normalize(const sf::Vector2<T>& v)
{
    const T len = length(v);
    T invLen = T(1);

    if (len != T(0))
    {
        invLen /= len;
    }

        return sf::Vector2<T>(v.x * invLen, v.y * invLen);
}
 

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Other methods on moving sprite from one point to another point?
« Reply #12 on: August 13, 2013, 10:23:26 pm »
The normalize function is then as follows:
template<typename T>
inline sf::Vector2<T> normalize(const sf::Vector2<T>& v)
{
    const T len = length(v);
    T invLen = T(1);

    if (len != T(0))
    {
        invLen /= len;
    }

        return sf::Vector2<T>(v.x * invLen, v.y * invLen);
}
 
Or simpler:
template <typename T>
sf::Vector2<T> unitVector(const sf::Vector2<T>& v)
{
    return v / length(v);
}

Normalizing a zero vector is mostly a logic error, which shouldn't be hidden. One could use assert for it. I personally prefer the name unitVector, because normalize sounds as if the argument is modified. That's also how I did it in Thor.Vectors.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Lee R

  • Jr. Member
  • **
  • Posts: 86
    • View Profile
Re: Other methods on moving sprite from one point to another point?
« Reply #13 on: August 14, 2013, 03:20:29 pm »
You could of course use an assert in the implementation I provided, should you feel it necessary. The choice between the two implementations then comes down to where you think the error check should happen, and in the case of an error, should it be considered fatal (i.e. do we really want to crash the entire application rather than returning a zero vector?).

I agree that the name 'normalize' does seem to imply a mutation.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Other methods on moving sprite from one point to another point?
« Reply #14 on: August 14, 2013, 03:32:48 pm »
The postcondition of the function is that it yields a unit vector, thus the caller expects the result to have length 1. When a zero vector is passed, this is impossible to achieve. Since the expectation cannot be met in any circumstances, the argument passed to unitVector() must be wrong.

So yes, crashing the application is the best way to immediately find the bug. Ignoring it will only let the error propagate and show up later, where it is much more difficult to find. I'm aware that there may be situations where one would really want a zero vector back; but in my opinion these cases are rare and should be handled explicitly by the user. The nice side effect of assert is that no performance is wasted to deal with situations that do not occur in correct code.

And I don't think there is any ambiguity concerning where to place the assert. The straightforward way is to check the parameter, so the code still remains very simple:
template <typename T>
sf::Vector2<T> unitVector(const sf::Vector2<T>& v)
{
    assert(v != sf::Vector2<T>());
    return v / length(v);
}

By the way, that's exactly how the implementation of thor::unitVector() looks.
« Last Edit: August 14, 2013, 03:40:42 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

 

anything