今回はJavaで配列ベースのフレームバッファを作ってみます。MemoryImageSourceオブジェクトを使うと配列の内容からImageオブジェクトを作成できましたが、このMemoryImageSourceオブジェクトのsetAnimated()、setFullBufferUpdates()メソッドで設定を行うと関連付けられた配列の内容をnewPixels()でリアルタイムにImageオブジェクトに反映できるようになります。つまり、配列の内容を変更してnewPixels()すると新しい配列の内容がMemoryImageSourceから作成したImageオブジェクトにも反映されるわけです。この配列によるImageの更新が十分に速くかつ配列の操作の処理速度も十分なら、各種の画像処理用フレームバッファはもちろんゲームのバックバッファなどにも使えそうですね。今回は、実際にこの辺りの処理速度を検証してみる事にしましょう。
フレームバッファの作成は簡単です。以下のように、MemoryImageSourceオブジェクトを作成してsetAnimated()、setFullBufferUpdates()を適用し、そのMemoryImageSourceオブジェクトを渡してcreateImageするだけ。これで、MemoryImageSourceオブジェクトのnewPixels()メソッドを呼び出せば、MemoryImageSourceに関連付けられた配列の内容がImageオブジェクトに反映されるようになります。
back=new int[512*512]; ms=new MemoryImageSource(512,512,back,0,512); ms.setAnimated(true); ms.setFullBufferUpdates(true); img=createImage(ms); ms.newPixels();
この例だと、int型配列backが512×512ピクセルのフレームバッファになり、その内容がimgに描画されるわけですね。今回は、アプレットの描画時にpaint()内でこのフレームバッファに512×512ピクセルの背景と64×64ピクセルのキャラクタを描いてみましょう。ともにback同様のint型配列で、背景の方は単純なコピー、キャラクタの方は抜き色によるソフトスプライトとして書き込んでいきます。キャラクタを描く位置はマウスカーソルの位置とし、マウスイベントで取得したカーソル位置を変数x, yに保持するようにしました(mouseMovedの度にrepaint()する)。
背景とキャラクタは以下のようにして適当に作っておきます。
bg=new int[512*512]; chr=new int[64*64]; for (i=0;i<512;i++) for (j=0;j<512;j++) { c=0xff000000+((i/2) << 8)+(j/2); bg[j+i*512]=c; } for (i=0;i<64*64;i++) chr[i]=0xff000000; for (i=0;i<64;i++) for (j=i/2;j<64-i/2;j++) { c=0xff000000+(i*4 << 16)+((63-i)*4); chr[j+i*64]=c; chr[j+(63-i)*64]=c; }
フレームバッファへの書き込みでは、まず背景bgをbackにコピーし、続いてキャラクタchrを0xff000000を抜き色に書き込んでいく通常のソフトスプライト処理を行います。
System.arraycopy(bg,0,back,0,512*512); for (int i=0;i<64;i++) for (int j=0;j<64;j++) if (j+x>=0 && j+x<512 && i+y>=0 && i+y<512 && chr[j+i*64]!=0xff000000) back[j+x+(i+y)*512]=chr[j+i*64];
これでフレームバッファの内容が更新されたので、MemoryImageSourceオブジェクトmsのnewPixels()を呼び出しイメージを更新してからそのイメージを描画します。
ms.newPixels(); g.drawImage(img,1,1,this);
アプレットの中でマウスカーソルを動かしてみてください。
アプレットの描画時には毎回512×512×4バイトの転送と64×64ピクセルの透過処理をしていますが、私の環境では十分な速度で動くみたいですね。
戻る |