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

Author Topic: Proper input handler Class  (Read 3334 times)

0 Members and 1 Guest are viewing this topic.

niccnacc

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Proper input handler Class
« on: January 28, 2013, 06:59:01 pm »
Hi!

Building up a Map Editor I have a Menu on the right with an entity of each test Sprite. Those are in a list of my child of sf::Sprite called ASprite. If I click on an Entity, and drag it over (or not for the first tests), I want a copy to be made and given to another list, wich is full of "world" sprites.

My code does copy the Sprite allready, but it does it quite often^^.
So 1 Click with the mouse results in many "Pressed"-True values from my Input Class.

I was told that a Singleton is not the way to go with it. > So how is this done properly, and what are my mistakes here for multiple "Pressed" occurences (I know that saving the event results in that, but I can't imagine another way of doing it better).

Edit: Change pretty much everything, edited the tiltle to specify my problem.
« Last Edit: January 29, 2013, 11:42:25 am by niccnacc »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10815
    • View Profile
    • development blog
    • Email
Re: Map Editor for Platformer
« Reply #1 on: January 28, 2013, 07:22:03 pm »
You should provide a complete and minimal example, otherwise we can only make wrong guess and it won't be helpful for you and frustrating for us. ;)

My blind guess would be some wrong input handling, given the ugly use of singleton for inputs etc... :-\
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

niccnacc

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Re: Map Editor for Platformer
« Reply #2 on: January 29, 2013, 08:39:14 am »
I figured out most of the problem by myself now. With
ASprite * copy = new ASprite((**it2));
giveToFunction(copy);
 
it worked, finally, allthough I thought I tried it before.

The Problem now reduced to:
My Input Class should tell, if the mouse is Pressed (once for a single click). What it does is saying yes for every iteration of the program during clicking - like a held down function.
I've tried my function with minimal setup and it worked - so 1 click = 1 pressed event.
I think the problem is about storing the event. The Lock I implemented here didn't do its job..

How should input be handled? I'm new to this whole thing and figured that accessing the Input from everywhere would be very practical (that's why Singleton)! Like the player could use the Input by himself, without the need for some container to search for him. Any suggestion would be fine :D.

My Input looks like this:

Input.cpp
#include "Input.h"

#include <iostream>


void Input::update(sf::Event event)
{
        this->event = event;
        eventLock = false;
        //KEYBOARD
        if(event.type == sf::Event::KeyPressed)
        {
                down.insert(event.key.code);
                return;
        }
        else if (event.type == sf::Event::KeyReleased)
        {
                down.erase(event.key.code);
                return;
        }
       
        //MOUSE
        else if(event.type == sf::Event::MouseButtonPressed)
        {
                down.insert(event.mouseButton.button);
                return;
        }
        else if (event.type == sf::Event::MouseButtonReleased)
        {
                down.erase(event.mouseButton.button);
                return;
        }
        else if (event.type == sf::Event::MouseMoved)
        {
                mousePosition.x = event.mouseMove.x;
                mousePosition.y = event.mouseMove.y;
                //std::cout << mousePosition.x << " " << mousePosition.y << std::endl;
                return;
        }
}


bool Input::pressed(int value)
{
        if(eventLock) return false;
        if( (event.type == sf::Event::KeyPressed || event.type == sf::Event::MouseButtonPressed)
                && event.key.code == value)
        {
                eventLock = true;
                return true;
        }
        return false;
}
 


Input.h
#ifndef __GutenMapEdit__Input__
#define __GutenMapEdit__Input__ 1


#include <iostream>
#include <set>
#include <SFML/Graphics.hpp>


class Input
{

public:
       
        void update(sf::Event event);
        bool pressed(int value);
        bool heldDown(int value);
        sf::Vector2i getMousePosition(){return mousePosition;}
       
private:
       
        std::set<int> down;
        sf::Vector2i mousePosition;
        sf::Event event;
        bool eventLock = false;
       
       
        /* Singleton */
public:
        static Input& instance()
        {
                static Input _instance;
                return _instance;
        }
private:
        Input () { };
        /* prohibition for copying a new instance */
       
        Input ( const Input& );
        ~Input () { };


};

 

Where the main calls:



sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)                                       
                        { window.close(); }
               
                        Input::instance().update(event);       
        }// Process events ^


 

I am completely self taught and any help how to do it better would be great. But please, spare words like ugly. No beginner is perfect, neither are you. Thanks in advance!
« Last Edit: January 29, 2013, 10:33:01 am by niccnacc »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10815
    • View Profile
    • development blog
    • Email
AW: Proper input handler Class
« Reply #3 on: January 29, 2013, 12:20:16 pm »
To me if seens like you're trying to reproduce what sf::Mouse::isButtonPressed and sf::Keyboard::isKeyPressed do. Or is there a difference?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

niccnacc

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Re: Proper input handler Class
« Reply #4 on: January 29, 2013, 12:51:47 pm »
If I get it right, isPressed states something like: the mouse button is currently pressed down.
So the problem with that is, that if I use it to copy a sprite and lay it on the map, the process is done so fast, that there are many iterations of my whole program in the time of one short pressing of the mousbutton.

sf::Mouse::isButtonPressed(sf::Mouse::Left)
 used in a Method doesn't give true for me for some reason.

What I need is a representation of just one Click. If the button is held, there shall not be more copies.
The sf::Keyboard::isKeyPressed(sf::Keyboard::Space) doesn't work either - starting to feel this has something to do with Mac or something.

As well as that, the functions above should return true even, if the window is not active, which could lead to strange things possibly.

cire

  • Full Member
  • ***
  • Posts: 138
    • View Profile
Re: Proper input handler Class
« Reply #5 on: January 29, 2013, 03:11:03 pm »
So 1 Click with the mouse results in many "Pressed"-True values from my Input Class.

You can process many events per main-loop iteration.  You only store one of them in your Input class.

Your pressed function doesn't differentiate between mouse buttons and keys.  In fact, it erroneously checks the event key code when there was a mouseButtonPressed event.  The return value can be completely unrelated to whether a mouse button was pressed or not.

Besides, which:

If I click on an Entity, and drag it over (or not for the first tests), I want a copy to be made and given to another list, wich is full of "world" sprites.

Once you're in the dragging state, you should only care about the mouseMoved event to keep the dragged item in the right spot on the screen and mouseButtonReleased to know when the user is finished dragging.

I would get rid of your ill-advised Input class until you better understand how the event system works.

niccnacc

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Re: Proper input handler Class
« Reply #6 on: January 29, 2013, 04:43:52 pm »
Thanks for the hint with the key-check on Mouse-event.
And I just forgot about the fact, that there are more events possible.
The thing is, that I want/need access to the Input from arround the program (can't imagine another way of getting the input everywhere without tons of functions for handing it over). For example, a Sprite should become selected if clicked on. So within the Sprite, if clicked is true and the cursor is on him, the bool turns true. And many other things.
That's why I don't want to use the Input from within main, because I would have to deligate many things from there to somewhere else.

The overall problem I have is, that I didn't do anything that big so far. I had complex topics like artificial intelligence, opengl basics within a pong game, but the overall structure was allways quite easy in terms of programming.
Maybe you could give me an insight in how handling Input should be done, or was implemented by your programs.. @exploiter I saw you did a tile map editor - quite similar to my project. Maybe you could give me advice?

Thanks for the help so far!