Arduino Projekt: Pong Spiel: Unterschied zwischen den Versionen
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 | const char DOWN_BUTTON_TWO = 5; | ||
const char | |||
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 | 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 | 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 | 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); | |||
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 | |||
// Taster Initialisieren | |||
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 | |||
while(millis() - start < 2000); // Solange millis kleiner als 2000ms ist | |||
display.display(); | |||
Ball_update = millis(); | |||
delay(1000); | |||
} | } | ||
// Punkteanzeige | // Punkteanzeige | ||
void drawScore() { | void drawScore() { | ||
display.setTextSize(2); | display.setTextSize(2); | ||
display.setTextColor(WHITE); | display.setTextColor(WHITE); | ||
display.setCursor( | display.setCursor(44, 0); | ||
display.println( | display.println(Player_one); | ||
display.setCursor( | display.setCursor(74, 0); | ||
display.println( | display.println(Player_two); | ||
} | } | ||
// Punkte zurücksetzten | // Punkte zurücksetzten | ||
void eraseScore() { | void eraseScore() { | ||
display.setTextSize(2); | display.setTextSize(2); | ||
display.setTextColor(BLACK); | display.setTextColor(BLACK); | ||
display.setCursor( | display.setCursor(44, 0); | ||
display.println( | display.println(Player_one); | ||
display.setCursor( | |||
display.println( | display.setCursor(74, 0); | ||
display.println(Player_two); | |||
} | } | ||
void loop() { | void loop() { | ||
drawScore(); | |||
bool update = false; // Ein bool enthält einen von zwei Werten, true oder false | |||
unsigned long time = millis(); | |||
static bool Up_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); | |||
if (time > Ball_update) { | |||
unsigned char New_x = Ball_x + Ball_dir_x; | 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_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 == 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; | |||
} | |||
// Checkt ob der Spieler Paddel getroffen wurde | |||
if(New_x == PLAYER_X && New_y >= Player_y && New_y <= Player_y + PADDLE_HEIGHT) { | |||
Ball_dir_x = -Ball_dir_x; | |||
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; | |||
update = true; // updated darum bool auf true | |||
} | } | ||
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); | |||
// 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
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!
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
- * In Abb. 3 wird die Schaltung für das Projekt " Arduino Pong Spiel" dargestellt.
Arduino Datei erstellen
- Erstellen der ersten Arduino Datei (Link zum Tutorial).
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:
- Kommunikation zum I2C/TWI Gerät.
- Kommunikation mit dem SPI Gerät.
- Adafruit GFX Grafik.
- 128x64 and 128x32 OLEDs Displays.
Lösung |
// Benötigte Bibliotheken
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
|
2) Initialisierung Arduino
Nachdem hinzufügen der Bibliotheken folgt die Initialisierung der benötigten Pins und Variablen.
Lösung |
/* Konstanten */
const char UP_BUTTON = 2;
const char DOWN_BUTTON = 3;
|
2.1) Taster
Test Text
Lösung |
/* Konstanten */
const char SCREEN_WIDTH = 128; // OLED Display Breite
const char SCREEN_HEIGHT = 64; // OLED Display Höhe
|
Schritt 4
- Nach dem Beenden von Schritt 3, kann nun das Ergebnis mit der Musterlösung verglichen werden.
Musterlösung
Quelle: Link
Lösung Code |
// Benötigte Bibliotheken
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
/* Konstanten */
const char UP_BUTTON = 2;
const char DOWN_BUTTON = 3;
const char UP_BUTTON_TWO = 4;
const char DOWN_BUTTON_TWO = 5;
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
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)
const char OLED_RESET; // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
/* Variablen deklarieren */
unsigned int Player_one = 0, Player_two = 0;
// Position vom Ball, Paddle und Spieler auf dem Display
unsigned char Ball_x = 64, Ball_y = 32; // UINT8_t == unsigned char
unsigned char Ball_dir_x = 1, Ball_dir_y = 1;
unsigned long Ball_update;
unsigned long Paddle_update;
const unsigned char CPU_X = 12; // Das const-Keywort steht für Konstanten
unsigned char Cpu_y = 16;
const unsigned char PLAYER_X = 115;
unsigned char Player_y = 16;
void setup() {
Serial.begin(9600);
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
// Taster Initialisieren
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
while(millis() - start < 2000); // Solange millis kleiner als 2000ms ist
display.display();
Ball_update = millis();
delay(1000);
}
// Punkteanzeige
void drawScore() {
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(44, 0);
display.println(Player_one);
display.setCursor(74, 0);
display.println(Player_two);
}
// Punkte zurücksetzten
void eraseScore() {
display.setTextSize(2);
display.setTextColor(BLACK);
display.setCursor(44, 0);
display.println(Player_one);
display.setCursor(74, 0);
display.println(Player_two);
}
void loop() {
drawScore();
bool update = false; // Ein bool enthält einen von zwei Werten, true oder false
unsigned long time = millis();
static bool Up_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);
if (time > Ball_update) {
unsigned char New_x = Ball_x + Ball_dir_x; // neue Ball Position
unsigned char New_y = Ball_y + Ball_dir_y;
// Checkt ob die verticalen Wände berüht werden
if (New_x == 0) { // Wand links
Ball_dir_x = -Ball_dir_x; // Wechselt die Richtung
New_x += Ball_dir_x + Ball_dir_x;
eraseScore(); // Punkt für Spieler
Player_one = Player_one + 1;
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 == 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;
}
// Checkt ob der Spieler Paddel getroffen wurde
if(New_x == PLAYER_X && New_y >= Player_y && New_y <= Player_y + PADDLE_HEIGHT) {
Ball_dir_x = -Ball_dir_x;
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;
update = true; // updated darum bool auf true
}
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);
// 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();
}
|
→ zurück zum Hauptartikel: BA: Arduino-Projekte für die Lehre