Global Inputs

Learn how to use SFML Global Inputs

Global Inputs

As discussed in Events & Global Inputs, Global Inputs are used to retrieve the state of inputs at the exact moment you request it. SFML offers to handle three types of Global Inputs

  • Keyboard using the static class sf::Keyboard
  • Mouse using the static class sf::Mouse
  • Joystick using the static class sf::Joystick
A big difference with Events is Global Inputs only check if a button is Pressed and not if a button is Released. If you need to know when a button gets Released you’ll have to use Events.

Keyboard Global Inputs

The class sf::Keyboard offers the method isKeyPressed to check if a key is currently Pressed.

static bool isKeyPressed (Key key)

This method is pretty simple to use, simply specify the key you want to check and a boolean will be returned. You can find the list of keys here : SFML Keyboard Keys List

// check if the Left CTRL key is pressed
bool isPressed = sf::Keyboard::isKeyPressed(sf::Keyboard::LControl);
// check if the Left ALT key is pressed
bool isPressed = sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt);

Modifier Keys Functions

One cool thing you can do with Keyboard Global Inputs is to create your own modifier keys functions. The code below is extracted from the Nero Game Engine source, it shows the implementation of the following functions

  • bool CTRL() : check if only CTRL is pressed
  • bool SHIFT() : check if only SHIFT is pressed
  • bool ALT() : check if only ALT is pressed
  • bool CTRL_SHIFT() : check if only CTRL and SHIFT are pressed
  • bool CTRL_ALT() : check if only CTRL and ALT are pressed
  • bool SHIFT_ALT() : check if only SHIFT and ALT are pressed
//check if only CTRL is pressed
bool CTRL()
{
    return   sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) &&
            !sf::Keyboard::isKeyPressed(sf::Keyboard::LShift)   &&
            !sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt);
}
//check if only SHIFT is pressed
bool SHIFT()
{
    return  !sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) &&
             sf::Keyboard::isKeyPressed(sf::Keyboard::LShift)   &&
            !sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt);
}
//check if only ALT is pressed
bool ALT()
{
    return  !sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) &&
            !sf::Keyboard::isKeyPressed(sf::Keyboard::LShift)   &&
             sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt);
}
//check if only CTRL and SHIFT are pressed
bool CTRL_SHIFT()
{
    return   sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) &&
             sf::Keyboard::isKeyPressed(sf::Keyboard::LShift)   &&
            !sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt);
}
//check if only CTRL and ALT are pressed
bool CTRL_ALT()
{
    return   sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) &&
            !sf::Keyboard::isKeyPressed(sf::Keyboard::LShift)   &&
             sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt);
}
//check if only SHIFT and ALT are pressed
bool SHIFT_ALT()
{
    return  !sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) &&
             sf::Keyboard::isKeyPressed(sf::Keyboard::LShift)   &&
             sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt);
}

Mouse Global Inputs

The class sf::Mouse offers the method isButtonPressed to check if a mouse button is currently pressed. SFML supports five mouse buttons (Left, Right, Middle, XButton1, XButton2). In addition, you have four other methods to retrieve and update the position of the mouse.

//Check if button is pressed
static bool         isButtonPressed(Button button)
//Get mouse position
static Vector2i     getPosition() //Global position
static Vector2i     getPosition(const Window &relativeTo) //Local position
//Update mouse position
static void 	    setPosition(const Vector2i &position) //Global position
static void 	    setPosition(const Vector2i &position, const Window &relativeTo) //Local position

The mouse position can be Global (relative to your computer screen) or Local (relative to your SFML window). The methods getPosition and setPosition let you specify your SFML window in order to retrieve or update the local position.

Joystick Global Inptus

The class sf::Joystick offers the three methods below to retrieve the current state of a joystick connection, buttons and axes position.

bool connected = sf::Joystick::isConnected(joystickId)
bool isPressed = sf::Joystick::isButtonPressed(joystickId, buttonId)
float position = sf::Joystick::getAxisPosition(joystickId, axisId);

Improving our Gamepad Class

Using that new information, let’s improve our Gamepad Class so it can use the joystick global inputs

First, we can remove the attribute bool mConnected and the method setConnected from our class. We only keep the method isConnected() that will return the current state of the controller using global input.

bool Gamepad::isConnected() const
{
    return sf::Joystick::isConnected(getId());
}

Then, we add two methods to get the current state of buttons and the position of axes. That means we can check if a button is pressed like that : isButtonPressed(JSButton::Square), and get the position of an axis like that : getAxisPosition(JSAxis::LeftAnanlogX). Pretty cool, isn’t it.

If you look closely in the code below you can see ButtonMappingReverse and AxisMappingReverse. These two mappings are created by simply inverting the keys and values of ButtonMapping and AxisMapping, it happens when the mappings are provided to the Gamepad class (expand Reverse Mapping below to see the code). The C++ language does not provide bidirectional mapping so we do it our way !?

void Gamepad::setButtonMapping(const JSButtonMapping& mapping)
{
    mButtonMapping = mapping;
    for (auto const& item : mapping)
    {
        mButtonMappingReverse[item.second] = item.first;
    }
}
void Gamepad::setAxisMapping(const JSAxisMapping& mapping)
{
    mAxisMapping = mapping;
    for (auto const& item : mapping)
    {
        mAxisMappingReverse[item.second] = item.first;
    }
}
bool Gamepad::isButtonPressed(const JSButton& button)
{
    return sf::Joystick::isButtonPressed(getId(), mButtonMappingReverse.at(button));
}
float Gamepad::getAxisPosition(const JSAxis& axis)
{
    switch(axis)
    {
        case JSAxis::DPadX: return sf::Joystick::getAxisPosition(getId(), mAxisMappingReverse.at(JSAxis::DPadX));
        case JSAxis::DPadY: return sf::Joystick::getAxisPosition(getId(), mAxisMappingReverse.at(JSAxis::DPadY));
        case JSAxis::LeftAnalogX: return sf::Joystick::getAxisPosition(getId(), mAxisMappingReverse.at(JSAxis::LeftAnalogX));
        case JSAxis::LeftAnalogY: return sf::Joystick::getAxisPosition(getId(), mAxisMappingReverse.at(JSAxis::LeftAnalogY));
        case JSAxis::RightAnalogX: return sf::Joystick::getAxisPosition(getId(), mAxisMappingReverse.at(JSAxis::RightAnalogX));
        case JSAxis::RightAnalogY: return sf::Joystick::getAxisPosition(getId(), mAxisMappingReverse.at(JSAxis::RightAnalogY));
        case JSAxis::ShoulderX: return sf::Joystick::getAxisPosition(getId(), mAxisMappingReverse.at(JSAxis::ShoulderX));
        case JSAxis::ShoulderY: return sf::Joystick::getAxisPosition(getId(), mAxisMappingReverse.at(JSAxis::ShoulderY));
        default: 0.f;
    }
}