在画布之间切换时,j2me屏幕闪烁

时间:2020-03-05 18:54:23  来源:igfitidea点击:

我正在使用j2me编写手机游戏。在这个游戏中,我使用了多个Canvas对象。
例如,游戏菜单是Canvas对象,实际游戏也是Canvas对象。
我注意到,在某些设备上,当我从一种Canvas切换到另一种Canvas(例如从主菜单切换到游戏)时,屏幕会瞬间"闪烁"。我正在使用自己的双缓冲Canvas。

反正有避免这种情况的方法吗?

解决方案

回答

我们是否使用双缓冲?如果设备本身不支持双重缓冲,则应定义一个屏幕外缓冲区(图像)并先对其进行绘制,然后将最终结果绘制至真实屏幕。对每个画布都执行此操作。这是一个例子:

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 ms之类的大文件,以确保事先调用了setCurrent()方法。这样,设备可能会设法在显示尝试绘制之前进行更改。

最可能的问题是这是设备问题,并且可以使用一个Canvas简单地解决闪烁问题。可能不是我们想听到的。 :)

回答

我会说,使用多个画布通常是不好的设计。在某些手机上,它甚至会崩溃。最好的方法实际上是使用一个画布跟踪应用程序的状态。然后在绘画方法中,我们将拥有

protected void paint(final Graphics g) {
  if(menu) {
    paintMenu(g);
  } else if (game) {
    paintGame(g);
  }
}

有更好的方法来处理带有屏幕对象的应用程序状态,这将使设计更整洁,但我认为主意是:)

/贾纳斯·西姆(JaanusSiim)

回答

如果我们正在编写游戏,则最好使用GameCanvas类。为此目的,它要好得多,如果使用得当,它应该可以解决问题。

回答

假设,为应用程序使用1个画布和一个满意的机器代码是一个好主意。但是,我必须在(MOTO v3)上测试应用程序的唯一设备在资源加载时崩溃,原因是1个GameCanvas中加载的代码太多/无法加载(尚未尝试使用Canvas)。这是真实的痛苦,而且我还没有找到解决该问题的解决方案。
如果我们很幸运能够测试大量设备,那么既要实现这两种方法,又要为每台设备制作几乎所有版本的游戏,都是值得的。