Roguelike console en C++

Roguelike console en C++

Introduction

«Linux n'est pas pour les jeux !» — une phrase désuète : il existe maintenant de nombreux jeux formidables spécialement conçus pour ce système étonnant. Pourtant, parfois, on désire quelque chose de particulier, qui te conviendrait… J'ai donc décidé de créer ce quelque chose de spécial.

Base

Je ne vais pas montrer et expliquer tout le code (ce n'est pas très intéressant) — juste les points principaux.

1.Personnage

Tous les paramètres du personnage sont énumérés ici (santé, armure, expérience, etc.), l'accent étant mis sur le rendu et la direction du mouvement (qui est actuellement manquant).

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

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

string color; // la couleur sera utilisée comme indicateur de l'état du héros

void hero() // ici se déplace le héros vers les coordonnées (x ; y)
{
  cout << "e[u " << "e[0;0H"; // restauration de la position du curseur, effacement par un espace
  for (int i = 0; i <= x; i++)
    cout << RIGHT;              // macro "e[1C"
  for (int i = 0; i <= y; i++)
    cout << DOWN;             // macro "e[1B"
  cout << "e[s" << color << "╬"; // sauvegarde de la position du curseur
}

2.Gestion

Comment déplacer le personnage est assez clair (x—++, y—++). Mais le traitement du clavier est plus intéressant :

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

Il ne reste plus qu'à définir les « symboles de contrôle ». On peut le faire avec un switch, mais je le déteste.

switch(...) case .. : ... ; break mieux comme ça

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

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

Magnifique ! Bouclons les fonctions et parcourons l'écran ! Mais c'est un peu brusque… Le curseur clignote et les lettres… Corrigeons ça !

//До цикла
  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");

Ouf ! Un pour cent est prêt !

3.Le monde environnant

Ici, nous faisons des tableaux pour x, y des morceaux du monde et les morceaux eux-mêmes. (char o[N]), même pour les monstres et les bonus.

Créons une fonction world(int objx[N] .... objy[N] ... obj[N], ... objcolor[N]) par analogie avec hero(), mais avec des paramètres et une boucle supplémentaire pour afficher le tableau… pour l'intérêt, dessinons uniquement dans le champ de vision (vis) (if (ox[k] < vis && oy[k]....))

Nous remplissons actuellement l'écran avec des morceaux du monde à l'aide d'un simple for et sculptons procéduralement des salles et des couloirs, tout en intégrant des ennemis et des objets, pour un maximum de randomisation n'oublions pas 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.Interaction

Il nous faut maintenant éviter de traverser les murs et les monstres, recevoir des bonus des objets.

Nos bien-aimés for et #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.Menu

Nous affichons simplement le menu à l'écran en numérotant les éléments, en utilisant getkey() pour traiter le choix du joueur. Nous écrivons la barre de statut du personnage, mettons en œuvre le menu de progression, rédigeons l'histoire et obtenons ce que j'appelle «Subsoil» («Sous-sol»).

Conclusion

C'est quelque chose. Vous pouvez y jouer, en téléchargeant, décompressant et en lançant de cette manière :

$ sudo chmod +x Subsoil-1.0/Subsoil

$ Subsoil-1.0/Subsoil

, ou enfin, inspiré, écrire votre propre aventure selon vos goûts. Je vous préviens à l'avance : mon jeu n'est pas facile !

Liens

Génération procédurale, Inspiration.

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster