کنسول roguelike در C++

کنسول roguelike در C++

معرفی

«لینوکس برای بازی نیست!» یک عبارت قدیمی است: اکنون بازی‌های فوق‌العاده‌ی زیادی وجود دارند که به‌طور خاص برای این سیستم فوق‌العاده طراحی شده‌اند. اما گاهی اوقات، شما چیزی خاص می‌خواهید، چیزی که دقیقاً مناسب شما باشد... و من تصمیم گرفتم آن چیز خاص را خلق کنم.

پایه

من تمام کد را به شما نشان نمی‌دهم و نمی‌گویم (خیلی جالب نیست) - فقط نکات اصلی را.

۱. شخصیت

تمام پارامترهای شخصیت (سلامتی، زره، تجربه و غیره) در اینجا فهرست شده‌اند. نکته جالب، طراحی و جهت حرکت (که در حال حاضر وجود ندارد) است.

int x = 5, y = 5;
    hp = 100,
    maxhp = 100,
    dm    = 20,
    armor = 0,
    xp    = 0,
    level = 0,
    diff  = 10, // сложность
    pos   = 0; // направление

bool reg = 0,
       Mdm = 0, // бонусы
       ght = 0;

string color; // цвет будет использован в качестве индикатора состаяния героя

void hero()  // здесь происходит перемещение героя на координаты (x ; y)
{
  cout << "e[u " << "e[0;0H"; // восстановление позиции курсора, затирание пробелом
  for (int i = 0; i <= x; i++)
    cout << RIGHT;              // макрос "e[1C"
  for (int i = 0; i <= y; i++)
    cout << DOWN;             // макрос "e[1B"
  cout << "e[s" << color << "╬"; // сохранение позиции курсора
}

۲. مدیریت

نحوه‌ی حرکت دادن یک کاراکتر از قبل مشخص است (x-++، y-++). اما نحوه‌ی کار با کیبورد جالب‌تر است:

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

تنها کاری که باقی مانده تنظیم «کاراکترهای کنترلی» است. این کار را می‌توان با سوئیچ انجام داد، اما من از آن متنفرم.

switch(...) case .. : ... ; break اینجوری بهتره.

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

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

عالیه! ما داریم توابع رو دور می‌زنیم و صفحه رو اسکرول می‌کنیم! اما یه کم نامنظمه... مکان‌نما مدام سوسو می‌زنه، حروف هم همینطور... این مشکل رو حل خواهیم کرد!

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

اووووه! یه درصد آماده‌ای!

۳. دنیای اطراف ما

در اینجا ما آرایه‌هایی برای x و y قطعه از جهان و خود قطعات می‌سازیم. (char o[N])، برای هیولاها و پاداش‌ها هم همینطور.

ایجاد یک تابع world(int objx[N] .... objy[N] ... obj[N], ... objcolor[N]) به قیاس با hero()، اما با پارامترها و یک حلقه اضافی برای خروجی آرایه... برای سرگرمی، ما فقط در میدان دید (vis) رسم می‌کنیم (if (ox[k] < vis && oy[k]....))

حالا ما صفحه را با ذرات جهان با استفاده از یک روش ساده برای پر کردن و خالی کردن اتاق‌ها و معابر به صورت رویه ای پر می‌کنیم، در عین حال دشمنان و اشیاء را وارد می‌کنیم، برای تصادفی بودن کامل، فراموش نمی‌کنیم 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);
    }
  }
}

۴. تعامل

حالا باید به نحوی از عبور از دیوارها و هیولاها اجتناب کنیم و از آیتم‌ها امتیاز بگیریم.

موارد مورد علاقه ما for و #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++ ;
    }
  }

۵. منو

ما به سادگی منو را روی صفحه نمایش می‌دهیم، آیتم‌ها را شماره‌گذاری می‌کنیم و انتخاب بازیکن را با استفاده از getkey() پردازش می‌کنیم. ما یک نوار وضعیت شخصیت می‌نویسیم، یک منوی سطح‌بندی پیاده‌سازی می‌کنیم، یک پیش‌زمینه می‌نویسیم و در نهایت چیزی که من آن را «خاک زیرین» نامیده‌ام، حاصل می‌شود.

نتیجه

این چیزی شبیه به این است. می‌توانید آن را بازی کنید، بارگیری، آن را از حالت فشرده خارج کرده و به این صورت اجرا می‌کنیم:

$ sudo chmod +x Subsoil-1.0/Subsoil

$ Subsoil-1.0/Subsoil

یا، در نهایت الهام گرفتید، برای خودتان یک ماجراجویی به دلخواهتان بنویسید. توجه داشته باشید: بازی من آسان نیست!

لینک‌ها

تولید رویه ای, الهام‌بخش.

منبع: www.habr.com

اضافه کردن نظر