Laby­rinth­spiel mit Joy­stick und TFT

Lese­zeit: 8 Minu­ten
Lösung
Seite als PDF
Navi­ga­ti­on

Die Bewe­gun­gen eines Joy­sticks bewe­gen einen Ball durch ein Laby­rinth. Beim Druck auf den But­ton wird die Zeit­mes­sung gestartet

So sieht es aus:

Der Joy­stick besteht aus zwei Poten­tio­me­tern, jeweils einer für die X-Achse und einer für die Y-Achse. Bei­de lesen bei den Bewe­gun­gen die Span­nung und lie­fern dem Ardui­no jeweils einen ana­lo­gen Wert, der zwi­schen 0 und 1023 liegt.

Die Wer­te kön­nen je nach Joy­stick leicht nach oben oder unten abwei­chen. Die Beschrif­tung und die Rei­hen­fol­ge der Pins kön­nen sich je nach Joy­stick unterscheiden.

Ach­seBezeich­nungAnschluss
X-AchseVRx/VERA0
Y-AchseVRy/HORA1
But­tonSW/SEL7

Mit Hil­fe eines Joy­sticks wird auf einem TFT-Monitor ein Ball durch ein klei­nes Laby­rinth bewegt. Am Ziel wird die Zeit gemessen.

1 -> Gnd -> GND
2 -> VCC -> 5V
3 -> RESET -> D9
4 -> D/C -> D8
5 -> CARD_CS (nicht ange­schlos­sen)
6 -> TFT_CS -> D10
7 -> MOSI -> D11
8 -> SCK -> D13
9 -> MISO (nicht ange­schlos­sen)
10 -> LITE ->5V

Pin­be­le­gung Adaf­ruit 1,8 Zoll TFT ST7735

SPI

Benö­tig­te Bauteile:

  • Joy­stick
  • Adaf­ruit 1,8 Zoll TFT
  • Lei­tungs­dräh­te

Baue die Schal­tung auf.
(Fah­re mit der Maus über das Bild, um die Bezeich­nun­gen der Bau­tei­le zu sehen)

Benö­tig­te Bibliotheken:

Sketch → Biblio­thek ein­bin­den → Biblio­the­ken verwalten

Ardui­no IDE 1.8x:

Ardui­no IDE 2.x:

Metho­den der Biblio­thek Adaf­ruit ST7735/TFT

Metho­deAnwei­sungPara­me­ter
TFT star­tenbegin();
Farb­sche­ma bestimmeninitR(initR(INITR_*TAB););BLACKTAB
GREENTAB
REDTAB
Bild­schirm ausrichtensetRotation(Richtung);Rich­tung = 0 → nicht drehen
Rich­tung = 1 → 90° drehen
Rich­tung = 2 → 180° drehen
Rich­tung = 3 → 270 ° drehen
Bild­schirm­hin­ter­grundfillScreen(Farbe);Bild­schirm­hin­ter­grund füllen
Linie zeich­nendrawLine(StartX, Star­tY, EndeX, EndeY, Farbe);
hori­zon­ta­le Linie zeichnendrawFastHLine(StartX, Star­tY, Län­ge, Farbe);
ver­ti­ka­le Linie zeichnendrawFastVLine(StartX, Star­tY, Län­ge, Farbe);
Recht­eck zeichnendrawRect(StartX, Star­tY,, Brei­te, Höhe, Farbe);
abge­run­de­tes Recht­eck zeichnendrawRoundRect(StartX, Star­tY, Brei­te, Höhe, Ecken­ra­di­us, Farbe);
aus­ge­füll­tes Recht­eck zeichnenfill.Rect(StartX, Star­tY, Brei­te, Höhe, Füllfarbe);
Kreis zeich­nendrawCircle(MittelpunkX, Mit­tel­punk­tY, Radi­us, Farbe);
Aus­ge­füll­ten Kreis zeichnenfillCircle(MittelpunktX, Mit­tel­punk­tY, Radi­us, Füllfarbe);
Cur­sor setzensetCursor(x, y);
Text­grö­ße setzensetTextSize(Textgröße);Text­grö­ße:
1 - 4
Text­far­be bestimmensetTextColor(Farbe);
Text schrei­benprint("Text"); println("Text");
Zei­len­um­bruchsetTextWrap(true/false);fal­se → Text fließt über den Rand des TFTs hinaus
true → Text wird am Ende umgebrochen

Bei­spiel mit Gra­fik und Text

So sieht es aus:

Für das Laby­rinth wird das TFT-Module ver­ti­kal ausgerichtet.

Adres­sie­rung der Bildpunkte

Bin­de die benö­ti­gen Biblio­the­ken ein und defi­nie­re die Varia­blen. Beach­te die Kommentare.

/*
  Pinbelegung:
  GND      (1) - GND
  VCC      (2) - 5V
  RESET    (3) - D9
  D/C      (4) - D8
  CARD-CS  (5) -
  TFT-CS   (6) - D10
  MOSI     (7) - D11
  SCK      (8) - D13
  MISO     (9) -
  LITE    (10) - 5V
*/

# include <Adafruit_GFX.h>
# include <Adafruit_ST7735.h>
# include <SPI.h>

// Pins zuordnen
# define TFT_CS        10
# define TFT_RST        9
# define TFT_DC         8

// Name des TFTs und die zugeordneten Pins
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
/*
  Farben als hexadezimal definiert
  alternativ:
  int SCHWARZ = 0;
  int BLAU = 15;
  . . .
*/
# define SCHWARZ    0x0000 // dezimal 0
# define BLAU       0x000F // dezimal 15
# define ROT        0xF800 // dezimal 406664
# define GRUEN      0x0E81 // dezimal 3713
# define CYAN       0x07FF // dezimal 2047
# define MAGENTA    0xF81F // dezimal 63519
# define GELB       0xAFE5 // dezimal 65504
# define WEISS      0xFFFF // dezimal 65535
# define BRAUN      0xFC00 // dezimal 64512
# define GRAU       0xF7F0 // dezimal 63472
# define GRUENGELB  0xAFE5 // dezimal 45029
# define DUNKELCYAN 0x03EF // dezimal 1007
# define ORANGE     0xFD20 // dezimal 64800
# define PINK       0xFC18 // dezimal 64536

// Farbe der Blöcke
# define FARBE GRUEN

// Farbe des Kreises
# define KREISFARBE GELB

// Farbe der Schrift
# define SCHRIFTFARBE WEISS

// Joystick
// analoge Pins
int XAchse = A0;
int YAchse = A1;

// Button/Knopf
int JoystickButton = 7;

// Zustand des Buttons
int ButtonLesen;

// Spiel starten wenn * gedrückt wurde
bool SpielStart = false;

// Radius des kreises
const int Radius = 10;

// Abstand zu den Rändern
const int Abstand = Radius * 2;

// je höher, dest langsamer
const int Geschwindigkeit = 100;

// Bewegung des Kreises in Pixeln
const int Bewegung = 5;

// Startposition des Kreises
int CursorX = Radius;
int CursorY = tft.height() / 2 - Abstand;

// Variablen für die Auswertung der Bewegung des Joysticks
int PositionX;
int PositionY;

// Variable für die Zeitmessung
long Start;

void setup()
{
  // Startbildschirm
  // schwarzes Farbschema vertkale Ausrichtung (nicht drehen)
  // Cursor setzen, Schriftgröße und -farbe definieren
  tft.initR(INITR_BLACKTAB);
  tft.setRotation(0);
  tft.fillScreen(SCHWARZ);
  tft.setTextSize(2);
  tft.setCursor(1, 10);
  tft.setTextColor(SCHRIFTFARBE);

  tft.println("Start:");
  tft.print("-> Button");
  pinMode(JoystickButton, INPUT_PULLUP);
}

Wenn du die ein­ge­bau­te Biblio­thek TFT ver­wen­den willst ...

# include <TFT.h> 
# include <SPI.h>

TFT tft = TFT(TFT_CS, TFT_DC, TFT_RST);

Der setup-Teil:

void setup()
{
  // Startbildschirm
  // schwarzes Farbschema vertikale Ausrichtung (nicht drehen)
  // Cursor setzen, Schriftgröße und -farbe definieren
  tft.initR(INITR_BLACKTAB);
  tft.setRotation(0);
  tft.fillScreen(SCHWARZ);
  tft.setTextSize(2);
  tft.setCursor(1, 10);
  tft.setTextColor(ROT);

  tft.println("Start:");
  tft.print("-> Button");
  pinMode(JoystickButton, INPUT_PULLUP);
}

Der loop-Teil. Beach­te die Kommentare.

void loop()
{
  // Button/Knopf auswerten
  ButtonLesen = digitalRead(JoystickButton);
  if (ButtonLesen == LOW)
  {
    // Spiel wird gestartet
    SpielStart = true;

    // Parcours bauen
    ParcoursBauen();

    // Zeitmessung starten
    Start = millis();
  }

  // wenn der Button gedrückt wurde -> SpielStart -> true
  if (SpielStart)
  {
    // Bewegung der X-Achse lesen
    PositionX = analogRead(XAchse);

    // Bewegung X-Achse nach oben
    if (PositionX > 600)
    {
      // Kreis an der aktuellen Position "löschen"
      tft.fillCircle(CursorX, CursorY, Radius, SCHWARZ);

      // wenn der Bildschirmrand oben noch nicht erreicht wurde
      // rückwärts -> Richtung x = 1 bewegen
      if (CursorY > Radius) CursorY -= Bewegung;

      // Kreis an der neuen Position zeichnen
      tft.fillCircle(CursorX, CursorY, Radius, KREISFARBE);
      delay(Geschwindigkeit);
    }

    // Bewegung X-Achse nach unten
    if (PositionX < 300)
    {
      // Kreis an der aktuellen Position "löschen"
      tft.fillCircle(CursorX, CursorY, Radius, SCHWARZ);

      // wenn der Bildschirmrand rechts noch nicht erreicht wurde
      // vorwärts -> Richtung tft.height() bewegen
      if (CursorY < tft.height() - Radius) CursorY += Bewegung;

      // Kreis an der neuen Position zeichnen
      tft.fillCircle(CursorX, CursorY, Radius, KREISFARBE);
      delay(Geschwindigkeit);
    }

    // Bewegung Y-Achse nach links
    if (PositionY < 300)
    {
      // Kreis an der aktuellen Position "löschen"
      tft.fillCircle(CursorX, CursorY, Radius, SCHWARZ);

      // wenn der Bildschirmrand links noch nicht erreicht wurde
      // rückwärts -> Richtung linken Bildschirmrand bewegen
      if (CursorX > Radius) CursorX -= Bewegung;

      // Kreis an der neuen Position zeichnen
      tft.fillCircle(CursorX, CursorY, Radius, KREISFARBE);
      delay(Geschwindigkeit);
    }

    // Bewegung Y-Achse nach rechts
    PositionY = analogRead(YAchse);

    if (PositionY > 600)
    {
      // Kreis an der aktuellen Position "löschen"
      tft.fillCircle(CursorX, CursorY, Radius, SCHWARZ);

      // Abfrage, ob der rechte Rand erreicht wurde, nicht nötig
      // wird in der nächsten Bedingung abgefragt
      CursorX += Bewegung;

      // Kreis an der neuen Position zeichnen
      tft.fillCircle(CursorX, CursorY, Radius, KREISFARBE);
      delay(Geschwindigkeit);
    }

    // rechter Bildschirmrand erreicht -> Spielende
    if (CursorX > tft.height() - Radius)
    {
      ErgebnisZeigen();
    }
  }
}

Jetzt feh­len noch die Metho­den Ergeb­nis­Zei­gen() und ParcoursBauen():

void ErgebnisZeigen()
{
  // Zeit berechnen
  int Sekunden;
  long VerstricheneZeit = millis() - Start;
  Sekunden = int(VerstricheneZeit / 1000);

  // Zeit anzeigen
  tft.fillScreen(SCHWARZ);
  tft.setTextColor(SCHRIFTFARBE);

  tft.setTextSize(2);
  tft.setCursor(1, 10);
  tft.println("Zeit:");
  tft.println(String(Sekunden) + " s");

  tft.setCursor(1, 40);
  tft.println();
  tft.println("Neustart:");
  tft.println("-> Taste");
  SpielStart = false;
}

void ParcoursBauen()
{
  CursorX = Radius;
  CursorY = tft.height() / 2 - Abstand;
  tft.fillScreen(SCHWARZ);

  // Kreis anzeigen
  tft.fillCircle(CursorX, CursorY, Radius, KREISFARBE);

  // Parcours "bauen"
  tft.fillRect(65, 35, 5, 45, FARBE);
  tft.fillRect(1, 1, 35, 35, FARBE);
  tft.fillRect(1, 80, 70, 80, FARBE);
  tft.fillRect(110, 1, 70, 95, FARBE);
  tft.fillRect(110, 130, 140, 160, FARBE);
}

Startseite
Aufgaben A-Z
Suchen
Downloads
Fehlermeldungen
Seite als PDF

Ver­wand­te Aufgaben:


Letzte Aktualisierung: 7. Dez 2021 @ 11:57