Teil 3: Die Tastatur (2)

TIGCC-Tutorial für Einsteiger.

Teil 3: Die Tastatur (2)

Beitragvon saubue am 27. Juli 2008 00:31

Heute werden wir die 2. Lektion ausweiten. Vorraussetzung, um das zu verstehen ist natürlich das Verständnis der Lektionen davor.

a) Weitere Verwendung von kbhit()

Wie zuvor schon angesprochen, können wir kbhit() auch noch anders verwenden. Das nächste Projekt sollte 'key3' heissen.

Code: Alles auswählen
// C Source File
// Created 30.08.04; 15:43:32

#include [tigcclib.h]

// Haupt-Funktion
void _main(void)
{
  // Lösche Bildschirminhalt
  clrscr();           
 
  // Schrifgröße auf 'klein' stellen
  FontSetSys(F_4x6);
 
  // In einer 'while'-Schleife wird auf einen  Tastendruck gewartet
  while (!kbhit())
    // Schreibe "Drück' Enter!!" auf den Bildschirm
    printf("Drück' Enter!!n");

  if (ngetchx() == KEY_ENTER)
    // Unser Benutzter ist unseren Anweisungen gefolgt
    printf("nnnNa endlich!!!!n");
  else
    // Da müssen wir ihn wohl ermanen :)
    printf("nnnDu wirst es wohl nie lernen....");

  // Auf Tastendruck warten
  ngetchx();
}


Wir vorher beschrieben, leert kbhit() den Tastaturspeicher nicht, d.h. ngetchx() 'denkt', dass eine Taste gedrückt wird und gibt so den entsprechenden Wert zurück (den wir ja auf KEY_ENTER hin prüfen). Danach wird der Speicher von ngetchx() entleert, so dass wir als nächstes mit ngetchx() ganz gewohnt warten können, bis sich der Benutzer das Ergebnis angesehen hat. Also hätten wir bei 'key2' auch zweimal ngetchx() statt GKeyFlush() benutzten können.
Doch was bringt mir kbhit()? Nun ja, ihr könnt gleichzeitig auf einen Tastendruck warten und Sachen ausführen, z.B. ein Quadrat über den Bildschirm laufen lassen und so weiter. Allerdings ist kbhit() ziemlich langsam, und deshalb werden wir nun eine dritte Methode kennenlernen: _rowread().


b) _rowread bzw. _keytest

Wir benutzen nun nicht direkt _rowread, sondern _keytest, eine Funktion, die _rowread benutzt aber etwas einfacher ist.

Und schon wieder ein Programm! Diesmal soll es 'key4' heissen:

Code: Alles auswählen
// C Source File
// Created 31.08.04; 16:02:02

#include <tigcclib.h>

/* AUTO_INT_1 und AUTO_INT_5 speichern */
inline void saveAutoInts(INT_HANDLER *savint1, INT_HANDLER *savint5)
{
    /* Handler speichern */
    *savint1 = GetIntVec(AUTO_INT_1);
    *savint5 = GetIntVec(AUTO_INT_5);

    /* Handler umlenken */
    SetIntVec(AUTO_INT_1, DUMMY_HANDLER);
    SetIntVec(AUTO_INT_5, DUMMY_HANDLER);
}


/* AUTO_INT_1 und AUTO_INT_5 wieder herstellen */
inline void restoreAutoInts(INT_HANDLER savint1, INT_HANDLER savint5)
{
    /* Handler wieder herstellen */
    SetIntVec(AUTO_INT_1, savint1);
    SetIntVec(AUTO_INT_5, savint5);
}

// Haupt-Funktion
void _main(void)
{
  // Die beiden Interrups
  INT_HANDLER savint1, savint5;
   
  // AUTO_INT_1 und AUTO_INT_5 speichern
  saveAutoInts(&savint1, &savint5);
 
  // Lösche Bildschirminhalt
  clrscr();           
 
  // Schrifgröße auf 'mittel' stellen
  FontSetSys(F_6x8);
 
  // Wir sagen dem Benutzer, was er gedrückt hat, bis er [ESC] drückt
  do {
      
    if (_keytest(RR_LEFT)) {
      // Der Benutzer hat 'links' gedrückt   
      printf("linksn");
    }
         
    if (_keytest(RR_RIGHT)) {
      // Der Benutzer hat 'rechts' gedrückt
      printf("rechtsn");
    }   
               
    if (_keytest(RR_UP)) {
      // Der Benutzer hat 'hoch' gedrückt
      printf("hochn");
    }   
               
    if (_keytest(RR_DOWN)) {    
      // Der Benutzer hat 'runter' gedrückt
      printf("runtern");
    }
            
  } while (!_keytest(RR_ESC));
 
  // AUTO_INT_1 und AUTO_INT_5 wieder herstellen
  restoreAutoInts(savint1, savint5);
}


OK, wie wir beim Testen sehen zeigt das Programm immer die Taste an, die wir drücken (sei sie denn eine Richtungstaste). Aber was macht denn _keytest?? Es wird geprüft, ob wir eine Taste drücken, und zwar die, die als Parameter (in der TIGCC Doc stehen die vordefinierten Tasten drin) angegeben ist. Doch diesmal word nicht KEY_ESC sondern RR_ESC, wobei der Wert zwi Zahlen beschriebt: Die Reihe und Spalte der Taste [ESC]. Wenn ihr mehr hierzu wissen wollt, dann schaut in der TIGCC Documentation unter _rowread. Wird die Taste also gedrückt, wird '1' zurückgegeben, wenn nicht, dann '0'. Wieder kann von if() direkt auf wahr oder falsch geprüft werden. Nach printf() wird der Tastaturspeicher wieder geleert, da sonst Fehler auftreten könnnen. Welche? Probiert es aus! Alles dauert solange bis..

Code: Alles auswählen
} while (!_keytest(RR_ESC));


..wir [ESC] drücken. Die do-Schleife unterscheidet sich nicht groß von der while-Schleife, es führt etwas so lange aus, wie der von while geprüfte Wert wahr ist. Also hier so lange, wie [ESC] nicht gedrückt wird.
Ihr seht, dass wir einer if-Schleife nun mehrere Bedinggungen haben, also fassen wir sie mit zwei geschweiften Klammern ein. Das ganze gilt auch für die do-while-Schleife.


c) _keytest_optimized

Wir nehmen einfach das gleiche Beispiel wie zuvor, jedoch mit dem Befehl _keytest_optimized. Nennt es einfach 'key5'.

Code: Alles auswählen
// C Source File
// Created 31.08.04; 16:02:02

#include <tigcclib.h>

/* AUTO_INT_1 und AUTO_INT_5 speichern */
inline void saveAutoInts(INT_HANDLER *savint1, INT_HANDLER *savint5)
{
    /* Handler speichern */
    *savint1 = GetIntVec(AUTO_INT_1);
    *savint5 = GetIntVec(AUTO_INT_5);

    /* Handler umlenken */
    SetIntVec(AUTO_INT_1, DUMMY_HANDLER);
    SetIntVec(AUTO_INT_5, DUMMY_HANDLER);
}


/* AUTO_INT_1 und AUTO_INT_5 wieder herstellen */
inline void restoreAutoInts(INT_HANDLER savint1, INT_HANDLER savint5)
{
    /* Handler wieder herstellen */
    SetIntVec(AUTO_INT_1, savint1);
    SetIntVec(AUTO_INT_5, savint5);
}

// Haupt-Funktion
void _main(void)
{
  // Die beiden Interrups
  INT_HANDLER savint1, savint5;
   
  // AUTO_INT_1 und AUTO_INT_5 speichern
  saveAutoInts(&savint1, &savint5);
   
  // Lösche Bildschirminhalt
  clrscr();           
 
  // Schrifgröße auf 'mittel' stellen
  FontSetSys(F_6x8);
 
  // Wir sagen dem Benutzer, was er gedrückt hat, bis er [ESC] drückt
  do {
       
    BEGIN_KEYTEST   

    if (_keytest_optimized(RR_LEFT)) {
      // Der Benutzer hat 'links' gedrückt   
      printf("linksn");
    }
         
    if (_keytest_optimized(RR_RIGHT)) {
      // Der Benutzer hat 'rechts' gedrückt
      printf("rechtsn");
    }   
               
    if (_keytest_optimized(RR_UP)) {
      // Der Benutzer hat 'hoch' gedrückt
      printf("hochn");
    }   
               
    if (_keytest_optimized(RR_DOWN)) {     
      // Der Benutzer hat 'runter' gedrückt
      printf("runtern");
    }

    END_KEYTEST
             
  } while (!_keytest(RR_ESC));
 
  // AUTO_INT_1 und AUTO_INT_5 wieder herstellen
  restoreAutoInts(savint1, savint5);
}


Eigentlich hat sich nicht viel verändert, allerdings ist das dazugekommen:

Code: Alles auswählen
BEGIN_KEYTEST

....

END_KEYTEST


mit _keytest_optimized() kann nur in dem von diesen zwei Befehlen beschriebenen Raum geprüft werden (für unsere while()-Bedingung benutzen wir erneut _keytest(). Allerdings hätten wir END_KEYTEST auch dahinter setzen können).

OK, so weit so gut, und nächstes Mal gibt's dann Variablen.


------------------


Korrekturen:
  • Stefan Heule - 20061104
      - Die Interrupts müssen unbedingt (!) umgeleitet werden.
      - GKeyFlush aufzurufen macht keinen Sinn mehr, wenn die Interrupts umgeleitet sind.
"All animals are equal. But some animals are more equal than others." - George Orwell (Animal Farm)

boolsoft - software development for texas instruments 68k calculators
Benutzeravatar
saubue
Administrator
Administrator
 
Beiträge: 1434
Registriert: 11. März 2005 13:55
Wohnort: Freiburg im Breisgau

Re: Teil 3: Die Tastatur (2)

Beitragvon Erger am 5. Dezember 2008 13:55

Warum schreibt er bei mir z.B. rechts 30 mal auf den Bildschirm obwohl ich die Taste doch nur ein einzies mal drücke?
Erger
Mobi Newbie
Mobi Newbie
 
Beiträge: 13
Registriert: 4. Dezember 2008 20:11

Re: Teil 3: Die Tastatur (2)

Beitragvon Stefan Heule am 5. Dezember 2008 15:17

Kuzre Antwort: Weil C schnell ist :)

Lange Antwort: Mit den _keytest-Funktionen wird ganz im Gegensatz zu ngetchx und ähnlichen Funktionen der Status einer Taste abgefragt. Da gibt es zwei mögliche Antworten, entweder die Taste wird gerade gedrückt, oder eben nicht. Ganz anders bei ngetchx (und allen ähnlichen Funktionen, insbesonder auch die hier in der KB verfügbaren, schnelleren Alternativen): Dort wird gewartet, bis eine Taste gedrückt wird, und dann wird der Wert dieser Taste zurückgegeben.
In diesem Beispiel haben wir also einen Schleife, in der bei jedem Durchgang abgefragt wird, welche Taste gerade gedrückt wird, und dann wird entsprechend etwas ausgegeben. Wenn du nun die Taste "nach Rechts" drückst, wird die Schleife (auch wenn du nur relativ kurz drückst) mehrmals ausgeführt, und somit wird "Rechts" auch mehrmals ausgegeben.
Diese Art von Funktionen, also _keytest, ist z.B. nützlich bei Spielen wie etwa Snake, da will man einfach wissen, drückt der User gerade Rechts, und dann eine entsprechende Aktion einleiten. Wird aber nichts gedrückt, will man trotzdem etwas machen, z.B. die Schlange bewegen. Ganz anders z.B. in einem Menu, da will man normalerweise einfach so lange warten, bis der User eine Eingabe getätigt hat, und dann das Menu entsprechend aktualisieren. Hier sind ngetchx und Konsorten nützlich.

Ich hoffe, das hilft.
68k-FAQ - Hilfe zum Ti-89 (Titanium) und Voyage 200
z80-FAQ - Hilfe zum Ti-83+, Ti-84
ticalc.org - Spiele/Programme für alle Modelle
Benutzeravatar
Stefan Heule
Moderator
Moderator
 
Beiträge: 2782
Registriert: 11. April 2006 20:57


Zurück zu Grundlagen: TIGCC

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast