Skocz do zawartości

Gra Snake na ekranie LCD 2X16


Pomocna odpowiedź

Podoba Ci się ten projekt? Zostaw pozytywny komentarz i daj znać autorowi, że zbudował coś fajnego!

Masz uwagi? Napisz kulturalnie co warto zmienić. Doceń pracę autora nad konstrukcją oraz opisem.

  • 3 tygodnie później...
(edytowany)

Teraz pora na wersję 2.0, gdzie wąż oraz jabłka będą miały jeden pixel. Choć ten wyświetlacz może mieć chyba tylko 8 własnych znaków, więc może pixel 2x2 będzie bardziej dostępny.

Przykładowy enkoder

Edytowano przez Marooned
  • Lubię! 2
  • 2 lat(a) później...

Żeby jabłko lepiej wyglądało wstaw do zmiennej:

String appleBody = "@"

Zamiast znaku

"@"

 to wstaw emotkę 

"🍎"

 

Bo podejrzewam że to jedzenie dla węża :). Wypróbuję ten projekt zainteresował mnie zobaczę go tylko na żywo bo film jest nie dostępny.

  • 1 rok później...
(edytowany)
Dnia 14.03.2022 o 22:32, arek1996 napisał:

Witam, 

Z nadmiernej ilości czasu postanowiłem, że zrobię grę Snake w Arduino na ekranie LCD 2 x 16.

Kod może słaby ale ciężko mi się piszę w Arduino Idle żeby zachować czysty i zrozumiały kod. Typu if w ifie zamiast małego short if'a, czy błędy w formatowaniu. 

Kod programu:

#include <LiquidCrystal.h>

#define PIN_UP 8
#define PIN_DOWN 9
#define PIN_LEFT 10
#define PIN_RIGHT 11
#define PIN_GAME_START_STOP 12

enum Directions
{
  UP = 0,
  DOWN = 1,
  LEFT = 2,
  RIGHT = 3
};

struct Positions
{
  int x;
  int y;
  int type;
 
};

LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

int x = 15;
int y = 1;
int matrix[2][16] = { {1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} };
struct Positions snakePositions[32];
String snakeHeads[4] = {"^", "_", "<", ">"};
String snakeBody = "*";
String appleBody = "@";
bool gameStarted = false;
struct Positions snakeData;

Directions snakeDirection = Directions::RIGHT;
int snakeLength = 2;
int snakeHeadPosition[2] = {2, 0};

int gameLoop = 0;
int framesPerSecond = 1;
int vectorX, vectorY;

void setup() {
  //PINS
  pinMode(PIN_GAME_START_STOP, INPUT_PULLUP);
  pinMode(PIN_UP,INPUT_PULLUP);
  pinMode(PIN_DOWN,INPUT_PULLUP);
  pinMode(PIN_LEFT,INPUT_PULLUP);
  pinMode(PIN_RIGHT,INPUT_PULLUP);
  
  Serial.begin(9600);
  
  //Set correct frames
  framesPerSecond *= 1000;
  
  lcd.clear();
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Snake game"); 
  lcd.setCursor(0, 1); 
  lcd.print("Press to start");
  
}

void loop() {
  if(digitalRead(PIN_UP) == LOW)
  {
    if(snakeDirection != Directions::DOWN)
    {
    snakeDirection = Directions::UP; 
    }
  }
  if(digitalRead(PIN_DOWN) == LOW)
  {
      if(snakeDirection != Directions::UP)
    {
      snakeDirection = Directions::DOWN;
    }
  }
    if(digitalRead(PIN_LEFT) == LOW)
  {
    if(snakeDirection != Directions::RIGHT)
    {
    snakeDirection = Directions::LEFT;
    }
  }
    if(digitalRead(PIN_RIGHT) == LOW)
  {
    if(snakeDirection != Directions::LEFT)
    {
    snakeDirection = Directions::RIGHT;
    }
  }
  setDirection();
  if(digitalRead(PIN_GAME_START_STOP) == LOW)
  {
    gameStarted = true;
    delay(100);
    if(gameStarted)
    {
      setSnakeAtBeginPosition();
    }
  }

  if(gameStarted && (gameLoop > framesPerSecond) )
  {
    gameLoop = 0;
    onLoop();
  }

  if(gameStarted){
    //Game loop
    delay(10);
    gameLoop += 10;
  }
}

void setSnakeAtBeginPosition()
{
    lcd.clear();
    lcd.setCursor(snakeHeadPosition[0], snakeHeadPosition[1]);
    lcd.print(snakeHeads[snakeDirection]);
    
    for(int i = 0; i < snakeLength; i++ )
    {
      lcd.setCursor(i, 0);
      lcd.print(snakeBody);
    }
    snakePositions[0].x = 2; 
    snakePositions[0].y = 0;
    snakePositions[0].type = 2;
    snakePositions[1].x = 1;
    snakePositions[1].y = 0;
    snakePositions[1].type = 1; 
    snakePositions[2].x = 0;
    snakePositions[2].y = 0;
    snakePositions[2].type = 1; 
    for(int i = 3; i < 32; i++)
    {
      snakePositions[i].x = 0;
      snakePositions[i].y = 0;
      snakePositions[i].type = 0;
    }
    setApple();
}

void setDirection()
{
  switch(snakeDirection)
  {
        case Directions::RIGHT:
    {
      vectorX = 1;
      vectorY = 0;
    }
    break;
        case Directions::LEFT:
    {
      vectorX = -1;
      vectorY = 0; 
    }
    break;
        case Directions::UP:
    {
      vectorX = 0;
      vectorY = -1;
    }
    break;
        case Directions::DOWN:
    {
      vectorX = 0;
      vectorY = 1;
    }
    break;
  }
}

void onLoop()
{
  bool useBufor = false;
  int bufor[2];

  if(snakeLength >= 31)
  {
    //END GAME
  }

  for(int i = 0; i <= x; i++)
  {
    for(int j = 0; j <= y; j++)
    {
      if(matrix[j][i] != 3){
        matrix[j][i] = 0;
      }
    }
  }
  
  for(int z = 0; z <= snakeLength; z++ )
  {
    if(!useBufor){
      bufor[0] = snakePositions[z].x;
      bufor[1] = snakePositions[z].y;
      int newX = snakePositions[z].x + vectorX;
      int newY = snakePositions[z].y + vectorY;
      newX = newX > x ? 0 : newX;
      newX = newX < 0 ? x : newX;
      newY = newY > y ? 0 : newY;
      newY = newY < 0 ? y : newY;
      if(newX == snakeData.x && newY == snakeData.y)
      {
        snakeLength++;
        setApple();
      }
      snakePositions[z].x = newX;
      snakePositions[z].y = newY;
      matrix[snakePositions[z].y][snakePositions[z].x] = snakePositions[z].type;
      useBufor = true;
    }else
    {
      int tempX = snakePositions[z].x;
      int tempY = snakePositions[z].y;
      snakePositions[z].x = bufor[0];
      snakePositions[z].y = bufor[1];
      matrix[snakePositions[z].y][snakePositions[z].x] = 1;
      bufor[0] = tempX;
      bufor[1] = tempY;
    }
  }
  draw();
}

void setApple()
{
   int x = random(0, 17);
  int y = random(0,2);
  while(matrix[y][x] == 0)
  {
    matrix[y][x] = 3;
    snakeData.x = x;
    snakeData.y = y;
    snakeData.type = 3;
  }
}

void draw()
{
  lcd.clear();
  for(int i = 0; i <= x; i++)
  {
    for(int j = 0; j <= y; j++)
    {
      if(matrix[j][i] == 1)
      {
        lcd.setCursor(i, j);
        lcd.print(snakeBody);
      }
      if(matrix[j][i] == 2)
      {
        lcd.setCursor(i, j);
        lcd.print(snakeHeads[snakeDirection]);
        snakeHeadPosition[0] = i;
        snakeHeadPosition[1] = j;
      }
      if(matrix[j][i] == 3)
      {
        lcd.setCursor(i, j);
        lcd.print(appleBody);
      }
    }
  }
}


Efekt: (polecam dać x2 prędkość)

Ogólnie jak tylko uporam się z tym projektem ze Snake’iem, mam już w głowie kilka innych pomysłów na wykorzystanie płytki. Ostatnio trochę wkręciłem się w gry o tematyce kasynowej i pomyślałem, że fajnie byłoby spróbować stworzyć coś w rodzaju prostego automatu (slot machine) na Arduino. Na razie nie mam jeszcze konkretnego pomysłu jak to sensownie zrealizować, ale obserwuję sobie różne mechaniki, które stosują współczesne platformy i może coś mnie zainspiruje. Wiadomo, że nie da się odwzorować wszystkich funkcji, jakie mają prawdziwe gry kasynowe, ale mimo wszystko ciekawi mnie, czy dałoby się stworzyć chociaż namiastkę tego klimatu w wersji na mikrokontrolerze. Ostatnio zauważyłem, że wiele współczesnych kasyn online pozwala zacząć grę od bardzo niskich kwot, typu 10 zł, i grając sam zwracam uwagę na takie szczegóły jak minimalny depozyt czy sposób rozpoczęcia rozgrywki. Dla tych, którzy też interesują się tą tematyką, https://plkasynaonline.com/platnosci/blik-10-zl/ może się okazać pomocnym przewodnikiem po polskich kasynach z możliwością gry od 10 zł depozytu. Z własnego doświadczenia mogę powiedzieć, że takie opisy naprawdę ułatwiają wejście do gry, zwłaszcza jeśli ktoś dopiero zaczyna korzystać z takich platform. Jak na mnie, to taka możliwość całkiem mocno wpływa na sam gameplay, bo nie trzeba od razu robić dużych wkładów, co sprawia, że rozgrywka staje się bardziej dostępna. Taka drobna rzecz, a może całkiem zmienić odbiór całego projektu. Może udałoby się to przełożyć na prosty mechanizm „wrzucenia” punktu lub żetonu, który odblokowuje możliwość uruchomienia gry czy losowania symboli. Nie musi to być nic skomplikowanego, ale fajnie byłoby pobawić się logiką i stworzyć coś, co nawiązuje do tej struktury, jaką znamy z prawdziwych slotów czy automatów.

 

Minęło już trochę czasu od założenia tego wątku, ale projekt wciąż wygląda bardzo ciekawie. Jestem ciekaw, czy udało się dopracować mechanikę gry i czy pojawiły się jakieś nowe funkcje, np. liczenie punktów, detekcja kolizji czy zwiększająca się trudność. Jeśli projekt był dalej rozwijany, chętnie zobaczyłbym finalną wersję albo krótkie demo działania na wyświetlaczu. Tego typu minimalistyczne gry mają swój klimat i fajnie pokazują możliwości mikrokontrolera w praktyce.

Edytowano przez laind

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...