Microsoft MakeCode for Minecraftに入門してみた

# はじめに
Minecraftをプログラミング教育の教材として使用する「MakeCode for Minecraft」を使ってみました。
以前よりプログラミング教育教材として使用されていることは知っていましたが、Minecraftを遊んでいる身としては、整地、自動採掘が簡単にできるのはとても魅力的でした。
調べてみると意外と日本語の情報が少なかったので、私の触った範囲での使い方を紹介します。

# 環境
* Minecraft for Windows 10
* Code Connection for Minecraft 

# なぜMakeCode？
Minecraftでプログラミング学習をする方法は、MakeCodeの他に「Tynker」「Scratch」などのツールがあります。いずれもビジュアルプログラミングによりプログラミングを学習します。MakeCodeもビジュアルプログラミングによってプログラミングを学ぶことができますが、JavaScriptでプログラムを作成することができます。
ビジュアルプログラミングでプログラミングの感覚が分かった後、JavaScriptでコーディングする練習をすることで、より実践に近い学習ができる、それがMakeCodeの特徴だと考えています。

# 基本的な仕組み
MakeCodeでは、プログラミングで建築、収穫、採掘を自動化できますが、そのやり方には大きく2つの方法があります。

## 任意のブロックに置き換える
任意座標のブロックを、好きなブロックに置き換えます。座標はX,Y,Zで指定します。
この方法では、プログラムを実行すれば一瞬にして岩山をダイヤモンド鉱石の山に変えたり、空中に建築物を設置することができます。元の空間にあったブロックは、設定により消滅（置き換える）か、破壊（アイテムとして落ちる）かを選択することができます。
また、置き換えるブロックを「空気ブロック」にすることで、一瞬で巨大な穴を掘ることもできます。洞窟や炭鉱探しに便利です。

## エージェントに作業を指示する
MakeCodeを起動すると、ワールドの中にエージェントという作業員が登場します。

![04.png](https://qiita-image-store.s3.amazonaws.com/0/43330/dd6ae410-e79e-ca43-9f40-b3b7cbc664f8.png)

このエージェントはプレイヤーと同じ動作（積み上げる、掘削、耕す）をします。エージェントに作業をさせるということは、エージェントに「ブロックを置け」「前の地面を掘れ」という指示をプログラミングで与えることになります。
エージェントがプレイヤーの動作をトレースする分、「任意のブロックに置き換える」方法に比べ、作業に時間がかかりますが、「耕す」「アイテムを拾う」という行動はエージェントでなければできません。
その為、採掘や畑づくり、トラップタワーなどで落としたアイテムの回収といった作業に向いています。

# 準備編
## インストール
### Minecraft
Minecraft MakeCode for Minecraftを使用するには、「Minecraft for Windows 10」でなければいけません。Minecraft for Windows10は、Microsoft Storeから購入しましょう。

### Code Connection for Minecraft 
MinecraftとMakeCode（プログラミング環境）を接続するためのツールです。
ソフトウェアは[ダウンロードサイト](https://minecraft.makecode.com/setup)より取得します。
インストーラが取得出来たら、インストーラの指示に従ってインストールしましょう。


## 環境設定
必要なソフトウェアのインストールが完了したら、Minecraftを起動し、プログラミングができるように環境設定をしましょう。といっても、設定は1つです。

| 設定 | 値 |
| :--- | :--- |
| チートの実行 | ON |

# 起動～プログラミングまで
続いてCode Connectionを起動し、プログラミングができる状態にします。
先ほど起動したMinecraftでワールドを作成し、ワールド内に入っておきましょう。
ワールドに入ったらCode Connectionを起動します。正常に起動すると次のような画面が表示されます。

![02.png](https://qiita-image-store.s3.amazonaws.com/0/43330/c96d31bc-eb55-1e99-8aa3-12899355433a.png)

マスキングしている箇所には、「connect」というコマンドと、続いてIPアドレス、ポート番号が記載されています。このコマンドをMinecraftのチャットウィンドウから送信することで、Code Connectionに接続されます。下図のような感じです。

**チャットウィンドウからコマンドを実行**
![03-1.png](https://qiita-image-store.s3.amazonaws.com/0/43330/f6d3e938-bb00-58d7-65ea-51a5c7704907.png)

**MinecraftとCode Connectionの接続が完了**
![03-2.png](https://qiita-image-store.s3.amazonaws.com/0/43330/59ed4f94-8e84-efba-f157-1af052c68547.png)

接続が完了すると、Code Connectionの画面が変更し、開発ツールの選択画面が表示されます。
MakeCodeを選択しましょう。
![03.png](https://qiita-image-store.s3.amazonaws.com/0/43330/7bdee8ab-99ae-5e42-a816-5d94d38df986.png)


MakeCodeが起動するとエディタ画面が表示されます。エディタはブロックによるプログラミング画面とJavaScriptのプログラミング画面を切り替えることができます。

**ブロックのプログラミング画面、右：JavaScriptのプログラミング画面**
![05.png](https://qiita-image-store.s3.amazonaws.com/0/43330/9f7e0c88-677c-f02f-9a9f-9944029972bd.png)

JavaScriptのプログラミング経験のある方の場合、初めはブロックでざっくりプログラムを構築して、細かなプログラミングはJavaScriptで書く方が効率が良いと思います。
最初からJavaScriptで始めるには、関数などを全て覚えておかなければいけないですし（あらかじめマニュアルを頭に入れておけば別ですが）、宣言、条件などを1つ1つブロックで書くのは、プログラミングの知識がある方だと面倒に感じるかもしれません。私の場合、計算式や繰り返し条件などはほとんどJavaScriptで書きました。

# プログラミング編
では、実際につかってみたコードを紹介します。これでも一部（かつ初歩的なもの）ですので、詳細は公式のマニュアルをご覧ください。雰囲気を掴んでもらえればうれしいです。

## ブロックを置く
### ■任意の座標にブロックを置く
```javascript
player.onChat("go", function () {
    blocks.place(blocks.block(Block.LapisLazuliBlock), positions.create(0, 0, 3))
})
```
![07.png](https://qiita-image-store.s3.amazonaws.com/0/43330/ea6acc44-231c-0655-198f-564a2b097b75.png)


### ■任意の座標A～座標Bにブロックを置く
```javascript
player.onChat("go", function () {
    blocks.fill(
    blocks.block(Block.PlanksOak),
    positions.create(0, 10, 0),
    positions.create(10, 20, 10),
    FillOperation.Replace
    )
})
```
![08.png](https://qiita-image-store.s3.amazonaws.com/0/43330/47e52e84-995f-33d0-3e5c-9cbc5f7175a6.png)


## エージェントを操作する
### ■エージェントを自分の位置に戻す
```javascript
player.onChat("go", function () {
    agent.teleportToPlayer()
})
```
![09.png](https://qiita-image-store.s3.amazonaws.com/0/43330/988d7e03-7d47-2293-89fc-9fbe92d65845.png)


### ■エージェントを移動する
```javascript
// エージェントを前に5ブロック移動
player.onChat("go", function () {
    agent.move(SixDirection.Forward, 5)
})

```
![10.png](https://qiita-image-store.s3.amazonaws.com/0/43330/73f2b686-2a15-87c3-29fb-99cc13d291c6.png)


### ■エージェントの向きを変える
```javascript
// 向きを左に変える
player.onChat("go", function () {
    agent.turn(TurnDirection.Left)
})

```
![11.png](https://qiita-image-store.s3.amazonaws.com/0/43330/ae6acb10-ed59-8edb-e427-110951e1bd7a.png)


### ■エージェントの前にブロックを置く
エージェントにブロックを置かせる場合、エージェントに設置するブロックを持たせる必要があります。エージェントにブロックを持たせるには、エージェントを右クリックしてエージェントのスロットをオープンします。
![12.png](https://qiita-image-store.s3.amazonaws.com/0/43330/7d39b5e6-0970-b590-2045-7790b0525453.png)

エージェントが使用するアイテムを指定するには、スロットの番号を指定します。何も指定しなかった場合は、スロット番号0（左上の隅）のアイテムが対象になります。

```javascript
player.onChat("go", function () {
    // スロットの2番を指定する
    agent.setSlot(3)

    // エージェントの前にブロックを置く
    agent.place(SixDirection.Forward)
})
```
![13.png](https://qiita-image-store.s3.amazonaws.com/0/43330/23c2441d-1577-9f2d-8199-599ddd1896bd.png)


### ■エージェントの前にブロックを破壊する
主に採掘で使用します。プレイヤーは縦2ブロック分が必要なため、プレイヤーが通過できるようにするにはエージェントの移動と組み合わせて2ブロック分の採掘を繰り返すようにプログラミングしましょう。

```javascript
player.onChat("go", function () {
    agent.destroy(SixDirection.Forward)
})
```
![14.png](https://qiita-image-store.s3.amazonaws.com/0/43330/83c24729-bcb0-7eb2-acf8-49e96c16617a.png)


### ■エージェントの前を耕す
```javascript
player.onChat("go", function () {
    agent.till(SixDirection.Forward)
})
```
![15.png](https://qiita-image-store.s3.amazonaws.com/0/43330/03b79a91-abd0-f52b-38ca-ec2d3f914a4e.png)


### ■エージェントにアイテムを拾わせる
全てのアイテムを拾う方法と、指定したアイテムのみ拾う方法があります。

```javascript
// 全てのアイテムを拾う
player.onChat("pickup1", function () {
    agent.collectAll()
})

// ダイヤモンドのみ拾う
player.onChat("pickup2", function () {
    agent.collect(blocks.item(Item.Diamond))
})
```
![16.png](https://qiita-image-store.s3.amazonaws.com/0/43330/92ac9c51-e9fa-e661-620f-025bcb337595.png)


## プログラミングしてみる
### ■変数
```javascript
// 変数を宣言
let i = 0

player.onChat("go", function () {
    // 変数に値を設定する 
    i = 10
})
```
![17.png](https://qiita-image-store.s3.amazonaws.com/0/43330/1c62f03d-f45f-67ab-fd9f-a6000dc4699a.png)


### ■分岐
```javascript
let i = 0
player.onChat("go", function () {
    i = 10
    if (i > 5) {
        blocks.place(blocks.block(Block.Grass), positions.create(0, 0, 3))
    } else {
        blocks.place(blocks.block(Block.Cobblestone), positions.create(0, 0, 3))
    }
})
```
![18.png](https://qiita-image-store.s3.amazonaws.com/0/43330/4f3041b0-0d7c-6d48-9334-725d2ed8e8fc.png)


### ■繰り返し（for）
```javascript
let i = 0
player.onChat("go", function () {
    i = 10
    for (let i0 = 0; i0 < i; i0++) {
        blocks.place(blocks.block(Block.Grass), positions.create(0, 0, i))
    }
})
```
![19.png](https://qiita-image-store.s3.amazonaws.com/0/43330/7f99b10e-c066-2622-c875-08a5f6dcc1a8.png)


### ■繰り返し（while）
```javascript
let i = 0
player.onChat("go", function () {
    i = 0
    while (i < 10) {
        blocks.place(blocks.block(Block.Grass), positions.create(0, 0, i))
        i += 1
    }
})
```
![20.png](https://qiita-image-store.s3.amazonaws.com/0/43330/a8328dc5-52af-6649-4eb7-1342e9793fed.png)


### ■関数（引数なし）
ブロックで関数を作る場合、「関数の定義」と「関数の呼び出し」は別ブロックになることを注意してください。

```javascript
player.onChat("go", function () {
    PutStone()
})
function PutStone() {
    blocks.fill(
    blocks.block(Block.RedSand),
    positions.create(-5, 10, -5),
    positions.create(5, 10, 5),
    FillOperation.Replace
    )
}
```
![21.png](https://qiita-image-store.s3.amazonaws.com/0/43330/7ee0bd0d-63a4-bf95-43f2-2019a9ba30ae.png)


### ■関数（引数あり）
引数ありの関数はブロックで作成することができません。JavaScriptで実装することになります。
JavaScriptで実装したものは、JavaScriptブロック（背景が灰色のブロック）で表示されます。

```javascript
player.onChat("go", function () {
    let cnt = add(6, 4)
    blocks.place(blocks.block(Block.Grass), positions.create(0, 0, cnt))
})
function add(x: number, y: number) {
    return x + y
}
```
![21-1.png](https://qiita-image-store.s3.amazonaws.com/0/43330/eaf9159b-8ee1-54fd-9ffd-91df499def1d.png)


# やってみてわかったこと
## 外部サービス（JavaScriptモジュール、WebAPI等）は使用できない
JavaScriptが使えるのでなんでも自由にできそうですが、実際はそうではありませんでした。
基本的には、変数や基本構文はしようできますが、関数はMakeCodeが提要しているものしか使用できません。たとえば、Date関数は使用できません。
また、外部のJavaScriptモジュールや、WebAPIをRESTで呼び出すということもできません。

## エージェントは一人だけ
エージェントはワールドに一人しか存在できません。よって、大掛かりな建築や採掘をするには向いていません。採掘の場合は、代替案として「ブロックを置く」機能で元あったブロックを「置き換え」ではなく「破壊」にすることでもともとあったブロックをアイテム化することができます。あとは地道に拾いましょう。

## エージェントはプレイヤーから64ブロック以上離れると機能しない
エージェントの距離が64ブロック以上離れるとエージェントに指示が届かなくなります。
そのため、エージェントに指示を与える場合は必ずエージェントの近くでコマンドを出すか、「エージェントを自分の位置に戻す」コマンドを使って、エージェントを呼び寄せてから実行しましょう。


# せっかくだからいろいろやってみた
プログラミングを使えば、通常のMinecraftで実現することが大変なことが一瞬でできるようになります。
実際にやってみたことを紹介します。

## 大量のTNTを爆破する
多くのMinecrafterなら一度は大量のTNTを爆破したいと思ったことはあるはず。
クリエイティブモードでもTNTを1つずつ積むのは苦行ですよね。でもMakeCodeを使えば次のプログラムで一瞬にして大量のTNTを積み上げることができます。
やり方は簡単で、上記で紹介した「任意の座標A～座標Bにブロックを置く」で設置するブロックにTNTを指定して、設置位置を調整するだけです。実際のコードはこんな感じです。
![22.png](https://qiita-image-store.s3.amazonaws.com/0/43330/9c41c2c1-93c9-7988-7a0a-e53fb25397d1.png)

実行しました。圧巻の景色です。
![23.png](https://qiita-image-store.s3.amazonaws.com/0/43330/1d0546b3-fe72-c580-745d-5968d18d752c.png)

早速爆破しました。パソコンへの負荷が半端ないです。
![24.png](https://qiita-image-store.s3.amazonaws.com/0/43330/4280affd-9d49-ecdb-60bc-cd48794166b1.png)

クレーターができました。先ほどのコマンドを何度も実行すれば、世界に大穴を開けることができます。
![25.png](https://qiita-image-store.s3.amazonaws.com/0/43330/aa7c65b0-2c6c-57f9-29a9-27b572fb4655.png)


## 岩盤を破壊する
Minecraftで地中を深く掘り進めると岩盤の層に到達します。岩盤は通常は破壊できないブロックですが、エージェントを使うと岩盤を破壊することが可能です。
ちなみに岩盤の下は「奈落」の世界です。通常はエンドの世界からしか行くことができませんが（通常奈落に堕ちると死んでしまいます！）MakeCodeを使えば通常世界から奈落へいくことができます。
やり方は簡単で、エージェントに足元をひたすら掘り進めるだけです。
奈落から地上を見上げるとこういう景色です。薄暗くひたすら何もありません。天井に岩盤が敷き詰められているだけの空間です。
![26.png](https://qiita-image-store.s3.amazonaws.com/0/43330/3eb8c3e5-9a20-39b9-724b-d7b273e21107.png)


# おわりに
プログラミング勉強の入門としては充実したツールなんじゃないかと思いました。小中学生は夢中になるでしょうね。
また、Minecrafterの視点でみると、大掛かりな整地、採掘ができるのは非常に魅力的です。とはいえ、採掘の作業自体がMinecraftの醍醐味でもあるので、ほどほどに使用するのが良いかと思います。

# 参考
* [MakeCode for Minecraft Documentation](https://minecraft.makecode.com/docs)
* [できる パソコンで楽しむ マインクラフト プログラミング入門 Microsoft MakeCode for Minecraft 対応](https://www.amazon.co.jp/%E3%83%91%E3%82%BD%E3%82%B3%E3%83%B3%E3%81%A7%E6%A5%BD%E3%81%97%E3%82%80-%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80-Microsoft-MakeCode-Minecraft/dp/4295003514/ref=sr_1_fkmr0_1?ie=UTF8&qid=1532836970&sr=8-1-fkmr0&keywords=MakeCode+for+Minecraft+Documentation)