在不冻结 UI 线程的情况下实现游戏循环的最佳方法

2023-11-22

我正在尝试用 Java 制作一个简单的 2D 游戏。

到目前为止我有一个JFrame,带有一个菜单栏,以及一个扩展的类JPanel并覆盖它paint方法。现在,我需要开始一个游戏循环,我将在其中更新图像的位置等。然而,我一直在思考如何最好地实现这一目标。我应该使用多线程吗?因为如果你在主线程上放置无限循环,UI(以及我的菜单栏)肯定会冻结?

到目前为止,这是我的代码:

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JPanel;

@SuppressWarnings("serial")
public class GameCanvas extends JPanel {

    public void paint(Graphics g) {
        while (true) {
            g.setColor(Color.DARK_GRAY);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

@SuppressWarnings("serial")
public class Main extends JFrame {

    GameCanvas canvas = new GameCanvas();
    final int FRAME_HEIGHT = 400;
    final int FRAME_WIDTH = 400;

    public static void main(String args[]) {
        new Main();
    }

    public Main() {
        super("Game");

        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenuItem startMenuItem = new JMenuItem("Pause");
        menuBar.add(fileMenu);
        fileMenu.add(startMenuItem);

        super.add(canvas);
        super.setVisible(true);
        super.setSize(FRAME_WIDTH, FRAME_WIDTH);
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        super.setJMenuBar(menuBar);
    }
}

有什么指示或技巧吗?我应该把我的循环放在哪里?在我的主类中,还是在我的 GameCanvas 类中?


您的游戏循环(模型)不应位于任何 GUI 类(视图)附近。它使用您的 GUI 类——但即使您可能想通过中介(控制器)来完成。确保正确执行的一个好方法是检查您的模型是否没有单个“include javax.swing.???”。

你能做的最好的事情就是让游戏循环保持在它自己的线程中。每当您想在 GUI 中进行更改时,请使用 SwingWorker 或小孩子现在使用的任何东西将其强制到 GUI 线程上以执行该操作。

这实际上很棒,因为它让您思考 GUI 操作(这将构成您的控制器)。例如,您可能有一个名为“Move”的类,其中包含移动背后的 GUI 逻辑。您的游戏循环可能会使用正确的值(要移动的项目、最终位置)实例化“移动”,并将其传递给 GUI 循环进行处理。

一旦达到这一点,您就会意识到,只需为每个 GUI 操作添加一个简单的“撤消”即可轻松撤消任意数量的操作。您还会发现用 Web GUI 替换 Swing GUI 更容易...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在不冻结 UI 线程的情况下实现游戏循环的最佳方法 的相关文章

随机推荐

  • 更改 Makefile 标志时如何强制重新编译?

    我正在编译一些具有依赖关系的项目 因此我不必每次都重新编译 但是当我将 Dsome flags 添加到 CFLAGS 时 它不会重新编译 dep CPPS CC CFLAGS INC M CPPS gt dep 我添加到我的 CFLAS D
  • 有没有办法参数化cloudformation资源名称?

    我正在尝试使云形成模板上的 AutoScalingGroup 名称动态化 我在想这是否可以通过参数或其他方式实现 DynamicASGName Type AWS AutoScaling AutoScalingGroup Properties
  • gfortran 找不到那里的库

    我在将程序链接到库时遇到问题 我以前从未这样做过 所以我可能做了一些愚蠢的事情 但据我所知 我正在做正确的事情 我需要链接我的程序foo f90去图书馆libbar a它位于我的主目录下的其他目录中 我输入命令 gfortran c foo
  • 连接 String 和 Int 以形成文件名前缀

    我正在使用 PowerShell 为目录中的多个文件创建重命名脚本 这里有两个问题 我有一个字符串变量 strPrefix ACV 100 和一个整数计数器 intInc 000001我希望增加计数器 intInc1 gt 2 然后将两者连
  • 用于地理数据项目的数据可视化工具[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我对数据可视化的整个想法还很陌生 所以我希望人们能为我指明有效工具的方向 以解决我遇到的问题 我有很多数字数据 它们是计数 这些数据与具有两个字母的
  • 使用 jackson json 将属性添加到 json 字符串

    我将 json 字符串存储到 mysql 的文本字段中 插入后 我想更新我的 json 字符串并使用 jackson json 将 mysql 行 id 添加到其中 我有一个 Json 格式的 java 字符串 thing val 我希望在
  • 如何配置 Wildfly 来提供静态内容(如图像)?

    我有一个在 Wildfly 8 0 0 Final 上运行的 JavaEE 应用程序 该应用程序使用了很多图像 我不想将它们存储在数据库中 因此它们被写入硬盘 例如 如何配置 Wildfly Undertow 以便在某个 URL 上提供这些
  • 如何将 svg 画布保存到本地文件系统

    有没有办法允许用户在使用浏览器在 javascript svg 画布上创建矢量图之后 将此文件下载到本地文件系统 SVG 对我来说是一个全新的领域 所以如果我的措辞不准确 请耐心等待 您可以避免往返服务器 对 SVG xml 进行 Base
  • 使用显式构造函数返回不可复制的不可移动对象

    如果我们有一个具有非显式构造函数的不可移动 不可复制的类 我们可以返回它并按如下方式使用 在 C 11 中 include
  • 如何阻止div换行?

    我用CSS定义了一个div height 100 width 360px float left 现在 我有一个按钮可以动态地将这些 div 添加到正文中 问题是 当浏览器窗口太多而无法容纳时 它们会将下一个 div 放置在其他 div 的下
  • 如何使用sql获取上个月的第一天和最后一天

    我想获取上个月的第一天 如 01 01 2013 我也想获取上个月的最后一天 如 01 31 2013 如果我们是在三月 那么我想做同样的事情 比如 02 01 2013 和 02 28 2013 等等 谢谢 这应该可以做到 First d
  • 无法从程序集中加载类型“ADODB.FieldsToInternalFieldsMarshaler”

    我有以下代码 MAPITable mt rStores MAPITable Recordset rs new Recordset rs mt ExecSQL SELECT EntryID http schemas microsoft com
  • 为什么在 0.13.7 中执行调试会失败并显示“无法在库路径上找到代理库 jdwp:transport”?

    更新后从0 13 6 to 0 13 7我无法调试SBT 它是使用安装的Homebrew 我尝试重新安装它 brew doctor什么也没显示 我没有更改 重新安装Java之间SBT update lgr sbt v jvm debug 5
  • 如何在Android中追踪消息?

    我想开发一个跟踪发送 接收短信的应用程序 我的意思是 当用户从其设备发送消息时 消息详细信息应保存到我提供的表中 同样 当设备收到任何短信时 也应该将其保存到我提供的表格中 注意用户使用Android默认的消息应用程序发送消息 我的意思是我
  • 如何修复 gradle 构建错误 配置根项目时出现问题?

    每次我尝试构建一个项目时都会发生这种情况 Android studio 版本 3 4 Gradle 同步在配置构建时失败 由于某种原因 它无法从 url 获取资源 但我可以从浏览器下载该文件 Caused by org gradle api
  • 如何在 Spring MVC 应用程序中插入 TCP-IP 客户端服务器

    我想知道是否可以在 spring mvc 应用程序和使用 TCP IP 连接的遗留系统之间插入双向连接 如前所述 遗留系统使用 TCP ip 而不是 http 因此无需谈论 HTTP 更好 谢谢 See 弹簧集成 您可以使用消息传递网关将
  • 文件系统如何处理并发读/写?

    用户A请求系统读取文件foo同时用户 B 希望将他或她的数据保存到同一个文件中 在文件系统级别如何处理这种情况 大多数文件系统 但不是全部 使用锁定来保护对同一文件的并发访问 锁可以是独占的 因此第一个获得锁的用户可以获得访问权限 后续用户
  • 将文本(单个字母)附加到文本文件中每行的末尾

    以下是我正在使用的文本文件的示例 437868313 2436413 Wyatt Trenton 08 21 2003 211000010262002 211000010262002 2014 01 54435A000 510 Social
  • 将表更改迁移到生产 sailsjs 表的最佳方法

    我刚刚从数据库中丢失了 11 000 条记录 只是运行 sailsjs 命令 其中没有 prod 部分 所以我想我应该问当 Model js 更改时更改生产服务器上的表的最佳方法是什么 Thanks 永远不应该在生产中进行自动迁移 这是一种
  • 在不冻结 UI 线程的情况下实现游戏循环的最佳方法

    我正在尝试用 Java 制作一个简单的 2D 游戏 到目前为止我有一个JFrame 带有一个菜单栏 以及一个扩展的类JPanel并覆盖它paint方法 现在 我需要开始一个游戏循环 我将在其中更新图像的位置等 然而 我一直在思考如何最好地实