Konzeptfrage: Integration einer Steuerungsmethode in eine Anwendung



  • Hallo.
    Ich habe ein "normales" Programm (kein Spiel o.ae.), das ich gern neben Tastatur und Maus mit z.B. einem Gamepad bedienen koennen wuerde. Zu diesem Zweck habe ich bereits einige Vorbereitungen getroffen, sodass die Eingaben des Geraetes jetzt im Programm als Events zur Verfuegung stehen. Jedes Event traegt dabei Informationen darueber mit sich, in welchem genauen Zustand sich die Achsen/Knoepfe des Geraetes zum Zeitpunkt der Event-Ausloesung befanden.
    Ziel ist, die mit der Bedienung des Geraetes verbundenen Aktionen fuer den Nutzer konfigurierbar zu machen. Das ist allerdings nicht zwingend notwendig.

    Nun zu den Fragen:
    Auf welche Art verbinde ich die Events mit dem, was das Programm am Ende tun soll? Es soll z.B. unterschieden werden, ob eine Taste kurz oder lange gedrueckt wird oder ob dabei bestimmte andere Tasten gedrueckt sind.

    Gibt es gute, performante Abstraktions-Ansaetze fuer dieses Problem, die ich uebernehmen oder zumindest als Vorlage verwenden koennte?

    Ich habe momentan keinerlei Idee, wie ich eine durch den Nutzer konfigurierbare Steuerung dieser Art angehen koennte. Ueber jede Idee und jeden Hinweis wuerde ich mich sehr freuen. 🙂



  • enum class Action{Rechts, Links, Leertaste};
    
    void react(Action action){
        if (action == Action::Leertaste)
            ....;
    }
    
    array<Action, 256> actionmap;
    
    void setSpaceKeyInput(unsigned char input){
        //setzt für taste nummer input die leertastenaktion
        actionmap[input] = Action::Leertaste;
    }
    
    void input(unsigned char input){
        //taste nummer input wurde gedrückt
        react(actionmap[input]);
    }
    


  • Netter Anfang, aber ich nutze keine Tastatur als Eingabe. Analoge Achsen, Mehrfacheingaben (mehrere Tasten gleichzeitig oder Tasten und Achsen gleichzeitig) und von der Zeit zwischen "Press" und "Release" abhaengige Aktionen sollten enthalten sein. All das stellt weiterhin konzeptionell ein Problem dar. Deiner Loesung entnehme ich, dass ich alle moeglichen Kombinationen von Eingaben vordefinieren und dann vom Nutzer mit Programm-Aktionen "verkabeln" lassen soll. Aber allein die Definition der Aktionen wuerde vermutlich eine riesige, unuebersichtliche Funktion bilden (~1000 Zeilen), die mit diversen Timern arbeitet und deren Implementierung eine ganze Menge Zeit fressen wuerde. Und am Ende wird Flexibilitaet weiterhin nur vorgetaeuscht. Ist das wirklich der gaengige, vernuenftige und "schoenste" Ansatz? Ich moechte nicht viel Zeit in eine verdammt haessliche Funktion investieren, all das "hardcoden" und mich auf ein extrem schwer erweiterbares System einfahren.

    Nichtsdestotrotz schonmal danke fuer den Denkanstoss. Ein grosser Teil meines Problemes bleibt aber bestehen.



  • Dir bleibt nichts anderes uebrig, einen Zustandsautomat zu realisieren. Dazu gibt es genug Design patterns und Literatur.

    und mich auf ein extrem schwer erweiterbares System einfahren

    Es ist deines und du kannst es jederzeit aendern. Du wirst es sowieso nicht beim ersten Wurf zufriendenstellend loesen (nun vielleicht sind deine Ansprueche anders). Also nicht labern sondern machen.

    Und sonst: dein Problem ist zu vage um einen echten Ansatz zu liefern, da Steuerung immer davon abhaengt, was gesteuert wird.



  • Stiefel2000 schrieb:

    Deiner Loesung entnehme ich, dass ich alle moeglichen Kombinationen von Eingaben vordefinieren und dann vom Nutzer mit Programm-Aktionen "verkabeln" lassen soll.

    Andersrum. Alle möglichen Programm-Aktionen vordefinieren (musst du eh machen) und dann vom Nutzer mit Eingaben belegen lassen (kommst du auch nicht drum rum wenn du auf Konfigurierbarkeit bestehst).
    Action muss kein enum sein, es kann auch ein struct mit TastenID (Joystick-Achsen haben auch eine TastenID), Stärke (Als float, normale Tasten haben nur 0 oder 1, Joysticks haben Werte zwischen 0 und 1) und Zeitstempel der letzten Aktion sein. Wahrscheinlich lohnt es sich zwei verschiedene Eingabegeräte zu unterstützen: tastenartige (mit ID und Zeitstempel) und schieberartige (mit ID und Position).
    Weiterhin kann die actionmap statt auf eine Action auf eine Callback-Funktion verweisen, dann hast du für jede Aktion eine kleine Funktion.
    Dann kannst du dir noch eine Lookup-Funktion schreiben, die den Zustand abfragt (Funktion ClickActivate: Wenn ShiftModifier1 gehalten wurde und MausSchieber1 auf Position X, dann tu dies, else jenes).



  • "Zustandsautomat"? Gut, das klingt nach einem Punkt, den ich mit Google und Co. angreifen kann.

    Ich hatte angefangen, eine grosse Fallunterscheidung per switch einzubauen. Da ich aber schon beim Gebrauch von nur drei Tasten (noch ohne Achsen etc.) durch die vielen moeglichen Kombinationen eine ganze Menge Code produziert hatte, dachte ich, dass es bestimmt eine effizientere Herangehensweise gibt. Wenn dem nicht so ist, brauche ich eine effizientere Strukturierung. Die vorgeschlagene Actionmap ist schon ein guter Anfang, aber es gibt sicher noch weitere Massnahmen, die ich bisher uebersehen habe. Ein Prinzip, das nicht mehr von der genauen Eingabe, sondern nur noch der Eingabe-Art abhaengt, waere toll und wuerde die noetige Code-Menge sicher um einen Faktor zehn verringern (also: Taste, Taste lang, Taste + Taste, Taste + Taste lang, Achse, Achse + Taste, ...). Ich werde noch ein wenig drueber nachenken - weitere Hinweise sind aber gern gesehen. 🙂

    Soweit erstmal vielen Dank!


Anmelden zum Antworten