読者です 読者をやめる 読者になる 読者になる

Minecraftとタートルと僕

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

モニタ使用のチュートリアル

モニタ(Monitor)の基礎知識

  • コンピュータのすぐ隣(上下左右どちらでも)に置いたモニタに色々な表示ができる
  • モニタブロックを四角形の形に置けば結合して大きな一つのモニタとなる(どのサイズまでいけるかは知らない)
  • カラー表示させたいならAdvanced Monitor(金色)を使うこと
  • モニタ表示の方法は以下の3種類あるが(たぶん)、この記事では、1番目について説明する。
    • モニタ側であらかじめ用意された関数を使って、直接モニタへ表示操作を行う。
    • コンピュータの画面に表示しているものを「monitor」コマンドを使ってそのまま隣接したモニタに表示する。なお、コンピュータ画面の表示についてはTerm APIを使うこと。
    • Term APIの中に、「隣接したモニタに表示先を切り替える」関数(redirect/restore)があるので、利用する

モニタに用意された関数を見る方法

モニタにはあらかじめ色々な関数が用意されている。

関数一覧は、非公式日本語Wikiにまとめてあるのでぜひ見よう。便利!

あるいは、プログラムを実行することで関数一覧を表示させることもできる。
以下のプログラムを入力して実行しよう。
ここではコンピュータの上にモニタを設置したと仮定する。

mon = peripheral.wrap("top")

for k,v in pairs(mon)
  print(k,' = ',v)
end

peripheral.wrap(モニタの設置方向)によって、外部装置としてモニタを認識させている。
変数monには、table型で、モニタ操作のための関数が入っている。
for ~ endの部分は、tableの中身を全部表示するための慣用表現。Luaではよく使うので覚えておくと吉。

チュートリアル1:「モニタに時間を表示する」

(2014/07/27誤植修正、setCursorPosition → setCursorPos)

f:id:hevohevo:20131205074853p:plain:h300

mon = peripheral.wrap("top")

mon.clear()

while true do
 time = os.time()
 time_str = textutils.formatTime(time)

 mon.setCursorPos(1,1)
 mon.clearLine()
 mon.write(time_str)

 sleep(1)
end
  • mon = peripheral.wrap("top") は、外部装置を直接操作するときの決まり文句。
    • 外部装置がコンピュータの右にあるなら"right"、左なら"left"、下にあるなら"bottom"
    • 変数monに、外部装置を操作するための関数群を代入している。変数名は好きな名前でいい。
    • この中身はtable型なので、mon.ほげほげ() という形式で、用意された関数を利用可能。
  • mon.clear()は、モニターに表示されている内容を全部消去する。
    • プログラム開始時に1回だけ、実行しておくと良い。
    • モニタが大きいと全消去するのに時間がかかるので、多用すると画面がチラつく可能性アリ。
  • os.time()は、os APIであらかじめ用意された関数。ゲーム内時間を実数で返す。
    • 18時ちょうどなら18、18時半なら18.5のように返すが、18.75(つまり18時45分)とか言われても時計表示としては見づらすぎる
    • なので、textutils APIの formatTime関数を使うことで時計表示形式に直している。
    • なお、formatTimeの2番目の引数としてtrueを与えると24時間表示となる。
    • textutils.formatTime(18.75) → "6:45 PM"
    • textutils.formatTime(18.75,true) → "18:45"
  • mon.setCursorPos(1,1)は、カーソルの位置(文字表示する位置)を一番左上にセットしている。
    • setCursorPos(横,縦)という書式で、一番左上が座標(1,1)となっている。
    • もし2行目の先頭から文字表示したいならsetCursorPos(1,2)とする。
    • 現在のカーソル位置を常に把握しておくのは大変なので、たとえ冗長であったとしても、write()する直前の位置でカーソル位置をセットしておくとバグが減るのでお勧め。
  • mon.clearLine() は、その行に表示されている文字列を消去する。
    • ここでは前回の時計表示を消している。
  • mon.write(文字列)は、現在のカーソル位置から文字列を書き込んでいく。
    • print()関数と異なり、「自動改行はしない」。
    • カーソル位置(1,1)でwrite("abcde")すると、現在のカーソル位置は(6,1)に移動する。
    • また、write()による書き込みは、以前の表示への上書きなので注意。
    • たとえば、1行目に"12345"と表示されているときに、カーソル位置(1,1)からwrite("abc")すると、1行目の表示は、"abc45"となる。
    • だから、write()する前にclearLine()を使って前の表示を消しておくか、綺麗に上書きできるよう文字列の長さを調整しておくこと。
  • sleep(1)
    • while文使うときはsleep()を必ず入れる。これはCCプログラマのお約束。
    • 今回は実時間1秒のスリープを入れているので、この時間表示は実時間1秒ごとに更新される。

チュートリアル2:「明るいうちは黄色、暗くなったら青で時間を表示」

(2014/07/27誤植修正、setCursorPosition → setCursorPos)

f:id:hevohevo:20131205074857p:plain:h300

mon = peripheral.wrap("top")

mon.clear()

while true do
 time = os.time()
 time_str = textutils.formatTime(time)

 if time > 6 and time < 18.5 then
   mon.setTextColor(colors.yellow)
 else
   mon.setTextColor(colors.blue)
 end

 mon.setCursorPos(1,1)
 mon.clearLine()
 mon.write(time_str)

 sleep(1)
end

ゲーム内時間6:00~18:30(実数表現では、6~18.5)を黄色、それ以外の時間を青にしているけれど、厳密に言うとこれは昼夜の区別ではないので注意。
ベッドに入ることができる時間が18:30~で、起きると6:00になるというそれだけの理由!
実際はどうなんだろう。どこかに資料ないだろうか・・・・・・。

チュートリアル3:「ゲーム内経過日数も、時計と一緒に表示する」

(2014/07/27誤植修正、setCursorPosition → setCursorPos)

f:id:hevohevo:20131205074901p:plain:h300

mon = peripheral.wrap("top")

mon.clear()

while true do
 time = os.time()
 time_str = textutils.formatTime(time)

 day = os.day()

 if time > 6 and time < 18.5 then
   mon.setTextColor(colors.yellow)
 else
   mon.setTextColor(colors.blue)
 end

 mon.setCursorPos(1,1)
 mon.clearLine()
 mon.write(time_str)

 mon.setCursorPos(1,2)
 mon.clearLine()
 mon.write(day.."days")

 sleep(1)
end

os.day()関数で、ゲーム内経過日数を得ることができる。
mon.setCursorPos(1,2)することで、2行目に経過日数を表示している。

画像内の日数については突っ込まないこと。ゲーム内1日が実時間20分として、……我ながらドン引きw こまめにベッドで寝ているからだよね。きっと。

最後に

このチュートリアルを書いたのは、日本語 Minecraft WikiにあるCCページのコメントで、モニターのチュートリアルを希望している人がいたからなんだけど、Wikiでこれだけの分量を書くとさすがに顰蹙ものだよね・・・・・・。
この記事を転載してもいいので、だれか短くWikiのページにまとめてくれる人はいないかな(チラッチラッ

日本語 Minecraft WikiにあるCCページと言えばもうひとつ気になるのが、
掲載されているプログラムにインデントないのはWikiのシステム的な問題かな?
サブ関数ほとんど作ってない長文プログラムがあるけど、インデントないのとあいまって見るのが苦痛すぎる。