Wie oft pro Sekunde Tastatur abfragen?



  • Ich bin ziemlich unerfahren mit 3D-Spiele-Programmierung, bezüglich der Steuerung meiner Spielfigur hätte ich mir überlegt, den Nummernblocktasten von
    1 bis 9 jeweils eine von 8 Richtungen zuzuweisen (die Szene wird von einer - relativ zur Spielfigur - fix montierten 3rd-Person-Kamera aus gesehen).
    Eigentlich ist die Frage bestimmt einfach für die erfahrenen Haudegen hier:
    Wie oft pro Sekunde würdet ihr die Tastur abfragen, damit die Spielfigur 'angenehm' zu steuern ist? (ich werde als Reaktion auf eine Tastatureingabe auch manchmal den Map-Vertexbuffer Lock()en müssen, um ihn mit neuen Daten bezüglich der veränderten Umgebung zu füttern). Ich befürchte, dass die Spielbarkeit arg darunter leidet, wenn ich die Tastatur zu oft abfrage und deshalb zu häufig den Map-Vertexbuffer sperren muss. Sind 2x pro Sekunde genug, oder ist das zu wenig? Wie gesagt, habe nicht sonderlich viel Erfahrung mit Spieleprogrammierung, aber vielleicht sind hier ja ein paar Haudegen.
    Thx für Tipps.



  • 2x pro Sekunde halte ich für zu wenig. 10x sollten es schon sein.
    Du könntest es aber auch von der Rechenleistung des Computers abhängig machen, indem Du pro angezeigtes Frame einmal die Tastatur abfragst und eine entsprechende Bewegung von der seit dem letzten Frame vergangenen Zeit abhängig machst.



  • Ich würde auch pro Frame fragen. Ich mache auch immer am ende der "Render_Frame" Funktion sämtliche abfragen und berechnungen. Ich denke das es so am genauesten Funktioniert. Bei den Heutigen Rechenleistungen dürfte dies kein Problem darstellen.

    greez denjo303



  • Ich befürchte, dass die Spielbarkeit arg darunter leidet, wenn ich die Tastatur zu oft abfrage

    Die Spielbarkeit leidet insbesondere wenn die Steuerung (allgemeiner: die Spiellogik) einmal pro Frame laeuft, die Framerate aber durch zeitweise erhoehte Komplexitaet sinkt.
    Darum macht es durchaus Sinn zu ermitteln ob eine Taste nur einen Bruchteil eines Frames gedrueckt war.
    Die dadurch notwendigen Aenderungen zur Darstellung des naechsten Frames muessen natuerlich nur ein mal erzeugt werden (siehe MVC-Pattern).
    Die Suche sollte diverse Themen zur Entkopplung von Rendering und Gamelogik liefern.



  • denjo303 schrieb:

    Ich würde auch pro Frame fragen.

    Ich auch.
    Ich würde sogar so weit gehen zu sagen dass das "der Übliche Weg" ist.



  • Servus,

    Events, Listener? Ich persönlich würde die Darstellung und das virtuelle System in verschiedenen Schichten legen.



  • du kannst ja in ner eigenen methode, die du am ende jedes Rendervorgangs, mit nem Input-Device abfragen. geht schnell und unkompliziert. Mit DX zumindest...

    Maus dagegen würde ich lieber am anfang jedes Rendervorgangs abfragen. Ansonsten hat man son hinterhergeziehe, und das fühlt sich komisch an. Als ob dein rechner nicht die leistung bring die er hat...



  • da hat windows schon eine schöne ereignissteuerung WM_KEYDOWN, WM_KEYUP und ähnliches. und ihr wollte x mal pro sekunde die tastatur pollen 😕



  • ist halt der "normale" weg um bewegung (First Person Cam) zu realisieren. Die Key Ereignisse, ok geht auch... Ich find aber das es doch schneller oder viel mehr Direkter geht wenn man über ein Input Device den KeyState pro frame abfragt. Das brauch auch nicht viel mehr leistung als auf window Messages zu warten.



  • hustbaer schrieb:

    denjo303 schrieb:

    Ich würde auch pro Frame fragen.

    Ich auch.
    Ich würde sogar so weit gehen zu sagen dass das "der Übliche Weg" ist.

    Ich bin absoluter Laie auf diesem Gebiet...
    Aber was genau bringt es mir öfter abzufragen als ich Logik Ticks habe?

    Oder hat man vielleicht dann auch noch "Input Ticks" wo man dann zB sagen kann die Taste war 1/3 Logik Tick lang gedrückt also werden die Werte mit 1/3 multipliziert oder so?

    Danke 🙂



  • denjo303 schrieb:

    ist halt der "normale" weg um bewegung (First Person Cam) zu realisieren. Die Key Ereignisse, ok geht auch... Ich find aber das es doch schneller oder viel mehr Direkter geht wenn man über ein Input Device den KeyState pro frame abfragt.

    aber polling ist unter einem multitasking-betriebssystem wie windows generell schlecht, weil sehr viele versuche ins leere laufen und sinnlos rechenzeit verbrauchen. was meinst du mit "pro frame"? ist damit periodischer bildaufbau gemeint, obwohl sich möglicherweise nichts geändert hat? das hört sich für mich auch nicht gerade vorteilhaft an.



  • Ich speichere bei Key Events (WM_KEYDOWN/WM_KEYUP etc.) die Werte ob die Taste gedrückt sind in einer Variable oder einem Feld von bools (Bei vielen Tasten bool bKeyboard[256]). So kann ich bei der Spiellogik dann einfach das Feld/ die Variable abfragen und schauen ob die Taste gedrückt ist und zusammen mit der Zeit die Figur bewegen. Ist nicht rechenintensiv da die Nachrichtenschleife eh durchlaufen wird und dank der Zeitmessung läuft die Spielfigur auf jedem Rechner gleichschnell...



  • besten Dank für die Ratschläge.
    10x pro Sekunde sollte es also sein. thx 🙂



  • Shade Of Mine schrieb:

    hustbaer schrieb:

    denjo303 schrieb:

    Ich würde auch pro Frame fragen.

    Ich auch.
    Ich würde sogar so weit gehen zu sagen dass das "der Übliche Weg" ist.

    Ich bin absoluter Laie auf diesem Gebiet...
    Aber was genau bringt es mir öfter abzufragen als ich Logik Ticks habe?

    Oder hat man vielleicht dann auch noch "Input Ticks" wo man dann zB sagen kann die Taste war 1/3 Logik Tick lang gedrückt also werden die Werte mit 1/3 multipliziert oder so?

    Danke 🙂

    Normalerweise hat man mehr Logik-Ticks als Frames. In dem Fall ist es üblich pro Frame die Tasten zu pollen. Hat man weniger Logik-Ticks als Frames reicht es natürlich vor jedem Logik-Tick die Tasten abzufragen.



  • general bacardi schrieb:

    aber polling ist unter einem multitasking-betriebssystem wie windows generell schlecht, weil sehr viele versuche ins leere laufen und sinnlos rechenzeit verbrauchen. was meinst du mit "pro frame"? ist damit periodischer bildaufbau gemeint, obwohl sich möglicherweise nichts geändert hat? das hört sich für mich auch nicht gerade vorteilhaft an.

    ein spiel läuft in einer endlosschleife, in der ständig gerendert wird, außer der v-sync capped die fps. das kommt daher, dass spielgrafik wie ein film ist, wo sich sowieso andauern etwas verändert (animationen) und würde man nur rendern, wenn sich was ändert würde man auf so ziemlich die selbe anzahl rendervorgänge kommen (zumindest vermute ich, dass es da herührt 😉 ). wenn man ganz lustig ist, kann man sicher auch eine rendering engine bauen, die nur frames rendert, in denen sich etwas verändert hat, was imo aber nichts bringt und zu aufwändig ist.

    zur tastaturfrage: in allen sachen, die ich bisher geschrieben habe, habe ich logik und input 1x pro frame verarbeitet. das kann man bei hobbyprojekten, wo eine moderne grafikkarte grad mal ein auge halb aufmacht und noch leise schnarcht getrost machen 😉

    ansonsten sind 40 millisekunden ein intervall, den der mensch als flüssig empfindet (entspricht 25 fps -> fernsehen -> flüssig). sprich: langsamer und man könnte die verzögerung merken, schneller und man merkt keinen unterschied.



  • hustbaer schrieb:

    In dem Fall ist es üblich pro Frame die Tasten zu pollen.

    Und wie macht man es dann wenn die Taste nur 1/3 eines Logik Ticks gedrückt war? Rechnet man dann den Bewegungswert mal 0,3 ?


  • Mod

    ueblich ist es pro logiktick ein update alle inputs zu besorgen, das ist nicht nur tastatur betreffend, sondern auch netzwerk daten, timer und was auch immer als input noetig ist.
    diese daten sind dann stabil waehrend die logik durchlaeuft (sprich, die zeit laeuft nicht weiter), sodass nichts asynchron wird.

    da die logik das einzige ist was wirklich daten 'verarbeitet', macht es nur an dieser stelle sinn die daten abzulesen.

    die graphik ist wie bei einem mvc pattern quasi nur viewer und interpoliert zwischen states, logik und input findet meist nicht statt.

    es gibt natuerlich ausnahmen, manche shooter wollen das minimum an reaktionszeit bieten. oder man will dass bei einem rts selbst mit 15fps der mauscursor noch vernuenftig laeuft etc.

    @Shade Of Mine
    wenn du nicht gerade spezialhardware hast die soeinen genauen wert wiedergibt, wirst du wohl an der abtastrate des spieles haengenbleiben.



  • rapso schrieb:

    wenn du nicht gerade spezialhardware hast die soeinen genauen wert wiedergibt, wirst du wohl an der abtastrate des spieles haengenbleiben.

    Ne, da hast du mich falsch verstanden.

    Aber der Rest deines Posts hat mir alles erklärt was ich wissen wollte 🙂

    Vielen Dank

    PS:

    Eine Frage noch:
    Wie machst du es, rapso, wenn du jetzt so einen Spezialfall hast? Ähnlich wie die Logik Ticks nur eben Input Ticks alle 20ms oder dergleichen? Oder doch pro Frame?


  • Mod

    Shade Of Mine schrieb:

    Eine Frage noch:
    Wie machst du es, rapso, wenn du jetzt so einen Spezialfall hast? Ähnlich wie die Logik Ticks nur eben Input Ticks alle 20ms oder dergleichen? Oder doch pro Frame?

    speziallfaelle haben oft eine spezialloesung. wenn man z.b. ein strategiespiel macht, nimmt man defaultmaessig einen hardware cursor (der restriktionen hat z.b. oft nur 32x32pixel) oder man baut zumindestens eine option dafuer ein, ein cursor der springt ist naemlich viel schlimmer als eine schlechte framerate.
    wenn ich z.b. eine demo schreibe, sync ich nur mit der soundlib, da kann man dann auch krumme werte haben, aber man laeuft immer synchron.
    frueher als man immer 60hz hatte, hab ich einfach alles gemacht was zu machen war und dann die buffer geswappt, das hatte automatisch auf 60hz gesynct, da musste man keinen expliziten logic durchlauf haben, es war immer

    while(..)
    {
    input
    logic
    render
    swap(vsync)
    }
    

    und es war auch weniger getrennt, weil man dann z.b. erst beim rendern etwas evaluiert hatte was sichtbar ist (z.b. ob ein gegner dich sieht, sah man indem man rausfand ob du den gegner siehst, ob du irgendwo einen glow-particle bzw lense effect hast, sah man indem man aus dem zbuffer ein pixel las etc.). und wieviel man zeichnet fand man heraus indem man dauernt abfragte wieviel zeit man zum naechsten vsync hat und dann hoerte man einfach damit auf, kurz vorher. bis der vsync dann kam, hat man 'unwichtiges' gemacht, z.b. nen buffer loeschen und dann geswapt.

    jetzt wird das natuerlich komplexer, neben den einfluessen von aussen z.b. dass mal icq anspringt und mal die platte einschlaeft, kommt hinzu dass man mehrere threads laufen hat die an moeglichst wenigen punkten sich synchen, aber dennoch moeglichst sehr gleichmaessig ausgelastet sind, sodass da auch wieder logic und rendern ein wenig 'balanziert' wird und das eine die aufgaben des anderen uebernimmt um weniger overhead zu haben oder um idle-time auszunutzen.


Anmelden zum Antworten