Snake con oled sdd1306

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();
  }

}

A prima occhiata xx_snake e yy_snake sono int, quindi possono diventare negativi.
Io per sicurezza cambierei
if( (xx_snake == 0) || (xx_snake==127) || (yy_snake==0) || (yy_snake==63) )
in
if( xx_snake <= 0 || xx_snake>=127 || yy_snake<=0 || yy_snake>=63 )
P.S. ho tolto un pò di tonde inutili

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.