StarCruiserのバグを潰そう

StarCruiser GAME OVER 時の画面StarCruiserは結構好きなサンプルです。しかし、遊んでてゲームオーバーになると

Exception in MIDlet's paint method
**Dummy PrintStackTrace**

と例外が表示されて、ちょっと気になります。バグなので直しましょう。

midp-fcs\segi\starcruiserで作業することにしました。必要なファイルをコピーします。

D:\midp-fcs\segi\starcruiser>copy \midp-fcs\src\example\starcruiser\*.java .

これでMovingStar.javaStarCanvas.javaStarCruiser.javaがコピーされました。

paintメソッドで例外が出てるので、まずはそれを探します。ソースファイルを見てくとStarCanvas.javaの377行目からpaintメソッドが記述されてます。

これをボーッと見ていくと399行から402行に

if (gameOver) {
    g.drawString("GAME OVER", width / 2, height / 2,
                 Graphics.HCENTER);
}

とあります。ゲームオーバーのときだけ例外が出てるので、ここが怪しいとあたりをつけました。確かめるために

if (gameOver) {
    try {
        g.drawString("GAME OVER", width / 2, height / 2,
                     Graphics.HCENTER);
    } catch (Exception ex) {
        System.out.println("----");
        ex.printStackTrace();
        System.out.println(ex.toString());
        System.out.println("----");
    }
}

として、コンパイル・実行してみましょう。

D:\midp-fcs\segi\starcruiser>mkdir tmpclasses
D:\midp-fcs\segi\starcruiser>javac -d tmpclasses -classpath tmpclasses -bootclasspath /midp-fcs/classes *.java
D:\midp-fcs\segi\starcruiser>preverify -classpath tmpclasses;/midp-fcs/classes tmpclasses
D:\midp-fcs\segi\starcruiser>cd output
D:\midp-fcs\segi\starcruiser\output>midp example.starcruiser.StarCruiser

javacのオプションに-d tmpclasses -classpath tmpclassesを付けてます。packageが指定されてるソースファイルをコンパイルするときに、こうする方法もあります。

上のコマンドでStarCruiserが実行されるので、遊びます。ゲームオーバーになると

----
**Dummy PrintStackTrace**
java.lang.IllegalArgumentException: Invalid anchor
----

と表示され、上のソースの部分、すなわち

g.drawString("GAME OVER", width / 2, height / 2,
             Graphics.HCENTER);

java.lang.IllegalArgumentExceptionを投げることが解ります。

「別に この文 間違ってないやろ?」と疑問に思いながらも「APIドキュメントを作ろう」で作ったAPIドキュメントを見ます。GraphicsクラスのdrawStringメソッドを見ましょう。

例外のところに“IllegalArgumentException - if anchor is not a legal value”と書かれてるので、どうもanchorの指定、ここではGraphics.HCENTERの指定が適切でないようです。メソッドの説明のところに“See anchor points”とあって“anchor points”にリンクがはられているのでクリックしてみましょう。

“Anchor Points”の説明にジャンプするので読んでいきます。しばらく読むと

The definition of the anchor point must be one of the horizontal constants (LEFT, HCENTER, RIGHT) combined with one of the vertical constants (TOP,BASELINE, BOTTOM) using the logical OR operator.

とあって、anchorは水平方向を指定する定数と垂直方向を指定する定数をOR演算子でつなげたものでなくてはならないと書かれてます。

StarCruiserではGraphics.HCENTERと水平方向は指定してるんですが、垂直方向が指定されてないのでIllegalArgumentExceptionが投げられてることが解ります。垂直方向も指定するように

g.drawString("GAME OVER", width / 2, height / 2,
             Graphics.HCENTER | Graphics.BASELINE);

と変更しましょう。コンパイル・検証・実行します。

D:\midp-fcs\segi\starcruiser>javac -d tmpclasses -classpath tmpclasses -bootclasspath /midp-fcs/classes *.java
D:\midp-fcs\segi\starcruiser>preverify -classpath tmpclasses;/midp-fcs/classes tmpclasses
D:\midp-fcs\segi\starcruiser>cd output
D:\midp-fcs\segi\starcruiser\output>midp example.starcruiser.StarCruiser

デバグ後の StarCruiser GAME OVER 時の画面ゲームオーバーになったときは左の画面が表示されるようになりました。これでデバグ完了です。


前の項目へ次の項目へ
「MIDPで遊ぼう!」のページへ
せぎてつ伝言板
このページの感想をどうぞ!
お名前(匿名OK):

メールアドレス:
最終更新日 : 2000年10月29日(土)
tetsu@segi.org