人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

勇者は足踏みした

前回の勇者は移動はできますが足踏みしてませんね。足踏みってのは言うまでもないと思いますが

f:id:aidiary:20100306231942g:plain

のことです。

rpg05.jar

アニメーション

ボールを動かす(2004/9/19)にも書きましたが、アニメーションはいくつかの画像を順番に切り替えることで作れます。今回使う画像は下の2つです。

f:id:aidiary:20100306231943g:plain

よーく見てください。手足の位置が少しずれています。この2つの画像を順番に切り替えれば足踏みしているように見えるわけです。

アニメーション用スレッド

アニメーションを実現する手段としてスレッドを使います。今回は今までと違ってアニメーション用スレッドクラスを新しく作りました。前は Runnableインタフェースを実装していましたが、今回はThreadクラスを拡張しています。run()の中に実行させたい処理を書くのはどっちでも同じです。

    // アニメーションクラス
    private class AnimationThread extends Thread {
        public void run() {
            while (true) {
                // countを切り替える
                if (count == 0) {
                    count = 1;
                } else if (count == 1) {
                    count = 0;
                }
                
                repaint();
                
                // 300ミリ秒休止=300ミリ秒おきに勇者の絵を切り替える
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } 
            }
        }
    }

内部クラスというのはクラスの中に作ったクラスのことです。今回はMainPanelクラスの中にAnimationThreadクラスを作っているのでAnimationThreadは内部クラスになっています。内部クラスにするとMainPanelのインスタンス変数にアクセスできるという利点があります。例ではcountにアクセスしています。

run()では300ミリ秒ごとにcountの値を0、1、0、1、0、1、0、1・・・というように切り替えています。countの値が0のときは左の画像、countの値が1のときは右の画像を表示するようにするためです。

画像の表示

countの値に応じて表示する画像を切り替えます。イメージの表示にdrawImage()を使うのは今までどおりですが、今回は引数が違っています。今回使ったdrawImage()は、

   g.drawImage(Image img,
               int dx1, int dy1, int dx2, int dy2,
               int sx1, int sy1, int sx2, int sy2,
               ImageObserver observer) 

です。このメソッドはソース画像(img)の(sx1,sy1)-(sx2,sy2)の部分をgの(dx1,dy1)-(dx2,dy2)に描画できます。実際に画像を表示するコードは、

    // countの値に応じて表示する画像を切り替える
    g.drawImage(heroImage, x*CS, y*CS, x*CS+CS, y*CS+CS,
                count*CS, 0, CS+count*CS, CS, this);

の部分です。このコードの意味を図示すると下のようになります。ソース画像(heroImage)の座標をcountによって変えているのが分かるでしょうか?

f:id:aidiary:20100306231939g:plain