我在用Java做游戏。基本上,我有两个不同的“平面”更新,我需要照顾。底层是实际的游戏绘画本身。它只是一个覆盖整个JPanel的JFrame,并被绘制为使用它的Graphics对象。
我使用一个固定的时间步骤来处理这些第一个图形更新。为了防止不必要的更新,我重写了paintComponent()方法,完全不做任何事情,因为我已经编写了一个自定义render(float interpolation)方法来处理这个问题。
但是,除了原始鼠标单击和键盘输入之外,此面板不能接受任何输入。我需要创建各种菜单,文本框等的能力,也是在屏幕上。喜欢各种能力,甚至是“菜单”按钮,通常出现在大多数游戏的左上角。
为了处理这个输入,比如创建按钮,我有第二个JPanel,它应用了setOpaque(false)。然后创建我可能需要的各种Swing组件,比如一个JButton。
要包含这两个JPanels,我使用一个JLayeredPane,并适当地设置它们的层,如下所示。这样,输入层应该始终位于实际游戏层的顶部。
下面的代码显示了如何创建和添加Swing组件。addLoginDialog()是一种为登录添加Swing组件的方法。它已经过测试并正常工作,而不是问题所在。
private void initComponents()
{
//This code is inside of the JFrame
wholePane = new JLayeredPane();
add(wholePane);
guiPanel = new GUIPanel();
guiPanel.setOpaque(false);
gamePanel = new RPGPanel();
gamePanel.setOpaque(false);
wholePane.add(gamePanel, JLayeredPane.DEFAULT_LAYER);
wholePane.add(guiPanel, JLayeredPane.POPUP_LAYER);
guiPanel.addLoginDialog();
}所以当我运行代码时,我会感到可怕的闪烁。这是从我的固定时间步骤~每秒60次运行的代码。
public void handleRepaint()
{
//I don't use repaint() for the game drawing so I can be sure that fps is controlled.
Graphics g = gamePanel.getGraphics();
gamePanel.render(g);
g.dispose();
wholePane.repaint();
}问题是,我认为,两种不同的屏幕更新系统发生了冲突。标准的paintComponent()系统对于更多的静态屏幕是很好的,但是当我需要持续更新并跟踪fps时,我不能让更新随机进行。
但是,对于输入层,我只想像Swing一样进行更新。当鼠标移动到按钮上时,当我的组件被移动或调整大小时,等等。
另外,请注意屏幕闪烁的方式:背景图像变为空白,然后重复出现。输入面板总是在那里,但实际上是绘制在游戏绘图的后面,这是不应该发生的,因为它被放置在默认层中。我知道它并没有完全消失的原因是因为游戏画是部分透明的,所以我可以看到它下面,我添加的按钮仍然在那里。
我的主要问题是,如何停止闪烁?为什么当游戏绘图在JLayeredPane中较低层的面板上绘制时,游戏绘图被绘制在输入组件之上?和我认为最重要的是,是什么导致了闪烁?谢谢你的帮助。
发布于 2013-12-30 06:32:45
为什么游戏绘图是在输入组件之上绘制的,而游戏绘图是在JLayeredPane中较低层的面板上进行的?
主要是因为你绕开了Swing的运作方式。
让我们从以下事实开始:Graphics上下文是一个共享资源(通常每个本机对等方都有一个Graphics上下文),也就是说,每个组件都获得相同的上下文,这意味着,当您使用自己的绘图例程时,您基本上是在绘制其他所有内容。
RepaintManager负责决定应该绘制什么和什么时候。所以你现在看到的是两位艺术家为了同一幅画布而斗争,想同时在画布上作画,这简直是一团糟。
再加上Swing的绘画过程并不是线程安全,你就会陷入一片混乱之中。
如果你绝对必须有控制,那么你需要从方程式中移除Swing的绘画引擎。
首先看一下被动渲染与主动渲染
ps-使用BufferStrategy也有硬件加速的好处。
https://stackoverflow.com/questions/20833913
复制相似问题