gpt4 book ai didi

java - 如何在java游戏中分离 View 和模型?

转载 作者:行者123 更新时间:2023-12-01 18:32:36 24 4
gpt4 key购买 nike

我正在使用 MVC 设计模式(使用 Swing)在 Java 中制作游戏,但我不知道如何将 Controller 类与 View 类分开。

到目前为止,我有一个包含所有数据的模型,一个负责所有逻辑的 Controller ,现在我考虑如何分离 View 。

我有 GameView,它扩展了 Jpanel 并有一个paintComonent:

@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
draw(g2D);

}


public void draw(Graphics2D g2D){
drawComponent(background, g2D);
drawComponent(arenaController.getArena().getPlane(), g2D);
drawComponent(arenaController.getArena().getPlayer().getBoat(), g2D);

ArrayList<PlaneDrop> planeDrops = arenaController.getArena().getPlaneDrops();
for(PlaneDrop planeDrop : planeDrops){
drawComponent(planeDrop, g2D);
}
g2D.drawString("Life: " + arenaController.getArena().getPlayer().getLife(), 10, 30);
g2D.drawString("Score: " + arenaController.getArena().getPlayer().getScore(), GAME_WIDTH - 50, 30);
}

但另一方面,我有负责配置和运行的 GameEngine
@Override
public void run() {
arenaController.init();
long waitTime = 0;

Graphics g = this.getGraphics();
gameViewer.paintComponent(g);

while(arenaController.isRunning()){
long startTime = System.currentTimeMillis();

gameViewer.paintComponent(g);
update(); // update game
gameViewer.repaint();
long endTime = System.currentTimeMillis() - startTime;
waitTime = (MILLISECOND / FPS) - endTime / MILLISECOND;

try{
Thread.sleep(waitTime);
} catch (Exception e){}

}
}

引擎中的 run() 方法调用 View 的 paintComponent() 方法(对我来说这听起来像 Controller --> 调用查看器)但我发现这不是最好的方法,不建议这样做直接调用paintComponent()。

所以我想要 Controller 和 View 的清晰分离,但我很难找到合适的方法来做到这一点。

最佳答案

好的,所以你遇到了一系列问题。

第一的

Swing 已经是一个 MVC

第二

今天教授和讨论的“MVC”形式实际上并不是MVC的初衷。它被认为更多的是指导方针或建议,而不是稳定的规则或范式。

问题是,你最终会得到坚持所有模型、 Controller 和 View 绝对分离的“纯粹主义者”,在某些情况下,这会损害 API 或解决方案(当你最终遇到“大规模 View Controller ”问题时) )。

为什么?考虑一个按钮。它是一个 View ,它有一个模型,它可以充当 Controller 。

您不需要单独的“ Controller ”来控制按钮。它可以向底层系统注册它需要监控的键盘和鼠标操作。它可以协调模型和自身( View )之间的变化,它成为一个独立的工作单元。

说真的,你能想象每次创建按钮或任何其他 UI 组件时都必须创建一个单独的 Controller ......😱😓

当您将按钮添加到另一个容器( View )时,该按钮将充当它自己的 View / Controller 。然后父容器可能有一个更大的模型和一些它正在“控制”或协调的 subview 。

容器也可以通过一个外部 Controller 来控制,该 Controller 用于协调容器和大模型之间的变化,允许它被解耦,但在这种情况下,我会将它设计成这样,以便实现逻辑被解耦,因此外部 Controller 不关心“如何”完成的事情,只是有一个契约(Contract)允许这些层之间的信息传递。

那么,有什么意义呢?

不要执着于试图产生一个“干净的”MVC,尤其是在 Swing 中,你会听得一头雾水。

还要记住,您可以让一个 Controller 与另一个 Controller 对话,这允许它在子 Controller 不需要或想要父 Controller 可能可用的所有信息的地方传播信息。它还允许它控制截然不同的 Controller ,从而实现更大的元素解耦和良好的即插即用方法。

那么,这对您有何帮助?

这应该为您提供一些可以跳出的地方。

如果您不想要 GameEngine要直接与 View 对话,您可以建立一个“渲染” Controller 。谁负责协调游戏引擎对模型与底层 View 所做的更改(即,安排渲染 channel )。

这将允许 GameEngine “控制”一个或多个“渲染” Controller ,并允许将底层渲染的实际完成方式与 GameEngine 分开。

您可以这样做,因为 Controller 可以负责其他 Controller - 它只是模型和下一层(通常是 View )之间的协调器

在这个例子中,你可以简单地通过改变“渲染” Controller 的实现来改变渲染系统(如果你使用 interface s,这将变得更简单)而不影响 GameEngie。 ,归根结底,这就是遵循这种设计的好处——通过解耦实现责任分离。

传递思想...

  • 永远不要调用paintComponent直接地。 protected 是有原因的
  • 不要使用 getGraphics .这不是在 Swing 中完成自定义绘制的方式。 getGraphics充其量只是 Swing 最后一次油漆传球的快照。请记住,在 Swing 中,您不控制绘制过程,这是由您负责的,相反,您安排绘制 channel (即 repaint )并让系统负责重置
  • 如果您想要/需要控制绘画过程,那么您需要使用 java.awt.CanvasBufferStrategy反而。
  • 关于java - 如何在java游戏中分离 View 和模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60131137/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com