13

我正在用 Java 创建我的第一个游戏。游戏是大富翁。我正在努力设计游戏以模拟其基于回合的结构(管理玩家回合)。我想允许一个人控制的玩家和一个或多个人工智能控制的玩家玩游戏。

我的具体问题是我不知道是否实现游戏循环,即可以管理玩家和与大富翁游戏直接相关的变量的循环,(想想诸如提示每个玩家轮到他们的事情,增加轮到下一个玩家,或者从每个玩家那里得到骰子——依次)。我并不是指“游戏循环”一词的更底层含义,它更多地涉及在屏幕上绘制帧、更新物理或以特定时间速率更新 AI。

我的理解是,我尝试实现我需要的选择是:

  1. 实现一个完全由事件驱动的程序,它没有这样的游戏循环,或者
  2. 实现一个游戏循环——在后台长时间运行并且只要游戏运行就基本上永无止境的东西。这将是更程序化的方法。

当我第一次开始尝试解决这个问题时,我遇到了 UI 冻结的问题,因为我的游戏循环永无止境并且完全消耗了它正在运行的线程(我只是做了一个非常简单的 while 循环来说明这一点) . 所以我努力创建一个SwingWorker来封装我的游戏循环。这解决了 UI 冻结的问题,但仍然让我想知道我是否走错了路。

作为一般规则,我发现网络上的大多数建议似乎都倾向于任何事件驱动的方法,因此我当前使用 a 的实现SwingWorker可能是朝着错误方向迈出的一步。但我无法完全掌握如何为这个特定任务实现一个完全事件驱动的系统(意味着不存在游戏循环)。在我看来,必须在某个地方存在一个循环来管理玩家回合。

以下是我的具体问题:

  1. 游戏循环(正如我所描述的那样)是否适用于诸如大富翁之类的回合制游戏 - 特别是用于排队玩家转弯并提示合适的玩家轮到他们,一次一个玩家(并排队整个过程/序列包括转弯的步骤)?
  2. 如果要创建一个纯粹的事件驱动系统来管理玩家回合,你如何迭代每个玩家以提示他们轮到他们并继续迭代直到游戏结束?
  3. 如果要使用游戏循环来解决上述特定问题,它是否必须在自己的线程中运行(可能使用SwingWorker)以避免冻结 UI?我的情况是特定于 Java 的,但我想我也会对非 Java 特定情况的答案感兴趣。

目前,我使用 MVC 模式组织了我的代码。我的控制器是我的游戏循环(实际SwingWorker线程)所在的位置。它远未完成,但它有助于说明我如何在我所谓的“游戏循环”中管理玩家回合。

SwingWorker来自控制器的代码:

swingWorker = new SwingWorker<Void, Model>() {
@Override
protected Void doInBackground() throws InterruptedException {
gameLoopRunning = true;
while (gameLoopRunning) {

    //to do: use a timer instead of thread.sleep
    Thread.sleep(1000);

    //user turn prompt
    if (model.getActivePlayer().isUserControlled()) {

        boolean userRolled = false;
        while(!userRolled) {
            System.out.println("Roll the dice please...");
            Thread.sleep(3000);
        }

    }
    //bot turn prompt
    else {
        //insert code for bot rolling dice here
        model.rollDice();
    }

    publish(model);

    Thread.sleep(1000);
    model.incrementPlayerTurn();
    publish(model);

}
return null;
}

@Override
protected void process(List<Model> chunks) {
Model gameModel = chunks.get(chunks.size() - 1);
//hard-coded for 6 players
for (int i = 0; i < 6; i++) {
    view.getPlayerPanel(i).setTurn(gameModel.getPlayers().get(i).isTurn());
}
view.getGamePanel().getDice().setDie1(model.getDie1());
view.getGamePanel().getDice().setDie2(model.getDie2());
}

};
swingWorker.execute();
4

1 回答 1

11

SirDarius 的评论很到位。

不过,对于像推进玩家回合这样简单的事情,您实际上并不需要费心去实现一个完整的有限状态机。

就 MVC 而言,这是你应该为人类玩家做的:

  • 模型:提供将活动玩家推进到下一个玩家并通过“转轮过程”(即掷骰子、移动活动玩家的标记等)的方法。因为大部分转向过程是事件驱动的,所以这些方法调用将由控制器中的事件侦听器进行。

  • 视图:当活跃玩家完成他们的回合时引发事件,以及在各种其他输入上引发事件。

  • 控制器:每当一个玩家完成他们的回合,告诉模型前进到下一个玩家,并再次开始“回合过程”。每当玩家提供输入时,都会触发一个事件,告诉模型前进到回合的下一阶段。

对于AI玩家,可以使用大部分相同的代码,但让转弯进程由视图驱动是没有意义的。相反,该模型需要有另一种专门针对 AI 玩家的“转向过程”方法。唯一的区别是代码将连续执行而无需等待来自视图的输入,而不是成为一系列事件侦听器。

于 2013-07-25T22:58:33.977 回答