Design: wie geht ihr mit Usereingaben um?



  • Hoi 🙂

    Ich hab mal 'ne superdumme Frage (erschlagt mich nicht wenn ich die offensichtliche Loesung nicht sehe): wie geht ihr mit Usereingaben um? bei mir sieht das meistens so aus, dass ich ein "input"-modul habe, dessen "handle()" - Methode bei jedem Frame 1x aufgerufen wird...

    Das kann z. B. so aussehen:

    bool InputManager::handle()
    /****************************************************************************
     * handle possible input
     * RETURN:
     *	true if a END_PGROGRAM - Input was given, false in any other case
     ****************************************************************************/
    {
    	while ( SDL_PollEvent(&m_event) )
    	{
    		switch(m_event.type)
    		{
    			case SDL_QUIT:
    				return true;
    				break;
    
    			case SDL_KEYDOWN:
    				// end program on ESC-key
    				if (m_event.key.keysym.sym == SDLK_ESCAPE)
    				{
    					return true;
    					break;
    				}
    				return handleKeyboard();
    				break;
    
    			case SDL_MOUSEBUTTONDOWN:
    				return handleMouseButton();
    				break;
    
    			case SDL_MOUSEMOTION:
    				return handleMouseMotion();
    				break;
    		}
    	}
    	return false;
    }
    

    d.h. die verschiedenen Arten von Eingabe-Events werden durch verschiedene Methoden behandelt... z. B. :

    bool InputManager::handleMouseButton()
    /****************************************************************************
     * handle Mousebutton-Messages
     * RETURN:
     *	true if a END_PGROGRAM - Input was given, false in any other case
     ****************************************************************************/
    {
    	// testfunction
    
    	switch (m_event.button.button)
    	{
    		case SDL_BUTTON_RIGHT:
    			// cancel screen-content
    			Video->Display()->fill(Color(0, 0, 0) );
    			break;
    		case SDL_BUTTON_LEFT:
    			// ...
    			break;
    	}
    	return false;
    }
    

    Was mich daran stoert:
    zum einen find ich's bloed, dass jede Funktion, die bei Benutzereingaben aufgerufen werden soll, in einer der handleXXX() - Funktionen eingetragen werden muss, da die Datei, die diese handleFoo() - Funktionen enthaelt dadurch zum #include - Monster wird, das so ziemlich jede erdenkliche andere Datei benoetigt und dabei ab und an auch include-Probleme erzeugt.... Andererseits kann ich mir nicht vorstellen, wie man eine "dynamische" Tastaturbelegung damit realisieren will, die man zur Laufzeit aendern kann, schliesslich ist bereits in handleKeyboard() festgelegt, welche Taste welche Aktion aufruft....

    Eine Moeglichkeit, die mir eingefallen ist, waere eine sdt::map zu verwenden, die die moeglichen Ereignisse und Funktionszeiger zu den aufzurufenden Funktionen enthaelt, aber

    a) hab ich angst dass das vielleicht langsam ist und
    b) was wohl viel wichtiger ist: einige der aufzurufenden Funktionen koennten ja Parameter benoetigen (z. B. die aktuellen Mauskoordinaten), andere wiederum nicht, und soviel ich mit meinem (zugegeben sehr beschraenkten) Wissen uber Funktionszeiger verstehe, ist das mit den Funktionszeigern dann nicht mehr realisierbar.... 😕

    Deshalb meine Frage: wie loest ihr solche Situationen, wie geht ihr mit dem Userinput um?



  • Ne ganz simple Methode wäre erstmal eine abstrakte Basisklase zu schreiben, die einfach eine virtuelle Funktion Execute() hat. Nun leitest du für jede mögliche Useraktion eine Klasse davon ab. Zum Beispiel die Klasse Forward, deren Execute() Methode erhöht dann die aktuelle Geschwindigkeit des Spielers. Nun legst du ein Array aus Pointern auf die Basisklasse an, für jede Tasten einen Arrayeintrag. Wenn nun einer Taste eine Aktion zugewiesen soll, wird das in das Array eingetragen (z.B. Array[ SDL_BUTTON_UP ]= new Forward(); ). Kommt nun ein Event, schaust du ob dafür ein Objekt im Array ist und rufst dessen Execute Methode auf. Wenn jetzt die Forward Klasse die Mauskoordinaten bräuchte, einfach in der Klasse einen Zeiger darauf speichern der einfach direkt in dem Moment abrufen.

    Aber 'ne std::map Lösung ist sicher auch nicht zu langsam, da es ja pro Frame nicht tausende Ereignisse gibt. Definitiv der falsche Ort zum Optimieren...


Anmelden zum Antworten