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

Author Topic: Sprite Movement on Single MouseClick  (Read 10643 times)

0 Members and 1 Guest are viewing this topic.

Tex Killer

  • Full Member
  • ***
  • Posts: 242
    • View Profile
Sprite Movement on Single MouseClick
« Reply #15 on: January 14, 2012, 07:54:57 am »
Take all the lines from
Code: [Select]
Direction /= Distance; up and put inside the if. You better make your Direction vector and your Distance variable outside the main loop as well, so that they remain on multiple iterations.

The last three lines I think you should change.
Make something like this:
Code: [Select]
float Speed = 40.f;
float DistanceMoved = Speed * Clock1.GetElapsedTime() / 1000.f;
if (DistanceMoved > Distance) {
    DistanceMoved = Distance;
}
PlayerObj.SetPosition(Origin + Direction * DistanceMoved);

If you want to change the speed, change the 40.f to something else.

LucasShadow

  • Jr. Member
  • **
  • Posts: 52
    • View Profile
Sprite Movement on Single MouseClick
« Reply #16 on: January 14, 2012, 05:20:48 pm »
Hey Tex Killer, I tried to implemented the changes you suggested, with declaring the Direction, Distance, and Origin vectors outside the main loop. However, I still have the same problem: The sprite doesn't move.

Code: [Select]
if (App.GetInput().IsMouseButtonDown(sf::Mouse::Left)); {
            NewX = App.GetInput().GetMouseX();
            NewY = App.GetInput().GetMouseY();
            Clock1.Reset();
            sf::Vector2f Origin = PlayerObj.GetPosition();
            sf::Vector2f Destination(NewX, NewY);
            sf::Vector2f Direction = Destination - Origin;
            // calculate distance between origin and destination points
            float Distance = sqrt( (Destination.x - Origin.x) * (Destination.x - Origin.x) + (Destination.y - Origin.y) *  (Destination.y - Origin.y) );
            // vector normalization (you obtain a unit vector = vector of lenght 1)
            Direction /= Distance;}
            float Speed = 50000.f;
            float DistanceMoved = Speed * Clock1.GetElapsedTime() / 1000.f;
            if (DistanceMoved > Distance) {
            DistanceMoved = Distance;
            }
        PlayerObj.SetPosition(Origin + Direction * DistanceMoved);

Tex Killer

  • Full Member
  • ***
  • Posts: 242
    • View Profile
Sprite Movement on Single MouseClick
« Reply #17 on: January 15, 2012, 12:26:38 am »
I think there is something wrong in other part of your code. Debug it to see which position is being set at each iteration, and check how is the sprite being draw.

LucasShadow

  • Jr. Member
  • **
  • Posts: 52
    • View Profile
Sprite Movement on Single MouseClick
« Reply #18 on: January 16, 2012, 04:27:20 pm »
Everything seems to be correct, though I may have messed up with declaring the variables outside of the loop?
Code: [Select]
#include <SFML/Graphics.hpp>

 int main()
 {
     sf::RenderWindow App(sf::VideoMode(800, 600), "Sprite Test");

     sf::Image ForestTileImg;
     sf::Image PlayerImg;
     if(!ForestTileImg.LoadFromFile("forest_terrain_tile.png")) {
        return EXIT_FAILURE;
     }
     if(!PlayerImg.LoadFromFile("player.png")) {
        return EXIT_FAILURE;
     }

     ForestTileImg.SetSmooth(false);
     PlayerImg.SetSmooth(false);

     sf::Sprite PlayerObj;
     sf::Sprite ForestTileObj;

     ForestTileObj.SetImage(ForestTileImg);
     ForestTileObj.SetPosition(400,284);

    PlayerObj.SetImage(PlayerImg);
    PlayerObj.SetPosition(400, 284);

    float OldX = PlayerObj.GetPosition().x;
    float OldY = PlayerObj.GetPosition().y;
    float NewX = (OldX + 1);
    float NewY = (OldY - 1);
    sf::Clock::Clock(Clock1);

    sf::Vector2f Origin = PlayerObj.GetPosition();
    sf::Vector2f Destination(NewX, NewY);
    sf::Vector2f Direction = Destination - Origin;
    float Distance = sqrt( (Destination.x - Origin.x) * (Destination.x - Origin.x) + (Destination.y - Origin.y) *  (Destination.y - Origin.y) );

     while (App.IsOpened())
     {
         sf::Event Event;
         while (App.GetEvent(Event))
         {
             if (Event.Type == sf::Event::Closed)
                 App.Close();
         }
         App.Clear();

         if (App.GetInput().IsMouseButtonDown(sf::Mouse::Left)); {
            NewX = App.GetInput().GetMouseX();
            NewY = App.GetInput().GetMouseY();
            Clock1.Reset();
            sf::Vector2f Origin = PlayerObj.GetPosition();
            sf::Vector2f Destination(NewX, NewY);
            sf::Vector2f Direction = Destination - Origin;
            // calculate distance between origin and destination points
            float Distance = sqrt( (Destination.x - Origin.x) * (Destination.x - Origin.x) + (Destination.y - Origin.y) *  (Destination.y - Origin.y) );
            // vector normalization (you obtain a unit vector = vector of lenght 1)
            Direction /= Distance;}
            float Speed = 50000.f;
            float DistanceMoved = Speed * Clock1.GetElapsedTime() / 1000.f;
            if (DistanceMoved > Distance) {
            DistanceMoved = Distance;
            }
         PlayerObj.SetPosition(Origin + Direction * DistanceMoved);

         App.Draw(PlayerObj);
         App.Draw(ForestTileObj);
         App.Display();
     }
     return EXIT_SUCCESS;
 }

Tex Killer

  • Full Member
  • ***
  • Posts: 242
    • View Profile
Sprite Movement on Single MouseClick
« Reply #19 on: January 16, 2012, 10:53:25 pm »
You are redeclaring all the variables inside the loop again. Just use the ones you declared before.

LucasShadow

  • Jr. Member
  • **
  • Posts: 52
    • View Profile
Sprite Movement on Single MouseClick
« Reply #20 on: January 17, 2012, 02:19:45 am »
Okay, but there is one problem. Dont I need to declare the NewX, NewY variables twice? Once for a defining them for the definitions of the vectors outside of the loop, and a second time within the if statement that collects data from the mouse position:

Code: [Select]
   float NewX = 0;
    float NewY = 0;
    sf::Clock::Clock(Clock1);
    sf::Vector2f Origin = PlayerObj.GetPosition();
    sf::Vector2f Destination(NewX, NewY);
    sf::Vector2f Direction = Destination - Origin;
    float Distance = sqrt( (Destination.x - Origin.x) * (Destination.x - Origin.x) + (Destination.y - Origin.y) *  (Destination.y - Origin.y) );

     while (App.IsOpened())
     {
         sf::Event Event;
         while (App.GetEvent(Event))
         {
             if (Event.Type == sf::Event::Closed)
                 App.Close();
         }
         App.Clear();

         if (App.GetInput().IsMouseButtonDown(sf::Mouse::Left)); {
            NewX = App.GetInput().GetMouseX();
            NewY = App.GetInput().GetMouseY();
            Clock1.Reset();
            Direction /= Distance;}
            float Speed = 50000.f;
            float DistanceMoved = Speed * Clock1.GetElapsedTime() / 1000.f;
            if (DistanceMoved > Distance) {
            DistanceMoved = Distance;
            }
         PlayerObj.SetPosition(Origin + Direction * DistanceMoved);

Tex Killer

  • Full Member
  • ***
  • Posts: 242
    • View Profile
Sprite Movement on Single MouseClick
« Reply #21 on: January 17, 2012, 06:39:28 am »
In your code, you are not declaring them twice. In fact, I think your Destination vector should start off with the same value as the Origin vector, so that it starts not moving.

Actually, NewX and NewY don't need to be even declared outside the if, as they are only temporary variables that you use to make the Destination vector... But hey, you are not updating the Destination vector inside the if! You must change the destination on the mouse click, right?

You must also update the Origin vector, the Direction vector and the Distance variable. All of this before this line:
Code: [Select]
Direction /= Distance;

If all of this is set right, I think the code should work... But keep in mind that with the current speed, the movement would be pratically instantaneous.

LucasShadow

  • Jr. Member
  • **
  • Posts: 52
    • View Profile
Sprite Movement on Single MouseClick
« Reply #22 on: January 17, 2012, 07:11:23 am »
I did ask you suggested.  The Destination vector in the beginning to the Origin vector outside of the loop.  The NewX and NewY are now inside the loop, and the Destination vector is now  updated inside the if statement. Everything else is updated as well.  

Code: [Select]
   sf::Clock::Clock(Clock1);
    sf::Vector2f Origin = PlayerObj.GetPosition();
    sf::Vector2f Destination = Origin;
    sf::Vector2f Direction = Destination - Origin;
    float Distance = sqrt( (Destination.x - Origin.x) * (Destination.x - Origin.x) + (Destination.y - Origin.y) *  (Destination.y - Origin.y) );

     while (App.IsOpened())
     {
         sf::Event Event;
         while (App.GetEvent(Event))
         {
             if (Event.Type == sf::Event::Closed)
                 App.Close();
         }
         App.Clear();

         if (App.GetInput().IsMouseButtonDown(sf::Mouse::Left)); {
            Clock1.Reset();
            float NewX = App.GetInput().GetMouseX();
            float NewY = App.GetInput().GetMouseY();
            Origin = PlayerObj.GetPosition();
            sf::Vector2f Destination(NewX, NewY);
            Direction = Destination - Origin;
            Direction /= Distance;}
            float Speed = 500.f;
            float DistanceMoved = Speed * Clock1.GetElapsedTime() / 1000.f;
            if (DistanceMoved > Distance) {
            DistanceMoved = Distance;
            }
         PlayerObj.SetPosition(Origin + Direction * DistanceMoved);


Bugs: One, the player does not show up on the screen on startup. I think it has something to do with this code:
Code: [Select]
   sf::Vector2f Destination = Origin;
    sf::Vector2f Direction = Destination - Origin;


Second, still nothing happens when the mouse is clicked. Perhaps related to the first bug?

Tex Killer

  • Full Member
  • ***
  • Posts: 242
    • View Profile
Sprite Movement on Single MouseClick
« Reply #23 on: January 17, 2012, 09:14:28 pm »
Every time you put the type before the variable name, you are (re)declaring it. You didn't updated the Destination variable inside the if, you redeclared it. See:
Code: [Select]
sf::Vector2f Destination(NewX, NewY);
Also, you are still not updating the Distance variable inside the if. The distance can start with 0 at the beginning as well, as the origin and destination are the same.

LucasShadow

  • Jr. Member
  • **
  • Posts: 52
    • View Profile
Sprite Movement on Single MouseClick
« Reply #24 on: January 17, 2012, 10:02:08 pm »
How would I update the Destination and Distance vectors then?  Because doing:
Code: [Select]
Destination = (NewX, NewY);
Doesnt work (error).  And I can not find any other commands in the documentation that would allow for the vector to be updated within the if statement.

Naufr4g0

  • Full Member
  • ***
  • Posts: 112
    • View Profile
Sprite Movement on Single MouseClick
« Reply #25 on: January 17, 2012, 10:14:52 pm »
Quote from: "LucasShadow"
How would I update the Destination and Distance vectors then?  Because doing:
Code: [Select]
Destination = (NewX, NewY);
Doesnt work (error).  And I can not find any other commands in the documentation that would allow for the vector to be updated within the if statement.


The right code is:

Code: [Select]

Destination = sf::Vector2f (NewX, NewY);


Additionally, I think you have to check events for mouse inside the while statement, instead of using App.GetInput() method, cause they have a different behavior.
App.GetInput().IsMouseButtonDown() returns true continuously untill you release the button.
App.GetEvent() returns a true value only at the moment you press the button.

LucasShadow

  • Jr. Member
  • **
  • Posts: 52
    • View Profile
Sprite Movement on Single MouseClick
« Reply #26 on: January 17, 2012, 10:48:53 pm »
I got it to work now thanks to everyone. Just one little thing lol. The player continuously follows the cursor, even though everything is now within the if statement, it doesnt wait for an action from the mouse.

Code: [Select]
        if (App.GetInput().IsMouseButtonDown(sf::Mouse::Left));
            {
            Clock1.Reset();
            float NewX = App.GetInput().GetMouseX();
            float NewY = App.GetInput().GetMouseY();
            sf::Vector2f Origin = PlayerObj.GetPosition();
            sf::Vector2f Destination = sf::Vector2f (NewX, NewY);
            sf::Vector2f Direction = Destination - Origin;
            float Distance = sqrt( (Destination.x - Origin.x) * (Destination.x - Origin.x) + (Destination.y - Origin.y) *  (Destination.y - Origin.y) );
            Direction /= Distance;
            float Speed = .5f;
            PlayerObj.SetPosition(Origin + Direction * Speed);
            }

Tex Killer

  • Full Member
  • ***
  • Posts: 242
    • View Profile
Sprite Movement on Single MouseClick
« Reply #27 on: January 17, 2012, 11:45:52 pm »
Sorry, only now I noticed the ; on the end of this line:
Code: [Select]
if (App.GetInput().IsMouseButtonDown(sf::Mouse::Left));
This makes your if empty, and all the code goes outside it. Get rid of the ;.

Overall, having a good identation helps you see the code better, so I sugest you format all your code.

LucasShadow

  • Jr. Member
  • **
  • Posts: 52
    • View Profile
Sprite Movement on Single MouseClick
« Reply #28 on: January 18, 2012, 01:32:39 am »
Ah, thank you for that lol Little embarrassing to miss a little colon. It is nearly perfect guys, thank you very much. However, the player now only moves if the mouse button is held down, even though the PlayerObj.SetPosition command is outside of the if statement:
Code: [Select]
   sf::Vector2f Origin = PlayerObj.GetPosition();
    sf::Vector2f Destination = Origin;
    sf::Vector2f Direction = Destination - Origin;
    float Speed = .5f;

     while (App.IsOpened())
     {
         sf::Event Event;
         while (App.GetEvent(Event))
         {
             if (Event.Type == sf::Event::Closed)
                 App.Close();
         }
         App.Clear();

         if (App.GetInput().IsMouseButtonDown(sf::Mouse::Left))
            {
            float NewX = App.GetInput().GetMouseX();
            float NewY = App.GetInput().GetMouseY();
            Origin = PlayerObj.GetPosition();
            Destination = sf::Vector2f (NewX, NewY);
            Direction = Destination - Origin;
            float Distance = sqrt( (Destination.x - Origin.x) * (Destination.x - Origin.x) + (Destination.y - Origin.y) *  (Destination.y - Origin.y) );
            Direction /= Distance;
            }
         PlayerObj.SetPosition(Origin + Direction * Speed);

Tex Killer

  • Full Member
  • ***
  • Posts: 242
    • View Profile
Sprite Movement on Single MouseClick
« Reply #29 on: January 18, 2012, 03:22:25 am »
Obsviously, this is because you've put everyting inside the if a couple of posts before. Nobody said that it was a good thing to do.