Nota
Ciao, benvenuto nella community SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts su Facebook! Approfondisci Raspberry Pi, Arduino ed ESP32 con altri appassionati.
Perché unirsi?
Supporto Esperto: Risolvi problemi post-vendita e sfide tecniche con l’aiuto della nostra community e del nostro team.
Impara & Condividi: Scambia consigli e tutorial per migliorare le tue competenze.
Anteprime Esclusive: Ottieni l’accesso anticipato agli annunci di nuovi prodotti e anteprime esclusive.
Sconti Speciali: Goditi sconti esclusivi sui nostri prodotti più recenti.
Promozioni e Concorsi Festivi: Partecipa a concorsi e promozioni festive.
👉 Pronto a esplorare e creare con noi? Clicca [Qui] e unisciti oggi stesso!
GIOCO - Pong
Questo è un semplice gioco Pong progettato utilizzando un display OLED e una scheda Arduino. Nel gioco Pong, i giocatori competono contro il computer, controllando una paletta verticale per respingere una palla rimbalzante. L’obiettivo è impedire che la palla superi il bordo della propria paletta, altrimenti l’avversario segna un punto.
Le meccaniche del gioco possono essere suddivise nelle seguenti parti:
Movimento della palla - La palla si muove nella direzione corrente a una velocità impostata. Ogni volta che la palla colpisce una paletta, la sua velocità aumenta, rendendo il gioco più difficile.
Movimento della paletta - Utilizzata per bloccare il movimento della palla, la paletta può muoversi su o giù. I giocatori controllano la propria paletta usando i pulsanti, mentre la paletta del computer segue automaticamente la posizione della palla.
Punteggio - Ogni volta che la palla supera il bordo sinistro o destro dello schermo, il giocatore o il CPU corrispondente segna un punto.
Componenti Necessari
In questo progetto, abbiamo bisogno dei seguenti componenti.
È sicuramente conveniente acquistare un kit completo, ecco il link:
Nome |
ELEMENTI IN QUESTO KIT |
LINK |
|---|---|---|
Elite Explorer Kit |
300+ |
Puoi anche acquistarli separatamente dai link sottostanti.
INTRODUZIONE COMPONENTI |
LINK ACQUISTO |
|---|---|
- |
|
- |
Collegamenti
Nota
Per proteggere il Power Pack del Modulo di Alimentazione, caricalo completamente prima di utilizzarlo per la prima volta.
Schema Elettrico
Codice
Nota
Puoi aprire il file
12_pong_oled.inonel percorsoelite-explorer-kit-main\fun_project\12_pong_oleddirettamente.Oppure copia questo codice nell’Arduino IDE.
Nota
Per installare la libreria, usa l’Arduino Library Manager e cerca «Adafruit SSD1306» e «Adafruit GFX» e installale.
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}
Come funziona?
La struttura del programma può essere suddivisa nelle seguenti cinque parti:
Importare le Librerie Necessarie - Utilizzate per controllare lo schermo OLED e leggere gli input dei pulsanti.
Definire Costanti e Variabili Globali:
Definizioni per la larghezza e l’altezza dello schermo OLED. Definizioni per i pulsanti e i pin di reset dell’OLED. Posizione, velocità, dimensione e direzione della palla e delle palette. Punteggi per il giocatore e il CPU.
Inizializzazione:
Inizializzare la comunicazione seriale, lo schermo OLED e visualizzare l’interfaccia iniziale. Impostare i pulsanti come input e collegare le resistenze pull-up. Disegnare il campo da gioco.
Ciclo Principale:
Leggere lo stato dei pulsanti. Muovere la palla in base alla frequenza di aggiornamento impostata. Rilevare le collisioni tra la palla e le palette o i muri, regolando la direzione e la velocità della palla di conseguenza. Aggiornare lo schermo con i punteggi in base agli eventi di punteggio. Aggiornare le posizioni delle palette.
Funzioni Aggiuntive:
crossesPlayerPaddleecrossesCpuPaddle- Utilizzate per rilevare se la palla collide con la paletta del giocatore o del CPU.drawCourt- Disegna il campo da gioco sullo schermo OLED.displayScore- Visualizza i punteggi del giocatore e del CPU sullo schermo.