人工知能に関する断創録

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

キャラクターイベント

簡単イベントを導入します。キャラクターイベントです。今までは王様や兵士などの作成、追加はmain()に直接書き込んでいました。今回は、キャラクターを外部のイベントファイルから読み込んでキャラクターを簡単に追加できるようにします。

pyrpg12.zip
f:id:aidiary:20100731152628p:plain

イベントファイルの形式

イベントファイルは下のようなテキストファイルです。

 # test2.evt
 # イベントファイル
 CHARA,king,2,1,0,0,しろが ないぞよ。
 CHARA,minister,3,1,0,1,はやく しろを たててくだされ。
 CHARA,soldier,4,1,0,1,ぶきは そうびしないと いみがないぞ。

各行が1つのイベントを表しています。とはいっても今はキャラクターイベントしかないので1つの行が1人のキャラクターだと考えてください。各行は、左からイベントタイプ、キャラクター名、X座標、Y座標、キャラクターの向き、移動タイプ、はなしたときのメッセージを表しています。それぞれの情報はカンマで区切られています。また、#で始まる行はコメント行でイベントをロードするときは無視されます。

2行目を見てください。これは王様を表しています。CHARAはキャラクターイベントであることを示します。後でいろいろなイベント(TREASURE、DOOR、MOVEなど)を追加するときにどのイベントか区別できるようにしています。次のkingはキャラクター名です。前回説明したように画像ファイルの名前と同じです。次の2,1は王様の初期位置(マス単位)です。マップの(2,1)に置かれます。次の0はキャラクターの向きです。キャラクターの向きはグローバル領域で

DOWN,LEFT,RIGHT,UP = 0,1,2,3

と定義しています。つまり、0はDOWN(下向き)です。次の0は移動タイプです。移動タイプはグローバル領域で

STOP, MOVE = 0, 1  # 移動タイプ

と定義しています。つまり、0はSTOP(静止)です。これを1にすると王様はランダム移動します。最後の「しろが ないぞよ。」は、プレイヤーが話しかけたときに表示されるメッセージです。メッセージを表示する処理は後で追加します。

スクリプト側でこのイベントファイルをロードして自動的にキャラクターを作るようにします。

イベントファイルのロード

次に上で書いたイベントファイルをロードする処理を見てみます。イベントはマップごとにロードされるのでMapクラスに処理を追加します。Mapクラスのload_event()がそれです。イベントファイルはマップファイルと同じ名前で拡張子をevtにしたものを想定しています。たとえば、test2.mapに対応するイベントファイルはtest2.evtです。

    def load_event(self):
        """ファイルからイベントをロード"""
        file = os.path.join("data", self.name + ".evt")
        # テキスト形式のイベントを読み込む
        fp = codecs.open(file, "r", "utf-8")
        for line in fp:
            line = line.rstrip()  # 改行除去
            if line.startswith("#"): continue  # コメント行は無視
            data = line.split(",")
            event_type = data[0]
            if event_type == "CHARA":  # キャラクターイベント
                self.create_chara(data)
        fp.close()

コメントに書いてあるとおりです。イベントファイルを1行ずつ読み込んで順番に処理しています。コメント行は無視しています。split()は引数で指定した文字で文字列を分解してリストに格納するメソッドです。たとえば、

 line = "CHARA,king,2,1,0,0,しろが ないぞよ。"
                      ↓
 data = ["CHARA", "king", "2", "1", "0", "0", u"しろが ないぞよ。"]

のようになります。数値でもすべて文字列型で分解される点に注意してください。ここでは、イベントタイプがCHARAの場合に上のdataというリストをcreate_chara()に渡してキャラクターを作成しています。

キャラクターの作成

最後にキャラクターの作成を行うcreate_chara()を見てみます。

    def create_chara(self, data):
        """キャラクターを作成してcharasに追加する"""
        name = data[1]
        x, y = int(data[2]), int(data[3])
        direction = int(data[4])
        movetype = int(data[5])
        message = data[6]
        chara = Character(name, (x,y), direction, movetype, message)
        self.charas.append(chara)

先ほどのdataリストからキャラクター作成に必要な属性を読み取っています。先ほど書いたようにdataはすべて文字列型で分解されているので必要に応じてint()で整数型に変換しています。すべて読み取ったらCharacterクラスのコンストラクタでCharacterオブジェクトを作成します。前回と違ってmessageが増えたので注意してください。最後にマップのcharasリストにキャラクターを登録すれば完成です。

今回の修正によってmain()でキャラクターを作成、マップへ登録する処理がなくなっています。マップファイルを作成するときにイベントファイルも合わせてロードし、キャラクター作成、マップへの登録が自動的になされます。ただし、playerだけは別でmain()で作成しています。

今回はキャラクターイベントだけでしたが、あとでいろいろなイベントが書けるよう改良していきます。