Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

So, I'm trying to make my sprite walk to the X-coordinate of my mouse click. This is my code:

currentMouseState = Mouse.GetState();
            MouseState mouseState = Mouse.GetState();
            if (lastMouseState.LeftButton == ButtonState.Released && currentMouseState.LeftButton == ButtonState.Pressed)
            {
                int mouseposx = mouseState.X;
                if (playerPosition.X < mouseposx)
                    {
                        playerPosition.X += 3;
                    }               
                if (playerPosition.X > mouseposx)
                    {
                        playerPosition.X -= 3;                           
                    }
            }`

The problem is that the sprite will walk only 3 pixels and then stop. If I use while instead, like this:

  currentMouseState = Mouse.GetState();
            MouseState mouseState = Mouse.GetState();
            if (lastMouseState.LeftButton == ButtonState.Released && currentMouseState.LeftButton == ButtonState.Pressed)
            {
                int mouseposx = mouseState.X;
                while (playerPosition.X < mouseposx)
                    {
                        playerPosition.X += 3;
                    }               
                while (playerPosition.X > mouseposx)
                    {
                        playerPosition.X -= 3;
                    }
            }

it will simply teleport to the X-coordinate instead. I tried adding a delay using Thread.Sleep(ms), but that just made it freeze and then teleport anyway.

So, what should I do?

EDIT: This is the new code, by Byte56.

currentMouseState = Mouse.GetState();
            MouseState mouseState = Mouse.GetState();
            if (lastMouseState.LeftButton == ButtonState.Released && currentMouseState.LeftButton == ButtonState.Pressed)
            {
                if (playerPosition.X - mouseState.X < 3)
                {
                    playerPosition.X = mouseState.X;
                }
                else if (playerPosition.X < mouseState.X)
                {
                    playerPosition.X += 3;
                }
                else if (playerPosition.X > mouseState.X)
                {
                    playerPosition.X -= 3;
                }
            }

edit3:

 void update()
        {
            // Check if the player has reached the target, if not, move towards it. 
            if (playerPosition.X - playerTarget.X < 3)
            {
                playerPosition.X = playerTarget.X;
            }
            else if (playerPosition.X > playerTarget.X)
            {
                playerPosition.X -= 3;
            }
            else if (playerPosition.X < playerTarget.X)
            {
                 playerPosition.X += 3;
            }


        }

and

 currentMouseState = Mouse.GetState();
            MouseState mouseState = Mouse.GetState();

            if (lastMouseState.LeftButton == ButtonState.Released && currentMouseState.LeftButton == ButtonState.Pressed)
            {
                // This will give the player a target to go to. 
                playerTarget.X = mouseState.X;
            }
            update();
share|improve this question
    
Is this coding running in a spearate thread? –  olevegard May 13 '13 at 17:48
    
No, this code is directly inside the update() method –  Elias Finoli May 13 '13 at 18:07
    
look up how a game loop works. –  Stephen May 13 '13 at 19:45
add comment

3 Answers

up vote 8 down vote accepted

Using a while loop inside your game loop is a basic no-no. Think about how the code is being executed and you'll realize why it just teleported or was frozen and then teleported. (hint: how much of that code do you think is run before the next time your graphics are updated?)

You want to have a target position, then on each iteration of your game loop check to see if your character has arrived at the target position. If it hasn't arrived yet, move it slightly closer.

if (lastMouseState.LeftButton == ButtonState.Released && currentMouseState.LeftButton == ButtonState.Pressed) 
{
    targetPosition.set(mouseState.X, mouseState.Y);
}

if (Math.Abs(playerPosition.X - targetPosition.X) < playerSpeed) 
{ 
   //handle the case where we're very close and would over shoot the position by moving
   playerPosition.X = targetPosition.X; 
}
else if (playerPosition.X < targetPosition.X)
{
    //we're at a position less than the target, add to our position
    playerPosition.X += playerSpeed;
} 
else if (playerPosition.X > targetPosition.X)
{
    //we're at a position greater than the target, subtract from our position
    playerPosition.X -= playerSpeed;
}

Remember that computers only do exactly what you tell them.

share|improve this answer
3  
Also using Thread.sleep() should be discouraged. It's better to have a timer that gives you a delta time for making movement correct. –  olevegard May 13 '13 at 17:51
    
I tried using your code, but it still doesn't work. Now it moves 3pxl and stops if mousepos.X < playerPosition.X and teleports if mousepos.X > playerPosition.X... –  Elias Finoli May 13 '13 at 18:00
    
@EliasFinoli your post with your new code. –  olevegard May 13 '13 at 18:12
    
@olevegard, the new code is now in the bottom of my Question. Could not answer my own question since I dont have enough rep for that. –  Elias Finoli May 13 '13 at 18:18
    
@EliasFinoli Mark this as the accepted answer, then. This is the correct fix for your issue. –  Andy_Vulhop May 13 '13 at 18:57
show 4 more comments

You need a variable that stores the position that was clicked ( the target of the object. ) This position could be set when you check the rest of your input like this

MouseState mouseState = Mouse.GetState();
if (lastMouseState.LeftButton == ButtonState.Released && currentMouseState.LeftButton == ButtonState.Pressed)
{
    // This will give the player a target to go to. 
    playerTarget.X = mouseState.X;
}

Now we have the position the object is supposed to go to. Now we need to move it towards it. We need to do this every iteration of the main loop, but outside of the code that checks the input. It is useful to put this in a separate function.

 void update( )
 {
     // Check if the player has reached the target, if not, move towards it. 
     if (playerPosition.X < playerTarget.X)
     {
         playerPosition.X += 3;
     }
     else if (playerPosition.X > playerTarget.X)
     {
         playerPosition.X -= 3 ;
     }

 }

This function works just like your function, but it will be execute ever frame regardless of pressed buttons. Now all you have to do is add a function call to this function in your main loop :

 update ( ); 
share|improve this answer
    
I don't really understand the logic in this code. Could you explain? Appreciate your help! –  Elias Finoli May 13 '13 at 19:29
    
@EliasFinoli Added some explanation and simplified to make my logic more clear –  olevegard May 13 '13 at 19:43
    
Thank you. Though, how/where do I declare playerTarget? Can't seem to figure that little bit out. –  Elias Finoli May 13 '13 at 20:00
    
@EliasFinoli Declare it in the same place as playerPosition. It's just a 2d vector that holds the target of the player. –  olevegard May 13 '13 at 20:01
    
This worked, except when it reaches it's destination, it sometimes (most cases actually) lags back and forth like 3 pixels (I'm guessing 3 pixels since that's my speed) I tried adding this line: else if (playerPosition.X - playerTarget.X < 3) { playerPosition.X = playerTarget.X; } but that didn't really help. Any ideas? –  Elias Finoli May 13 '13 at 20:20
add comment

Could this be causing your issues?

if (lastMouseState.LeftButton == ButtonState.Released && currentMouseState.LeftButton == ButtonState.Pressed)

You are saying here:

If the left mouse button was released AND is being pressed currently;

This seems like contradicting actions, mouse buttons are usually pressed first, then released to signify a singular action (or continuously pressed to signify on-going action(s)). Perhaps what you are looking for is here is:

If the left mouse button was released OR is being pressed currently;

if (lastMouseState.LeftButton == ButtonState.Released || currentMouseState.LeftButton == ButtonState.Pressed)

Try that out and see what it does to your teleporting and short-stops.

share|improve this answer
    
No, was released && isDown is just a way of making sure this is the first frame this button was pressed. The or statement will be true in all cases except if the button was down in the previous frame and was pressed in this one. –  olevegard May 13 '13 at 18:42
    
In one way, it's behaving more like I want it to, but it's moving regardless if I click or not. This is what the movement looks like: youtube.com/watch?v=jFpzCXrKpFI&feature=youtu.be –  Elias Finoli May 13 '13 at 18:56
2  
He is actually checking if the "lastMouseState" was released and the "currentMouseState" is pressed. So the if statement itself is fine. –  UnderscoreZero May 13 '13 at 19:59
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.