人工知能に関する断創録

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

マップの新規作成

今回は新しいマップを作れるようにします。新しいマップを作るときはマップの名前、行数、列数、デフォルトマップチップを指定します。これらの情報を入力する必要がありますが、Pygameにはテキストボックスが用意されていません。自作する必要があります。RPG編のメッセージウィンドウの表示(2008/6/28)で作成したWindowクラスを拡張してキー入力を読み取れるInputWindowも合わせて作ります。

マップの新規作成はNキーです。マップ名、行数、列数、デフォルトマップチップを入力すると新しいマップが作られます。今まで作ってたマップは消えてしまうので注意してください。

pymap05.zip
f:id:aidiary:20100807175519p:plain

テキストを入力する

キー入力を読み取るInputWindowを作成します。InputWindowは下のように使います。

  name = input_wnd.ask(screen, "NAME?")
  row = int(input_wnd.ask(screen, "ROW?"))
  col = int(input_wnd.ask(screen, "COL?"))
  default = int(input_wnd.ask(screen, "DEFAULT?"))

InputWindowのask()を呼び出すと画面上にスクリーンショットのようなウィンドウが表示されます。このウィンドウでキーを入力するとテキストが表示されます。バックスペースキーでテキストを消すこともできます。入力できるのは大文字のアルファベットまたは数字だけです。日本語は入力できません。エンターキーを押すとウィンドウが消えて入力した内容はask()の戻り値になります。

InputWindowの詳細

InputWindowはRPG編のメッセージウィンドウの表示(2008/6/28)で作ったWindowクラスの拡張です。テキストはメッセージエンジン(2008/6/28)で作ったMessageEngineを使っています。

class InputWindow(Window):
    def __init__(self, rect, msg_engine):
        Window.__init__(self, rect)
        self.msg_engine = msg_engine
    def get_key(self):
        """キー入力を読み取る"""
        while True:
            event = pygame.event.poll()
            if event.type == KEYDOWN:
                return event.key
            else:
                pass
    def draw(self, screen, message):
        Window.draw(self, screen)
        if len(message) != 0:
            self.msg_engine.draw_string(screen,
                            self.inner_rect.topleft, message)
            pygame.display.flip()
    def ask(self, screen, question):
        cur_str = []
        self.show()
        self.draw(screen, question)
        while True:
            key = self.get_key()
            if key == K_BACKSPACE:
                cur_str = cur_str[0:-1]
            elif key == K_ESCAPE:
                return None
            elif key == K_RETURN:
                break
            elif K_0 <= key <= K_9 or K_a <= key <= K_z:
                cur_str.append(chr(key).upper())
            self.draw(screen, question + u" " + "".join(cur_str))
        return "".join(cur_str)

ask()でメッセージウィンドウを表示したらwhileループに入り、get_key()で入力したキーを取得してcur_strに追加しています。cur_strはdraw()で画面に描画されます。このコードは、InputBoxを参考に作成しました。残念ながらPygameでは日本語入力ができないようです。というかPygameの元になっているSDLでもできないようです。これだとMMORPGのチャットとかは作れないですね・・・何かいい方法があればいいんですが。

マップの新規作成

新規作成の処理はイベントハンドラに書いています。Nキーを押すとマップ名、行数、列数、デフォルトマップチップをたずねるInputWindowが表示されます。入力したデータで新しいMapオブジェクトを作り、mapに格納しています。

            elif event.type == KEYDOWN and event.key == K_n:
                # 新規マップ
                try:
                    name = input_wnd.ask(screen, "NAME?")
                    row = int(input_wnd.ask(screen, "ROW?"))
                    col = int(input_wnd.ask(screen, "COL?"))
                    default = int(input_wnd.ask(screen, "DEFAULT?"))
                except ValueError:
                    print "Cannot create map"
                    continue
                map = Map(name, row, col, default, palette)

これで新しいマップを作れるようになったのですがまだ保存ができません。次回はマップを保存する機能を実装します。