Arduino Projekt: Pong Spiel: Unterschied zwischen den Versionen

Aus HSHL Mechatronik
Zur Navigation springen Zur Suche springen
Zeile 137: Zeile 137:
|       
|       
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
// Benötigte Bibliotheken
// Benötigte Bibliotheken  
#include <SPI.h>
#include <SPI.h>
#include <Wire.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_GFX.h>                    
#include <Adafruit_SSD1306.h>
#include <Adafruit_SSD1306.h>


Zeile 146: Zeile 146:
const char UP_BUTTON = 2;
const char UP_BUTTON = 2;
const char DOWN_BUTTON = 3;
const char DOWN_BUTTON = 3;
 
const char UP_BUTTON_TWO = 4;
const char SCREEN_WIDTH = 128;     // OLED display Breite, in Pixel
const char DOWN_BUTTON_TWO = 5;
const char SCREEN_HEIGHT = 64;     // OLED display Höhe, in Pixel


const unsigned char PADDLE_RATE = 33;        // const: Konstant, wert bleibt unverändert
const unsigned char PADDLE_RATE = 33;        // const: Konstant, wert bleibt unverändert
const unsigned char BALL_RATE = 16;          // unsigned long: kann keine negativen Zahlen speichern, der Bereich liegt zwischen 0 und 4,294,967,295 (2^32 - 1)
const unsigned char BALL_RATE = 16;          // unsigned long: kann keine negativen Zahlen speichern
const unsigned char PADDLE_HEIGHT = 25;
const unsigned char PADDLE_HEIGHT = 25;
const char SCREEN_WIDTH = 128;      // OLED Display Breite
const char SCREEN_HEIGHT = 64;    // OLED Display Höhe


// Deklaration für das verwendete Display, verbindung zum I2C (SDA, SCL pins)
// Deklaration für das verwendete Display, verbindung zum I2C (SDA, SCL pins)
const unsigned char OLED_RESET = 4; // Reset pin # (or -1 if sharing Arduino reset pin)
const char OLED_RESET; // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


/* Variablen deklarieren */
/* Variablen deklarieren */
unsigned int Player_score = 0, Ai_score = 0;
unsigned int Player_one = 0, Player_two = 0;
 
 




Zeile 176: Zeile 176:
unsigned char Player_y = 16;
unsigned char Player_y = 16;


 
       
void setup() {
void setup() {
  Serial.begin(9600);
    Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // Starte das Display
    display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // Starte das Display        


   
    display.display();                          // Display aktualisierung
    unsigned long start = millis();            // Gibt die Anzahl von Millisekunden zurück, seit das Arduino-Board das aktuelle Programm gestartet hat


  display.display();                         // Display aktualisierung
    // Taster Initialisieren
  unsigned long start = millis();             // Gibt die Anzahl von Millisekunden zurück, seit das Arduino-Board das aktuelle Programm gestartet hat
    pinMode(UP_BUTTON, INPUT);
    pinMode(DOWN_BUTTON, INPUT);               
    digitalWrite(UP_BUTTON,1);
    digitalWrite(DOWN_BUTTON,1);
   
    // Taster zwei
    pinMode(UP_BUTTON_TWO, INPUT);
    pinMode(DOWN_BUTTON_TWO, INPUT);               
    digitalWrite(UP_BUTTON_TWO,1);
    digitalWrite(DOWN_BUTTON_TWO,1);
    display.clearDisplay();                     // Display alle pixel ausschalten


  // Taster Initialisieren
    while(millis() - start < 2000);           // Solange millis kleiner als 2000ms ist
  pinMode(UP_BUTTON, INPUT);
  pinMode(DOWN_BUTTON, INPUT);
  digitalWrite(UP_BUTTON, 1);
  digitalWrite(DOWN_BUTTON, 1);
  display.clearDisplay();                     // Display alle pixel ausschalten


  while (millis() - start < 2000);          // Solange millis kleiner als 2000ms ist
    display.display();
 
  display.display();


  Ball_update = millis();
    Ball_update = millis();
  delay(1000);
    delay(1000);
  Paddle_update = Ball_update;
}
}
// Punkteanzeige
// Punkteanzeige
void drawScore() {
void drawScore() {              
  // draw AI and player scores
   display.setTextSize(2);
   display.setTextSize(2);
   display.setTextColor(WHITE);
   display.setTextColor(WHITE);
   display.setCursor(45, 0);
   display.setCursor(44, 0);
   display.println(Player_score);
   display.println(Player_one);


   display.setCursor(75, 0);
   display.setCursor(74, 0);
   display.println(Ai_score);
   display.println(Player_two);  
}
}
// Punkte zurücksetzten
// Punkte zurücksetzten
void eraseScore() {
void eraseScore() {                              
  // erase AI and player scores
   display.setTextSize(2);
   display.setTextSize(2);
   display.setTextColor(BLACK);
   display.setTextColor(BLACK);
   display.setCursor(45, 0);
   display.setCursor(44, 0);
   display.println(Player_score);
   display.println(Player_one);
   display.setCursor(75, 0);
 
   display.println(Ai_score);
   display.setCursor(74, 0);
   display.println(Player_two);
}
}


void loop() {
void loop() {
  drawScore();  
    drawScore();
 
 
  bool update = false;                          // Ein bool enthält einen von zwei Werten, true oder false
    bool update = false;                          // Ein bool enthält einen von zwei Werten, true oder false
  unsigned long time = millis();
    unsigned long time = millis();


  static bool Up_state = false;
    static bool Up_state = false;
  static bool Down_state = false;
    static bool Down_state = false;
    static bool Up_state_two = false;
    static bool Down_state_two = false;
   
    Up_state |= (digitalRead(UP_BUTTON) == LOW);                  // Taster auslesen
    Down_state |= (digitalRead(DOWN_BUTTON) == LOW);
    Up_state_two |= (digitalRead(UP_BUTTON_TWO) == LOW);                  // Taster auslesen
    Down_state_two |= (digitalRead(DOWN_BUTTON_TWO) == LOW);


  Up_state |= (digitalRead(UP_BUTTON) == LOW);                  // Taster auslesen
  Down_state |= (digitalRead(DOWN_BUTTON) == LOW);


  if (time > Ball_update) {
  if (time > Ball_update) {
     unsigned char New_x = Ball_x + Ball_dir_x;                 // neue Ball Position
     unsigned char New_x = Ball_x + Ball_dir_x;               // neue Ball Position
     unsigned char New_y = Ball_y + Ball_dir_y;
     unsigned char New_y = Ball_y + Ball_dir_y;


Zeile 245: Zeile 252:
       New_x += Ball_dir_x + Ball_dir_x;
       New_x += Ball_dir_x + Ball_dir_x;
       eraseScore();                        // Punkt für Spieler
       eraseScore();                        // Punkt für Spieler
       Player_score = Player_score + 1;
       Player_one = Player_one + 1;
       drawScore();
       drawScore();
         
         
        }
        if(New_x == 127) {                      // Wand rechts
            Ball_dir_x = -Ball_dir_x;            // Wechselt die Richtung
            New_x += Ball_dir_x + Ball_dir_x;
            eraseScore();                        // Punkt für den Computer
            Player_two = Player_two+1;
            drawScore();
        }     


        // Checkt ob die horizontalen Wände berüht werden
        if(New_y == 0 || New_y == 63)  {
            Ball_dir_y = -Ball_dir_y;          // Wechselt die Richtung
            New_y += Ball_dir_y + Ball_dir_y;
           
        }


    }
        // Checkt ob der Computer Paddel getroffen wurde
    if (New_x == 127) {                     // Wand rechts
        if(New_x == CPU_X && New_y >= Cpu_y && New_y <= Cpu_y + PADDLE_HEIGHT) {
      Ball_dir_x = -Ball_dir_x;           // Wechselt die Richtung
            Ball_dir_x = -Ball_dir_x;
      New_x += Ball_dir_x + Ball_dir_x;
            New_x += Ball_dir_x + Ball_dir_x;
      eraseScore();                        // Punkt für den Computer
        }
      Ai_score = Ai_score + 1;
      drawScore();
    }


    // Checkt ob die horizontalen Wände berüht werden
        // Checkt ob der Spieler Paddel getroffen wurde
    if (New_y == 0 || New_y == 63) {
        if(New_x == PLAYER_X && New_y >= Player_y && New_y <= Player_y + PADDLE_HEIGHT) {
      Ball_dir_y = -Ball_dir_y;           // Wechselt die Richtung
            Ball_dir_x = -Ball_dir_x;
      New_y += Ball_dir_y + Ball_dir_y;
            New_x += Ball_dir_x + Ball_dir_x;
        }
       
        display.drawPixel(Ball_x, Ball_y, BLACK);
        display.drawPixel(New_x, New_y, WHITE);
        Ball_x = New_x;
        Ball_y = New_y;


    }
        Ball_update += BALL_RATE;


    // Checkt ob der Computer Paddel getroffen wurde
        update = true;              // updated darum bool auf true
    if (New_x == CPU_X && New_y >= Cpu_y && New_y <= Cpu_y + PADDLE_HEIGHT) {
      Ball_dir_x = -Ball_dir_x;
      New_x += Ball_dir_x + Ball_dir_x;
     }
     }
       
        display.drawFastVLine(CPU_X, Cpu_y, PADDLE_HEIGHT, BLACK);
        if(Up_state_two) {
            Cpu_y -= 1;
        }
          if(Down_state_two) {
            Cpu_y += 1;
        }
        Up_state_two = Down_state_two = false;
        if(Cpu_y < 1) Cpu_y = 1;
        if(Cpu_y + PADDLE_HEIGHT > 63) Cpu_y = 63 - PADDLE_HEIGHT;
        display.drawFastVLine(CPU_X, Cpu_y, PADDLE_HEIGHT, WHITE);
       


    // Checkt ob der Spieler Paddel getroffen wurde
        // Spieler Paddel
    if (New_x == PLAYER_X && New_y >= Player_y && New_y <= Player_y + PADDLE_HEIGHT) {
        display.drawFastVLine(PLAYER_X, Player_y, PADDLE_HEIGHT, BLACK);
      Ball_dir_x = -Ball_dir_x;
        if(Up_state) {
      New_x += Ball_dir_x + Ball_dir_x;
            Player_y -= 1;
    }
        }
 
        if(Down_state) {
    display.drawPixel(Ball_x, Ball_y, BLACK);
            Player_y += 1;
    display.drawPixel(New_x, New_y, WHITE);
        }
    Ball_x = New_x;
        Up_state = Down_state = false;
    Ball_y = New_y;
        if(Player_y < 1) Player_y = 1;
 
        if(Player_y + PADDLE_HEIGHT > 63) Player_y = 63 - PADDLE_HEIGHT;
    Ball_update += BALL_RATE;
        display.drawFastVLine(PLAYER_X, Player_y, PADDLE_HEIGHT, WHITE);
 
    update = true;               // updated darum bool auf true
  }
 
  if (time > Paddle_update) {
    Paddle_update += PADDLE_RATE;


    // Computer Paddel
        update = true;


    display.drawFastVLine(CPU_X, Cpu_y, PADDLE_HEIGHT, BLACK);
    const unsigned char Half_paddle = PADDLE_HEIGHT >> 1;
    if (Cpu_y + Half_paddle > Ball_y) {
      Cpu_y -= 1;
    }
    if (Cpu_y + Half_paddle < Ball_y) {
      Cpu_y += 1;
    }
    if (Cpu_y < 1) Cpu_y = 1;
    if (Cpu_y + PADDLE_HEIGHT > 63) Cpu_y = 63 - PADDLE_HEIGHT;


     display.drawFastVLine(CPU_X, Cpu_y, PADDLE_HEIGHT, WHITE);
     if(update)
 
        display.display();
 
    // Spieler Paddel
    display.drawFastVLine(PLAYER_X, Player_y, PADDLE_HEIGHT, BLACK);
    if (Up_state) {
      Player_y -= 1;
    }
    if (Down_state) {
      Player_y += 1;
    }
    Up_state = Down_state = false;
    if (Player_y < 1) Player_y = 1;
    if (Player_y + PADDLE_HEIGHT > 63) Player_y = 63 - PADDLE_HEIGHT;
    display.drawFastVLine(PLAYER_X, Player_y, PADDLE_HEIGHT, WHITE);
 
    update = true;
  }
 
  if (update)
    display.display();
}
}
</syntaxhighlight>
</syntaxhighlight>

Version vom 18. Juli 2023, 13:36 Uhr

Abb. 1: Pong Spiel

Autor: Justin Frommberger

Aufgabenstellung

  • Das Ziel dieses Projektes ist eigenes Pong spiel umzusetzen.
  • Ein Punkt (Ball) bewegt sich auf dem Bildschirm hin und her.
  • Jeder der beiden Spieler steuert einen senkrechten Strich (Schläger), den er mit einem Drehknopf (Paddle) nach oben und unten verschieben kann.
  • Lässt man den „Ball“ am „Schläger“ vorbei und berührt die Wand, erhält der Gegner einen Punkt.

Benötigte Software

  • Aktuellste Arduino IDE mit der Version für ihren PC. (Download link)
  • Bibliotheken für das OLED Display: Adafruit_SSD1306 und Adafruit-GFX-Library downloaden.
    • Klicke oben rechts in GitHub auf Code und dann downloade die Zip-Datei.
    • Um die Zip-Datei in ihre Arduino Bibliothek einzubinden, folgen diese Schritte: (Link)

Benötigte Materiallien

Tabelle 1: Materialliste

Nr. Anz. Beschreibung Bild Pos. Anz. Beschreibung Bild
1 Funduino Arduino UNO R3
viele Jumper Kabel, männlich/männlich
1 Steckbrett
4 Taster
1 0.96 I2C OLED Display

Vorab wichtig zu wissen!

Abb. 2: OLED Display

Arduino Uno R3:

  • Der Arduino besitzt unterschiedliche Schnittstellen, weil der Arduino ein digitaler Mikrocontroller ist, kann er nur  5 Volt ausgeben oder annehmen.
  • Bei einer konstanten  5 V Spannung, ist die LED immer gleich hell, so ist das Ziel die Spannung zur LED zu reduzieren.
  • Dafür wird eine Pulsweitenmodulation (PWM) Schnittstelle benötigt, denn bei den anderen Schnittstellen ist dies nicht möglich.
  • Bei einem geringen PWM-Wert ist das  5 V Signal kaum noch vorhanden und bei einem hohen PWM-Wert liegt das  5 V Signal nahezu durchgehend am Pin an.
  • Durch die PWM Schnittstelle kann nun die LED unterschiedlich hell leuchten, da die Spannung anpassbar ist.
  • Die [PWM] Schnittstellen sind ganz einfach zu erkennen an diesem Zeichen (~)

Steckbrett:
Erklärung zum Arbeiten mit einem Steckbrett (klicken!)

OLED Display:
Das Display verfügt über vier Pins:

  • VCC: Pin für die Spannungsversorgung, anzuschließen an den 5V Pin des Mikrocontrollers
  • GND: Ground-Pin, anzuschließen an den GND Pin des Mikrocontrollers
  • SDA und SCL: mit den dafür vorgesehenen Kontakten am Mikrocontroller
    • Beim UNO R3 gibt es dafür oberhalb des Pin 13 einen SDA und SCL Pin, alternativ können auch die analogen Pins A4 (SDA) und A5 (SCL) verwendet werden.

Aufbau Schaltung

Abb.3 Schaltung Pong Spiel
  • * In Abb. 3 wird die Schaltung für das Projekt " Arduino Pong Spiel" dargestellt.


Arduino Datei erstellen

Programmierung Vorkenntnisse

  • Kenntnisse in den Programmierrichtlinien für die Erstellung von Software. (Link)
  • Grundkenntnisse von Projekt 1-5 verstanden haben. (Link)
  • Grundkenntnisse für das Projekt "Arduino Pong Spiel" verstehen. (Link)

Programmierung Anleitung

  • Nachdem die Schritte 1 und 2 abgeschlossen sind, kann mit der Programmierung des Projektes gestartet werden.

1) Bibliotheken einfügen

Zuerst muss, für das Projekt Pong Spiel die heruntergeladenen Bibliotheken eingefügt werden.

Benötigt wird:

  1. Kommunikation zum I2C/TWI Gerät.
  2. Kommunikation mit dem SPI Gerät.
  3. Adafruit GFX Grafik.
  4. 128x64 and 128x32 OLEDs Displays.

2) Initialisierung Arduino

Nachdem hinzufügen der Bibliotheken folgt die Initialisierung der benötigten Pins und Variablen.

2.1) Taster

Test Text




Schritt 4

  • Nach dem Beenden von Schritt 3, kann nun das Ergebnis mit der Musterlösung verglichen werden.

Musterlösung

Quelle: Link



→ zurück zum Hauptartikel: BA: Arduino-Projekte für die Lehre