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

Author Topic: GetInput() trouble  (Read 2114 times)

0 Members and 1 Guest are viewing this topic.

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
GetInput() trouble
« on: March 23, 2011, 05:02:30 am »
Hello,
I have the following code that allows a sprite to move (in this case the main player's sprite) using the default arrow keys:

Code: [Select]
void NewPlayer::ProcessInputs(sf::RenderWindow &Target)
{
    //The code follows:
    //If an arrow key is pressed
    //If the sprite if bellow or above the axis value required
    //Move the sprite

    //UP
    if(Target.GetInput().IsKeyDown(sf::Key::Up))
        if(splayer.GetPosition().y > 40.0)
            splayer.Move(0,-m_movespeed);

    //DOWN
    if(Target.GetInput().IsKeyDown(sf::Key::Down))
        if(splayer.GetPosition().y < 730.0)
            splayer.Move(0,m_movespeed);

    //LEFT
    if(Target.GetInput().IsKeyDown(sf::Key::Left))
        if(splayer.GetPosition().x > 240)
            splayer.Move(-m_movespeed,0);

    //RIGHT
    if(Target.GetInput().IsKeyDown(sf::Key::Right))
        if(splayer.GetPosition().x < 780.0)
            splayer.Move(m_movespeed,0);

}


However it's glitching me a bit.
If the sprite reaches the top of the screen and if i keep pressing UP, the sprite doesn't move, good!
However if I keep pressing UP and then press DOWN at the same time, the sprite nudges down a bit and doesn't move until I release UP.
The only problem here is that little nudge. Even though it's just a small movement, it feels really strange during gameplay.
EDIT: (The same thing happens with Left and Right Keys)

Here's a picture to understand better what happens:

Left: Just Pressing UP
Right: Pressing UP and DOWN

What could I change in my code to fix this?
Thanks in advance

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
GetInput() trouble
« Reply #1 on: March 23, 2011, 08:41:05 am »
This happens because of the order of processing: When you're at y=0.0 and press the up key, the splayer.Move( 0, -m_movespeed ) is skipped (because the sprite's y position is below 40.0). The next statement checks if the down key is pressed and moves the sprite accordingly to the bottom.

To solve the issue you can for example use an sf::Vector2f and set the x and y components to form a movement vector, like:
Code: [Select]

sf::Vector2f velocity( 0.f, 0.f );
if( key == up ) {
  velocity.y -= 1.f;
}
if( key == down ) {
  velocity.y += 1.f;
}
...


This way when you press both buttons, the resulting y component of 'velocity' will be 0, i.e. no movement at all.

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
GetInput() trouble
« Reply #2 on: March 23, 2011, 03:17:17 pm »
Thanks for the quick reply,
I'm not very sure if I understood the solution well.

I tried the following:
Code: [Select]
void NewPlayer::ProcessInputs(sf::RenderWindow &Target)
{
    sf::Vector2f m_movespeed(0.f, 0.f);

    if(Target.GetInput().IsKeyDown(sf::Key::Down))
        if(splayer.GetPosition().y < 730.0)
            m_movespeed.y += 5.f;

    if(Target.GetInput().IsKeyDown(sf::Key::Up))
        if(splayer.GetPosition().y > 40.0)
            m_movespeed.y -= 5.f;

    if(Target.GetInput().IsKeyDown(sf::Key::Left))
        if(splayer.GetPosition().x > 240.0)
            m_movespeed.x -= 5.f;

    if(Target.GetInput().IsKeyDown(sf::Key::Right))
        if(splayer.GetPosition().x < 780.0)
            m_movespeed.x += 5.f;

        splayer.Move(m_movespeed.x,m_movespeed.y);
}


But the problem is still there. Sorry I'm being thick here but what am I doing wrong?
Thanks in advance

EDIT: I think I got it working:
Code: [Select]
void NewPlayer::ProcessInputs(sf::RenderWindow &Target)
{
    sf::Vector2f m_movespeed(0.f, 0.f);

    if(Target.GetInput().IsKeyDown(sf::Key::Down))
    {
        if(splayer.GetPosition().y < 730.0)
            m_movespeed.y = 5.f;
        else
            m_movespeed.y = 0.f;
    }

    if(Target.GetInput().IsKeyDown(sf::Key::Up))
    {
        if(splayer.GetPosition().y > 40.0)
            m_movespeed.y = -5.f;
        else
            m_movespeed.y = 0.f;
    }

    if(Target.GetInput().IsKeyDown(sf::Key::Right))
    {
        if(splayer.GetPosition().x < 780.0)
            m_movespeed.x = 5.f;
        else
            m_movespeed.x = 0.f;
    }

    if(Target.GetInput().IsKeyDown(sf::Key::Left))
    {
        if(splayer.GetPosition().x > 240.0)
            m_movespeed.x = -5.f;
        else
            m_movespeed.x = 0.f;
    }
   
    splayer.Move(m_movespeed.x,m_movespeed.y);
}


But I'm getting that feel that the code is excessively long for something so simple.
Thanks for the help   :)

devlin

  • Full Member
  • ***
  • Posts: 128
    • View Profile
GetInput() trouble
« Reply #3 on: March 23, 2011, 07:04:03 pm »
I would separate the conditions into something like this:

(this below is pseudocode written without checking syntax etc - but you should get the idea of it)

Code: [Select]

    const sf::Input & myInput = Target.GetInput();

    if(myInput.IsKeyDown(sf::Key::Down))
            m_movespeed.y += 5.f;

    if(myInput.IsKeyDown(sf::Key::Up))
            m_movespeed.y -= 5.f;

    if(myInput.IsKeyDown(sf::Key::Left))
            m_movespeed.x -= 5.f;

    if(myInput.IsKeyDown(sf::Key::Right))
            m_movespeed.x += 5.f;

    sf::Vector2f newPos(splayer.GetPosition().x + m_movespeed.x, splayer.GetPosition().y + m_movespeed.y);

    newPos.x = min(newPos.x, 780);  // or replace with a proper clamp function
    newPos.x = max(newPos.x, 240);  //
    newPos.y = min(newPos.y, 730);  //
    newPos.y = max(newPos.y, 40);   //

    splayer.SetPosition(newPos);

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
GetInput() trouble
« Reply #4 on: March 24, 2011, 02:03:27 pm »
Didn't even remember there was a min() and max(). I'll go with that solution, thanks for the help  :wink: