SFML community forums

Help => General => Topic started by: vcjr on January 04, 2014, 05:10:42 am

Title: Using sf::Keyboard::isKeyPressed in a class - InputManager help!
Post by: vcjr on January 04, 2014, 05:10:42 am
So I have stumbled into a minor blockade again fallowing an old tutorial that I have managed to slowly convert into 2.1.
The problem here is that since window.GetInput() is no Longer Usable since that function is from SFML 1.6, I found that the new way to do things in 2.1 is different. I'll post the sample of code in case someone in the future is fallowing the CodingMade Easy Platformer tutorials.


SFML 1.6
InputManager.h
#ifndef INPUTMANAGER_H
#define INPUTMANAGER_H

#include <vector>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
class InputManager
{
public:
        InputManager();
        ~InputManager();

        void Update(sf::Event event);

        bool KeyPressed(int key);
        bool KeyPressed(std::vector<int> keys);

        bool KeyReleased(int key);
        bool KeyReleased(std::vector<int> keys);

        bool KeyDown(sf::RenderWindow &Window,int key);
        bool KeyDown(sf::RenderWindow &Window, std::vector<int> keys);
private:
        sf::Event event;
};

#endif
InputManager.cpp
#include "InputManager.h"


InputManager::InputManager()
{
}


InputManager::~InputManager()
{
}

void InputManager::Update(sf::Event event)
{
        this->event = event;
}

bool InputManager::KeyPressed(int key)
{
        if (event.Key.Code == key)
                return true;
}

bool InputManager::KeyPressed(std::vector<int> keys)
{
        for (int i = 0; i < keys.size(); i++)
        {
                if (event.Key.Code == keys[i])
                        return true;
        }
        return false;
}

bool InputManager::KeyReleased(int key)
{
        if (event.Key.Code == key && sf::Event::KeyReleased)
                return true;
        return false;
}

bool InputManager::KeyReleased(std::vector<int> keys)
{
        for (int i = 0; i < keys.size(); i++)
        {
                if (event.Key.Code == keys[i] && sf::Event::KeyReleased)
                        return true;
        }
        return false;
}

bool InputManager::KeyDown(sf::RenderWindow &Window, int key)
{
        if (Window.GetInput().IsKeyDown(key))
                return true;
        return false;

}

bool InputManager::KeyDown(sf::RenderWindow &Window, std::vector<int> keys)
{
        for (int i = 0; i < keys.size(); i++)
        {
                if (Window.GetInput().isKeyDown(keys[i]))
                        return true;
        }
        return false;
}
 

You can Notice the difference Since in 1.6 you have to put "event.Key.Code" in capitals while in 2.1 is lower case.

SFML 2.1
The Guy has alot of errors in his "C++ Sfml Platformer Made Easy Tutorial 6 - InputManager [Part 1]" tutorial but he probably covers them in part 2.

The really problem that I'm trying to solve is How would I implement "sf::Keyboard::isKeyPressed"  in the header file would replacing things to this help:

        bool KeyDown(sf::Keyboard::isKeyPressed,int key);
        bool KeyDown(sf::Keyboard::isKeyPressed, std::vector<int> keys);

        //or would removing int key, and the vector help ?
 
if everything works Ill post the sfml 2.1 converted version here.
Title: Re: Using sf::Keyboard::isKeyPressed in a class - InputManager help!
Post by: vcjr on January 04, 2014, 06:39:47 am
After a little more hard thinking and a hour later I think i found the solution but please correct me if this is wrong . I only assume is correct since I dint receive any compile error :D

SFML 2.1
InputManager.h
   bool KeyDown(sf::Keyboard::Key key);
   bool KeyDown(std::vector<sf::Keyboard::Key> keys);
 
and InpuManager.cpp
bool InputManager::KeyDown(sf::Keyboard::Key key)
{
        if (sf::Keyboard::isKeyPressed(key))
                return true;
        return false;

}

bool InputManager::KeyDown(std::vector<sf::Keyboard::Key> keys)
{
        for (int i = 0; i < keys.size(); i++)
        {
                if (sf::Keyboard::isKeyPressed(keys[i]))
                        return true;
        }
        return false;
}
 

So far that was my pain in the behind. Also and to explain what I did to justify if I'm actually right or not or just to explain my way of thinking on why I did it that way. Well, after 20 minutes of plundering the Docs there was only one way to implement Keyboard::isKeyPressed(Key key) <---- I didn't notice that until 20+ more minutes later before that rock hit my head, I kept doing what I showed you in the first post without any success. So the solution was that if i passed a sf::Keyboard::Key type to the function and in the cpp I utilized the magic of isKeyPressed everything would work. Sorry if my way of explaining is harsh to grasp, my c++ wording isn't at it's perfection yet.


PS. If there's a better way please tell me :D
Title: Re: Using sf::Keyboard::isKeyPressed in a class - InputManager help!
Post by: Nexus on January 04, 2014, 10:02:47 am
Everytime somebody shows code from the CodingMadeEasy tutorial, it's just questionable (see here (http://en.sfml-dev.org/forums/index.php?topic=12226.msg84907#msg84907) and here (http://en.sfml-dev.org/forums/index.php?topic=10167.msg69883#msg69883)). I don't recommend to follow his tutorials, they teach very bad C++ style and wrong SFML usage.

Concrete example:
bool KeyReleased(int key);
bool KeyReleased(std::vector<int> keys);
Keys are not stored as int, but sf::Keyboard::Key. There's no need to lose type safety. Furthermore, it's unnecessary to copy the whole container, a const reference would do. Additionally, the container overload could call the simple overload to avoid code duplication.

bool InputManager::KeyReleased(int key)
{
    if (event.Key.Code == key && sf::Event::KeyReleased)
        return true;
    return false;
}
Not only is the if condition unnecessary (a direct return would also work), but here it's also plain wrong. sf::Event::KeyReleased is a constant.

InputManager::~InputManager()
{
}
Again unnecessary. See also rule of three/five.

The whole design of InputManager is flawed. It stores a single event and constantly overrides it. The idea of such abstractions is to separate input handling and game logic, which is exactly not possible in the case here, because one needs to update and poll InputManager for every single event -- in the end, you have a lot of boilerplate code that simplifies nothing.

I honestly don't think it's worth to fix his codes or port them to SFML 2.1, since they're fundamentally broken. You should rather have a look at the tutorials of people who know how to program in C++. For example, those of SuperV1234 (http://en.sfml-dev.org/forums/index.php?topic=13677.0) are very nice.
Title: Re: Using sf::Keyboard::isKeyPressed in a class - InputManager help!
Post by: vcjr on January 04, 2014, 05:35:09 pm
Thanks for the reply, the only reason I was fallowing his tutorial was to see how I would implement a way to manage everything separately for example to have : an Inputmanager, contentmanager, and even a player class to the current little game I have where its a top down shooter. The code that I have is all over the place and in Main.cpp, I want to see how I would organize  it better you know so the code could actually look like it was done for a game not a cake of things everywhere.
Title: Re: Using sf::Keyboard::isKeyPressed in a class - InputManager help!
Post by: amir ramezani on January 04, 2014, 06:09:12 pm
the best tutorial is the SFML's tutorial
read it first and enjoy
Title: Re: Using sf::Keyboard::isKeyPressed in a class - InputManager help!
Post by: vcjr on January 04, 2014, 06:22:31 pm
the ones where?
Title: Re: Using sf::Keyboard::isKeyPressed in a class - InputManager help!
Post by: Nexus on January 04, 2014, 06:39:26 pm
[...] to see how I would implement a way to manage everything separately for example to have : an Inputmanager, contentmanager, and even a player class to the current little game I have where its a top down shooter.
Since you're talking about a top-down shooter, that's exactly what we're developing in the SFML book (http://en.sfml-dev.org/forums/index.php?topic=11992) (the e-book is very cheap at the moment). We also split the game into modular components (input, resources, game logic, sound, network, states...) and show a possible design. If you don't want to buy the book, there's still the GitHub repository (https://github.com/SFML/SFML-Game-Development-Book) where you can see all of its source code.

the ones where?
Here. (http://www.sfml-dev.org/resources.php)
Title: Re: Using sf::Keyboard::isKeyPressed in a class - InputManager help!
Post by: vcjr on January 04, 2014, 07:39:45 pm
Oh , I was thinking about that book but since you clarified what it has I'll just try to buy the digital version.