Bemerkung
Hallo und willkommen in der SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasten-Gemeinschaft auf Facebook! Tauchen Sie tiefer ein in die Welt von Raspberry Pi, Arduino und ESP32 mit anderen Enthusiasten.
Warum beitreten?
Expertenunterstützung: Lösen Sie Nachverkaufsprobleme und technische Herausforderungen mit Hilfe unserer Gemeinschaft und unseres Teams.
Lernen & Teilen: Tauschen Sie Tipps und Anleitungen aus, um Ihre Fähigkeiten zu verbessern.
Exklusive Vorschauen: Erhalten Sie frühzeitigen Zugang zu neuen Produktankündigungen und exklusiven Einblicken.
Spezialrabatte: Genießen Sie exklusive Rabatte auf unsere neuesten Produkte.
Festliche Aktionen und Gewinnspiele: Nehmen Sie an Gewinnspielen und Feiertagsaktionen teil.
👉 Sind Sie bereit, mit uns zu erkunden und zu erschaffen? Klicken Sie auf [ hier ] und treten Sie heute bei!
SPIEL - Pong
Dies ist ein einfaches Pong-Spiel, das mit einem OLED-Display und einem Arduino-Board entwickelt wurde. Im Pong-Spiel treten Spieler gegen den Computer an, indem sie einen vertikalen Schläger steuern, um einen hüpfenden Ball zurückzuprallen. Das Ziel ist es, zu verhindern, dass der Ball an der Kante Ihres Schlägers vorbeigeht, sonst erzielt der Gegner Punkte.
Die Spielmechanik kann in folgende Teile unterteilt werden:
Ballbewegung - Der Ball bewegt sich in seiner aktuellen Richtung mit einer festgelegten Geschwindigkeit. Jedes Mal, wenn der Ball mit einem Schläger kollidiert, nimmt seine Geschwindigkeit zu, was das Spiel herausfordernder macht.
Schlägerbewegung - Wird verwendet, um die Bewegung des Balls zu blockieren, der Schläger kann sich nach oben oder unten bewegen. Spieler steuern ihren eigenen Schläger mit Knöpfen, während der Schläger des Computers automatisch der Position des Balls folgt.
Punktzahl - Immer wenn der Ball über den linken oder rechten Rand des Bildschirms hinausgeht, erzielt der entsprechende Spieler oder CPU Punkte.
Benötigte Komponenten
Für dieses Projekt benötigen wir die folgenden Komponenten.
Es ist definitiv praktisch, ein ganzes Kit zu kaufen, hier ist der Link:
Name |
ARTIKEL IN DIESEM KIT |
LINK |
|---|---|---|
Elite Explorer Kit |
300+ |
Sie können sie auch einzeln über die untenstehenden Links kaufen.
KOMPONENTENBESCHREIBUNG |
KAUF-LINK |
|---|---|
- |
|
- |
Verdrahtung
Schaltplan
Code
Bemerkung
Sie können die Datei
12_pong_oled.inodirekt unter dem Pfadelite-explorer-kit-main\fun_project\12_pong_oledöffnen.Oder kopieren Sie diesen Code in die Arduino IDE.
Bemerkung
Um die Bibliothek zu installieren, verwenden Sie den Arduino-Bibliotheksmanager und suchen Sie nach „Adafruit SSD1306“ und „Adafruit GFX“ und installieren Sie diese.
1/*
2 This code creates a basic Pong game using an Arduino Uno, an OLED display,
3 and buttons. Players use the buttons to control a vertical paddle and bounce
4 back a moving ball to prevent it from passing their paddle. Scoring happens
5 when the ball goes off the screen edges.
6
7 Board: Arduino Uno R4
8 Component: OLED Display Module and Button
9 Library: https://github.com/adafruit/Adafruit_SSD1306 (Adafruit SSD1306 by Adafruit)
10 https://github.com/adafruit/Adafruit-GFX-Library (Adafruit GFX Library by Adafruit)
11*/
12
13
14#include <SPI.h>
15#include <Wire.h>
16#include <Adafruit_GFX.h>
17#include <Adafruit_SSD1306.h>
18
19#define UP_BUTTON 3
20#define DOWN_BUTTON 2
21
22#define SCREEN_WIDTH 128 // OLED display width, in pixels
23#define SCREEN_HEIGHT 64 // OLED display height, in pixels
24
25// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
26#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
27Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
28
29// ball set
30const unsigned long BALL_RATE = 16;
31int ball_x = 64, ball_y = 32;
32int ball_speed = 1;
33int8_t ball_dir_x = 1, ball_dir_y = 1;
34
35//flash rate
36unsigned long ball_update;
37unsigned long paddle_update;
38
39// paddle set
40const unsigned long PADDLE_RATE = 33;
41const uint8_t PADDLE_HEIGHT = 16;
42const uint8_t CPU_X = 12;
43int8_t cpu_y = 16;
44const uint8_t PLAYER_X = 115;
45int8_t player_y = 16;
46int paddle_speed = 3;
47
48// score
49uint8_t player_score = 0;
50uint8_t cpu_score = 0;
51
52
53void setup() {
54 Serial.begin(115200);
55
56 randomSeed(analogRead(A0));
57 ball_dir_x = random(0, 2) * 2 - 1;
58 ball_dir_y = random(0, 2) * 2 - 1;
59
60 display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
61 display.display();
62
63 pinMode(UP_BUTTON, INPUT);
64 pinMode(DOWN_BUTTON, INPUT);
65
66 unsigned long start = millis();
67
68 display.clearDisplay();
69 drawCourt();
70
71 while (millis() - start < 2000)
72 ;
73
74 displayScore();
75 display.display();
76
77 ball_update = millis();
78 paddle_update = ball_update;
79}
80
81void loop() {
82 bool update = false;
83 unsigned long time = millis();
84
85 static bool up_state = false;
86 static bool down_state = false;
87
88 /* check if the button pressed */
89 up_state |= (digitalRead(UP_BUTTON) == LOW);
90 down_state |= (digitalRead(DOWN_BUTTON) == LOW);
91
92 /* refresh the ball */
93 if (time > ball_update) {
94 int new_x = ball_x + ball_dir_x * ball_speed;
95 int8_t new_y = ball_y + ball_dir_y * ball_speed;
96
97 // Check if it hits the horizontal walls.
98 if (new_y <= 0 || new_y >= SCREEN_HEIGHT - 1) {
99 ball_dir_y = -ball_dir_y;
100 new_y += ball_dir_y + ball_dir_y * ball_speed;
101 displayScore();
102 }
103
104 // Check if it hits the CPU paddle
105 if (crossesCpuPaddle(ball_x, new_x, ball_y)) {
106 ball_dir_x = -ball_dir_x;
107 new_x = CPU_X + 1;// move the ball's position to the left edge of the paddle
108 ball_speed++; // speeds up
109 }
110
111 // Check if it hits the player paddle
112 if (crossesPlayerPaddle(ball_x, new_x, ball_y)) {
113 ball_dir_x = -ball_dir_x;
114 new_x = PLAYER_X - 1; // move the ball's position to the right edge of the paddle
115 ball_speed++; // speeds up
116 }
117
118 // Check if it hits the vertical walls
119 if (new_x <= 0 || new_x >= SCREEN_WIDTH - 1) {
120 if (new_x <= 1) {
121 player_score++;
122 }
123 if (new_x >= 126) {
124 cpu_score++;
125 }
126 /* reset ball */
127 displayScore();
128 ball_speed = 1; // reset speed
129 new_x = 64; // reset position
130 // new_y = 32;
131 ball_dir_x = (ball_dir_x > 0) ? -1 : 1; // reset direction
132 ball_dir_y = (random(0, 2) == 0) ? 1 : -1; // reset direction
133 }
134
135 display.drawPixel(ball_x, ball_y, BLACK);
136 display.drawPixel(new_x, new_y, WHITE);
137 ball_x = new_x;
138 ball_y = new_y;
139
140 ball_update += BALL_RATE; // next refresh time
141 update = true;
142 }
143
144 /* refresh paddles */
145 if (time > paddle_update) {
146 paddle_update += PADDLE_RATE; // next refresh time
147
148 // CPU paddle
149 display.drawFastVLine(CPU_X, cpu_y, PADDLE_HEIGHT, BLACK); //clear paddle
150 const uint8_t half_paddle = PADDLE_HEIGHT >> 1;
151 if (cpu_y + half_paddle > ball_y) {
152 cpu_y -= paddle_speed;
153 }
154 if (cpu_y + half_paddle < ball_y) {
155 cpu_y += paddle_speed;
156 }
157 // constraint position
158 if (cpu_y < 1) cpu_y = 1;
159 if (cpu_y + PADDLE_HEIGHT > 63) cpu_y = 63 - PADDLE_HEIGHT;
160 display.drawFastVLine(CPU_X, cpu_y, PADDLE_HEIGHT, WHITE); //show paddle
161
162 // Player paddle
163 display.drawFastVLine(PLAYER_X, player_y, PADDLE_HEIGHT, BLACK); //clear paddle
164 if (up_state) {
165 player_y -= paddle_speed;
166 }
167 if (down_state) {
168 player_y += paddle_speed;
169 }
170 up_state = down_state = false;
171 // constraint position
172 if (player_y < 1) player_y = 1;
173 if (player_y + PADDLE_HEIGHT > 63) player_y = 63 - PADDLE_HEIGHT;
174 display.drawFastVLine(PLAYER_X, player_y, PADDLE_HEIGHT, WHITE); //show paddle
175 update = true;
176 }
177
178 if (update)
179 display.display();
180}
181
182bool crossesPlayerPaddle(uint8_t old_x, uint8_t new_x, uint8_t ball_y) {
183 return old_x < PLAYER_X && new_x >= PLAYER_X && ball_y >= player_y && ball_y <= player_y + PADDLE_HEIGHT;
184}
185
186bool crossesCpuPaddle(uint8_t old_x, uint8_t new_x, uint8_t ball_y) {
187 return old_x > CPU_X && new_x <= CPU_X && ball_y >= cpu_y && ball_y <= cpu_y + PADDLE_HEIGHT;
188}
189
190void drawCourt() {
191 display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, WHITE);
192}
193
194void displayScore() {
195 display.fillRect(SCREEN_WIDTH / 2 - 20, 10, 60, 10, BLACK);// clear
196
197 display.setCursor(SCREEN_WIDTH / 2 - 20, 10);
198 display.setTextSize(1);
199 display.setTextColor(WHITE);
200
201 display.print(cpu_score);
202 display.print(" - ");
203 display.print(player_score);
204}
Wie funktioniert des?
Die Programmstruktur kann in die folgenden fünf Teile unterteilt werden:
Notwendige Bibliotheken importieren - Verwendet zur Steuerung des OLED-Bildschirms und zum Lesen von Tasteneingaben.
Konstanten und globale Variablen definieren:
Definitionen für OLED-Bildschirmbreite und -höhe. Definitionen für Tasten und OLED-Reset-Pins. Position, Geschwindigkeit, Größe und Richtung des Balls und der Schläger. Punktzahlen für Spieler und CPU.
Initialisierung:
Initialisieren Sie die serielle Kommunikation, den OLED-Bildschirm und zeigen Sie die anfängliche Oberfläche an. Stellen Sie Tasten als Eingänge ein und verbinden Sie Pull-up-Widerstände. Zeichnen Sie das Spielfeld.
Hauptschleife:
Lesen Sie die Zustände der Tasten. Bewegen Sie den Ball basierend auf der eingestellten Aktualisierungsrate. Erkennen Sie Kollisionen zwischen dem Ball und den Schlägern oder Wänden und passen Sie die Richtung und Geschwindigkeit des Balls entsprechend an. Aktualisieren Sie den Bildschirm mit Punktzahlen basierend auf Punktereignissen. Aktualisieren Sie die Positionen der Schläger.
Zusätzliche Funktionen:
crossesPlayerPaddleundcrossesCpuPaddle- Wird verwendet, um zu erkennen, ob der Ball mit dem Schläger des Spielers oder der CPU kollidiert.drawCourt- Zeichnet das Spielfeld auf dem OLED-Bildschirm.displayScore- Zeigt die Punktzahlen des Spielers und der CPU auf dem Bildschirm an.