回合制游戏设计:事件驱动与游戏循环

时间:2013-07-25 21:46:58

标签: java events swingworker event-driven-design

我正在用Java创建我的第一个游戏。这场比赛是垄断。我正在努力设计游戏以模拟其回合制结构(管理玩家转弯)。我想允许一个人控和一个或多个AI控制的玩家玩这个游戏。

我的具体问题是我不知道是否实施游戏循环,这意味着可以管理玩家的循环以及与大富翁游戏直接相关的变量,(想想诸如提示每个玩家的轮到他们,转向下一个玩家,或者从每个玩家那里获得骰子。我并不是指“游戏循环”一词的更低级含义,它更多地涉及屏幕上的绘图框架,更新物理或以特定的时间更新AI。

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

  1. 实施完全由事件驱动的程序,该程序没有这样的游戏循环,或
  2. 实现一个游戏循环 - 在后台长时间运行并且只要游戏正在运行就基本上永无止境。这将是更具程序性的方法。
  3. 当我第一次尝试解决这个问题时,我遇到了我的UI冻结问题,因为我的游戏循环永无止境,并且完全消耗了它运行的线程(我只是做了一个非常简单的while循环到说明这一点)。所以我开始创建一个SwingWorker来封装我的游戏循环。这解决了UI冻结的问题,但仍然让我想知道我是否走错了路。

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

    以下是我的具体问题:

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

1 个答案:

答案 0 :(得分:9)

SirDarius的评论很有见。

尽管如此,对于像推进玩家转弯一样简单的事情,你并不需要费心去实现一个完整的有限状态机。

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

  • 模型:提供将活跃玩家推进到下一个玩家并运行&#34;转弯过程的方法&#34; (即掷骰子,移动现役玩家的代币等)。由于大部分转弯过程都是事件驱动的,因此这些方法调用将来自控制器中的事件侦听器。

  • 视图:当活动玩家完成转弯时提升一个事件,并在各种其他输入上引发事件。

  • 控制器:每当玩家完成转弯时,告诉模特前进到下一位玩家,然后开始&#34;转弯过程&#34;再次。每当玩家提供输入时,将触发一个事件,告诉模型前进到转弯的下一阶段。

对于 AI 玩家,可以使用大多数相同的代码,但是通过视图驱动转弯进度没有意义。相反,该模型需要另一个&#34;转弯过程&#34;专门针对AI玩家的方法。唯一的区别是代码将在不等待视图输入的情况下连续执行,而不是一系列事件侦听器。