Minecraftとタートルと僕

PCゲームMinecraftのMOD「ComputerCraft」の情報を集めたニッチなブログです。

sleep実装からイベントを学ぶ(4)―メニュー画面を作る

ひゃっはー! ようやく仕事納めだ。年末進行やっとおわた。
更新するぜ。ちょー更新するぜ。

前回の課題について

前回出した課題は、以下のようなメニュー画面を作ることでした。
f:id:hevohevo:20131228221958p:plain:w400

解答例

解答例は以下のとおり。
前回の「@」キャラクター移動プログラムを素直に改造すると次のようなプログラムになるはずです。

http://pastebin.com/CrqTxpMj

プログラム解説

メイン部分が肥大化しているので個人的には気持ち悪いのですが、とにかく解説していきましょう。

  • L8-13)このプログラムの要となるmoveSymbol(x,y)の定義部分ですが、「>」というキャラクタを動かすことくらいでしょうか、変更点は。
  • L18-24)メニューの項目を書き込む部分です。画面に文字を書き込む関数については、次の節にまとめました。
  • L27)このプログラムで拾うイベントはKeyイベントのみです。
  • L28)現在カーソルがある位置のX座標とY座標の2つの値が返ってきます。
    • 2つの値のうちY座標しか使わないので、X座標に該当する値は無名変数(形式的にここに代入するけど実際には使わずに捨てるよ)に代入します。無名変数は「_」(半角アンダーバー)と記載します。
    • なお、このカーソル現在位置のY座標(変数y)は以下のために使います。
      • (1)キャラクターがメニューからはみ出さないようにy座標をIFの条件節に使う
      • (2)選択を確定する時にY座標を使ってどの選択をしたかを判別する(y=1ならEASY)
  • L30)IFでイベントの名前が「key」であることを確認。なおこのIF文を削っても正常に動きます。
  • L31-34)keycodeを調べて、「↑」「↓」のみキャラクターを移動しています。
  • L35-53)keycodeを調べてスペースキーだった場合の処理を書いています。
    • キャラクターの現在Y座標によって、処理を分岐させています。以下は、Y=1、すなわちEASYを選択した場合の解説です。
      • L37)まず、画面表示を全部消去して
      • L38)カーソル位置を(1,1)にセット
      • L39)画面にEASYと書き込んで
      • L40)breakでwhileループを抜けてプログラム終了。

【補足】画面に文字を書き込む関数について

(2014/02/04修正・追記) term.write()関数と、write関数は別の関数であるにも関わらず混同した書き方をしていました。お詫びと訂正をいたします。

  • ターミナル画面に文字を書き込むときは普通は、term.write() write()を使います。
  • ただしterm.write() write()は、print()と異なり、書き込んだ後に自動改行しません。
  • term.write() write()で改行させたい場合には、改行コード「¥n」(半角円マーク、小文字n)を使います。
    • なお、CCは日本語を使えませんので、CC上での表示は、「¥」(半角円マーク)から「\」(半角バックスラッシュ)に変わっています(上記プログラムのL20を参照)。

よって、次のようにterm.write() write()関数を使うと、

write("123\n456\n789")

以下のようにターミナル画面上に表示されます。

123
456
789


以下の3つの例はほぼ同じ動作を行います。全て、カーソルの座標が(1,1)から(1,2)になることに注意してください。

> term.setCursorPos(1,1) -- 座標(1,1)にカーソル位置をセット
> write("123")
> term.setCursorPos(1,2) -- 次の行の先頭にカーソル位置をセット(つまりは改行)
> term.setCursorPos(1,1)
> write("123\n")  -- 改行コードにより改行
> term.setCursorPos(1,1)
> print("123")      -- 自動改行

解答例2(全体的に再構成版)

なお、上記のものに不満があったので、全体的に再構成したのがこちら。
http://pastebin.com/AvjNZdSZ

解説はしませんが、いくつかポイントを。

  1. メイン部分が肥大化しているので、サブ関数でモジュール化することでモテカワスリムに
  2. メニュー項目を後から追加・編集可能に。config部分を書き換えることで設定可能。
  3. メニューを常に画面の左上に表示するというのは味気ないので、画面のどの位置にメニュー表示するかを設定可能にした。設定項目はBASE_XとBASE_Y。
  4. スペースキーで選択をした後に、選択項目によって行う内容を分岐させる処理はchoose()関数に委託。

次回のお話

こんどは、イベントの中でもすこしだけ特殊な、タイマーイベントについて解説しましょう。
今度の更新は早めにできる予定です。

ではでは。(次回、年内に更新する予定なので年の瀬のあいさつはまだしませんよ)