java 和 libGDX / LWJGL 游戏全屏尺寸错误,适用于 Ubuntu 上的多个显示器

Posted

技术标签:

【中文标题】java 和 libGDX / LWJGL 游戏全屏尺寸错误,适用于 Ubuntu 上的多个显示器【英文标题】:java and libGDX / LWJGL game fullscreen wrong size for multiple monitors on Ubuntu 【发布时间】:2013-05-03 09:33:26 【问题描述】:

我正在开发一个 libGDX(LWJGL 之上的库)游戏项目,并从几个不同的工作站使用 Intellij IDEA IDE:

Windows 7 x64 笔记本电脑,带两个显示器(1920x1080 和 1600x1200),nVidia GT540M。 Ubuntu 12.04 LTS 在配备单显示器 (1366x768)、英特尔集成显卡的笔记本电脑上运行。 Ubuntu 12.04 LTS 在具有两个显示器(1920x1080 和 1280x1024)、nVidia GTS 450 的桌面上。

我在 Ubuntu 机器上使用 OpenJDK for Java 6,在 Windows 机器上使用 Sun/Oracle Java 6(我听说 Java 6 是为了与 android 兼容而使用的)。

全屏运行时:

Windows 7 笔记本电脑:工作正常。 Ubuntu 笔记本电脑:工作正常。 Ubuntu 桌面:背景图片放大显示,只有一部分适合屏幕。 +

进一步研究,我看到对 Gdx.graphics.getHeight() 和 Gdx.graphics.getWidth() 的调用返回了覆盖两个显示器所需的矩形大小,在我的例子中是 3200x1080,但是当我告诉我的游戏要全屏运行,它只使用其中一个显示器,所以相机设置为 1920x1080,但我的相机移动和平铺地图平移认为他们有 3200x1080 可以使用,这使得事情扭曲和无法使用(因为角色可以从屏幕向右走)。

我猜我的问题实际上来自 awt.Toolkit 的 getScreenSize() 调用返回的尺寸,但我不知道如何更深入地询问它以获取它实际使用的屏幕尺寸去全屏。

我的 DesktopStarter 获取屏幕大小并设置全屏如下:

    LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
    Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
    cfg.width = screenDimension.width;
    cfg.height = screenDimension.height;
    cfg.fullscreen = true;
    new LwjglApplication(new Game1(), cfg);

是否有解决方法来获得“全屏”实际启动的显示器的高度/宽度?​​

所以我看到的问题是执行 game.jar 文件,退出游戏,然后再次重复执行,导致 Gdx.graphics.getDisplayModes 返回的模式列表中显示不同的显示模式( ) -- 作为 PT下面指出,这是 LWJGL 的Display.getAvailableDisplayModes() 的一个薄包装。为什么会这样?为什么在 Ubuntu 的后续运行中会出现一组不同的模式?

编辑:根据 P.T. 的建议,将 LWJGL 引用置于问题之中,因为提供显示模式列表的似乎是 LWJGL。

谢谢!

【问题讨论】:

Gdx.graphics.getDisplayModes() 是否返回更一致的有用结果? (有点鸡和蛋,因为你必须先初始化 libgdx 才能查询它。) @P.T.谢谢!虽然不是直接有用,因为它只是返回所有支持的显示模式的列表,大概是由 JRE 与硬件的接口报告的。我使用了这个提示,并在我的 Game.Create() 中设置了一个循环来旋转所有模式,选择最高分辨率(仅高达 1920x1200),然后选择在该分辨率下具有最高刷新率的那个。除非使用两个(或更多)极低分辨率显示器(这样它们的宽度加起来等于或小于 1920),否则会选择可播放的默认值。添加它作为答案,我会标记它 - 除非出现更好的情况。 ;) 实际上,在玩了这个之后,我发现Gdx.graphics.getDisplayModes() 在我的 Ubuntu 工作站上是零星的。通常,在它报告的 43 种模式中,根本没有列出 1920x1080。然而有时,它列出了几种不同的刷新率?令人沮丧。 来源 (github.com/libgdx/libgdx/blob/master/backends/gdx-backend-lwjgl/…) 显示 Libgdx 只是在使用 org.lwjgl.opengl.DisplayMode 您可能会将其重新标记/改写为 LWJGL 问题吗? (并且您可能可以在 Libgdx 初始化之前使用 LWJGL API ...) 不是编程答案,而是:这是大多数 linux 游戏和多显示器的持续问题。正在研究像 Wayland 这样的 X 替代品的原因之一。请提供一种在命令行或配置文件中覆盖分辨率检测的方法,以确保 linux 多显示器的人可以玩你的游戏:) 【参考方案1】:

我不确定,但它对我有用。只需在“开始”游戏后设置大小,如下代码所示:

public static void main(String[] args) 
    LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
    cfg.title = "Palmeiras!!";
    cfg.vSyncEnabled = false;
    cfg.forceExit = true;
    cfg.allowSoftwareMode = true;
    new LwjglApplication(new Palmeiras(null), cfg);

    Gdx.graphics.setDisplayMode(Gdx.graphics.getDesktopDisplayMode().width,
            Gdx.graphics.getDesktopDisplayMode().height, true);

让我知道它是否对你有用。

【讨论】:

【参考方案2】:
GraphicsDevice monitors[]=GraphicsEnvironment.getScreenDevices(); 

Dimension screen_resolution[monitors.length];

for (int monitorID = 0; monitorID < monitors.length; monitorID++)

    screen_resolution[monitorID] = new Dimension(monitors[monitorID].getDisplyMode().getWidth(),monitors[monitorID].getDisplyMode().getHeight());

【讨论】:

【参考方案3】:

我会避免使用 Toolkit.getDefaultToolkit(),而只使用 lwjgl.util.Display.getAvailableDisplayModes() 或 libgdx 描述的方法。

一旦你设置了一个全屏窗口,获取它的大小(如果你的设置方法还不知道的话)并且只使用它上面的信息。

如果 Display.getAvailableDisplayModes() 在不同的执行中改变了它的排序顺序,只需重新排序并使用最大的可用或使用标准的并提供游戏内设置来更改它们。

【讨论】:

如果你要复制我的答案,请至少保留格式。【参考方案4】:

这里

http://www.lwjgl.org/wiki/index.php?title=LWJGL_Basics_5_%28Fullscreen%29

你会发现一个方便的方法让 lwjgl 为你的桌面选择一个合适的全屏显示模式。您也可以使用相同的方法来确定分辨率,并在以后将其用于您的 gl ops。

【讨论】:

【参考方案5】:

我会避免完全使用 lwjgl。表面上看起来很简单,但是当您尝试添加更高级的功能时,您会意识到 OpenGL 上的包装器不会为您提供该功能,或者它会使程序慢 3 倍。我建议转向 c++ 和 OpenGL(如果这是一个选项)。你会惊讶于它的简单性。 否则,跨平台库通常确实存在这些故障。要解决您的问题,您需要停止依赖库来确定您的视口分辨率。相反,请枚举所有可能的显示模式并根据您选择最好的一种。这将导致更多定义的行为,并且比使用看起来像是魔术的默认配置更容易调试。一般来说,您希望始终确保您知道您正在使用什么数据。更糟糕的是,我刚刚注意到您在包装器上使用了包装器。这过于复杂,并且会减慢渲染速度,远远超出您的想象(平均 20 倍)。

【讨论】:

是的,每个 wrapper 上的 wrapper 总是平均减慢一切 20 倍。仅使用包装器只会使其慢 3 倍。这是直截了当的事实。包装器永远无法提供与被包装的东西相同的功能。只有 C++ 是唯一真正的语言,它非常简单,一个 3 岁的孩子可以用它制作游戏。 -1 更不用说 C++ 自动比 Java 更好更快!网上说是,所以我当然应该相信!克里斯蒂安,除非你有消息来源来证实你非常不准确的问题,否则请不要试图混淆 OP 并给他无益的谎言。 -1 我并不是说所有的包装器都很糟糕,但在这个特定的例子中,libGDX 非常糟糕。举个例子,看看这个比较: 我想非常清楚地说明我已经在本地使用了 OpenGL,使用了 LWJGL,并在各种活动中使用了 libGDX。 LWJGL 比 C++ 慢只是因为它的内存管理。 java.nio.Buffers 可能会缓解一些问题区域,但不是全部。尝试在纯 Java 中快速创建交错的顶点数据 - 不是那么容易,是吗?至于 libGDX……它对其绘图程序的控制很少(类似于 XNA)。它决定把手举到空中然后说:“给你,一个包装好的 LWJGL 上下文的句柄,用它做你想做的事。” "更不用说 C++ 自动比 Java 更好更快!" -> Java 在使用 C++ 构建的 JVM 中运行。非争论,Java 永远不会比 C++ 快。这就像试图说 C++ 程序将比编写优化的机器代码更快。此外,如果您喜欢浏览这些类型的网站(根据匿名用户名判断),我强烈建议您停止。【参考方案6】:

也许获取您当前使用的显示器的尺寸,因此在不同尺寸的显示器上,只需获取尺寸即可。对于不同尺寸的显示器,您可能需要做不同的事情。

也许背景图像被放大了,因为它认为它仍在其他屏幕上工作。

希望这会有所帮助,如果不是 gl

【讨论】:

【参考方案7】:

我会避免使用Toolkit.getDefaultToolkit(),而只使用lwjgl.util.Display.getAvailableDisplayModes() 或libgdx 描述的方法。

一旦你设置了一个全屏窗口,获取它的大小(如果你的设置方法还不知道的话)并且只使用它上面的信息。

如果Display.getAvailableDisplayModes() 在不同的执行中更改其排序顺序,只需重新排序并使用可用的最大排序或使用标准排序并提供游戏内设置来更改它们。

【讨论】:

【参考方案8】:

您可以使用 javafx.stage.screen 来解决此问题,但如果您坚持使用 Java 6,则必须添加 JavaFX,或者升级到 Java 7(它包含在 Java 7 SDK 中。)

来自文档:

"描述图形目标的特征,例如 监视器。在虚拟设备多屏环境中, 桌面区域可以跨越多个物理屏幕设备,边界 Screen 对象的个数与 Screen.primary 相关。

例如:

Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();

//将舞台边界设置为主屏幕的可见边界 stage.setX(primaryScreenBounds.getMinX()); stage.setY(primaryScreenBounds.getMinY()); stage.setWidth(primaryScreenBounds.getWidth()); stage.setHeight(primaryScreenBounds.getHeight());

stage.show();"

还有多种其他方法(getBounds(), getDpi(), getScreens() 等)也可能对您非常有用。

【讨论】:

Harvath II -- 感谢您的回复。我会看看我是否可以在我的 libGDX 游戏的上下文中完成这些工作——主要问题可能在于支持 Android ......我想尽可能避免平台依赖。我会试一试,看看我能做些什么。

以上是关于java 和 libGDX / LWJGL 游戏全屏尺寸错误,适用于 Ubuntu 上的多个显示器的主要内容,如果未能解决你的问题,请参考以下文章

频繁检查 LWJGL/JInput 游戏手柄按钮或轴时出现延迟,如何解决?

开源java游戏框架libgdx专题-08-中文显示与绘制

开源java游戏框架libgdx专题-01-libgdx介绍

开源java游戏框架libgdx专题-10-核心库-Viewport

开源java游戏框架libgdx专题-07-文件处理

开源java游戏框架libgdx专题-06-使用libgdx自带的日志方法