人工知能に関する断創録

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

宝箱

今回は宝箱

f:id:aidiary:20100404101710g:plain

です。イベントを追加するだけなので簡単です。ただアイテムを実装してないので中身はとれません。

rpg18.jar

宝箱イベント

宝箱はキャラクター(町の人)と同じくイベントとして実装します。イベントはevent.datにまとめて書いておき、マップをロードするときに一緒に読み込んでいます。event.datの中身は次のようになっています。

   TREASURE,8,7,120ゴールド
   TREASURE,9,7,たいまつ
   TREASURE,10,7,かぎ

TREASUREはこのイベントが宝箱であることをあらわしています。次の2つの数字(8,7)は宝箱の座標、最後の120ゴールドは宝箱の中身です。このマップには3つの宝箱があります。

イベントクラス

宝箱イベントは、TreasureEventクラスで管理しています。TreasureEventはEventクラスを拡張したクラスです。まずは、元となるEventクラスから見てみます。Eventクラスは宝箱やとびらなどほとんどのイベントの元となるクラスです。

public abstract class Event {
    // X座標
    protected int x;
    // Y座標
    protected int y;
    // チップ番号
    protected int chipNo;
    // ぶつかるか
    protected boolean isHit;
    
    /**
     * コンストラクタ
     * @param x X座標
     * @param y Y座標
     * @param chipNo チップ番号
     * @param isHit ぶつかるか
     */
    public Event(int x, int y, int chipNo, boolean isHit) {
        this.x = x;
        this.y = y;
        this.chipNo = chipNo;
        this.isHit = isHit;
    }
    
    /**
     * イベントを文字列に変換(デバッグ用)
     */
    public String toString() {
        return x + ":" + y + ":" + chipNo + ":" + isHit;
    }
}

abstractがついているのでEventのオブジェクトは作れません。拡張して使います。座標、チップ番号、イベントにぶつかるかなどは宝箱やとびらなど多くのイベントと共通する機能なのでEventにまとめています。宝箱はこのEventクラスを拡張して作っています。

public class TreasureEvent extends Event {
    // 宝箱に入っているアイテム名
    private String itemName;

    /**
     * @param x X座標
     * @param y Y座標
     * @param itemName 手に入るアイテム名
     */
    public TreasureEvent(int x, int y, String itemName) {
        // 宝箱のチップ番号は17でぶつからない
        super(x, y, 17, false);
        this.itemName = itemName;
    }

    /**
     * アイテム名を返す
     */
    public String getItemName() {
        return itemName;
    }

    /**
     * イベントを文字列に変換(デバッグ用)
     */
    public String toString() {
        return "TREASURE:" + super.toString() + ":" + itemName;
    }
}

super()でEventクラスのコンストラクタを呼び出しています。宝箱のチップ番号は17番です。あとアイテム名を保存するitemName という変数も用意しています。もしアイテムが実装されたらItemオブジェクトも変数として用意すればいいと思います。

イベントのロード

イベントをロードするのはMapクラスのloadEvent()です。

    /**
     * イベントをロードする
     * @param filename イベントファイル
     */
    private void loadEvent(String filename) {
        try {
            BufferedReader br = new BufferedReader(
                new InputStreamReader(
                    getClass().getResourceAsStream(filename)));
            String line;
            while ((line = br.readLine()) != null) {
                // 空行は読み飛ばす
                if (line.equals("")) continue;
                // コメント行は読み飛ばす
                if (line.startsWith("#")) continue;
                StringTokenizer st = new StringTokenizer(line, ",");
                // イベント情報を取得する
                // イベントタイプを取得してイベントごとに処理する
                String eventType = st.nextToken();
                if (eventType.equals("CHARA")) {  // キャラクターイベント
                    makeCharacter(st);
                } else if (eventType.equals("TREASURE")) {  // 宝箱イベント
                    makeTreasure(st);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

イベントファイルのロードについてはイベントファイルのロードで解説したので詳しくはそちらを見てください。ここでは、宝箱イベントの部分だけ追加されています。イベントタイプがTREASUREだったとき、makeTreasure()で宝箱イベントを作ります。

    /**
     * 宝箱イベントを作成
     */
    private void makeTreasure(StringTokenizer st) {
        // 宝箱の座標
        int x = Integer.parseInt(st.nextToken());
        int y = Integer.parseInt(st.nextToken());
        // アイテム名
        String itemName = st.nextToken();
        // 宝箱イベントを作成
        TreasureEvent t = new TreasureEvent(x, y, itemName);
        // 宝箱イベントを登録
        events.add(t);
    }

ファイルから座標、アイテム名などを読み取って、TreasureEventオブジェクトを作ります。作られたTreasureEventは eventsベクターに登録します。ここらへんはキャラクターのときと同じです。

しらべる

さいごに宝箱をしらべて中身を取る処理です。宝箱の上でスペースキーを押すとウィンドウに宝をゲットしたメッセージが表示されうようにします。 MainPanelクラスのmainWindowCheckInput()です。

    if (spaceKey.isPressed()) {  // スペース
        // 移動中は表示できない
        if (hero.isMoving()) return;

        // しらべる
        TreasureEvent treasure = hero.search();
        if (treasure != null) {
            // メッセージをセットする
            messageWindow.setMessage(treasure.getItemName() + "を てにいれた。");
            // メッセージウィンドウを表示
            messageWindow.show();
            // TODO: ここにアイテム入手処理を入れる
            // 宝箱を削除
            map.removeEvent(treasure);
            return;  // しらべた場合ははなさない
        }
        
        ・・・
    }

Charaクラスのsearch()で足元にある宝箱(TreasureEvent)を取得します。「〜をてにいれた」というメッセージをセットして表示すればメッセージウィンドウに表示されます。search()は簡単なメソッドです。

    /**
     * あしもとに宝箱があるか調べる
     * @return あしもとにあるTreasureEventオブジェクト
     */
    public TreasureEvent search() {
        Event event = map.eventCheck(x, y);
        if (event instanceof TreasureEvent) {
            return (TreasureEvent)event;
        }
        
        return null;
    }

(x,y)は勇者の座標です。この座標にTreasureEventがあるか調べて、あれば返します。