我正在使用j2me编写手机游戏。在这个游戏中,我使用了多个Canvas对象。 例如,游戏菜单是一个Canvas对象,实际的游戏也是一个Canvas对象。 我注意到,在某些设备上,当我从一个Canvas切换到另一个Canvas时,例如从主菜单切换到游戏时,屏幕瞬间“闪烁”。我正在使用自己的双缓冲Canvas。j2me画面在画布之间切换时闪烁
有没有办法避免这种情况?
我正在使用j2me编写手机游戏。在这个游戏中,我使用了多个Canvas对象。 例如,游戏菜单是一个Canvas对象,实际的游戏也是一个Canvas对象。 我注意到,在某些设备上,当我从一个Canvas切换到另一个Canvas时,例如从主菜单切换到游戏时,屏幕瞬间“闪烁”。我正在使用自己的双缓冲Canvas。j2me画面在画布之间切换时闪烁
有没有办法避免这种情况?
你使用双缓冲吗?如果设备本身不支持双缓冲,您应该定义一个屏幕外缓冲区(图像)并首先对其进行绘制,然后将最终结果绘制到实际屏幕上。为你的每个画布做这个。下面是一个示例:
public class MyScreen extends Canvas {
private Image osb;
private Graphics osg;
//...
public MyScreen()
{
// if device is not double buffered
// use image as a offscreen buffer
if (!isDoubleBuffered())
{
osb = Image.createImage(screenWidth, screenHeight);
osg = osb.getGraphics();
osg.setFont(defaultFont);
}
}
protected void paint(Graphics graphics)
{
if (!isDoubleBuffered())
{
// do your painting on off screen buffer first
renderWorld(osg);
// once done paint it at image on the real screen
graphics.drawImage(osb, 0, 0, Tools.GRAPHICS_TOP_LEFT);
}
else
{
osg = graphics;
renderWorld(graphics);
}
}
}
可能的解决方法是使用Display.callSerially()同步开关。闪烁可能是由于应用程序试图在画布切换仍在进行时画到屏幕上而引起的。在尝试再次调用run()之前,callSerially()应该等待重新绘制完成。
但是,这一切都完全依赖于手机,因为许多设备没有实现callSerially(),没关系按照官方文档中列出的实现。我已经知道与callSerially()正确工作的唯一设备是西门子手机。
另一种可能的尝试是将Thread.sleep()的值设置为1000毫秒,确保事先调用了setCurrent()方法。这样,设备可能会设法在可显示的绘图尝试之前进行更改。
最可能的问题是,它是一个设备问题,并保证闪烁的修复很简单 - 使用一个画布。可能不是你想听到的。 :)
我遵循你的建议,并在代码中放置了一个很长的Thread.sleep()。我发现闪烁实际上发生在Canvas'run()方法中的第一个repaint()之后。有什么想法吗? – Dimitris 2008-09-16 12:33:24
我会说,使用多个画布通常是不好的设计。在某些手机上它甚至会崩溃。最好的方法是使用一个画布来跟踪应用程序的状态。然后在paint方法你会
protected void paint(final Graphics g) {
if(menu) {
paintMenu(g);
} else if (game) {
paintGame(g);
}
}
有更好的方法来处理与画面对象应用程序的状态,这将使得设计更清洁,但我觉得你有这个想法:)
/JaanusSiim
假设在你的应用中使用1个带有状态机器代码的画布是个好主意。然而,我唯一需要测试应用程序的设备(MOTO v3)在资源加载时崩溃,仅仅因为代码过多/要在GameCanvas中加载(没有使用Canvas进行尝试)。这是痛苦的,因为它是真实的,我没有找到解决问题的方法。 如果你很幸运有很多设备可以测试,那么实施这两种方法是值得的,并且为每款设备制作游戏的版本非常有用。
我用类似于你的方法定义一个屏幕外缓冲区来使用双缓冲。当新Canvas的主线程开始运行时,总会发生闪烁。 – Dimitris 2008-09-15 21:14:59