Scratch2MCPI プログラミング⑤いろいろな種類の屋根を作る

⑤いろいろな種類の屋根を作る


Image


通称「豆腐ハウス」をご存知ですか? 上のスクリーンショットは、この講義の中で最初に作った家です(「マインクラフトで建築を楽しむ」参照)。屋根が真っ平らで豆腐みたいに、真四角な家のことを「豆腐ハウス」と言います。一番作りやすいので、初心者なら一度は作ると思いますが、慣れてくるともっとカッコいい家が作りたくなってくるものです。

三角屋根にグレードアップしたいのですが、平らな屋根に比べると手間と時間がかかってしまいます。こういうときこそプログラミングの出番です。プログラムで「三角屋根」を作ってみましょう。さらに「なだらかな屋根」や「とんがった屋根」、「丸い屋根」と形を変えて、いろいろな種類の屋根作りに挑戦します。


屋根の設計図を Excel で作成する


まずはこれから作る屋根をイメージするために、簡単な設計図を書いてみましょう。


Image


家の設計図を Excel で書いてみました。ごく普通の「 45度の屋根」です。これは分かりやすく、作りやすいので作ったことがある人もいるかもしれません。屋根の形は「横に1つ進むと、1つ上がる(下がる)」という繰り返しです。


Image


次の設計図は「なだらかな屋根」です。「横に2つ進むと、1つ上がる(下がる)」繰り返しになっています。


Image


「とんがり屋根」は、急角度の屋根です。「横に1つ進むと、2つ上がる(下がる)」という繰り返しです。


こういった屋根が作れたら楽しいです。建築の幅も広がります。

「プログラムで、いろいろな種類の屋根を建築するのは、どうすればよいか?」を考えていきます。


グラフについて


例えば、9つの点の集まりが与えられたとします。

(0, 3), (1, 4), (2, 5), (6, 9), (8, 8), (9, 7), (11, 5), (12, 4), (13, 3)


一見バラバラなデータの集まりですが、ある法則が隠されているのです。どんな法則なのか? 少し考えてみましょう。


その法則とは「すべての点がグラフの直線上に乗っかっている」ということです。下の図がそのグラフです。すべての点(赤点で示されている)がグラフ上にあることを確認してください。


Image


グラフとは、データを直感的に捉えられるように、視覚的に図として表したものです。一見バラバラな点の集まりもグラフ上の点として捉えると、ある法則を持ったものとして、理解しやすくなります。例えば、この点の集まりをグラフ上の点だと理解すれば、データとして与えられていない X = 3 の場合も Y = 6 であるだろうと、簡単に予測することができるようになるのです。


上の図をよく見てください。グラフ上の点で、屋根の高さを指定することができます。つまり、先ほど与えられた点の集まりは、「45度の屋根」を作るためのデータの一部であったのです。

もしグラフがなかったら、14段の屋根の場合は14個の高さのデータをあらかじめ計算してプログラムに与えておかなくてはなりません(これは配列と言います。次回学習します)。グラフの場合は、プログラムが自動で計算して高さを決めてくれるので便利です。

プログラムにグラフを取り入れてみましょう。


「45度の屋根」をプログラムで建築する


Image


グラフを利用したプログラムを作成していきましょう。「プログラムでこんな複雑な形が作れるかな」と心配になるかもしれません。しかし段階を追って一つずつ進めれば、それほど難しいプログラムではありませんから、安心してください。


X-Y 平面上にグラフ「y = x + 3」を描く


Image


グラフを描くための準備として、変数を3つ追加します。

カテゴリー「変数」→「新しい変数を作る」を選びます。変数名を「x」と入力して、「OK」をクリックします。同様に、変数「y」「z」も作成しておきます。これらの変数は、グラフ上の位置を表すために使用します。マインクラフトの世界の座標を表す「mcpiX」「mcpiY」「mcpiZ」とは、明確に役割を分けて考えていきます。


Image


上のスクリーンショットの通りにブロックを組み上げてください。赤枠の部分が変数の初期設定の部分です。マインクラフトの座標 (0, 0, 10)を基準点として、グラフを書いていくことを示しています。赤い屋根にするために、ブロックは「赤の羊毛(blockTypeId = 35, blockData = 14)」を選びました。そしてグラフの座標 x = 0 と設定しました。

青枠の部分がグラフを描くスクリプトです。[mcpiY v]を((x)+(3))にするが、グラフ(y = x + 3)から屋根の高さを決めるブロックです。[setBlock v]を送るで、その高さに赤いブロックを設置します。mcpiX, x の値を共に1つずつ増やしながら、14個のブロックを設置していきます。


[mcpiX v] を [0] にする
[mcpiY v] を [0] にする
[mcpiZ v] を [10] にする
[blockTypeId v] を [35] にする
[blockData v] を [14] にする
[x v] を [0] にする
(14) 回繰り返す
  [mcpiY v] を ((x)+(3)) にする
  [setBlock v] を送る
  (0.1) 秒待つ
  [mcpiX v] を (1) ずつ変える
  [x v] を (1) ずつ変える
end

スクリプトを実行して、45度の角度で1直線に登っていく線を描くことができました。

屋根の登り部分はできましたので、次は屋根の下りの部分を作っていきます。


X-Y 平面上にグラフ「y = x + 3 (x < 7)」「y = - x + 16 (7 ≦ x)」を描く


Image


上のスクリーンショットの通りにスクリプトを修正します。赤枠の部分は、条件分岐で参照するグラフを変えているスクリプトです。x の値が「0, 1, 2, 3, 4, 5, 6」のときは、グラフ「y = x + 3」によって屋根の高さを決定しています。そして、x の値が「7, 8, 9, 10, 11, 12, 13」のときは、グラフ「y = - x + 16」を参照して屋根の高さを決定しています。それ以外の部分は前項のスクリプトと全く同じです。


[mcpiX v] を [0] にする
[mcpiY v] を [0] にする
[mcpiZ v] を [10] にする
[blockTypeId v] を [35] にする
[blockData v] を [14] にする
[x v] を [0] にする
(14) 回繰り返す
  もし <(x) < [7]> なら 
    [y v] を ((x) + (3)) にする
  でなければ 
    [y v] を (((-1) * (x)) + (16)) にする
  end
  [setBlock v] を送る
  (0.1) 秒待つ
  [mcpiX v] を (1) ずつ変える
  [x v] を (1) ずつ変える
end

屋根の形に近づいてきました。次は Z方向に屋根を伸ばしてやります。


コラム グラフを計算で求める①

なぜ、下の屋根はグラフ「y = - x + 16」になるのだろう? と疑問に思った方へ、計算方法を示しておきます。

求めるグラフは、傾きがマイナス1と決まっていますから、y = - x + a と仮定することができます。この a の値を求めればよいのです。

条件としては、屋根の一番上の高さが、y = x + 3 と同じにならなくてはいけません。2つのグラフのつなぎ目は、y = x + 3(x = 6)と y = - x + a(x = 7)なので、


6 + 3 = - 7 + a

a = 16


となります、よってグラフ「y = - x + 16」が求められました。


Z方向に伸ばして、屋根を完成させる


Image


[setBlock v]を送る(10)回繰り返す[mcpiZ v]を(1)ずつ変えるで囲むことで、屋根をZ方向に伸ばすことができます。


[mcpiX v] を [0] にする
[mcpiY v] を [0] にする
[mcpiZ v] を [10] にする
[blockTypeId v] を [35] にする
[blockData v] を [14] にする
[x v] を [0] にする
(14) 回繰り返す
  もし <(x) < [7]> なら 
    [y v] を ((x) + (3)) にする
  でなければ 
    [y v] を (((-1) * (x)) + (16)) にする
  end
  (10) 回繰り返す 
    [setBlock v] を送る
    (0.1) 秒待つ
    [mcpiZ v] を (1) ずつ変える
  end
  [mcpiZ v] を (-10) ずつ変える
  [mcpiX v] を (1) ずつ変える
  [x v] を (1) ずつ変える
end

Z方向の10回繰り返しの後で、Z方向のリセットのため[mcpiZ v]を(-10)ずつ変えるを挿入することを忘れないようにしましょう。


グラフ部分をサブルーチンにする


Image


これで「45度の屋根」は完成ですが、今後の作業を進めやすくするために、サブルーチンを作って整理しておきます。


[mcpiX v] を [0] にする
[mcpiY v] を [0] にする
[mcpiZ v] を [10] にする
[blockTypeId v] を [35] にする
[blockData v] を [14] にする
[x v] を [0] にする
[roof v] を送って待つ

[roof v] を受け取ったとき
(14) 回繰り返す 
  [roof_height v] を送って待つ
  [mcpiY v] を (y) にする
  (10) 回繰り返す 
    [setBlock v] を送る
    (0.1) 秒待つ
    [mcpiZ v] を (1) ずつ変える
  end
  [mcpiZ v] を (-10) ずつ変える
  [mcpiX v] を (1) ずつ変える
  [x v] を (1) ずつ変える
end

(14)回繰り返すを切り離して、サブルーチン「roof」として分離します。


[roof_height v] を受け取ったとき
もし <(x) < [7]> なら 
  [y v] を ((x) + (3)) にする
でなければ 
  [y v] を (((-1) * (x)) + (16)) にする
end

グラフで高さを決める部分をサブルーチン「roof_height」として分離します(roof は屋根、height は高さのことで、アンダーバーでつなぎます)。ブロックを置く機能と屋根の高さを計算する機能を分けることで、屋根の形状を変更しやすくなります。


上のスクリーンショットを見てください。矢印で処理の流れを示しました。

変数の初期値を設定してから、[roof v]を送って待つで、サブルーチン「roof」を呼び出します。それから屋根の高さを決めるために[roof_height v]を送って待つで、x の値をサブルーチン「roof_height」に代入し、y の値を求めます。y の値を mcpiY に代入して、 Z方向に10個ブロックを置きます。「mcpiX,」「x」の値を1つずつ増やしながら、14回同じことを繰り返します。

以上が、サブルーチンの機能の説明です。矢印を見ながら処理の流れを理解しておいてください。


「なだらかな屋根」をプログラムで建築する


Image


屋根の形を変えるには、サブルーチン「roof_height」のグラフを変更するだけです。まずは「なだらかな屋根」を作ります。


Image


グラフを「y = 0.5 x + 7 (x < 7)」「y = - 0.5 x + 13.5 (7 ≦ x)」に変更しました。問題なく、なだらかな屋根が作成されました。成功です。


[roof_height v] を受け取ったとき
もし <(x) < [7]> なら 
  [y v] を (((0.5) * (x)) + (7)) にする
でなければ 
  [y v] を (((-0.5) * (x)) + (13.5)) にする
end

*サブルーチン「roof_height」において、x に 1 より小さい数をかけると、なだらかな屋根が建築できます。0.5 以外の数字にして確かめてみてください。

一つ注意点ですが、マインクラフトの世界の建築では小数点以下は無視されます。例えば、今回のグラフ「y = 0.5 x + 7 」について、mcpiX = 1, mcpiY = 7.5 の位置にブロックを置こうすると、高さは 7 の位置にブロックが設置されるのです。「ブロックの位置は小数点以下は切り捨て」ということを覚えておきましょう。


コラム グラフを計算で求める②

2つのグラフのつなぎ目は、y = 0.5 x + 7(x = 6)と y = - 0.5 x + a(x = 7)が同じ高さになるためには


3 + 7 = - 3.5 + a

a = 13.5


となります、よってグラフ「y = - 0.5 x + 13.5」が求められました。


「とんがり屋根」をプログラムで建築する


Image


グラフを「y = 2 x + 3 (x < 7)」「y = - 2 x + 29 (7 ≦ x)」に変更しました。


[roof_height v] を受け取ったとき
もし <(x) < [7]> なら 
  [y v] を (((2) * (x)) + (3)) にする
でなければ 
  [y v] を (((-2) * (x)) + (29)) にする
end

屋根の形はできましたが、すきまが空いてしまいました。これでは雨漏りしてしまうので、スクリプトを修正していきます。考え方としては、mcpiX が一つ動くとき、mcpiY が2段以上、上がる(下がる)ときはすきまができてしまうので、すきまを埋めるサブスクリプト「fill_gap(= すきまを埋める)」を追加します。


コラム グラフを計算で求める③

2つのグラフのつなぎ目は、y = 2 x + 3(x = 6)と y = - 2 x + a(x = 7)が同じ高さになるためには


12 + 3 = - 14 + a

a = 29


となります、よってグラフ「y = - 2 x + 29」が求められました。


サブルーチン「fill_gap」を追加する


Image


すきまを埋めるスクリプトを追加します。


[roof v] を受け取ったとき
(14) 回繰り返す 
  [roof_height v] を送って待つ
  [mcpiY v] を (y) にする
  (10) 回繰り返す 
    [setBlock v] を送る
    (0.1) 秒待つ
    [mcpiZ v] を (1) ずつ変える
  end
  [mcpiZ v] を (-10) ずつ変える
  [fill_gap v] を送って待つ
  [mcpiX v] を (1) ずつ変える
  [x v] を (1) ずつ変える
end

[mcpiZ v]を(-10)ずつ変えるの後ろに[fill_gap v]を送って待つを挿入します。

[fill_gap v]を受け取ったときの下に、すきま埋めのスクリプトを書いていきます。


カウンター変数の追加


Image


屋根の高さを比べるため、カウンター変数を追加します。i は現在の高さ、j は次の段の高さを表しています。


[fill_gap v] を受け取ったとき
[i v] を (((y) - (0.5)) を四捨五入) にする
[x v] を (1) ずつ変える
[roof_height v] を送って待つ
[j v] を (((y) - (0.5)) を四捨五入) にする
[x v] を (-1) ずつ変える

高さを比較しやすいように、戻り値 y の値は小数点以下切り捨てしてあります。(y)を四捨五入は四捨五入するブロックです。((y)-(0.5))を四捨五入 にすると、切り捨てとなります。( Scratch のバージョンアップにより、「を丸める」の表記が「を四捨五入」に変更されていますが、同じものと考えてください。)


すきまを埋める


Image


前後のカウンター変数を比べて、すきまを埋めるスクリプトを追加しました。


[fill_gap v] を受け取ったとき
もし <(x) < [13]> なら 
  [i v] を (((y) - (0.5)) を四捨五入) にする
  [x v] を (1) ずつ変える
  [roof_height v] を送って待つ
  [j v] を (((y) - (0.5)) を四捨五入) にする
  [x v] を (-1) ずつ変える
  もし <[1] < ((j) - (i))> なら 
    [mcpiX v] を (1) ずつ変える
    (((j) - (i)) - (1)) 回繰り返す 
      [mcpiY v] を (1) ずつ変える
      (10) 回繰り返す 
        [setBlock v] を送る
        (0.1) 秒待つ
        [mcpiZ v] を (1) ずつ変える
      end
      [mcpiZ v] を (-10) ずつ変える
    end
    [mcpiX v] を (-1) ずつ変える
  end
  もし <((j) - (i)) < [-1]> なら 
    (((i) - (j)) - (1)) 回繰り返す 
      [mcpiY v] を (-1) ずつ変える
      (10) 回繰り返す 
        [setBlock v] を送る
        (0.1) 秒待つ
        [mcpiZ v] を (1) ずつ変える
      end
      [mcpiZ v] を (-10) ずつ変える
    end
  end
end

Image


オレンジ枠が、一度に2段以上、上がってすきまができてしまう場合(1 < j - i)にすきまを埋めるスクリプトです。mcpiX を1つ増やしてから、すきまを埋める回数(j - i - 1)上方向にすきまを埋めていきます。

青枠が、一度に2段以上、下がってすきまができてしまう場合(j - i < - 1)にすきまを埋めるスクリプトです。すきまを埋める回数(i - j - 1)、下方向にすきまを埋めていきます。

最後に赤枠の部分ですが、x = 13 のとき、最後の屋根部品が1段になるように条件分岐を追加してあります。


苦労しましたが、これで雨漏りのしない屋根を作ることができました。これでどのようなグラフにも対応できる屋根作りスクリプトが完成しました。


*サブルーチン「roof_height」において、x に 1 より大きい数をかけると、急勾配の屋根が建築できます。2 以外の数字にして確かめてみてください。


「かまぼこ屋根」をプログラムで建築する


Image


ラズベリーパイにインストールされている「Mathematica(マセマティカ)」という数学ソフトで描いた円のグラフです。半径 6.5 中心が (6.5, 5) のグラフは


y = 6.5 2 - ( x - 6.5 ) 2 + 5

で表されます。


Image


サブルーチン「roof_height」を上のスクリーンショットの通りに変更してください。


[roof_height v] を受け取ったとき
[y v] を (([平方根 v] \( (((6.5) * (6.5)) - (((x) - (6.5)) * ((x) - (6.5)))) \)) + (5)) にする

かまぼこ屋根の建築が自動で行うことができます。円形がこんなに簡単に建築できるなんて、プログラミングは素晴らしい!


「コサイン屋根」をプログラムで建築する


Image


「Mathematica」で描いた三角関数(コサイン)のグラフです。振幅(振り幅)が 6 で 中心が (6.5, 5) のグラフは


y = 6

Cos [ 180 13

( x - 6.5 )

]
+ 5

で表されます。


Image


サブルーチン「roof_height」を上のスクリーンショットの通りに変更してください。


[roof_height v] を受け取ったとき
[y v] を (((6) * ([cos v] \( (((180) / (13)) * ((x) - (6.5))) \))) + (5)) にする

コサイン屋根の建築が自動で行うことができます。かまぼこ屋根と比べて勾配がなだらかで、なかなか良い形をしています。コサイン関数はバネの振動など、自然のあちこちに現れる関数で、数学上でも重要な意味を持っています。


「ファイル」→「名前をつけて保存」から、名前「mcpi_roof」をつけて保存しておきましょう。


いろいろな形の屋根を作ってきました。サブルーチン「roof_height」の数式を変更すれば、思い通りの形の屋根が建築できます。試してください。


このプロジェクト(mcpi_roof.sb)はダウンロードして、自分で確かめることがきます。

サンプルプログラムのページへ

(サンプルプログラムのページに移動します。ダウンロードしたいファイルのリンクをマウスで右クリックして、「対象をファイルに保存」などのメニューを実行してください。)


次回は、三角屋根と窓付きの壁を組み合わせて、1軒の家を完成させます。それから任意の場所に、任意の大きさで複数の家を作る方法を考えます。これができれば、当初の目標であった「家100軒の街つくり」が自動で行えるようになるのです。お楽しみに!


【宿題】自由に屋根を作ってみよう


あなたの考える「最もかっこいい屋根」を設計し、プログラミングで建築してください。