第4回:勝手にぐるぐる


キャラを動かす

ノートPCを購入して(SHARP Mebius PC-CB1-R5S)、そいつに Linux 入れてみるんだが、一向に言う事を聞いてくれん。無線 LAN カードが悪いのか?うむっっ。で、そっちに気を取られ前回から間があいた。
今回はアニメーション。キャラを動かす仕組みを探ってみた。
キャラを動かすには Thread を使うらしい。スレッドと読む。 Thread とは、Gooの英和辞典で引いてみると、「プログラムの別の部分と並行して実行できるプログラムの一部分」と出た。 Tread を使って時間間隔ごとに画面を再描画し、キャラが動いとる様に見せる。パラパラ漫画の要領やね。

Thread の使い方

Thread を組み込むには、Thread クラスがあるけん、そいつを親玉クラスとして Thread クラスを継承させるようにクラスを定義すればよい。

public class クラス名 extends Thread

こげなふうに書く。だがしかし、継承できるクラスは一つしかできん。Applet を作るには Applet クラスを必ず継承させないかんけん、

public class クラス名 extends Applet, Thread

としたいところ。こげなふうに複数のクラスを継承させるのを多重継承というらしい。Java は多重継承はできん。
じゃどげんして Thread クラスを組み込むの?
そういう場合は、インターフェースを使うらしい。

public class クラス名 implements 親玉インターフェイス1, 親玉インターフェイス2, ,..

こげなふうに書く。インターフェースは複数組み込める。 第3回の MouseMosionListener 何かもインターフェイスの仲間やった訳ね。 で、Thread は Runnable インターフェイスを使うと組み込めるらしい。 で、インターフェースっちゃなんね? 色々 Web とか文献を読んでみたところ、インターフェイスは名前と型が宣言されているだけのメソッドが記述してある変り種のクラスのようやん。 深く考えたら悩むので、とりあえず使ってみた。

Runnable インターフェイスを使ってみる

Runnable インターフェイスは run メソッドがインターフェース内で宣言されてるんで、run メソッドを自前で書かないといかん。 スレッドが作成されて実行が開始されると、run メソッドが呼ばれる仕組みらしい。
こんな Applet を作ってみた。



動いとる。壁に跳ね返るボールの動きみたいなの。ソースはこうなる。
import java.applet.Applet;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.Color;

public class GuruGuru1 extends Applet implements Runnable {
    int       x, y, r, h, m;
    boolean   fl;
    Thread    th;
    Dimension d;
    Image     bufImg;
    Graphics  bufGrp;

    public void init() {
        x = 100;      // 円の中心 x座標
        y = 100;      // 円の中心 y座標
        r = 20;       // 円の半径
        h = 3;        // 円の進行方向 1:左上 2:右上 3:右下 4:左下
        m = 1;        // 移動距離
        th = null;
        fl = true;
        d      = this.getSize();                       // アプレット領域の縦横サイズ
        bufImg = this.createImage(d.width, d.height);  // バッファ用イメージ
        bufGrp = bufImg.getGraphics();                  // バッファ用グラフィックス
        
    }

    public void start() {
        if (th == null) {
            th = new Thread(this);  // スレッドを作る
            th.start();
        }
    }

    public void run() {
        try {
            while (true) {
                switch (h) {
                    case 1:
                        x -= m; y -= m;
                        break;
                    case 2:
                        x += m; y -= m;
                        break;
                    case 3:
                        x += m; y += m;
                        break;
                    case 4:
                        x -= m; y += m;
                        break;
                }

                // 壁に当たった時の判別
                if (x >= d.width - r) {
                    if (h == 2) h = 1;
                    if (h == 3) h = 4;
                }
                if (x <= 0) {
                    if (h == 1) h = 2;
                    if (h == 4) h = 3;
                }
                if (y >= d.height - r) {
                    if (h == 4) h = 1;
                    if (h == 3) h = 2;
                }
                if (y <= 0) {
                    if (h == 2) h = 3;
                    if (h == 1) h = 4;
                }
                repaint();         // 再描画する update() → repaint() と呼ばれる
                Thread.sleep(10);  // 眠る
            }
        } catch (InterruptedException err) {}
    }

    public void update(Graphics g) {
        paint(g);
    }

    public void paint(Graphics g) {
        // 最初にバッファに書き込む
        bufGrp.setColor(Color.white);
        bufGrp.fillRect(0, 0, d.width, d.height);
        bufGrp.setColor(Color.blue);
        bufGrp.fillOval(x , y , r, r);
        // バッファを Applet 領域に書き出す。ちらつかない。
        g.drawImage(bufImg, 0, 0, this);
    }
}
面倒くさいので詳細はコメント読んでちょ。
これを応用して壁うちテニスゲームが作れるね。次はそれにする予定。

('02.03.21)


Back