# ドット絵作成プログラムを作ろう
# for文を使いこなそう
本章では、下のようなドット絵の作り方を学んでいきます。これはマインクラフトに登場する敵キャラ『クリーパー』の頭部です。(色は簡単にしています。)
前テキストでも学習したfor
文をさらに使いこなせるようになれば、好きなドット絵を作ることができるようになります。
少し難しい内容になりますが、できることがグッと広がるので、じっくり勉強していきましょう。
# for
文の『ネスト』
まずは、下のコードを見てみましょう。
import mcpi.minecraft as minecraft
import time
mc = minecraft.Minecraft.create()
x, y, z = mc.player.getPos()
for i in range(10):
mc.postToChat(i)
for j in range(5):
time.sleep(0.5)
mc.setBlock(x + j, y + i, z, 35, i)
実行すると、10色のブロックがポコポコと出来上がってくるのがわかるかと思います。その数は、全部で50個にのぼります。同時に、チャット画面に0
から9
までの数字が数え上げられていきますね。
このように、for
文の中にfor
文を使う、入れ子のようなプログラムを書くことができます。これをfor
文の ネスト と言います。このプログラムがどのように動いているのか、詳しく見ていきましょう。
1つ目のfor文
for i in range(10):
今まで勉強してきた
for
文です。range()
の中身の数字の回数だけ、for
文の中身をくりかえします。何回目のくりかえしなのかをチャットに表示
mc.postToChat(i)
くりかえしの回数がわかりやすいように、チャット画面に変数
i
の中身を表示しています。range(10)
の場合は、i
には最初に0
が代入され、くりかえしが進むたびに、1
,2
, ... ,9
まで増えていくのでした。2つ目のfor文
for j in range(5):
for
文の中でさらにfor
文を使います。この場合、range(5)
なので5回くりかえされるわけですが、1つめのfor
文の中なので、これ自体が10回くりかえされます。ややこしいですが、「5回くりかえす」ことを「10回くりかえす」ので、「5 × 10 = 50
回くりかえす」ことになるのです。変数
j
には、くりかえすたびに0
,1
,2
,3
,4
が順番に代入されていきます。0.5秒ずつ待つ
time.sleep(0.5)
くりかえされている順番がわかりやすいように、一回ずつ少し待ってから実行するようにしています。
羊毛ブロックを置く
mc.setBlock(x + j, y + i, z, 35, i)
ここではくりかえしの回数に応じた位置に、羊毛ブロックを置いています。
i
が0
から9
まで変化していくごとに、j
は0
から4
まで増えていきます。プログラムを実行すると、この
mc.setBlock()
メソッドは、mc.setBlock(x + 0, y + 0, z, 35, 0)
mc.setBlock(x + 1, y + 0, z, 35, 0)
︙mc.setBlock(x + 4, y + 0, z, 35, 0)
mc.setBlock(x + 0, y + 1, z, 35, 1)
mc.setBlock(x + 1, y + 1, z, 35, 2)
︙
︙mc.setBlock(x + 3, y + 9, z, 35, 9)
mc.setBlock(x + 4, y + 9, z, 35, 9)
というように変わっていきます。
# リストのリスト
for
文とは少し話が離れますが、リストの少し応用的な使い方を知っておきましょう。
データを番号付きでまとめるためのリストですが、その中身には文字列や数値だけでなく、下のように別のリストも入れることができます。
# 友達の"名前"、"性別"、"年齢"をまとめたリスト
friends = [["Tarou", "male", 14], ["Hanako", "female", 15], ["Takashi", "male", 13]]
例えば、friends[1]
のように番号を指定すると、その番号のリストが呼び出されます。この場合ならば["Hanako", "female", 15]
ですね。
またリストのリストは横に広がって見づらくなりやすいので、下のように書いて見やすくすることも可能です。
friends = [
["Tarou", "male", 14],
["Hanako", "female", 15],
["Takashi", "male", 13]
]
# クリーパーを作ろう
さてここまでの内容で、冒頭のクリーパーを作る準備はほとんど整いました。あとは、設計図となるクリーパーのドット絵があると良さそうです。ゲーム上の実物は、緑を中心としたまだら模様をしていますが、今回は簡単にするために、黄緑と黒の2色だけで作ります。
これを8×8の羊毛ブロックで作っていきます。羊毛ブロックは、番号35
ですが、色を0
〜15
までで選ぶことができました。
番号 | 色 | 番号 | 色 |
---|---|---|---|
0 | 白 | 8 | ライトグレー |
1 | オレンジ | 9 | シアン |
2 | マゼンタ | 10 | 紫色 |
3 | 空色 | 11 | 青 |
4 | 黄色 | 12 | 茶色 |
5 | 黄緑色 | 13 | 緑 |
6 | ピンク | 14 | 赤 |
7 | グレー | 15 | 黒 |
今回は、5
の黄緑と、15
の黒を使って、一つ一つのドットをブロックに置き換えていきます。
クリーパーを、8つのブロック行が、縦に8つ積み重なったものだと考えます。それぞれの行にあるブロックの色番号をリストにすると、例えば一番上の行は[5, 5, 5, 5, 5, 5, 5, 5]
、一番下の行は、[5, 5, 15, 5, 5, 15, 5, 5]
といった感じになります。こうすると、クリーパーを、各行のリストがまとまったリストとして表すことができそうです。
creeper_colors = [
[5, 5, 5, 5, 5, 5, 5, 5],
[5, 5, 5, 5, 5, 5, 5, 5],
[5, 15, 15, 5, 5, 15, 15, 5],
[5, 15, 15, 5, 5, 15, 15, 5],
[5, 5, 5, 15, 15, 5, 5, 5],
[5, 5, 15, 15, 15, 15, 5, 5],
[5, 5, 15, 15, 15, 15, 5, 5],
[5, 5, 15, 5, 5, 15, 5, 5]
]
あまり面影は感じられませんが、これがクリーパーをつくる各ブロックの色をまとめたものになります。あとは、これを上から一行ずつ羊毛ブロックにしていきます。実際のコードは下のようになります。
import mcpi.minecraft as minecraft
mc = minecraft.Minecraft.create()
x, y, z = mc.player.getPos()
creeper_colors = [
[5, 5, 5, 5, 5, 5, 5, 5],
[5, 5, 5, 5, 5, 5, 5, 5],
[5, 15, 15, 5, 5, 15, 15, 5],
[5, 15, 15, 5, 5, 15, 15, 5],
[5, 5, 5, 15, 15, 5, 5, 5],
[5, 5, 15, 15, 15, 15, 5, 5],
[5, 5, 15, 15, 15, 15, 5, 5],
[5, 5, 15, 5, 5, 15, 5, 5]
]
for i in range(8):
row = creeper_colors[i]
for j in range(8):
mc.setBlock(x + j, y + 8 - i, z, 35, row[j])
for
文の部分が分かりづらいですので、詳しく見ていきます。
for i in range(8):
row = creeper_colors[i]
creeper_colors
リストの要素数だけ、for
文でくりかえすようにしています。今回は8行のドット絵なので、8行分の色の情報リストが、要素として入っています。それを一つずつ取り出してブロックにしていきたいので、操作は8回くりかえすため、range(8)
としています。
変数i
には0
から7
までの数字が順に入っていきますので、くりかえすごとに、変数row
の中身は、creeper_colors[0]
からcreeper_colors[7]
まで変わっていきます。creeper_colors[0]
はcreeper_colors
リストの0
番目なので、[5, 5, 5, 5, 5, 5, 5, 5]
ですね。このようにrow
の中身は変化していきます。
英単語
「row(ロウ)」は英語で「行」という意味です。対して、列は英語で「column(カラム)」といいます。
次に2つ目のfor
文です。
for j in range(8):
mc.setBlock(x + j, y + 8 - i, z, 35, row[j])
今度は、各行について、横方向にブロックを並べるために、mc.setBlock()
メソッドを8回くりかえすことになります。
mc.setBlock(x + j, y + 8 - i, z, 35, row[j])
の引数が難しいですね。
# x座標: x + j
ここが、2つ目のfor
文によって変わるポイントになります。j
の値が大きくなるのに伴って、ブロックを置く場所がx方向にずれていきますね。
# y座標: y + 8 - i
ブロックを置く高さ、すなわちクリーパーの、上から何行目かを決めています。ここは、最初のfor
文で決まっています。上から積んでいくために、まず8
を足してからi
を引くことで、くりかえすたびにy + 8
、y + 7
、…、y + 1
まで1行ずつ下がっていきます。
y + 8
の状態で、x座標が大きくなりながら8つブロックを置き、次にy + 7
になり、同じくx座標が大きくなり…という流れで、8回×8回の、計64回ブロックを置いていきます。
# z座標: z
z座標は今回はz
のままで固定します。あまり考える必要はないでしょう。
# ブロック番号: 35
35
は羊毛ブロックでした。羊毛でないといけないわけではないのですが、色の種類が多いので、このような場合には扱いやすいです。
# ブロック種類(色): row[j]
ここでブロックの色を決めます。row
は、1つ目のfor
文がくりかえされるたびに、
[5, 5, 5, 5, 5, 5, 5, 5]
、
[5, 5, 5, 5, 5, 5, 5, 5]
、
︙
[5, 5, 15, 5, 5, 15, 5, 5]
と変化していくのでした。そして2つ目のfor
文がくりかえされるたびに、j
の値が大きくなるため、row[j]
でで取り出す要素も一つずつずれていきます。これと同時に、x座標も進んでいくので、一つ一つちがう色のブロックを置いていくことができます。(今回は2色しかありませんが…)
for
文のネストは慣れるまでとても難しいと思いますが、自分で手を動かして、プログラムを実行して身につけていきましょう。
# 応用編:好きな大きさのドット絵を自在に作るプログラム
今回作成したプログラムは、8×8マス専用のものでしたが、変数を上手く使うことで、簡単に好きな大きさのドット絵を作ることができます。
import mcpi.minecraft as minecraft
mc = minecraft.Minecraft.create()
x, y, z = mc.player.getPos()
colors = [
[0, 0, 15, 15, 15, 15, 15, 15, 0, 0],
[0, 15, 4, 4, 4, 4, 4, 4, 15, 0],
[15, 4, 4, 15, 4, 4, 15, 4, 4, 15],
[15, 4, 4, 15, 4, 4, 15, 4, 4, 15],
[15, 4, 4, 4, 4, 4, 4, 4, 4, 15],
[15, 4, 15, 4, 4, 4, 4, 15, 4, 15],
[15, 4, 15, 4, 4, 4, 4, 15, 4, 15],
[15, 4, 4, 15, 15, 15, 15, 4, 4, 15],
[0, 15, 4, 4, 4, 4, 4, 4, 15, 0],
[0, 0, 15, 15, 15, 15, 15, 15, 0, 0]
]
height = len(colors)
for i in range(height):
row = colors[i]
width = len(row)
for j in range(width):
mc.setBlock(x + j, y + height - i, z, 35, row[j])
試しに10×10マスのドット絵を作ってみました。
len()
を使って、colors
リスト、そこから取り出したrow
リストそれぞれの要素数を調べています。こうすることで、8
などの決まった数を入力しなくても、好きな大きさのドット絵を作ることができるようになります。
# おわりに
Prosenseではマインクラフトを使ったプログラミングの個別指導もおこなっております。
マンツーマンでレッスンを受けながらマインクラフトでプログラミングを学びたい方はいますぐProsenseのLINE公式アカウントに登録ください。