Konsolen-Roguelike in C++

Konsolen-Roguelike in C++

Einführung

„Linux ist nicht für Spiele!“ – dieser veraltete Satz gilt nicht mehr: Es gibt inzwischen viele großartige Spiele, die speziell für dieses wunderbare System entwickelt wurden. Manchmal möchte man jedoch etwas Besonderes, das genau zu einem passt… Daher habe ich beschlossen, dieses Besondere zu schaffen.

Basis

Ich werde den gesamten Code nicht zeigen und erläutern (das ist nicht besonders spannend) – nur die wesentlichen Punkte.

1. Charakter

Hier sind alle Parameter des Charakters aufgelistet (Gesundheit, Rüstung, Erfahrung usw.). Besonders interessant sind die Grafik und die Bewegungsrichtung (die zurzeit fehlt).

int x = 5, y = 5;
    hp = 100,
    maxhp = 100,
    dm    = 20,
    armor = 0,
    xp    = 0,
    level = 0,
    diff  = 10, // Schwierigkeit
    pos   = 0; // Richtung

bool reg = 0,
       Mdm = 0, // Boni
       ght = 0;

string color; // Die Farbe wird als Indikator für den Zustand des Helden verwendet

void hero() // Hier erfolgt die Bewegung des Helden zu den Koordinaten (x ; y)
{
  cout << "e[u " << "e[0;0H"; // Wiederherstellung der Cursorposition, Überschreibung mit Leerzeichen
  for (int i = 0; i <= x; i++)
    cout << RIGHT;              // Makro "e[1C"
  for (int i = 0; i <= y; i++)
    cout << DOWN;             // Makro "e[1B"
  cout << "e[s" << color << "╬"; // Speichern der Cursorposition
}

2. Steuerung

Wie man den Charakter bewegt, ist klar (x—++, y—++). Die Verarbeitung der Tastatur ist jedoch interessanter.

char key;
char getkey()
{
  system("stty raw");
  key = getchar();
  system("stty cooked");
  return key;
}

Jetzt müssen wir nur noch die "Steuerelemente" festlegen. Das kann man mit einem switch machen, aber ich mag ihn nicht.

switch(...) case .. : ... ; break Besser so

#define KEY if (key ==
#define I ){
#define J ;}else

void keys()
{
  getkey();
    KEY 'a' I x-- ; pos = 1 J
    KEY......
}

Wunderschön! Wir kapseln die Funktionen und bewegen uns über den Bildschirm! Aber es ist etwas ruckartig… Der Cursor blitzt und die Buchstaben… Das müssen wir verbessern!

//До цикла
  cout << "e[?25l"; //отключаем отображение курсора
  system("stty -echo"); //отключаем эхо-ввод
  system("xset r rate 120 10"); // изменяем задержку на более плавную
//После цикла
//-------Return_normal_system_settings--------
  cout << "e[00m";
  system("reset");
  system("xset r rate 200 20");

Huch! Ein Prozent ist geschafft!

3. Die Umgebung

Hier erstellen wir Arrays für x, y Stücke der Welt und die Stücke selbst (char o[N]), dasselbe für Monster und Boni.

Wir erstellen eine Funktion world(int objx[N] .... objy[N] ... obj[N], ... objcolor[N]) analog zu hero(), aber mit Parametern und einer zusätzlichen Schleife zum Ausgeben des Arrays… zum Spaß zeichnen wir nur im Sichtfeld (vis) (if (ox[k] < vis && oy[k]....))

Jetzt füllen wir den Bildschirm mit den Teilen der Welt durch eine einfache For-Schleife und bauen die Räume und Durchgänge prozedural aus, während wir gleichzeitig Feinde und Gegenstände einfügen. Um vollständige Zufälligkeit zu gewährleisten, vergessen wir nicht srand(time(NULL));

//------------------GENERATION---------------
void rooms()
{
  for (int i = 0; i <= 50; i++)
  {
    px[i] = rand() % 115 + 2;
    py[i] = rand() % 34 + 2;
    pl[i] = rand() % 5 + 5;
    ph[i] = rand() % 5 +  5;

    if (px[i] + pl[i] > 117) px[i] = 50 - pl[i] / 2; else
    if (px[i] < 2)           px[i] = 50 - pl[i] / 2; else
    if (py[i] < 1)           py[i] = 15 - ph[i] / 2; else
    if (py[i] + ph[i] > 37)  py[i] = 15 - ph[i] / 2;

    for (int j = 0; j <= i; j++)
    {
      while (px[i] > px[j] && px[i] < px[j] + pl[j])
        (px[i]+pl[i]/2 >= 55) ? px[i]++ : px[i]-- ;

      while (py[i] > py[j] && py[i] < py[j] + ph[j])
        (py[i]+ph[i]/2 >= 18) ? py[i]++ : py[i]-- ;

      while (px[i]+pl[i] > px[j] && px[i]+pl[i] < px[j] + pl[j])
        (px[i]+pl[i]/2 >= 55) ? px[i]++ : px[i]-- ;

      while (py[i]+ph[i] > py[j] && py[i]+ph[i] < py[j] + ph[j])
        (py[i]+ph[i]/2 >= 18) ? py[i]++ : py[i]-- ;
    }

    for (int j = 0; j <= i; j++)
    {
      while (px[j] + pl[j] >= 116) px[j]-- ;
      while (px[j] < 2)            px[j]++ ;
      while (py[j] < 1)            py[j]++ ;
      while (py[j] + ph[j] >= 37)  py[j]-- ;
    }
    tx[i] = px[i]+10; ty[i] = py[i]-3;

    if (i <= diff)
    {
      ex[i]  = px[i];
      ey[i]  = py[i];
      while (ex[i] < 10){ ex[i]++ ; epos[i] = 3 ;}
      while (ey[i] < 10){ ey[i]++ ; epos[i] = 1 ;}
      e[i]   = evar[pl[i]];
      ecolor[i] = "e[00me[31m";

      edm[i] = edmvar[pl[i]];
      ehp[i] = ehpvar[pl[i]];
      exp[i] = expvar[pl[i]];
    }
    rect(px[i], py[i], pl[i], ph[i]);
  }
}

void corrs()
{
  int pc, px, py;
  for (int i = 0; i <= 4; i++)
  {
    if (i < 2){
      px = 3;
      py = rand() % 33 + 3;
      pc = 110;
      line(px, py, pc, true);
      line(px, py+1, pc, true);
    } else {
      px = rand() % 100 + 3;
      py = 3;
      pc = 33;
      line(px, py, pc, false);
      line(px+1, py, pc, false);
    }
  }
}

4. Interaktion

Jetzt müssen wir aufpassen, nicht durch Wände und Monster zu gehen und Boni von Gegenständen zu bekommen.

Unsere geliebten for und #define

#define TOUCH if (x == ox[i] && y == oy[i] && pos ==
#define HIT   x == ex[i] && y == ey[i] && pos ==
 for (int i = 0; i <= n; i++)
  {
    if (i <= diff)
    {
     if (Mdm) ehp[i]-=2 ; // если бонус "массовый урон" включен
     epos[i] = 0;

     if (ex[i] < x+5 && ex[i] > x-5 &&
         ey[i] < y+5 && ey[i] > y-5  )
     {
       edel(i); // функция переписывающая предыдущее положение противника
       if (ex[i] < x I ex[i]++ ; epos[i] = 1 J
       if (ex[i] > x I ex[i]-- ; epos[i] = 2 J
       if (ey[i] < y I ey[i]++ ; epos[i] = 3 J
       if (ey[i] > y I ey[i]-- ; epos[i] = 4 ;}
     }
   for (int j = 0; j <= n; j++) // столкновение моба со стенками
       while (ex[i] == ox[j] && ey[i] == oy[j] || ex[i] == ex[j] && ey[i] == ey[j] && j != i)
       {
         if (epos[i] == 1) ex[i]-- ; else
         if (epos[i] == 2) ex[i]++ ; else
         if (epos[i] == 3) ey[i]-- ; else
         if (epos[i] == 4) ey[i]++ ;
       }

     if (x == ex[i] && y == ey[i]) //  "битва"
      {
       if (ehp[i] > 1)
       {
         ehp[i] -= dm;
         (edm[i] < armor) ?
         hp -= 0 :
         hp -= edm[i]-armor;
       } else {
         ex[i] = ey[i] = -1;
         xp += exp[i];
         ehp[i] = 12;
       }
     }
     if (!ght) // если не призрак проверять столкновение игрока с врагами
     {
       if (HIT 1) y++ ;else
       if (HIT 2) x-- ;else
       if (HIT 3) y-- ;else
       if (HIT 4) x++ ;
     }
    }
    if (!ght) // то же, но со стенами
    {
      TOUCH 1 I y++ J
      TOUCH 2 I x-- J
      TOUCH 3 I y-- J
      TOUCH 4 ) x++ ;
    }
  }

5. Menü

Das Menü wird einfach angezeigt, indem wir die Punkte nummerieren und mit getkey() die Auswahl des Spielers verarbeiten. Wir erstellen die Statusleiste des Charakters, implementieren das Level-Up-Menü, verfassen die Hintergrundgeschichte und erhalten das, was ich „Subsoil“ genannt habe.

Fazit

So etwas. Sie können es spielen, indem Sie es herunterladen, entpacken und so starten:

$ sudo chmod +x Subsoil-1.0/Subsoil

$ Subsoil-1.0/Subsoil

, oder letztendlich inspiriert, Ihr eigenes Abenteuer nach Ihrem Geschmack schreiben. Ich warne im Voraus: Mein Spiel ist nicht einfach!

Links

Prozedurale Generierung, Inspiration.

Quelle: habr.com

Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server 🔥 Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster