Ciao a tutti, per sfizio ed esercizio sto provando a programmare snake sfruttando un Arduino nano iot 33 e un display oled sdd1306 128x64.
Per quanto sia in fase embrionale qualcosa funziona:
- Ho programmato una intro animata con un rettangolo che si apre e compare un logo
- Si genera un rettangolo confinante il gioco (se snake ci sbatte contro gameover)
- si genera il seme random da prendere
- snake si muove correttamente e se prende il seme si allunga.
Sicuramente il codice è migliorabile, ma quello che non capisco è perché ogni tanto, in modo casuale e senza regole ben precise, il tutto si blocca e devo resettare il micro. Idee?
Vi ringrazio in anticipo
//variabile random coordinate per il seme
long xx_seme;
long yy_seme;
//livello di partenza (corrisponde alla lunghezza di snake
int level = 10;
//vettore coordinate (livello/lunghezza max 30)
int snake_x[30];
int snake_y[30];
//posizione iniziale
int xx_snake = 20;
int yy_snake = 20;
const int xx_snakestart = 20;
const int yy_snakestart = 20;
//movimento, se 0 snake resta fermo
int movimento_xx = 0;
int movimento_yy = 0;
//alla partenza le prime 10 coordinate coincidono (è la lunghezza...)
void snake_start() {
for (int i = 0; i < level; i++) {
snake_x[i] = xx_snakestart;
snake_y[i] = yy_snakestart;
xx_snake = xx_snakestart;
yy_snake = yy_snakestart;
}
}
//creo il seme random nel display oled (evito vicinanza con bordi)
void snake_createseme() {
xx_seme = random(20, 110);
yy_seme = random(10, 50);
}
void snakeGAME() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SNAKE V0.1");
//INTRO con animazione rettangolo che si apre
display.clearDisplay();
for (int i = 0; i < 18; i++) {
int larg = map (i, 0, 18, 0, 128);
int alt = map (i, 0, 18, 0, 64);
display.clearDisplay();
delay(25);
display.drawRect(64 - (larg / 2), 32 - (alt / 2), larg, alt, SSD1306_WHITE);
display.display();
}
//stampo logo bmp
oled_stampalogosnake();
//stampo su lcd i tasti di gioco + pausa 1,5 secondi
lcd.setCursor(0, 2);
lcd.print("SX -> S4 UP -> S2");
lcd.setCursor(0, 3);
lcd.print("DX -> S1 DO -> S3");
delay(1500);
//gioco vero e proprio
display.clearDisplay();
display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
snake = 1;
snake_createseme();
while (snake == 1) {
//leggo lo stato dei pulsanti (default LOW)
pinValues = read_shift_regs();
display_PULSANTI_values();
delay(10);
//se lo stato di un pulsante cambia....
if (pinValues != oldPinValues) {
if (pulsante_S[0] == 1) {
movimento_xx = 1; //destra
movimento_yy = 0;
}
if (pulsante_S[1] == 1) {
movimento_yy = -1; //alto
movimento_xx = 0;
}
if (pulsante_S[2] == 1) {
movimento_yy = +1; //basso
movimento_xx = 0;
}
if (pulsante_S[3] == 1) {
movimento_xx = -1; //sinistra
movimento_yy = 0;
}
}
delay(20);
xx_snake = xx_snake + movimento_xx;
yy_snake = yy_snake + movimento_yy;
//se prendo il seme avanzo di livello/lunghezza e rigenero nuovo seme random
if ((xx_snake == xx_seme) && (yy_snake == yy_seme)) {
level = level + 1;
snake_createseme();
}
//se tocco il bordo game over
if ((xx_snake == 0) || (xx_snake == 127) || (yy_snake == 0) || (yy_snake == 63)) {
display.setTextColor(SSD1306_WHITE);
display.setTextSize(2);
display.clearDisplay();
display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
display.setCursor(10, 5);
display.println(F("GAME OVER"));
display.display();
delay(500);
snake = 0;
break;
}
//traslo coordinate vecchie per far avanzare snake di lunghezza "level"
for (int i = level; i >= 0; i--) {
int j = i + 1;
snake_x[j] = snake_x[i];
snake_y[j] = snake_y[i];
}
//coordinata attuale
snake_x[0] = xx_snake;
snake_y[0] = yy_snake;
//stampo nuova posizione
display.clearDisplay();
for (int i = 0; i < level; i++) {
//rettangolo di contorno
display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
//snake
display.drawRect(snake_x[i], snake_y[i], 2, 2, SSD1306_WHITE);
//seme
display.drawRect(xx_seme, yy_seme, 2, 2, SSD1306_WHITE);
}
delay(20);
display.display();
}
}