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

Author Topic: Processing User Input  (Read 2415 times)

0 Members and 1 Guest are viewing this topic.

Grundkurs

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
Processing User Input
« on: September 11, 2014, 05:41:27 pm »
Hello there,
i'm writing a small application for displaying sprite-animations. I wrote the application once some months ago where i fetched the user input via the console and after gathering all important information it opened the sfml-window, loaded automatically the sprite sheet and displayed the animation at variable speed. Everything worked well but it was kind of ugly that the application was divided into two parts: The Console-Part and the SFML-Part. So i started to rewrite the Application where i fetched the user-input not in Console-Window mode but in sfml itsself. This looks now this way:
https://www.youtube.com/watch?v=jvdD38c_k94&feature=youtu.be

However the code i wrote to accomplish this is very tedious and kind of feels wrong so i was hoping someone might point me in to the right direction how to implement it better.
basically i concatenate all typed sf::keys from the user to a std::string variable and when the player presses Return it gets assigned to a "complete-String" variable which i use for processing the input.

Because there is several data that has to be collected via input (like
1.Question "a) load new sprite sheet, b) load last opened sprite sheet"
if User press a) ...
2.Question: Type Name of Sprite Sheet
if User inputs "Name.png" check if Name.png exists in folder etc.
3.Question....

So if player presses "a" the second question gets displayed, if the user answers second question appropriately the 3rd question gets displayed and so on...
i tried to solve this with a linked List of Option-Elements. They all inherit from
base class Option
class Option
{
public:
        Option();
        virtual ~Option();

        virtual std::string getStr() = 0;
        virtual Option* processInput(const std::string& input) = 0;
        Option* error;
        Option* next;
        Option* last;
};

So the implementation of the first questions looks like this:
#include "RootOption.h" //RootOption inherits from class Option
RootOption::RootOption()
{
}
RootOption::~RootOption()
{
}
std::string RootOption::getStr()
        {
        return std::string{ "a) load new sprite sheet\nb) load last opened sprite sheet" };
        }

Option* RootOption::processInput(const std::string& input)
        {
        if (input == "a" && next != nullptr) return next;
        return this;
        }
 

the parameter of processInput() is the complete String of the user-input that got passed to this method.
So if player presses "a", the next question gets displayed.
The call-side looks like this:
void Inputter::getUserInput() //method gets only invoked when player presses Return
        {
        currentOption = currentOption->processInput(mCompleteStr); //compute input in Option-Class
                                                                                                //and return appropriate next Option-Class
        println(mDisplayText, currentOption->getStr()); //print message of new Option
        }
 

This approach leads to a ton of different "Option classes" that inherits from Base Option Class and with it comes a lot of text and files and its not very flexible and horrible to code with. Unfortunately i dont have any idea how to make the traversing through the different questions and collecting information from the user more straight forward. Maybe someone has a good idea how to approach this kind of logic?
« Last Edit: September 11, 2014, 06:59:56 pm by Grundkurs »

Strelok

  • Full Member
  • ***
  • Posts: 139
    • View Profile
    • GitHub
Re: Processing User Input
« Reply #1 on: September 11, 2014, 06:44:16 pm »
Well, nothing comes in mind yet but
« Last Edit: September 11, 2014, 08:00:43 pm by Strelok »

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Processing User Input
« Reply #2 on: September 11, 2014, 08:09:13 pm »
Writing
Option() = default; // or just not mentioning it
virtual ~Option() = default;
 
Instead of implementing them with an empty body, is not only shorter to write, it is also preferable. Since then your constructor and destructor will be "trivial" which no user defined ctor/dtor ever is (not even if the body is empty).

Edit: Note; in this case only the constructor will be trivial. The destructor is not trivial since it is virtual, so for the dtor we just save some typing (in this case).
« Last Edit: September 11, 2014, 08:25:53 pm by Jesper Juhl »

Grundkurs

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
Re: Processing User Input
« Reply #3 on: September 15, 2014, 10:25:26 pm »
Hey guys, thanks for the hints, i didn't knew about the "ctor()= default;" instruction yet! I didnt had any good idea either, so i'll stick with my current solution, at least it behaves like it should. Greetings

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Processing User Input
« Reply #4 on: September 20, 2014, 07:00:31 pm »
Don't write your own data structures unless you have good reasons not to use existing ones in the STL or Boost. And avoid mixing of element functionality with container functionality unless you need intrusive containers.

Concerning your problem, why do you need a container of abstract option elements? Can't you forward one option at a time to the next menu? Or why not a container of strings?

Also avoid new/delete. In case you really need to store polymorphic objects in containers, use std::unique_ptr, as it handles memory for you.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

 

anything