j2meを使って携帯電話のゲームを書いています。このゲームでは、複数のCanvasオブジェクトを使用しています。たとえば、ゲームメニューはCanvasオブジェクトであり、実際のゲームもCanvasオブジェクトです。一部のデバイスでは、あるキャンバスから別のキャンバスに切り替えると、たとえばメインメニューからゲームに切り替えると、画面が瞬間的に「ちらつく」ことに気づきました。私は自分のダブルバッファキャンバスを使用しています。
これを回避する方法はありますか?
複数のキャンバスを使用することは、一般的に悪いデザインだと思います。一部の電話では、クラッシュすることさえあります。最善の方法は、アプリケーションの状態を追跡する 1 つのキャンバスを実際に使用することです。そして、ペイントメソッドでは、
protected void paint(final Graphics g) {
if(menu) {
paintMenu(g);
} else if (game) {
paintGame(g);
}
}
画面オブジェクトを使用してアプリケーションの状態を処理するより良い方法があります。これにより、デザインがきれいになりますが、アイデアは得られたと思います:)
/JaanusSiim
考えられる解決策は、Display.callSerially()を使用してスイッチを同期することです。ちらつきは、Canvasの切り替えがまだ進行中のときにアプリが画面に描画しようとしたことが原因である可能性があります。callSerially()は、run()を再度呼び出そうとする前に、再描画が終了するのを待つことになっています。
ただし、多くのデバイスはcallSerially()を実装していないため、これはすべて電話に完全に依存しています。公式ドキュメントに記載されている実装に従うことを気にしないでください。callSerially()で正しく動作することがわかっているデバイスは、Siemensの電話だけでした。
もう1つの可能な試みは、1000ミリ秒のような巨大なもののThread.sleep()を配置し、事前にsetCurrent()メソッドを呼び出していることを確認することです。このように、デバイスは、表示可能な描画を試みる前に、なんとか変更を加えることができます。
最も可能性の高い問題は、それがデバイスの問題であり、ちらつきの保証された修正が簡単であるということです-1つのCanvasを使用してください。おそらくあなたが聞きたかったものではないでしょう。:)
ゲームを作成している場合は、GameCanvasクラスを使用することをお勧めします。このような目的にははるかに優れており、適切に使用すると問題が解決するはずです。
仮説としては、アプリケーションのステート マシン コードで 1 つのキャンバスを使用することをお勧めします。ただし、(MOTO v3) でアプリケーションをテストする必要がある唯一のデバイスは、1 つの GameCanvas に読み込まれるコードが多すぎるため、リソースの読み込み時にクラッシュします ( 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);
}
}
}