Javaでゲームを作る入門 @ うぃき

BufferStrategyとFrameとCanvasについての考察

最終更新:

takejava

- view
管理者のみ編集可
BufferStrategyについての考察です。
こういう問題が発生したときの対処法はこうだ、という内容になるかと思います。
また、フルスクリーン化との問題も絡む場合があるのでその辺の内容も書ければと思います。

BufferStrategyというものが便利そうだぞ、ということで、
とりあえず使ってみた方は何人かはいるでしょう(私はそうでした)。
私は、ゲームを作り始めた当初は全く存在を知らなかったので、
バッファイメージの取得からフラッシュまで、1からコードを書いていました。
結局のところ、BufferStrategyはそいうったソースが煩雑になりがちな面倒な部分をすべて受け持ってくれるクラスなのです。
ただ、便利だからと言って、使い方を間違える、もしくは、知らないことがあると、どつぼにハマり、
もういやだ!二度と使うもんか!なんてことにもなってしまう可能性を秘めています。

例えば、以下のようなエラーがでたりします(でなかったとしてもそれはたまたま動いてるだけの可能性もあるので注意です)。
エラーの例1)
Exception in thread "main" java.lang.IllegalStateException: Component must have a valid peer
at java.awt.Component$FlipBufferStrategy.createBuffers(Component.java:3981)
at java.awt.Component$FlipBufferStrategy.<init>(Component.java:3955)
at java.awt.Component$FlipSubRegionBufferStrategy.<init>(Component.java:4478)
at java.awt.Component.createBufferStrategy(Component.java:3832)
at java.awt.Canvas.createBufferStrategy(Canvas.java:194)
at java.awt.Component.createBufferStrategy(Component.java:3755)
at java.awt.Canvas.createBufferStrategy(Canvas.java:169)
at Main.<init>(Main.java:80)
at Main.main(Main.java:37)

さぁ、このエラーのストックトレースを冷静に見られる方はいるでしょうか。

これはソース上では、キャンバスのインスタンスがcreateBufferStrategy()メソッドを呼び出しているだけなので、一見なにが悪いのかが分かりません。
ここで何も知らない人はどこをどう修正したらいいのか分からないので、ハングアップしてしまうでしょう。
すべてのエラーに対して言えることですが、
デバッグの基本はまず、自分のソースを疑うことです(基本パッケージのバグはほとんどないと思ったほうがいいという意味です、が全くないとも言えなかったりします)。
このエラーの場合は、呼び出すタイミングが怪しいと推測するのが正しいでしょう。

注目すべきは一行目の「Component must have a valid peer」という文言です。
わざわざこのように吐き出されているのです。注目せざるを得ません。
peerを確認しろ、peerが生成できてないですよ、peerが確定していませんよ、と言っています(ちなみにpeer確定問題などと言うようです)。

peerとは・・・と、語ってみたいところですが、そこまで知る必要はない、と言いますか、
そこまで調べていたらとても本筋のゲームプログラミングが進みそうにないということで、やめることにします。
今、重要なのは如何にしてこの問題を解決するか、ということにして逃げたいと思います。

さて、エラー内容、問題が把握できたところで、
じゃぁ、peerを確定すればいいのか!?いつ確定するものなんだ!?ということになると思います。
後者の、「いつ確定するか」を把握できれば、この問題は解決します。
peerはプログラマーが生成するようなものではなく、
javaシステムがOSに相談を持ちかけて作られるもの、そんなイメージでよいでしょう。
そしてこの問題については別の観点も必要のようです。・・つづく?


追記
ここからはソースをみて、触って理解に努めてください。つまり丸投げです、すいません。
下のソースをダブルクリックして、コピって、Eclipseなどにペして動かしてみてください。
とりあえずは正常に動くはずです。
クラス名は「Main」というありがちな名前でつけちゃったので、他のソースとぶつからないように新しいクラスを作ってくださいね。

ソース内容についてですが、Swing触ったことのある方なら、つっこみをいれたくなると思います。
そうです。EDTを使っていません。
これが、大元にして、かつ、わかりにくく、そして誰しもがぶつかる壁でもあります。

peer 窓 可視化 Graphics レイアウト サイズ
この辺のキーワードはかなりデリケートだったりします。
大体つまづくのがこの辺の問題で、そして、あきらめてしまうのもこの辺の問題だったりします。
がんがりまそう!

遊び方としては、まず全体の流れをざっとみて、コメントを固まり単位で外したり、setvisibleしなかったり、したり、packしたりしなかったりしてみてください。それからSwingとAWTの併用の恐さも体験できるやもしれません。

結局のところ、以下のあたりにきをつければ間違いないはずです。
  • setVisible(true)のタイミングに気をつける
  • setVisible含め、Swingの描画関係、もう全部でもいいぐらいですが、EDTスレッドでやるようにする
  • setVisibleのあとにグラフィックスの取得をする

そして、こんな感じに順番を守ればよいと思います。
  1. 画面の生成
  2. 画面の可視化
  3. そしてゲーム処理

あとSwingコンポーネントの上(画面手前)にAWTは乗せないほうが良いというか、乗せれない?感じなのと、その逆も若干バグがでることもあるので気をつけたいところです。

html2 plugin Error : このプラグインで利用できない命令または文字列が入っています。
記事メニュー
ウィキ募集バナー