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");

우와! XNUMX%가 준비되었습니다!

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.상호작용

이제 우리는 어떻게든 벽과 몬스터를 통과하지 않고 아이템으로부터 보너스를 받아야 합니다.

우리가 가장 좋아하는 것은 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++ ;
    }
  }

5.메뉴

우리는 단순히 메뉴를 표시하고 항목에 번호를 매기고 getkey()를 사용하여 플레이어의 선택을 처리합니다. 캐릭터의 상태 표시줄을 작성하고, 레벨링 메뉴를 구현하고, 배경 스토리를 작성하면 소위 "하층토"라는 결과가 나옵니다.

결론

이것은 이런 것입니다. 당신은 그것을 재생할 수 있습니다 다운로드한, 압축을 풀고 다음과 같이 실행합니다.

$ sudo chmod +x Subsoil-1.0/Subsoil

$ Subsoil-1.0/Subsoil

, 또는 마침내 영감을 받아 자신이 좋아하는 모험을 직접 작성하십시오. 미리 경고합니다. 내 게임은 쉽지 않습니다!

연결

절차적 생성, 격려자.

출처 : habr.com

코멘트를 추가