وحدة التحكم روجلايك في C++

وحدة التحكم روجلايك في C++

مقدمة

"لينكس ليس للألعاب!" - عبارة قديمة: يوجد الآن العديد من الألعاب الرائعة المخصصة لهذا النظام الرائع. لكن مع ذلك، في بعض الأحيان تريد شيئًا خاصًا يناسبك... وقررت إنشاء هذا الشيء المميز.

مؤسسة

لن أعرض وأخبر الكود بالكامل (إنه ليس مثيرًا للاهتمام) - فقط النقاط الرئيسية.

1. الشخصية

تم إدراج جميع معلمات الشخصية هنا (الصحة، والدروع، والخبرة، وما إلى ذلك). ومن المثير للاهتمام رسم واتجاه الحركة (وهو غير متوفر حاليًا).

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 << "╬"; // сохранение позиции курсора
}

2. الإدارة

كيفية تحريك الشخصية واضحة بالفعل (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");

رائع! واحد بالمائة جاهز!

3. العالم من حولنا

نحن هنا نصنع مصفوفات لقطع 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);
    }
  }
}

4. التفاعل

نحن الآن بحاجة إلى تجنب المرور عبر الجدران والوحوش بطريقة أو بأخرى والحصول على مكافآت من العناصر.

مفضلاتنا هي لـ و #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. القائمة

نقوم ببساطة بعرض القائمة وترقيم العناصر واستخدام getkey() لمعالجة اختيار اللاعب. نكتب شريط حالة الشخصية، وننفذ قائمة التسوية، ونكتب الخلفية الدرامية، ونحصل على ما أسميه "Subsoil".

اختتام

هذا شيء من هذا القبيل. يمكنك تشغيله بعد التنزيل، التفريغ والتشغيل مثل هذا:

$ sudo chmod +x Subsoil-1.0/Subsoil

$ Subsoil-1.0/Subsoil

أو، أخيرًا، ألهمك، اكتب لنفسك مغامرة ترضيك. أحذرك مقدمًا: لعبتي ليست سهلة!

روابط

التوليد الإجرائي, مشجع.

المصدر: www.habr.com

إضافة تعليق