java 回合制游戏设计:事件驱动与游戏循环
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17869353/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Turn-based Game Design: Event-Driven vs. Game Loop
提问by nairware
I am creating my first game in Java. The game is Monopoly. I am struggling with how I should design the game to model its turn-based structure (managing player turns). I want to allow for both a single human-controlled and one or multiple AI-controlled players to play the game.
我正在用 Java 创建我的第一个游戏。游戏是大富翁。我正在为如何设计游戏以模拟其回合制结构(管理玩家回合)而苦苦挣扎。我希望允许单个人类控制和一个或多个 AI 控制的玩家玩游戏。
My specific issue is that I do not know whether to implement a game loop or not, meaning a loop which can manage the players and the variables directly related to the game of Monopoly, (think of things such as prompting each player for their turn, incrementing the turn to the next player, or getting dice rolls from each player—in turn). I am not referring to the more low-level meaning of the term “game loop” which relates more to drawing frames on the screen, updating physics, or updating AI at a specific rate of time.
我的具体问题是我不知道是否要实现游戏循环,这意味着可以管理玩家和与大富翁游戏直接相关的变量的循环,(想想诸如提示每个玩家轮到他们,增加到下一个玩家的回合,或从每个玩家那里依次掷骰子)。我指的不是“游戏循环”一词的更底层含义,它更多地与在屏幕上绘制帧、更新物理或以特定时间速率更新 AI 相关。
My understanding is that my options for trying to implement what I need are either to:
我的理解是,我尝试实现我需要的选择是:
- Implement a completely event-driven program which has no such game loop, or
- Implement a game loop—something that is long-running in the background and basically never-ending as long as the game is running. This would be the more procedural approach.
- 实现一个完全由事件驱动的程序,它没有这样的游戏循环,或者
- 实现一个游戏循环——在后台长时间运行的东西,只要游戏在运行,基本上就永无止境。这将是更程序化的方法。
When I first started trying to solve this issue, I ran into problems of my UI freezing because my game loop was never-ending and was completely consuming the thread on which it was running (I just made a very simple while loop to illustrate this). So I went to the effort of creating a SwingWorker
to encapsulate my game loop. That solved the issue of UI freezes, but still left me wondering if I was going down the wrong path.
当我第一次开始尝试解决这个问题时,我遇到了 UI 冻结的问题,因为我的游戏循环永无止境并且完全消耗了运行它的线程(我只是做了一个非常简单的 while 循环来说明这一点) . 所以我努力创建一个SwingWorker
来封装我的游戏循环。这解决了 UI 冻结的问题,但仍然让我怀疑我是否走错了路。
As a general rule, I found that most advice on the web generally seems to favor any approach which is event-driven, and thus my current implementation utilizing a SwingWorker
could be a step in the wrong direction. But I cannot fully grasp how I would implement a completely event-driven system for this specific task (meaning no game loop present). It seems to me that a loop has to exist somewhere for managing the player turns.
作为一般规则,我发现网络上的大多数建议通常似乎支持任何事件驱动的方法,因此我当前使用 a 的实现SwingWorker
可能是朝着错误方向迈出的一步。但是我无法完全理解如何为这个特定任务实现一个完全事件驱动的系统(意味着不存在游戏循环)。在我看来,必须在某处存在一个循环来管理玩家回合。
Here are my specific questions:
以下是我的具体问题:
- Are game loops (as I am describing them) appropriate for turn-based games such as Monopoly—specifically for queuing the player turns and prompting the appropriate player for their turn, one player at a time (and queuing the entire procedure of/sequence of steps that comprise a turn)?
- If a purely event-driven system were to be created for managing player turns, how do you iterate through each player to prompt them for their turn and keep iterating until the game ends?
- If a game loop were to be used to solve the specific problem described above, does it have to be run within its own thread (possibly using
SwingWorker
) in order to avoid freezing the UI? My situation is Java-specific, but I suppose I would be interested in answers for non-Java-specific situations as well.
- 游戏循环(正如我所描述的)是否适用于回合制游戏,例如大富翁——特别是用于将玩家的回合排队并提示合适的玩家轮到他们,一次一个玩家(并将整个过程/顺序排队)?包含转弯的步骤)?
- 如果要创建一个纯粹的事件驱动系统来管理玩家轮次,您如何遍历每个玩家以提示他们轮到他们并保持迭代直到游戏结束?
- 如果要使用游戏循环来解决上述特定问题,它是否必须在自己的线程中运行(可能使用
SwingWorker
)以避免冻结 UI?我的情况是特定于 Java 的,但我想我也会对非特定于 Java 的情况的答案感兴趣。
Currently, I have my code organized using the MVC pattern. My controller is where my game loop (the actual SwingWorker
thread) resides. It is far from complete, but it helps illustrate how I am managing player turns in what I am calling a "game loop".
目前,我使用 MVC 模式组织了我的代码。我的控制器是我的游戏循环(实际SwingWorker
线程)所在的地方。它远未完成,但它有助于说明我如何在我所谓的“游戏循环”中管理玩家回合。
SwingWorker
code from controller:
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();
采纳答案by Luke
The comment from SirDarius is spot on.
SirDarius 的评论是正确的。
Though, for something as simple as advancing player turns, you don't really need to bother implementing a full fledged finite state machine.
不过,对于像推进玩家回合这样简单的事情,您真的不需要费心去实现一个成熟的有限状态机。
In terms of MVC, this is what you should do for humanplayers:
就MVC而言,这就是你应该为人类玩家做的事情:
The Model:Provide methods for advancing the active player to the next player and for running through the "turn process" (i.e. rolling the dice, moving the active player's token, etc.). Because much of the turn process is event driven, these method calls will be made from event listeners in the controller.
The View:Raise an event when the active player finishes their turn, as well as raising events on various other input.
The Controller:Whenever a player finishes their turn, tell the model to advance to the next player, and start the "turn process" again. Whenever a player provides input, an event will be fired that tells the model to advance to the next stage of the turn.
模型:提供将活跃玩家推进到下一个玩家和运行“回合过程”(即掷骰子、移动活跃玩家的令牌等)的方法。由于大部分转弯过程是事件驱动的,因此这些方法调用将由控制器中的事件侦听器进行。
视图:当活跃玩家完成他们的回合时引发一个事件,以及在各种其他输入上引发事件。
控制器:每当一个玩家完成他们的回合时,告诉模型前进到下一个玩家,并再次开始“回合过程”。每当玩家提供输入时,都会触发一个事件,告诉模型前进到回合的下一阶段。
For AIplayers, the majority of the same code can be used, but it does not make sense to have the turn progression be driven by the view. Instead, the model would need to have another "turn process" method which would be specifically for AI players. The only difference being that the code would execute in succession without waiting for input from the view, instead of being a series of event listeners.
对于AI玩家,可以使用大部分相同的代码,但是让视图驱动回合进程是没有意义的。相反,该模型需要有另一种专门针对 AI 玩家的“回合流程”方法。唯一的区别是代码将连续执行而无需等待来自视图的输入,而不是一系列事件侦听器。