【问题标题】:Adding split-screen multiplayer to c++ game将分屏多人游戏添加到 C++ 游戏
【发布时间】:2013-08-13 06:38:48
【问题描述】:

我正在使用 libnds 为 C++ 中的 NDS 编码,但这个问题不是 NDS 特定的。我目前有一个基于文本的游戏,其中顶部屏幕只显示一个徽标,而您在底部屏幕上玩。

所以我想添加一种单人 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();
            }
        }
    }
}

我知道 goto 令人困惑,可能被认为是一种坏习惯,但我想不出更好的方法。我的集成多人版本:

//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);
    }
}

除了这种方法是一种不好的做法之外,在实际的源代码中,我需要添加数百个 goto,这太耗时了。

感谢任何帮助。如果有人有任何问题或答案,请询问/回复。

编辑:虽然不喜欢这样做,但如果有人有方法,我愿意从头开始重写游戏。

【问题讨论】:

  • 关于goto,为什么不把常用功能放在函数中,在需要的时候调用呢?就像案件一样? 和在默认情况下。
  • 关于你的多人游戏和分屏问题,如果游戏从一开始就是为这个而设计的,这些东西会好多更好地工作。是的,我建议您简单地从头开始现有的解决方案并从新设计重新开始。将这些东西添加到已经有效的解决方案中总是会变得很糟糕,即使它有效。
  • @Joachim Pileborg:当然,我愿意从头开始重新设计整个游戏,只是我想不出办法。如果我能找到一种方法来做到这一点,那么它就会回答我的问题。

标签: c++ multiplayer goto devkitpro


【解决方案1】:

对每种情况使用 if-else 条件语句是一个最简单的解决方案。

例如:

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

甚至可以将每种情况下的代码放入将根据每个条件调用的其他函数中。 对于您的情况,这可能就足够了。

更灵活的解决方案(但复杂得多)是调度表。 这个想法是为每个所需的功能提供单独的函数,并将它们的指针放在一个数组中。然后,您可以使用这些函数指针通过索引表来调用它们。如果您要完成一系列执行(函数调用)并且希望轻松完成,或者希望在不更改程序的情况下根据输入获得不同的结果,这将非常有用。

下面有一个例子。 如果您将 std::cout 替换为 printf 并将 iostream 替换为 stdio 库,则此代码也可以在 C 中使用。

#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

【讨论】:

  • 我不知道为什么我没有想到第一个:)。对于其他查看这篇文章的人,只需将 if.. else if 语句更改为 switch 语句,就像我在上面使用 goto 所做的那样。
猜你喜欢
  • 1970-01-01
  • 2019-08-05
  • 1970-01-01
  • 2019-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多