Minecraftとタートルと僕

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

こちらのページは更新が滞っており、情報が古くなりつつあります。新しいCC情報サイトをはじめましたので、もしよければご参照ください。今後ともよろしくお願い申し上げます。

「百億のマインクラフトと千億のタートル」(https://hevo2.hatenablog.com/)

外部モニタに図形を描こう

前回までのお話

前回までは、「ターミナル画面」で絵を描く方法を紹介してきました。
今回は外部モニタに絵を描く方法を紹介しましょう。

今回も色を使うので、金色のAdvanced Monitorは必須です。
f:id:hevohevo:20140206195101p:plain:w300f:id:hevohevo:20140208011307p:plain:w300

まずは画素数のチェック

ターミナル画面でも画素数をチェックしましたが、同様に外部モニタも画素数がいくつなのかチェックしてみましょう。

local mon = peripheral.wrap("top") -- モニタ操作関数ゲット
mon.clear() -- モニタ表示消去
mon.setCursorPos(1,1) -- カーソル位置を初期化

local w, h = mon.getSize() -- サイズをゲット
mon.write(string.format("%d %d", w, h))

f:id:hevohevo:20140208012011p:plain
金モニタ1つだと、幅が7、高さが5であることがわかります。
もちろんモニタをたくさんつなげることで画素数を増やすことも可能です。

でも7x5という画素数だと少なく感じますね。
もっと増やすことはできないのでしょうか。

結論から言うと可能です。

外部モニタの画素数を増やす

すでに描画原理を知っていますよね。ようは、1文字=1つの点(画素)なのです。
ということは、文字のサイズを小さくして、画面内にできるだけたくさんの文字が書けるようにすれば良いわけです。

local mon = peripheral.wrap("top")
mon.clear()

mon.setTextScale(1)
local w0, h0 = mon.getSize()

mon.setTextScale(0.5)
local w1, h1 = mon.getSize()

mon.setCursorPos(1,1)
mon.write(string.format("before: %d, %d",w0,h0))

mon.setCursorPos(1,3)
mon.write(string.format("after: %d, %d",w1,h1))

f:id:hevohevo:20140208012812p:plain
文字の大きさは、倍率で指定することができます。最初は「1」です。
倍率は、mon.setTextScale()関数を利用することで、0.5から5.0までの0.5刻みで変更可能です。
今回はできるだけ画素数を多くするために、もっとも小さい文字、すなわち0.5に設定しました。

これで解像度を15x10まで増やすことができました。

なおこの手法は、外部モニタでしか使えません。
ターミナル画面では文字サイズを変えることができないのです。残念。

Paintutils APIを使う場合

前回紹介したPaintutils APIは、「ターミナル画面」で点を描き、線を引く関数を提供してくれるのですが、一工夫することでそのまま外部モニタにも出力することができます。

それはTerm APIのterm.redirect()term.restore()関数を使うことです。

term.redirect(モニタテーブル)

  • それ以降に行われるTerm APIによるターミナル画面系の描画を、指定したモニタにリダイレクト(自動転送)する。
  • 引数は、peripheral.wrap関数で取り出したモニタ関数テーブル

term.restore()

  • term.redirect()によって行われているリダイレクトをやめて、元のターミナル画面描画に戻す。
サンプルコード
-- ### function
function drawRectangle(startX, startY, goalX, goalY, color)
  for y=startY, goalY do
    paintutils.drawLine(startX, y, goalX, y, color)
  end
end

-- ### main
local mon = peripheral.wrap("top")
mon.setTextScale(0.5)

drawRectangle(2,2,9,9, colors.blue) -- ターミナル画面に長方形描画

term.redirect(mon) -- モニタにリダイレクト開始
drawRectangle(2,2,9,9, colors.blue) -- モニタに長方形描画
term.restore() -- リダイレクト、終了
外部モニタ側

f:id:hevohevo:20140208013256p:plain:h150

ターミナル画面側

f:id:hevohevo:20140208013403p:plain:h150

自分で描画関数を定義する

リダイレクトが嫌いな人は自分で関数を定義してもいいのですよ?
たとえば次のように。

function drawPixel(x, y, color, mon)
  mon.setBackgroundColor(color)
  mon.setCursorPos(x,y)
  mon.write(" ")
end

function drawRectangle(startX, startY, goalX, goalY, color, mon)
  mon.setBackgroundColor(color)
  for y=startY, goalY do
    for x=startX, goalX do
      mon.setCursorPos(x,y)
      mon.write(" ")
    end
  end
end

なお、drawLineは省略しました(斜め線を引くときの計算式がめんd)。

まとめ

外部モニタ(金色モニタ)に図形を描くときの基本知識

  • 「mon = peripheral.wrap(方向)」でモニタテーブルをゲット
  • mon.setTextScale(0.5)で、文字サイズを最小にして画素数アップ!
  • term.redirect(モニタテーブル)を使うことでターミナル画面に描画する関数をそのまま外部モニタ描画に流用できる。
    • たとえば Paintutils APIの drawPixel()やdrawLine()をそのままモニタ描画に使える。
    • print()やwrite()もリダイレクトされる
    • term.redirect()でリダイレクト開始、term.restore()でリダイレクト終了