2013-08-10 4 views
0

Я кодирую NDS в C++ с помощью libnds, но этот вопрос не является спецификацией NDS. В настоящее время у меня есть текстовая игра, в которой на верхнем экране отображается логотип, и вы играете на нижнем экране.Добавление многопользовательской игры с несколькими экранами в C++

Итак, я хочу добавить тип мультиплеер с одним DS, в котором один игрок играет на верхнем экране, а другой внизу. У меня нет проблем с настройкой текстового движка на обоих экранах, мне просто нужно найти способ эффективного кодирования в мультиплеере. Ниже я написал сводную или упрощенную версию.

Примечание: consoleClear() очищает экран и единственное место, где останавливается игра, - это функция паузы.

//Headers 

void display(int x,int y,const char* output)) 
{ 
    printf("\x1b[%d;%dH%s", y, x,output); 
} 

void pause(KEYPAD_BITS key) //KEYPAD_BITS is an ENUM for a key on the NDS 
{ 
    scanKeys(); 
    while (keysHeld() & key) 
    { 
     scanKeys(); 
     swiWaitForVBlank(); 
    } 
    while (!(keysHeld() & key)) 
    { 
     scanKeys(); 
     swiWaitForVBlank(); 
    } 
    return; 
} 

void pause() //Only used to simplify coding 
{ 
    pause(KEY_A); 
    return; 
} 

int main(void) 
{ 
    //Initializations/Setup 
    while (1) 
    { 
     if (rand()%2==1) //Say Hello 
     { 
      if (rand()%3!=1) //To Friend (greater chance of friend than enemy) 
      { 
       display(6,7,"Hello Friend!"); 
       display(6,8,"Good greetings to you."); 
       pause(); 
       consoleClear(); //Clears text 
       display(6,7,"Would you like to come in?"); 
       pause(); 
       //Normally more complex complex code (such as interactions with inventories) would go here 
      } 
      else //To enemy 
      { 
       display(6,7,"Hello enemy!"); 
       display(6,8,"I hate you!"); 
       pause(); 
       consoleClear(); 
       display(6,7,"Leave my house right now!!!"); 
       pause(); 
      } 
     } 
     else //Say goodbye 
     { 
      if (rand()%4==1) //To Friend (lesser chance of friend than enemy) 
      { 
       display(6,7,"Goodbye Friend!"); 
       display(6,8,"Good wishes to you."); 
       pause(); 
       consoleClear(); 
       display(6,7,"I'll see you tomorrow."); 
       pause(); 
       consoleClear(); 
       display(6,7,"Wait, I forgot to give you this present."); 
       pause(); 
      } 
      else //To enemy 
      { 
       display(6,7,"Goodbye enemy!"); 
       display(6,8,"I hate you!"); 
       pause(); 
       consoleClear(); 
       display(6,7,"Never come back!!"); 
       pause(); 
       consoleClear(); 
       display(6,7,"Good riddance!"); //I think I spelt that wrong... 
       pause(); 
      } 
     } 
    } 
} 

Я знаю, что gotos запутывают и могут считаться дурной привычкой, но я не могу думать о лучшем способе. Моя версия интегрирующей мультиплеере:

//Headers and same functions 

int game(int location) 
{ 
    switch (location) 
    { 
    case 1: goto one; break; 
    case 2: goto two; break; 
    case 3: goto three; break; 
    case 4: goto four; break; 
    case 5: goto five; break; 
    case 6: goto six; break; 
    case 7: goto seven; break; 
    case 8: goto eight; break; 
    case 9: goto nine; break; 
    case 10: goto ten; break; 
    default: break; 
    } 

    if (rand()%2==1) //Say Hello 
    { 
     if (rand()%3!=1) //To Friend (greater chance of friend than enemy) 
     { 
      display(6,7,"Hello Friend!"); 
      display(6,8,"Good greetings to you."); 
      return 1; 
one:; 
      consoleClear(); //Clears text 
      display(6,7,"Would you like to come in?"); 
      return 2; 
two:; 
      //Normally more complex complex code (such as interactions with inventories) would go here 
     } 
     else //To enemy 
     { 
      display(6,7,"Hello enemy!"); 
      display(6,8,"I hate you!"); 
      return 3; 
three:; 
      consoleClear(); 
      display(6,7,"Leave my house right now!!!"); 
      return 4; 
four:; 
     } 
    } 
    else //Say goodbye 
    { 
     if (rand()%4==1) //To Friend (lesser chance of friend than enemy) 
     { 
      display(6,7,"Goodbye Friend!"); 
      display(6,8,"Good wishes to you."); 
      return 5; 
five:; 
      consoleClear(); 
      display(6,7,"I'll see you tomorrow."); 
      return 6; 
six:; 
      consoleClear(); 
      display(6,7,"Wait, I forgot to give you this present."); 
      return 7; 
seven:; 
     } 
     else //To enemy 
     { 
      display(6,7,"Goodbye enemy!"); 
      display(6,8,"I hate you!"); 
      return 8; 
eight:; 
      consoleClear(); 
      display(6,7,"Never come back!!"); 
      return 9; 
nine:; 
      consoleClear(); 
      display(6,7,"Good riddance!"); //I think I spelt that wrong... 
      return 10; 
ten:; 
     } 
     return -1; 
    } 
} 
int main(void) 
{ 
    //Initializations/Setup 
    int location1 = -1, location2 = -1; 
    location1 = game(location1); 
    location2 = game(location2); 
    while (1) 
    { 
     scanKeys(); //Whenever checking key state this must be called 
     if (keysDown() & KEY_A) //A key is used to continue for player1 
      location1 = game(location1); 
     if (keysDown() & KEY_DOWN) //Down key is used to continue for player2 
      location2 = game(location2); 
    } 
} 

Помимо этого способ является плохой практикой, в самом исходном коде, у меня есть сотни GOTOS мне нужно было бы добавить что было бы слишком много времени.

Любая помощь приветствуется. Если у кого-то есть вопрос или ответ, спросите/ответьте.

Редактировать: Хотя это не рекомендуется, я готов переписать игру с нуля, если у кого-то есть способ сделать это.

+0

Что касается с последовательно открывает, почему бы не поставить общие функции в функции, и вызывать их по мере необходимости? Как в случае? * и * в случае по умолчанию. –

+0

Что касается вашей проблемы с многопользовательским и разделенным экраном, эти вещи будут работать * намного лучше, если игра была разработана для этого с самого начала. Да, я предлагаю вам просто поцарапать свое текущее решение и начать с нового дизайна.Добавление таких вещей к уже работающему решению всегда окажется плохим, даже если оно работает. –

+0

@Joachim Pileborg: Конечно, я готов перепроектировать всю игру с нуля, просто я не могу даже подумать о том, как это сделать. Если бы я мог найти способ сделать это, тогда это ответит на мой вопрос. –

ответ

1

Использование условных операторов if-else для каждого случая - простое решение, которое приходит на ум первым.

Например:

int game(int i){ 
    if(i == 1){ 
    //first case code here. 
    } 
    else if(i == 2){ 
    //second case code here. 
    } 
    //.... 
    return 0; 
} 

Код в каждом случае можно даже поместить в других функциях, которые будут вызваны в зависимости от каждого условия. Этого, вероятно, будет достаточно для вашего дела.

Более гибкое решение (но гораздо более сложным) является доставки таблица. Идея состоит в том, чтобы иметь отдельные функции с каждой желаемой функциональностью и накладывать указатели на них в массиве. Затем вы можете вызвать их, индексируя таблицу, используя эти указатели на функции. Это может быть очень полезно, если у вас есть последовательность исполнений (вызовы функций), которые нужно выполнить, и вы хотите сделать это легко или хотите получить разные результаты в зависимости от вашего ввода, без изменения вашей программы.

Ниже приведен пример. Этот код также может использоваться в C, если вы замените std :: cout на printf и iostream с stdio библиотека.

#include <iostream> 

using namespace std; 

// Arrays start from 0. 
// This is used for code 
// readability reasons. 
#define CASE(X) X-1 

typedef void (*chooseCase)(); 

// Functions to execute each case. 
// Here, I am just printing 
// different strings. 
void case1(){ 
    cout<< "case1" << endl; 
} 

void case2(){ 
    cout<< "case2" << endl; 
} 

void case3(){ 
    cout<< "case3" << endl; 
} 

void case4(){ 
    cout<< "case4" << endl; 
} 

//Put all the cases in an array. 
chooseCase cases[] = { 
    case1, case2, case3, case4 
}; 

int main() 
{ 
    //You can call each scenario 
    //by hand easily this way: 
    cases[CASE(1)](); 
    cout << endl; 

    //Idea: You can even set in another 
    // array a sequence of function executions desired. 
    int casesSequence[] = { 
     CASE(1), CASE(2), CASE(3), CASE(4),CASE(3),CASE(2),CASE(1) 
    }; 
    //Execute the functions in the sequence set. 
    for(int i = 0; i < (sizeof(casesSequence)/sizeof(int)); ++i){ 
     cases[casesSequence[i]](); 
    } 

    return 0; 
} 

Это будет печатать на выходе:

case1 

case1 
case2 
case3 
case4 
case3 
case2 
case1 
+0

Я не знаю, почему я не думал о первом :). И для тех, кто еще смотрит на этот пост, простое изменение команд if .. else if в оператор switch, как я сделал выше с gotos. –