Tastendruck



  • Hallo!

    Wie kann ich es machen, dass mein Programm nach Druck einer bestimmten Taste eine Funktion ausführt.

    Ich habe bisher den folgenden Code:

    #include <iostream>
    #include <curses.h>
    
    int main()
    {
         char c;
         while(true) {
              if((c=getch())=='q') {
                   cout << "Taste q gedrueckt.";
              }
              if((c=getch())=='w') {
                   cout << "Taste w gedrueckt.";
              }
         }
    }
    

    Aber da tut sich nichts, wenn ich q oder w drücke. 😞
    Kann mir jemand sagen, woran das liegt? ich suche mich hier schon dumm und dämlich.



  • Kannst du kbhit() verwenden (conio.h)? Falls ja, dann sieh mal hier:

    http://www.c-sar.de/forum/viewtopic-var-t-is-39320.html



  • http://www.c-plusplus.net/forum/viewtopic-var-t-is-39509.html

    _matze schrieb:

    Kannst du kbhit() verwenden (conio.h)? Falls ja, dann sieh mal hier:

    http://www.c-sar.de/forum/viewtopic-var-t-is-39320.html

    conio.h ist DOS Zeugs!



  • Aber das kbhit() klappt nicht. Das brauche ich aber, da getch() ja erst nen Wert zurückgibt, wenn acuch eine Taste gedrückt wurde.



  • rüdiger schrieb:

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-39509.html

    _matze schrieb:

    Kannst du kbhit() verwenden (conio.h)? Falls ja, dann sieh mal hier:

    http://www.c-sar.de/forum/viewtopic-var-t-is-39320.html

    conio.h ist DOS Zeugs!

    und genau deswegen gibts bei uns in der Firma eine conio für Linux, die intern "IOCtl" benutzt, ist leider close-source sonst würde ich die mal hier posten.

    Ansonsten benutz eine Suchmaschine deiner Wahl und such Code für kbhit unter Linux.



  • @nurf
    Oder einfach auf den Link von mir klicken :p

    @doppelkeks
    Ah, habe gerade erst dein Originalposting gelesen. IIRC musst du die curses erst initialisieren initscr(); , bevor du getch und co nutzen kannst.

    http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/

    Aber wenn du nur getch/kbhit nutzen willst, dann nimm einfach den Code aus dem Link, den ich weiter oben gepostet habe.



  • Danke soweit!
    Ihr habt mir schon ein ganzes Stück weitergeholfen! 🙂 Auch zu kbhit() habe ich im Netz eine Funktion (http://code.google.com/p/linux-kbhit/) gefunden.

    Leider wartet das Programm immer darauf, dass getch() (bei mir in linux_getch() umgetauft) eine Taste zurückgibt.

    int main()
    {
    	int key;
    	while((key = linux_getch()) != 'q')
    	{
    		cout << "Du hast eine Taste (nicht q) gedrueckt!\n";
    	}
    	cout << "\nTschuess!\n\n";
    }
    

    Hier erscheint der Text also erst wenn ich eine Taste (nicht q) gedrückt habe. Ich hätte esd aber lieber so, dass er den Text solange ausgibt, bis ich q gedrückt habe, also das Programm beende.



  • Gib doch einfach den Text vor der while-Schleife aus. 😕



  • Das sollte jetzt nur ein kleines Beispiel sein, um zu zeigen, was mein Problem ist. Bei meinem Programm habe ich einige andere Dinge vor.



  • doppelkeks schrieb:

    Das sollte jetzt nur ein kleines Beispiel sein, um zu zeigen, was mein Problem ist. Bei meinem Programm habe ich einige andere Dinge vor.

    Dann verstehe ich nicht so ganz, wo dein Problem ist. Beschreibe dann doch mal, was du vor hast.

    Wenn du nicht möchtest, dass read blockiert, dann kannst du zum Beispiel den System-Aufruf poll verwenden. Das aber nur unter Vorbehalt, weil ich nicht weiß, was du vor hast.



  • Das Programm (Pong) soll den Ball die ganze Zeit bewegen. Aber trotzdem soll es die ganze Zeit auf Tastatureingaben überprüfen, damit ich das Paddle bewegen kann. Bisher ist es leider so, dass sich der Ball nur dann bewegt, wenn ich irgendeine Taste gedrückt habe. Das liegt daran, dass die Abfrage getch() das Programm solange anhält, bis eine Taste gedrückt wird. Mit einer kbhit() ähnlichen Funktion könnte ich das verhindern indem ich vor getch() erst überprüfe ob überhaupt eine Taste gedrückt ist.

    Ich hoffe du hast verstanden was ich meine. (Ich erinnere nocheinmal daran, dass ich Linux verwende und deswegen die conio.h nicht verwenden kann. Ich habe mich aber schon in die ncurses eingearbeitet, bin also auf jeden Fall bereit dazu, diese zu verwenden. 🙂 )



  • Dann würde ich dir wirklich vorschlagen, dass du ncurses verwendest. Ich denke, dass das damit funktionieren sollte.

    Es geht natürlich auch, dass du stdin erst auf vorhandene Eingaben überprüfst (poll) und nur liest, wenn wirklich welche vorliegen. Das packst du mit einem sleep in eine Endlosschleife. ncurses sollte aber die bessere Wahl sein.



  • Ok dann werde ich das mit ncurses machen.
    Aber was muss ich den aufrufen, damit getch() nicht auf eine Eingabe wartet? (cbreak(),nocbreak(),raw(),noraw()) Oder habe ich da was falsch verstanden 😕

    Tut mir leid, dass ich mich so dumm anstelle, aber bin noch in den Änfängen meiner C++-Karriere.^^



  • OK, habe jetzt herausgefunden, wie es geht.

    #include <iostream>
    #include <curses.h>
    using namespace std;
    
    int main()
    {
    initscr();
    nodelay(stdscr,true);
    while(true)
    {
    	if(getch() == -1)
    	{
    		cout << ".";
    	}
    }
    endwin();
    }
    

    Komisch ist es nur, dass er immernoch Punkte ausgibt, wenn ich doch eine Taste drücke. 😕



  • Das könnte damit zusammenhängen, dass dein Programm schneller die Punkte schreibt, als wie das Terminal in der Lage ist, darzustellen. Füge mal ein man: usleep (3) in deine Schleife ein.



  • Mein Vorschlag:

    #include <iostream>
    #include <curses.h>
    #include <unistd.h>
    using namespace std;
    
    int main()
    {
      int ch;
      bool key_pressed;
      initscr();
      noecho();
      nodelay(stdscr,true);
      while(true)
      {
        key_pressed = false;
        while((ch = getch()) != ERR)
        {
          key_pressed = true;
        }
        if (key_pressed) {
          addstr(".");
        }
        usleep(50000);
      }
      endwin();
    }
    

    Edit: Vorschlag noch etwas überarbeitet.



  • Danke dir!
    Wenn ich die uSleep-Zeit runterstelle klappt es nicht mehr. Daran lag es also. Du hast mir sehr geholfen! 🙂



  • So, wollte hierfür jetzt nicht extra einen neuen thread erstellen...

    Bin mit meinem pong jetzt schon recht weit. http://rafb.net/p/WkksIP98.html
    Ich kann das Paddle auch sehr schön bewegen. Nur leider ist der Ball viieel zu schnell. Wenn ich ein sleep hinter das if(key != -1) schreibe bewegt sich der Ball zwar so langsam wie ich es will, aber das Paddle kann ich ohne Verzögerungen nicht mehr bewegen.
    Hätte vielleicht jemand eine Idee, wie ich dieses Problem beseitigen kann? 🙂



  • Zwei Möglichkeiten:

    1.) Mach einen Zähler, so dass der Ball nur jeden 100. Schleifendurchlauf um eine Position weiter gesetzt wird.

    2.) Repräsentiere die Koordinaten des Balls mit Gleitkomma-Zahlen und runde auf Bildschirm-Koordinaten. Dann kannst du den Ball in jedem Schleifen-Durchlauf z.B. um 0.001 Positionen verschieben.


Log in to reply