java 您如何组织游戏代码以适应 MVC 模式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/555283/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 12:50:49  来源:igfitidea点击:

How can you organize the code for a game to fit the MVC pattern?

javaoopdesign-patternsmodel-view-controller

提问by Ricket

I'm a freshman in college going for my computer science degree... I've programmed plenty the last several years but just lately I've been getting more into theoretical ideas about organizing code, design patterns, differences in languages, etc.

我是一名大学新生,正在攻读计算机科学学位......过去几年我已经编写了很多程序,但最近我对组织代码、设计模式、语言差异等的理论思想有了更多的了解。

I have a Java class, so I've dropped my C++ research/development and moved into Java and JOGL (Java OpenGL). It's wonderful! But that's beside the point.

我有一个 Java 课程,所以我放弃了我的 C++ 研究/开发,转向了 Java 和 JOGL(Java OpenGL)。太棒了!但这不是重点。

I want to make a small role-playing game, but this question really applies to any sort of game. How do you organize the game objects in a way that is structured, like the Model-View-Controller pattern? It looks to be an amazing pattern, very widely used and makes a lot of sense, but I'm having trouble figuring out how to implement it.

我想制作一个小型角色扮演游戏,但这个问题确实适用于任何类型的游戏。你如何以一种结构化的方式组织游戏对象,比如模型-视图-控制器模式?它看起来是一个了不起的模式,使用非常广泛并且很有意义,但是我在弄清楚如何实现它时遇到了麻烦。

For instance, I need to keep track of a GL object for drawing to the screen. I have to have classes that implement MouseListener, MouseMotionListener, MouseWheelListener, and KeyListener (or one class, an all-in-one input manager). And I have to put my game data somewhere where all these different classes can access and modify it; if someone presses a button on the keyboard, the input managing class needs to somehow perform the action that the key is mapped to; when a frame needs to be drawn, the graphics class needs to find a way to loop through all the different 'things' and draw them all.

例如,我需要跟踪一个用于绘制到屏幕的 GL 对象。我必须有实现 MouseListener、MouseMotionListener、MouseWheelListener 和 KeyListener 的类(或一个类,一个多合一的输入管理器)。我必须把我的游戏数据放在所有这些不同的类都可以访问和修改的地方;如果有人按下键盘上的按钮,输入管理类需要以某种方式执行该键映射到的操作;当需要绘制框架时,图形类需要找到一种方法来遍历所有不同的“事物”并将它们全部绘制出来。

And my biggest issue, the GUI; where does it tie into it all? It's something like the input, but not quite, and it needs to both set and get pieces of data from the actual game simulation... And complicating it even MORE is if I decide to try and add networking, which (similar to the GUI) also needs to have access to a lot of the data for modifying and reading...

还有我最大的问题,GUI;它与这一切有什么关系?它有点像输入,但不完全是,它需要从实际游戏模拟中设置和获取数据片段......如果我决定尝试添加网络,则更复杂的是(类似于 GUI ) 还需要访问大量的数据进行修改和读取...

Oh, I'm just all confused. I don't know how to make all this work together in an object-oriented fashion... It's easy enough writing things that clearly fit the patterns, but when you have tons of things happening all tied to one game loop, modifying each other and the game data and so on, ... I don't even know any more. Maybe I'm just making this a bigger deal than it actually is.

哦,我只是一头雾水。我不知道如何以面向对象的方式让所有这些一起工作......编写清晰符合模式的东西很容易,但是当你有大量的事情发生都与一个游戏循环相关联时,相互修改还有游戏数据等等,……我都不知道了。也许我只是想让这比实际情况更重要。

Has anyone else felt this way? Please offer some clarity to my situation so I can spend less time worrying and not knowing where to start!

有没有其他人有这种感觉?请清楚说明我的情况,这样我就可以减少担心和不知道从哪里开始的时间!

Edit: Found a nice diagram that might help me figure this all out... Source: (beware, PS file!) http://www.tucs.fi/publications/attachment.php?fname=TR553.ps.gz

编辑:找到了一个很好的图表,可以帮助我弄清楚这一切......来源:(当心,PS 文件!)http://www.tucs.fi/publications/attachment.php?fname=TR553.ps.gz

Edit2: I also like this guy's explanation of how he planned his MVC game: http://interactivesection.wordpress.com/2007/11/19/dum-de-dum-drum-my-first-mvc-game-development/

Edit2:我也喜欢这个人对他如何规划 MVC 游戏的解释:http: //interactivesection.wordpress.com/2007/11/19/dum-de-dum-drum-my-first-mvc-game-development/

Edit3: Another great article! http://dewitters.koonsolo.com/gamemvc.html

Edit3:又一篇很棒的文章! http://dewitters.koonsolo.com/gamemvc.html

采纳答案by John Munsch

It might help you to think of the Model as a kind of game API. What would your game be reduced to if there were no UI at all for the game ordained from the beginning? You mention that what you have in mind is an RPG, so in this case you can imagine having the player character, his/her inventory, spells, abilities, NPCs, and even things like the map and combat rules all being part of the model. It is like the rules and pieces of Monopoly without the specifics of how the final game displays that or how the user is going to interact with it. It is like Quake as an abstract set of 3D objects moving through a level with things like intersection and collision calculated but no rendering, shadows, or sound effects.

将模型视为一种游戏 API 可能会有所帮助。如果从一开始就注定的游戏根本没有用户界面,你的游戏会变成什么?你提到你想到的是 RPG,所以在这种情况下,你可以想象让玩家角色、他/她的物品栏、法术、能力、NPC,甚至地图和战斗规则等都成为模型的一部分. 这就像大富翁的规则和部分,没有关于最终游戏如何显示或用户将如何与之交互的细节。它就像 Quake 是一组抽象的 3D 对象,它们在一个关卡中移动,计算了交叉和碰撞等内容,但没有渲染、阴影或声音效果。

By putting all of those into the model the game itself is now UI agnostic. It could be hooked to an ASCII text interface like Rogue games have, or a command line UI akin to Zork, or a web based, or 3D UI. Some of those UIs might be a terrible fit depending upon the game mechanics, but they would all be possible.

通过将所有这些都放入模型中,游戏本身现在是 UI 不可知的。它可以连接到像 Rogue 游戏那样的 ASCII 文本界面,或类似于 Zork 的命令行 UI,或基于 Web 或 3D 的 UI。根据游戏机制的不同,其中一些 UI 可能非常不合适,但它们都是可能的。

The View layer is the UI dependent layer. It reflects the specific choice of UI you went with and will be very much dedicated to that technology. It might be responsible for reading the state of the model and drawing it in 3D, ASCII, or images and HTML for a web page. It is also responsible for displaying any control mechanisms the player needs to use to interact with the game.

View层是UI依赖层。它反映了您使用的 UI 的特定选择,并将非常专注于该技术。它可能负责读取模型的状态并以 3D、ASCII 或图像和 HTML 为网页绘制它。它还负责显示玩家需要用来与游戏交互的任何控制机制。

The Controller layer is the glue between the two. It should never have any of the actual game logic in it, nor should it be responsible for driving the View layer. Instead it should translate actions taken in the View layer (clicking on buttons, clicking on areas of the screen, joystick actions, whatever) into actions taken on the model. For example, dropping an item, attacking an NPC, whatever. It is also responsible for gathering up data and doing any conversion or processing to make it easier for the View layer to display it.

Controller层是两者之间的粘合剂。它不应该包含任何实际的游戏逻辑,也不应该负责驱动 View 层。相反,它应该将 View 层中执行的操作(单击按钮、单击屏幕区域、操纵杆操作等)转换为对模型执行的操作。例如,掉落物品、攻击 NPC 等等。它还负责收集数据并进行任何转换或处理,以使 View 层更容易显示它。

Now, the way I've described it above is as though there is a very distinct event sequence driving the game that is probably only really appropriate for a web game. That's because that's what I've spent my time on lately. In a game which is not driven by a user's request and a server's response like the web (e.g. a game running on the user's machine) you would probably want to make sure that the Model layer implemented the Observer pattern well. For example, if actions take place in the Model because time is passing then you might not want to have the View layer constantly polling the Model for updates. Instead by using the Observer pattern the Model could notify any observers of changes to Model objects as they happen. That could in turn be used to prompt immediate update to the View to reflect the change.

现在,我在上面描述的方式好像有一个非常独特的事件序列驱动游戏,它可能只真正适合网络游戏。那是因为这就是我最近花费的时间。在一个不受用户请求和服务器响应(如网络)驱动的游戏中(例如在用户机器上运行的游戏),您可能希望确保模型层很好地实现了观察者模式。例如,如果由于时间流逝而在模型中发生操作,那么您可能不希望视图层不断轮询模型以获取更新。相反,通过使用观察者模式,模型可以在模型对象发生变化时通知任何观察者。反过来,这可以用于提示立即更新视图以反映更改。

Then if 60 seconds passing resulted in some repairs happening for the player's base, the base could effect the repairs and immediately notify any Observers attached to it that the base has updated. The View could be attached as an Observer and note that it needs to re-display the base because its state has changed. The notification itself might have included enough information to update the View or it might have to turn around and consult the model in order to update, but the result will be the same.

然后,如果 60 秒过去了导致玩家基地发生了一些维修,基地可能会影响维修并立即通知任何附属于它的观察者基地已经更新。View 可以作为 Observer 附加,并注意它需要重新显示基础,因为它的状态已经改变。通知本身可能包含足够的信息来更新视图,或者它可能必须转身并咨询模型以进行更新,但结果将是相同的。

回答by Charlie Martin

You're getting along there. basically, ask yourself the question "which code would change if I had to change some part of the program?"

你在那里相处得很好。基本上,问自己一个问题“如果我必须更改程序的某些部分,哪些代码会更改?”

If it would change the way it looks without changing basic data, then it's in the view. If it is data that could be viewed in many ways, it's the model. And if it's how you play, then it's the control.

如果它会在不改变基本数据的情况下改变它的外观,那么它就在视图中。如果是可以通过多种方式查看的数据,那就是模型。如果这是你的比赛方式,那就是控制。

So if it's whether you draw an "axe" with two blades or one, it's view. If it's how many hit points damage you inflict with an axe, it's model. And if it's whether you swing the axe by typing "s" or by right clicking, it's control.

因此,如果是用两把刀片或一个刀片绘制“斧头”,那就是视图。如果是你用斧头造成多少生命值伤害,那就是模型。如果是通过键入“s”还是通过右键单击来挥动斧头,那就是控制。

回答by Erik Engheim

I feel with you I remember when I first discovered MVC I tried to cram everything into it. I did indeed make a game that utilized MVC pattern. What I have found later though was that what I did was overkill. I tried to fit pretty much every single class I made into one category in MVC.

我记得当我第一次发现 MVC 时,我试图把所有东西都塞进去。我确实制作了一个使用 MVC 模式的游戏。后来我发现我所做的太过分了。我试图将我创建的几乎每一个类都归入 MVC 中的一个类别。

What I suggest is to read "Design Patterns" by the gang of four. There are a lot of useful patterns besides MVC. Sometimes it doesn't make any sense to use MVC at all. Especially for games I am not sure if MVC is such a good idea. The reason being that you don't want to display a game object in many different ways (views), but you want to reuse a drawing code for many different types of game objects.

我的建议是阅读四人组的“设计模式”。除了 MVC 之外,还有很多有用的模式。有时使用 MVC 根本没有任何意义。特别是对于游戏,我不确定 MVC 是否是一个好主意。原因是您不想以多种不同的方式(视图)显示游戏对象,但您希望为许多不同类型的游戏对象重用绘图代码。

For my own 2D game engine I used the strategypattern quite actively. The game objects, like the player and the monsters I called a Sprite. I let the drawing of the sprite be handled by a strategy pattern. That is when I called sprite.draw()I would do something like this:

对于我自己的 2D 游戏引擎,我非常积极地使用了策略模式。游戏对象,比如玩家和我称之为Sprite的怪物。我让精灵的绘制由策略模式处理。那是当我调用sprite.draw() 时我会做这样的事情:

class Sprite {
  void draw() {
    this.view.draw(this.currentPosition, this.currentOrientation);
  }

  Point  currentPosition;    // Current position of this sprite
  double currentOrientation; // Facing angle of sprite
};

The benefit of this approach is that you can share a view object between several sprites. Because typically there will be a lot of e.g. monsters which will look the same but which will be a different positions and possibly behave different.

这种方法的好处是您可以在多个精灵之间共享一个视图对象。因为通常会有很多例如看起来相同但位置不同并且行为可能不同的怪物。

So behavior I would also use a strategy pattern which would be a object which contains code describing behavior. That way I can apply the same behavior to several monsters at different location. So each frame I would call an update()function to update position orientation and what monster does.

所以行为我也会使用一个策略模式,它是一个包含描述行为的代码的对象。这样我就可以对不同位置的几个怪物应用相同的行为。所以每一帧我都会调用一个update()函数来更新位置方向和怪物的作用。

class Sprite {
  void setUpdateAction(Action action) {
    this.updateAction = action;
  }

  void update(double start_time, double delta_time)
  {
    this.prevPosition = position();  
    advance(delta_time); // Advance to next position based on current speed and orientation

    this.updateAction.execute(this, start_time, delta_time);
  }

  Action updateAction;
};

There are loads of variations of this. In my current implementation I have even separated out currentPosition, speed, orientationand advance()into a separate object called MotionState. This is so I can build a search trees of possible positions and orientations when doing path searching algorithms. Then I don't want to carry with me information about how to behave each update or how sprite should be drawn.

这有很多变化。在我当前的实现中,我什至将currentPositionspeedorientationadvance()分离到一个名为MotionState的单独对象中。这样我就可以在执行路径搜索算法时构建可能位置和方向的搜索树。然后我不想随身携带有关如何执行每次更新或应如何绘制精灵的信息。

回答by Dave Swersky

The MVC concept of centralizing user interaction logic is a good model for game development.

MVC 集中用户交互逻辑的概念是游戏开发的一个很好的模型。

I've done a little work with Flash game development. Hereis an article about object pools in Flash. The concept is cross-platform and may give you some ideas.

我在 Flash 游戏开发方面做了一些工作。 是一篇关于 Flash 中对象池的文章。这个概念是跨平台的,可能会给你一些想法。

You're right to be concerned with all the stuff going on at one time. Depending on your game design, your game loop can have a lot to deal with. This is where you'll learn all the dirty optimization tricks, often the hard way :)

你对一次发生的所有事情都感到担忧是对的。根据您的游戏设计,您的游戏循环可能需要处理很多。在这里您将学习所有肮脏的优化技巧,通常是艰难的方式:)

There are many ways to organize your code- one option might be to write a GameManager class as a Singleton. All game objects tie back to it for management and user interaction. The GameManager handles all user input and dispatches messages to its object pool. You can use interfaces to define common communication patterns between game objects and the GameManager.

有很多方法可以组织您的代码 - 一种选择可能是将 GameManager 类编写为单例。所有游戏对象都与它联系起来进行管理和用户交互。GameManager 处理所有用户输入并将消息分派到其对象池。您可以使用接口来定义游戏对象和 GameManager 之间的通用通信模式。

As far as performance optimization goes, threading is very powerful. Asynchronous operation can ensure that you're not wasting those precious cycles.

就性能优化而言,线程非常强大。异步操作可以确保您不会浪费那些宝贵的周期。

回答by Rocket Surgeon

All of your listeners and handlers need to go inside the Controller class, state of the objects on screen (e.g. position, color, etc.) should be a part of your Model classes and whatever code that is drawing things on screen will be part of the View.

您所有的侦听器和处理程序都需要进入 Controller 类,屏幕上对象的状态(例如位置、颜色等)应该是 Model 类的一部分,并且在屏幕上绘制事物的任何代码都将是其中的一部分风景。

回答by Euan M

My way of thinking of MVC is as MDUC
Model
Display
User-input Controller

我对 MVC 的看法是作为 MDUC
模型
显示
用户输入控制器

The model contains the domain model objects
The display shows the current state and behaviour of the domain model objects on-screen.
The user-input controller handles all the user inputs.

模型包含领域模型对象
显示器在屏幕上显示领域模型对象的当前状态和行为。
用户输入控制器处理所有用户输入。

It's exactly the same pattern, but the names are just ever so slightly more descriptive, so I find what responsibilities each part of the pattern has is clearer, and so the meaning of the pattern is more memorable.

这是完全相同的模式,但名称只是稍微更具描述性,因此我发现模式的每个部分的职责更清晰,因此模式的含义更令人难忘。

Once you see that you are splitting data and model operations from displaying, from the user's inputs, it's easier to see where to group what in your own code.

一旦您看到您正在从显示中分离数据和模型操作,从用户的输入中,就可以更轻松地查看在您自己的代码中将内容分组的位置。