離島プログラマの雑記

島根県の離島、隠岐・西ノ島に移住して子育て中のフリープログラマです。

プログラミング教室近況 〜マイクラのレッドストーン回路で色々つくってみる〜

昨日のプログラミング教室は、マイクラ(Minecraft)でレッドストーンという回路が組めるブロックを使って色々つくってみました。


[Minecraft] レッドストーン回路でTNTキャノンを作ってみた

イクラでプログラミングしようとした場合、MakeCode などのマイクラ世界の外側にあるツールと連携させてScratchのようなブロックインタフェースでプログラムを書くことが多いのですが、マイクラ本体にもレッドストーンいう回路ブロックが実装されており、これで回路を組むことでスイッチ、センサーなどの入力を受けてピストン、発射装置などの出力を制御することができます。コンピュータ上のプログラミングというより、現実世界のハードウェア制御に近いので Arduino のようなマイコンでなにか作る感覚に似ています。

レッドストーン回路の良いところは、Scratch のように「ことば」による論理組み立てを行わなくても、ちゃんと動くものが作れるところです。今回は小学2年生の生徒にレッドストーン回路の基本的な使い方を教えてみたところ、レバーを操作して照明を点灯させるシステムを改造して、3つの花火を打ち上げるようにしたり、さらに遅延調節できるリピータを使って信号を遅延させることで、花火の打ち上げタイミングをずらしたりできました。自分で配線を考えてものをつなげたり、信号が伝わっている様子が目視できたりするのは、言語によるプログラミングよりも直感的に理解しやすいのかなと思います。

また、レッドストーンのシステム自体がマイクラ本体に実装されているというのもポイントで、外部ツールを連携してプログラミングを行う場合、すでにマイクラで遊んでいる子供たちはプログラミングはチート行為、つまり「ずるい」ことであるという感覚をもっている場合があります(外部ツールでは、本来は「ツルハシで地下から希少な鉱石を掘り出して、それを集めて合成して特殊なブロックを得る」といったような複雑な手順をスキップして、最初から特殊なブロックを大量に並べたりできる)。その点、レッドストーンはマイクラ世界の常識と矛盾しない位置づけとなっているため、子供たちにとっても受け入れやすいようです。

授業の最後には、TNTブロック(爆発させてダイナマイトのように地面を削ったりできるブロック)を遠くに発射する装置を一緒に考えて実現できました。単純に回路のプログラムを考える以外にも(マインクラフト内の)物理法則や道具の使い方、ブロックの性質など色々考慮する必要があり、設計はなかなか複雑な作業です。マイクラ歴は生徒のほうが長いので、マイクラ内での経験から得た知識や、友達や動画で得た知識などが豊富で、こちらもマイクラ世界の常識などを教わったりしながら進めました。

例えば、この装置の設計については以下のような議論や実験をしました。

  • TNTブロックを遠くに飛ばすための推進力をどうやって得るか?(発射装置自体の威力は弱く、単にTNTブロックを発射しても装置の目の前に落ちてしまい、装置もろとも吹き飛ばしてしまいます笑)

    • 案1) TNTブロックをピストンで押し出す
      • 実験の結果、ピストンではブロックを遠くに飛ばすような推進力は得られなかった
    • 案2) TNTブロックを氷の床で滑らせて遠くまで運ぶ(プレイヤーは氷上で滑ることから発想)
      • 実験の結果、TNTブロックは氷の床の上を滑らなかった
    • 案3) TNTブロックを別のTNTブロックの爆風で吹き飛ばす
      • 実験の結果、TNTブロックに隣接する別のTNTブロックは、爆風によって吹き飛ばず、その場で着火状態となるため失敗
        • ここで生徒の経験則で、以前に自分をTNTブロックで囲んで打ち上げる仕掛けを作った時は、確かにTNTブロックも吹き飛んでいたはず、とのことで再現してみる
          • 確かに吹き飛んでいくTNTブロックがあるが吹き飛ばないTNTブロックもある
            • TNTブロックの着火状態によって飛ぶ/飛ばないがあるのでは?という仮説を立てる
              • 着火状態のTNTブロックに他のTNTブロックの爆風を当てる
                • 吹き飛んだ!

という訳で、案3を採用。

他にも、

  • 推進用のTNTブロックの爆風で発射装置自体が壊れないようにするには?

    • 爆風を受ける壁は「岩盤」(TNTの爆風でも壊れない非常に硬いブロック。このブロックの存在は生徒に教えてもらいました)を使用する
      • 爆風が届かない程度の高さに発射装置を配置する
    • 壁に垂直にはレッドストーン回路が配線できない
      • 発射装置まで階段上にブロックを配置して配線
  • 推進用TNTブロックと飛ばされるTNTブロックの発射タイミングをどうやって制御するか?

    • 花火の打ち上げタイミングをずらしたやりかたと同じように、リピータを使って飛ばされるTNTブロックの発射タイミングを遅らせる

などの諸問題を解決してやっと完成しました。

f:id:k-aeg:20181029104948p:plain

f:id:k-aeg:20181029105024p:plain

動作する様子は(ちょっとわかりにくいですが)冒頭の動画をごらんください。

さて、傍から見るとゲームで遊んでいるだけに見えたりして、こんな無駄なものを作って何の意味があるのか?と問うのはナンセンスと思います(笑)

こういったものを熱中して作る過程で、知識や経験から仮説を立て、実験・検証し、実装するという一連のプロセスや、うまくいかない場合は事象を分解して考えるといった方法を自然と身につけることができます。これはものづくりに限らず、色んな場面で応用の効く力になると思います。

また、小学生の彼ら/彼女らにとって熱中できることがあるのは非常に重要で、その興味の範疇にあるものはすごい勢いで吸収し、また自分の力で考え、発展させることができます。一方、大人が将来役に立つよと言って押し付けるものは、大抵の場合、子どもたち自身にとっては重要でないものであり、自分ごとにはならず、なかなか身につきません。

つまり大人は、子供たちの目線で見て重要なものは何か?ということを考えて、それを尊重することが個性や創造力を引き伸ばす鍵になると思います。また、彼ら/彼女らとちゃんと議論しようと思ったら、子供扱いをせず対等な立場で接することが重要で、大人対子供、先生対生徒という上下関係の中での議論は一方的になりがちです。結果、子供は相手から正しい答えが出てくるのを待つようになり自分で思考することを放棄してしまいます。

子供との議論の中で、難しい説明は理解できないだろうと思って平易なことばで簡略化してしまうこともやってしまいがちですが、今回は、設計が少し複雑になってきた時、生徒が自分で紙とペンを持ってきて図を描いて整理しようしました。ことばにすると複雑な概念でも図にすると子供でも直感的に理解できるような話も多く、ことばによる思考や伝達が未熟な低学年でも、図解などの非言語的手段であれば高度な思考やコミュニケーションが可能ということにも気付かされました。

f:id:k-aeg:20181028121623j:plain

f:id:k-aeg:20181028121631j:plain

というわけで、こちらも色々得るものがあったなーと感じる授業でした。

Windows タブレットでデジタルサイネージ制作

あらすじ

隠岐・西ノ島に移住して早くも3年が過ぎましたが、去る7月21日、我らが西ノ島町にもすてきな図書館が完成しました。

f:id:k-aeg:20180919221002j:plain

今回この図書館のウェブサイト制作と館内のデジタルサイネージ(しまポータル)の制作を任せていただきました。 特にデジタルサイネージはあまり制作機会がないので制作記を記しておこうと思います。 備忘録を兼ねているのでかなり細かい話が多くて読みづらいですが。

f:id:k-aeg:20180920015649j:plain

システム構成

f:id:k-aeg:20180919230326j:plain

しまポータルでは、タッチ操作できるインタラクティブなコンテンツを計画していましたが、システム構成は予算の都合上、大型タッチパネルモニタではなく普通の大型テレビモニタと操作用のタブレットという構成になりました。ちなみに大型タッチパネルモニタは普通のテレビの3倍くらいのお値段...。

検討案 検討内容
大型モニタ + 画面表示用PC + 操作用タブレット モニタとPCはHDMI、PCとタブレットの接続はWiFi(リモートデスクトップ)となる。WiFI通信による操作遅延と、リモートデスクトップ自体の操作バネルが常に表示されており、ユーザが操作できてしまうという問題あり。
大型モニタ + 操作用タブレット 操作用タブレットとモニタはHDMIで接続。基本的に有線接続となるためケーブルの取り回しが効かなくなる。通信による操作遅延はないが、タブレット側で2つのモニタ出力をまかなう必要があるので、廉価タブレットオンボードGPUには若干負荷が高めか。

当初の案では、画面表示用PC + 大型モニタ + コントロールタブレットという構成で検討していましたが、Webサイトのブラウジングなど、モニタとコントローラの画面を完全に同期する必要があったので、タブレットから直に大型モニタに出力するシンプルな構成となりました。

コンテンツはウェブサイトと共にVPSに配置しており、タブレットからアクセスしています。

モニタへの出力方法

タブレットからモニタへの出力方法は無線・有線を検討しましたが、遅延や安定性などを考慮して有線としました。

検討案 検討内容
無線(ワイヤレスHDMI) 送信機のドングルが邪魔なので却下
無線(ChromeCast のような WiFi で飛ばすタイプ) タブレット本体がケーブルレスになるので取り回しが良い。動画などでは問題にならないが、インタラクティブなコンテンツは操作遅延が気になる。また、受信側のドングルは熱のこもりやすいモニタの裏側(しかもモニタは木枠で覆われたデザイン)に設置することになるため、動作が不安定になりそう。
有線(HDMI) ケーブルの取り回しやタブレット側接続端子の耐久性が問題だが、最も遅延が少なく安定している。

HDMIケーブルは通常のストレート型だと端子に負荷がかかるので、L字型(左向き)のものを使用しました。

タブレット選定

タブレットはモニタと画面をミラーリングする都合上、アスペクト比をなるべく揃えることと、キオスク端末としての設定の柔軟さ(と予算)で検討し、Windows10 Pro のタブレットを使用することにしました。

検討案 検討内容
iPad アスペクト比4:3であり、テレビ画面(16:9)と大きく異なるので却下。
Android タブレット 常に表示される操作ボタンバーのため、テレビのアスペクト比16:9より若干幅広な16:10のものがほとんどであり、テレビのアスペクト比に併せて出力した場合、タブレット側の上下に黒い帯ができてしまう。また Android のバージョンにもよるが、電源周りの設定等、キオスク端末として使うための機能が不十分であったり、それらの機能にバグがあるなどの理由で却下とした。
Windows タブレット 設定の方法は煩雑だが自由度が高く、機能的には十分。Android タブレットと同様にアスペクト比 16:10 のタブレットが多く、Android タブレットと同様に帯ができてしまう。稼働中に Windows Update が実行されないようにスケジューリングが必要なため、Windows 10 Pro エディションが必須(Home だと制御不可)。

機能や性能の要件的には Microsoft Surface シリーズがベストですが、経年劣化や故障によるリプレースも視野に入れると予算オーバーだったため、Lenovo 製の Windows10 タブレット(キーボード付き)を採用しました。Windows 10 Home のモデルしかなかったので、購入後に Pro にアップグレードしています。

Surface 以外で候補にしていたWindowsタブレットは以下の通りです。いずれも3万円台。

機種名 メーカー モニタサイズ 重さ プロセッサ ビデオカード メモリ ストレージ
LAVIE Hybrid ZERO HZ100/DA 2016年春モデル NEC 11.6インチ 398g Pentium 4405Y/1.5GHz インテル® HD グラフィックス 515 4GB 64GB
Diginnos DG-D09IW2SL ドスパラ 8.9インチ 495g Atom x5-Z8350/1.44GHz インテル HDグラフィックス400 4GB 64GB
ideapad Miix 320 80XF0007JP Lenovo 10.1インチ 550g Atom x5-Z8350/1.44GHz インテル HDグラフィックス400 4GB 64GB
WiZ KVK111KHD KEIAN 11.6インチ 730g Atom x5-Z8350/1.44GHz インテル HDグラフィックス400 4GB 32GB
dynabook S29/TG PS29TGP-NYB 東芝 8.9インチ 479g Atom Z3735F/1.33GHz Intel Atom® プロセッサー Z3700 シリーズ向けインテル® HD グラフィックス 2GB 32GB

コンテンツ制作

コンテンツ制作は、ウェブベースで行いました。廉価タブレットの性能を考えると Unity でネイティブアプリとして実装したほうがキビキビ動いて良かったんですが、ネイティブアプリ内でウェブサイトのブラウジングを扱うのがいろいろ厄介な感じだったので断念して、全部ウェブでやることにしました。イラストは西ノ島町出身のデザイナーまの悠さん( marumi03 )によるものです。

f:id:k-aeg:20180920021541j:plain

f:id:k-aeg:20180920021525j:plain

f:id:k-aeg:20180920021638j:plain

f:id:k-aeg:20180920021702j:plain

クライアント側は貸出ランキングや埋め込みブラウザの表示に vue.js、サザエや牛を触ったりできるインタラクティブ要素に phina.js + Box2d などを使って実装しました。 サーバ側はOPACから吐き出される貸出ランキングなどのCSVデータに、RubyopenBD から取得した書影URLを付加して JSON に成形したものを配信しています。貸出ランキングなどはサーバ側でレンダリングまでしたほうがおそらく速いんですが、今の所すべてクライアントまかせです。

Windows タブレットキオスク端末

いろいろなやり方があって試行錯誤しましたが、最終的にシンプルだけどあまり上品でない方法に落ち着きました(笑)

  1. キオスク画面用のローカルユーザで自動ログイン(管理者アカウントは別に用意しておく)
  2. スタートアップで explorer.exe(エクスプローラ) の強制終了と Chrome のフルスクリーンモード起動を行うバッチファイルを実行

ChromeKIOSKモードで大体の要件は満たせるのですが、explorer.exe の強制終了が必要なのはエッジスワイプ(画面端から画面内に向かってのスワイプ)対策です。エッジスワイプ操作が行われると、エクスプローラのアプリ一覧画面が表示されてしまい、Chrome の画面から抜け出せてしまいます。

デジタルサイネージを作ったので学んだことを晒してみる Part.1 - Qiita

エッジスワイプ自体を無効にする方法はいろいろウェブ上に乗っているのですが、現在のバージョン1803ではどれも無効なようで、最終的に確実な解決策が explorer.exe を殺す、という方法な訳です(笑)

explorer.exe を強制終了しても、タスクマネージャは Ctrl + Alt + delete キーで起動できるんですが、タブレット端末の場合は入力できないので問題なさそうです。(Surface とかハードウェア Windows ボタンがついている場合は電源ボタン + Windows ボタン長押しで起動できてしまうようですが...)

forest.watch.impress.co.jp

なお、一番真っ当なやり方としては、

  • Windows 構成デザイナー(ICD)でキオスク端末としてプロビジョニング
    • キオスク用アカウントの作成や、固定するアプリの指定(割り当てられたアクセス)、スクリーンの自動オフ無効化などをまとめて設定
  • 割り当てられたアクセスには Kiosk Browser を指定

だと思います。が、Kiosk Browser や IE11 ではタッチイベントを拾えず、うまくコンテンツが動かなかったのでやむなく却下としました(Microsoft Edge の開発者オプションでタッチイベント有効にできるぽいけど、Kiosk Browser ではできなそう)。

ちなみに開発当初、「割り当てられたアクセス」はストアアプリ限定のため、ブラウザとして使えるのはIE11のみ(Microsoft Edge はストアアプリだが「割り当てられたアクセス」に非対応、Chrome 等他社製ブラウザはストアアプリでないため使用不可)という状況でしたが、Windows 10 Fall Creators Update(バージョン1703)でMicrosoft 公式の Kiosk Browser(Edge の機能限定版) が実装されたので、これを使うことができるようになりました。

Kiosk Browser の細かい設定ができるようになったのは、Windows 10 April 2018 Update(バージョン1803)からで、Windows 構成デザイナー(ICD)を利用して規定のURLや表示するUIの設定を行うことができるようになったようです。

“割り当てられたアクセス”で使えるMicrosoft純正ブラウザ「Kiosk Browser」とは:企業ユーザーに贈るWindows 10への乗り換え案内(28) - @IT

さらに補足しておくと、Windows 構成デザイナー(ICD)にはストアアプリ版と Windows ADK 版の2種類あるんですが、ストアアプリ版は罠です!ストアアプリ版ではキオスク端末のプロビジョニングウィザードで、Required の項目を全部埋めてもパッケージのビルドができない不具合があってハマりました。Windows ADK 版を使いましょう。

docs.microsoft.com

なお、プロビジョニングウィザードで固定するアプリに Windows Classic のアプリが(ドキュメントには Windows 10 Proは非対応と書いてあるが)指定できたのでやってみたところ、キオスク用アカウントでサインインできなくなるばかりか、管理者アカウント側のエクスプローラが起動しなくなり復旧が大変でした(笑)

ちなみに復旧方法は、

  1. 管理者アカウントでログイン(画面真っ暗)
  2. Ctrl + Alt + Delete でタスクマネージャ起動
  3. 適当なプロセスの右クリックメニューから「ファイルの場所を開く」→ エクスプローラが起動する...がタスクバーはまだ表示されない
  4. タスクマネージャでファイルエクスプローラのアプリの「ファイルの場所を開く」
  5. explorer.exe をダブルクリックで起動 → タスクバー復活
  6. 原因となったプロビジョニングパッケージの削除 → http://www.wannko.net/windows10/etc/probijo2.html Windows10のプロビジョニングパッケージを解除・削除を行う方法
  7. 「regedit」を起動し、レジストリを編集。 キー名:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon 値名 :Shell に"eshell.exe"が設定されていたので、“explorer.exe” に置き換え(全ユーザ用の初期起動Shellの設定)。

Windows 10 でのシェルの置き換えについて | Ask CORE

Windows10でWindows ICDを使って埋め込みシェル起動ツール(Shell Launcher)を設定する方法

【cmd】Windows10でエクスプローラーが動かない時にコマンドプロンプトでエクスプローラーだけを再起動する方法 | onocom

2 でタスクマネージャ起動できるのに気づくのに時間がかかったり、3でエクスプローラが起動するけどタスクバーが表示されない状態でハマったり、7の当該レジストリを探したりなんだかんだで復旧に1日かかりました...。

以上、コンテンツについてあまり触れていないですが、とりとめのない制作記でした。中身の話はそのうち書くかも...

[2018/11/1追記]

パスワード有効期限の罠

Windows 10 のデフォルト設定ではパスワードの更新期限は42日に設定されているようです。

パスワードの有効期間 (Windows)

この期限が切れると自動ログインに失敗して、起動しなくなるので無期限に設定しておく必要があります。 この設定はローカルグループポリシーエディターで変更できます(要 Windows 10 Pro 以上)。

Windows10 - ローカルグループポリシーエディターを起動する方法 - PC設定のカルマ

プログラミング教室のPCを Raspberry Pi に置き換え&マイクラでプログラミング

しばらく更新が滞っていましたが、にしのしまデジタルラボ・プログラミング教室は、おとなり海士町での開講に伴い、「隠岐デジタルラボ・プログラミング教室(西ノ島教室、海士教室)」として活動しています。

西ノ島教室では、某所からお下がりでもらった10年前くらいのデスクトップPCを使っていましたが、故障が目立つようになってきたため、リプレースとして最新の Raspberry Pi3 B+ を導入してみました。

Raspberry Pi のOSである Raspbian には、しばらく前から Mincraft Pi (Raspberry Pi 用のマイクラ)がプリインストールされており、さっそく小学生に見つかった(笑)のでみんなで遊んでみることにしました。Mincraft Pi の特徴はスクリプトでプレイヤーを動かしたり、ブロックを配置したりできるところなので、普段使っている Scratch と接続してマイクラプログラミングもやってみます。

f:id:k-aeg:20180620162349j:plain

購入した機材

f:id:k-aeg:20180604114229j:plain

本体セットアップ

OSイメージの準備

www.raspberrypi.org

から「RASPBIAN STRETCH WITH DESKTOP」をダウンロードして dd コマンドで SDに書き込み。 手順はいろんなページに書いてあるので省略します。

記事によってはSDカードのフォーマット操作してますが、ddコマンドで書き込む時にパーティションごと消えるので事前のフォーマット操作は不要です。

あと、こんな落とし穴があるらしいけど jessie 時代の話なので、stretch ではどうなってるか不明ですが、まあ conv=sync オプションもつけて置いたほうが無難そうです。

akkiesoft.hatenablog.jp

電源投入〜デスクトップ表示まで

最近はオートログインで、電源入れただけで一気にデスクトップ表示まで行くんですね。 なにもしなくても pi ユーザーで自動ログインされます。初期パスワードは「raspberry」。

日本語化 + 日本語入力

こちらを参考に設定しました。

deviceplus.jp

Mincraft Pi セットアップ

Scratch2MCPI のインストール

こちらの記事の通り、Scratch と Minecraft Pi の Python I/F をつなぐ Scratch2MCPI をインストールします。

thinkit.co.jp

ローカルネットワーク内のワールド共有

  1. ワールド共有したい Raspberry Pi (最大5台)を同じ LAN 内に接続する
  2. ホストするマシンで Mincraft Pi を起動し、ワールドを作成して動ける状態にしておく
  3. 他のマシンでも Minecraft Pi を起動し、Join Game をクリックして Steve Pi (192.168.xxx.xxx) に接続

4台で接続してワールド共有してみましたが、けっこうサクサク動きます。

Scratch との接続

  1. Minecraft Pi を起動してプレイヤーを動かせる状態で、TAB でカーソル解放
  2. Scratch2MCPI を起動
  3. Scratch でプログラムを書いて実行

特にトラブルなくあっさりうまくいきました。ワールド共有中でもスクリプトは実行可能です。

あそんでみる

さて、小学生3人と一緒に遊んでみました。マイクラができると聞いたとたんテンション爆上がりです(笑) Scratch2 単体の動作は描画が多いと若干カクっとしましたが、Minecraft Pi はかなり軽快に動きます。

イクラ自体ほとんどやったことなかったので、小学生の遊び方を観察したりしてみましたが、マイクラ内で鬼ごっこしたり、石を並べて宝石店を作り出したり、なかなかクリエイティブな遊びかたをするので、これはデジタル版のレゴなんだな〜という感じがします。

Scratch を通してのプログラミングも少し手をつけてみて、プレイヤーを色んな場所にワープさせたり、ブロックを直線に並べてみたりもしましたが、いつも使っている Scratch のインタフェースなので割とスムーズに受け入れてくれました。

ただ、グローバル変数(mcpiX、mcpiY、mcpiZ)に座標をセットしてsetPosなどのコマンド送信、という流れは普通のScratchプログラミングと異なるお作法(アセンブリ言語レジスタに値をセットして命令発行している感じ)なのでちょっと慣れが必要そうです。気軽に並列処理しようとするとメチャクチャになります(笑)

というわけで、しばらくマイクラ+プログラミングで遊んでみようと思います。

プログラミング教室近況

今年2月に開講した「にしのしまデジタルラボ」プログラミング教室は早9ヶ月となり、口コミでメンバーも増え現在は6名が在籍しています。11月初めには地域の文化展にて生徒作品の展示も行うことができました。

f:id:k-aeg:20171128031431j:plain:w400
文化展展示の様子

開講からこれまでは、ミッションカードとオリジナルゲーム制作を中心に授業を進めてきましたが、どうしてもタイピングの遅さがネックになってきたので、今月はタイピング強化月間としてScratchで作ったタイピングゲームでタイムを競い合ったりしています。

競争要素を持ち込むと小学生たちの場外マウンティング合戦(足は俺のほうが速いとか、成績は俺のほうが良いとかw)が始まって少しサツバツとするのがデメリット(?)ですが、かなりモチベーションは高まるようです。競い合った結果、授業時間の90分だけでひらがな入力スピードが3倍くらいになるなど、タイピングのような単純なスキルアップには効果があるようです。

ところで、授業で使っているタイピングゲームのような教材は、生徒がやっていることの延長線上に見えるようになるべく Scratch で作っています。今回のタイピングゲームは1時間程度で完成しましたが、マルチプラットフォーム対応(開発機はMac、生徒PCはLinuxWindows)でこの程度のアプリケーションを同じくらいの学習コスト、制作時間でできる環境って他に案外無いのでは?

f:id:k-aeg:20171128033356p:plain:w400
授業で使っているタイピングゲーム

プロジェクトを公開しているので、以下のリンクからタイピングゲームを遊べます。 scratch.mit.edu

昨今のプログラミング教育において、「教育用言語」と目される Scratch 後をどう他につなげるかという至上命題みたいなものがありますが、Scratch のポテンシャルを十分に引き出すことができれば、(現状では制約が多いものの)かなり有用なツールになり得るという感触があります。JavaScript ベースの Scratch 3.0 がリリースされれば、自由度は高まっていくと思われるので今後どうなるか楽しみです。

ScratchブロックをHTMLで描画する方法

プログラミング教室の教材を作るために Scratch ブロックの画像が欲しかったんですが、いちいちスクリーンショットを撮るのも面倒だし、ラスタ画像ファイルだと解像度の問題で取り回しが不便なので、ベクタ画像出力かつ更新が簡単な方法を探していたらドンピシャのライブラリがありました。

ScratchのWikiやフォーラムでも使われている blob8108 氏作の Block Plugin(scratchblocks)です。このライブラリはブラウザ上で動作するブロック画像ジェネレータとしても公開されていますが、Webページに組み込めば Scratchスクリプトからブロック画像を生成してHTMLにSVGとして埋め込むことができます。

教材の製本も視野に入れると、画像編集ツールを介さずにHTMLで完結できればCSS組版とも相性が良さそうです。

使い方

ライブラリのインクルード

現在の最新バージョンはver3.1なので、以下のJSファイルをインクルードします。

<script src="https://scratchblocks.github.io/js/scratchblocks-v3.1-min.js"></script>

ブロック表記を英語以外(今回は日本語)にするためにはさらに以下の翻訳データをインクルードします。

<script src="https://scratchblocks.github.io/js/translations-v3.1-min.js"></script>
描画

実際に描画してみたサンプルを GitHub Pages で公開しておきました。

https://ag-k.github.io/scratchblocks-html-sample-ja/

サンプルコード全体は以下で参照できます。

https://github.com/ag-k/scratchblocks-html-sample-ja/blob/master/index.html

以下は各描画方法の説明です。

ベーシックな描画方法

HTMLの要素としてScratchスクリプトを記述しておき、scratchblocks.renderMatching() で指定したセレクタに該当する要素をまとめて描画します。 指定するセレクタは自由ですが、preタグだとそのままスクリプトが書けるので便利です。

<pre id="blocks1" class="blocks">
  @greenFlag がクリックされたとき
  x座標を (0) 、y座標を (0) にする
  ずっと
    (10)回繰り返す
      @turnright (10) 度回す
      (5) 歩動かす
    end
    次のコスチュームにする
  end
</pre>
<pre id="blocks2" class="blocks">
  このスプライトがクリックされたとき
  もし <(向き) = [90]> なら
    ペンを下ろす
  でなければ
    ペンを上げる
  end
</pre>
// 'pre.blocks' セレクタで指定された要素をまとめて描画
scratchblocks.renderMatching('pre.blocks', {
  languages: ['ja', 'en'],
  render: function(doc, cb) {
    doc.render(function(svg) {
      var el = document.createElement('div');
      el.appendChild(svg);
      cb(el);
    });
  },
});
インラインで描画

scratchblocks.renderMatching() の第2引数 option に inline: true を指定するとインラインでブロックを描画できます。

scratchblocks.renderMatching() の第2引数 option に inline: true を指定すると、<code class=b>スタンプ</code>のようにインラインでブロックを描画できます。
// インラインで描画
scratchblocks.renderMatching("code.b", {
  languages: ['ja', 'en'],
  inline: true
});
サイズを拡大して描画

今のところブロックが描画サイズは固定になっているようですが、大きくして使いたい場面があったので、描画結果のサイズを変更する方法を考えました。ブロックはSVG形式で描画されるので、Document.render() から取得できるSVG要素を拡大してやれば良さそうなのですが、scratchblocks.renderMatching() に渡した場合、SVG要素のサイズが取得できませんでした(clientWidth, clientHeight, viewBox が0)。

一方、Document.render() を単体で使う場合は SVG要素のサイズが取得できたので、scratchblocks.parse() でスクリプトをパースしたオブジェクトを Document.render() でレンダリングし、結果のSVG要素を指定されたスケールに拡大するようにしました。

<code id="big_blocks">
  @greenFlag がクリックされたとき
  x座標を (0) 、y座標を (0) にする
  ずっと
    (10)回繰り返す
      @turnright (10) 度回す
      (5) 歩動かす
    end
    次のコスチュームにする
  end
</code>
<code id="middle_blocks">
  @greenFlag がクリックされたとき
  x座標を (0) 、y座標を (0) にする
  ずっと
    (10)回繰り返す
      @turnright (10) 度回す
      (5) 歩動かす
    end
    次のコスチュームにする
  end
</code>
<code id="small_blocks">
  @greenFlag がクリックされたとき
  x座標を (0) 、y座標を (0) にする
  ずっと
    (10)回繰り返す
      @turnright (10) 度回す
      (5) 歩動かす
    end
    次のコスチュームにする
  end
</code>
// スケールを変更する場合のブロック描画関数
//   renderMatching()で呼び出される doc.render()ではSVGのサイズが取得できないため、
//   parse() と doc.render() を使用して描画する。
var renderScaledBlocks = function(target, scale) {
  var doc = scratchblocks.parse(target.innerHTML, {
    languages: ['ja', 'en'],
  });
  doc.render(function(svg) {
    target.innerHTML = "";
    target.appendChild(svg);
    //SVGの拡大処理
    svg.setAttribute("width", svg.clientWidth * scale);
    svg.setAttribute("height", svg.clientHeight * scale);
    svg.setAttribute("viewBox", "0 0 " + svg.clientWidth / scale + " " + svg.clientHeight / scale );
  });
};

//各HTML要素に記述したスクリプトを元にブロックを描画
var titleBlocks = document.getElementById('big_blocks');
renderScaledBlocks(titleBlocks, 2.0);
var middleBlocks = document.getElementById('middle_blocks');
renderScaledBlocks(middleBlocks, 1.5);
var smallBlocks = document.getElementById('small_blocks');
renderScaledBlocks(smallBlocks, 1.0);

SVGの拡大方法については以下の記事を参照しました。

ASCII.jp:HTML5のInline SVGをJavaScriptで操作 (2/5)|古籏一浩のJavaScriptラボ

[SVG] viewBoxについての考察

つまづきどころ

  • 画像を含むブロックの入力方法

    これらのブロックはブロック名に画像が含まれているので、文字列で表現する時はエイリアス文字列が設定されています。

    ブロック 日本語スクリプト
    f:id:k-aeg:20170227224919p:plain @greenflag がクリックされたとき
    f:id:k-aeg:20170227225645p:plain @turnright (15) 度回す
    f:id:k-aeg:20170227225720p:plain @turnleft (15) 度回す
  • 日本語に翻訳されていないブロックがある

    「() 回繰り返す」などのループは閉じるコマンド(英語版では「end」)が必要なんですが、日本語に翻訳されていないので、languages に"ja"と"en"の両方を指定した上で「end」と記述する必要があります。

おすすめ作業フロー

HTMLでスクリプト手書きは結構面倒なので、Scratch プロジェクトのブロックからscratchblockのスクリプトを生成するジェネレータを活用するとラクです。以下の手順で作業するのが良さそうです。

  1. Scratchでプロジェクトを作成
  2. ブロックを組んで動作確認
  3. generator :: scratchblocks でScratchプロジェクトをscratchblockスクリプトに変換
  4. scratchblockスクリプトをHTMLに貼り付け

サックスのメンテナンス用リークライトを自作してみる

離島という環境ゆえ、近くに楽器屋さんがありません。 楽器のメンテナンスのたびにフェリーで3時間かけて本土まで行くのも大変なので、簡単なメンテナンスは自分でできるようにしようと思いたちました。

調べた限り、分解&組み立てレベルのサックスメンテナンスに関する日本語の文献はこの本がベスト(というかこれしかない)のようです。

サクソフォン マニュアル 日本語版

サクソフォン マニュアル 日本語版

さっそく買って読んでみましたが、日常のメンテナンスからタンポの交換まで、全ページカラー写真でとても丁寧に書かれていて良書でした。さすがに自力でタンポ交換は無理そうでしたが…。 本書では息漏れチェックの手段として2つ紹介されており、1つは薄い紙で作った隙間ゲージをタンポに挟んで引っ張るというものと、もう1つはリークライトをボアに挿入して光が漏れる場所をチェックするというものです。

後者のリークライトは、LEAK LIGHTSのようなところで買えるのですが、大体$100以上とお高めなので、LEDテープで自作することにしました。作り方は、奥津サックスマウスピース製作さんのブログで紹介されている通りです。

okutsumouthpieces.com

用意するもの

作り方

まずはLEDテープを切り出します。

f:id:k-aeg:20170225150112j:plain

出来上がりの長さは市販品と同じ21インチ(約53cm)にします。半分で折り返してくっつけるので、倍の長さを切り出します。今回使用したLEDテープは5cm間隔で切断可能になっているので、105cmとしました。

f:id:k-aeg:20170225150102j:plain

切断可能な部分は丸い端子が4つ並んでいるところの真ん中の線です。 切断したら、裏面の両面テープを剥がして真ん中で折って貼り合わせます。

f:id:k-aeg:20170225150533j:plain

今回はクリアタイプの熱収縮チューブがなかったので、根本だけ短いチューブで固定することにしました。チューブをLEDテープの根本にかぶせてライターやヒートガン、はんだごてなどで熱を加えて収縮させます。

f:id:k-aeg:20170225151147j:plain

最後に、DCコネクター変換プラグにドライバーで赤線と黒線を接続します。LEDは極性があるので注意が必要です。赤線は+、黒線は−につながないとLEDが壊れます(たぶん)。

f:id:k-aeg:20170225153407j:plain

これで完成です。ACアダプタを接続していざ点灯! ちゃんと尽きました。カメラのホワイトバランスで暗めに写ってますが、肉眼で見ると結構明るいです。

f:id:k-aeg:20170225153528j:plain

サックスに入れてみるとこんな感じになります。

f:id:k-aeg:20170225153815j:plain

総工費としては2000円以下で自作できました。めでたしめでたし。

子供向けプログラミング教室の開講とインターンシップを受け入れた話

今週は、西ノ島デジタルラボと称して子供向けのプログラミング教室を開講したり、近くの高校からインターン生を受け入れるなど、プログラミング教育について色々と知見を得られたので記録しておこうと思います。

プログラミング教室

昨年末から準備を進めていた子供向けプログラミング教室ですが、1月末に申込者があったため2月より開講の運びとなりました。一応「西ノ島デジタルラボ」という名前をつけているのは、今後プログラミング講座以外に、ファブ系(CAD、3Dプリンタ等デジタル工作機)の講座なども展開したいという事と、今は固定の活動場所は無いけれど、将来的にはPCやデジタル工作機などを常設して活動できるような拠点があると良いなーという想いからです。

インフラとしては町内の船越地区の公会堂をお借りして、お古のデスクトップパソコン数台に軽量 Linux を入れて、Scratch のオフラインエディタをインストールして実施しました。ネット環境が無いのがネックですが、データ保存用のUSBメモリを配布したりして、当面はオフラインで進められそうです。第1回の授業はインターン期間と重なったので、会場設営などインターン生に少しお手伝いしてもらいました。

低学年向けの配慮について

そんなわけで、第1回の授業は小学2年生と3年生の2名でのスタートでした。内容としては、ビジュアル言語のScratchを使ってゲームを作ろう、というスタンダードなものです。元々は小学4年生以上という条件で始めようと考えていましたが、低学年の子のほうがプログラミング(というよりゲーム制作?)に興味があるようで、希望者や興味がある層は軒並み低学年の子でした。当初、小学4年生という区切りにしていたのは、主に以下のような理由によります。

  1. 抽象的思考ができるようになる年齢(と言われているらしい)
  2. 低学年の子にとってはマウスやキーボードの操作自体が難しい(以前に実施したプログラミング体験講座での観察から)
  3. 低学年に読めない漢字が多い(教材に配慮が必要)

逆に上記をなんとかできれば、低学年向けにも実施できるだろうということで、せっかく希望者がいるのだしと、挑戦してみることにしました。

実際取り組んでみた結果、

  • 1については、第1回実施時点では内容もそこまで踏み込んでおらず、N数も2なので何とも言えませんが、想定よりもずっと積極的に探究心をもって取り組んでくれているので、経験を積んで土台を固めていくことで壁を乗り越えられるかも、という感触です。

  • 2については、マウスをクリックした時にカーソルがずれてしまったり、アルファベットが読めないのでローマ字が入力できないといった問題になりますが、対策としては子供の手に合うように小さめマウスを用意したり、マウス操作練習のゲームをScratchで作ったり、ローマ字入力表を配布したりしました。ただ、マウス操作は若干ぷるぷるしているものの、操作自体には支障がなかったのでマウス操作練習ゲームの出番はなかったり、アルファベットが読めなくてもローマ字入力表とにらめっこして、象形文字を読むかの如くに該当する文字を見つけ出してタイプしたりと、思ったより適応力が高く杞憂だった部分も多かったです。

  • 3については、プリント教材にはすべてルビを振るようにしました。画面上ではルビは表示されませんが、読めない漢字があっても絵として覚えられるようなので、特に操作のストレスになっている感じは見受けられませんでした。Scratch はすべての表示をひらがなにするモードがあるんですが、全部ひらがなだと逆に読みづらいし、前述のとおり漢字モードでも支障はなさそうなので、そのまま使ってもらっています。

という感じで、このまま継続していけそうな気がしています。

授業の進め方について

まず前提として、このプログラミング教室では何を目指すのかということですが、若年層向けのプログラミング教育の方向性としては大きく分けて以下の2つの方向性があると考えています。

  1. 教養としてのプログラミング
    • プログラミングができるようになることよりも、プログラミングというプロセスを通して論理的思考や創造性、問題解決能力といったものを身につけることを目的とする
  2. 実用としてのプログラミング
    • 職業や趣味として実用的なソフトウェアを制作できる能力を身につけることを目的とする

この教室では基本的にプログラミング自体に興味があることを前提として、2に重きを置いた方向性を目指しています。教養という意味では、今後小学校でも必修化されるプログラミングの授業で扱われるべきかなと思います。ただ、プログラムを書くことそのものは表現の一手段でしかないので、結局はどちらの方向性をとるにしても(プログラムによって動作を指示される対象となる)コンピュータというものの性質や振舞いを理解した上で、

  • どんなことができるのか
  • 何をしたいのか
  • どのようにやるのか

といったことを考えるのが本質なのかなとも思います。プログラミング言語というだけあって、あくまでコンピュータと対話するためのコミュニケーション手段でしかないので、例えば英語だけ勉強しても(言語自体への興味は別として)、肝心の伝えたい情報や欲しい情報がなければ意味がないのと同じです。 というわけで、授業の進め方としては以下の3つのフェーズを繰り返しながら発展させていくイメージです。

  1. 探求フェーズ
    • 自由にプログラムを組みながら、色々な機能を試したり、必要な概念を身につける
  2. 構想フェーズ
    • 紙のワークシートなどを使いながら、どんなものを作るかじっくり考える
  3. 実践フェーズ
    • 考えたものをプログラムとして形にする

初回授業の雑感

初回は探求フェーズということで、自由にプログラムを組んでいきますが、何も無い状態では右も左もわからない状態なので、適当なタイミングでちょっとした課題を出したり、同じ課題を別のやり方で実現してみたり、ということ繰り返しました。探求フェーズでは好奇心を重視して、課題からちょっと逸れたりしてもそのまま続けてもらい、その方向で発展できることがあれば新たに課題を設定することで、枝葉のように多方向に知識や経験を広げていきます。

一方、課題をこなすこと以上に大切なのは、遊ぶ時間をじっくり取ることでした。例えば、移動距離を指定する場所にありえないような大きい数値をいれたらどうなるか?とか、数値にマイナスを2つつけたらどうなるか?など直接課題に関係ないことでも、コンピュータの性質や振舞いを知るのには重要なことです。ただ、同じことを何度も繰り返して無限ループに入ってしまう場合があるので、そういう時には新しい機能や他のやり方のヒントを投下して興味を引きつけるとすんなり抜け出してくれました。

生徒同士の相互作用もなかなか有効に働きました。各々の好奇心ベースで進んでいくので、進んでいく方向も異なりますが、隣の人が自分の知らないことをやっていると真似してみたり、自分が経験したことで隣の人がつまづいていたら教えてあげたり、わからないところを一緒に考えたりというアクションが見られました。 情報の非対称性があることで、それを共有するモチベーションが生まれているようです。何より友達同士で教え合うほうが、先生が直接教えるよりも真剣に受け取っている感じがします(笑)。

インターンシップ受け入れ

話は変わって、隠岐島前地域唯一の高校である隠岐島前高校では、キャリア教育の一環として職業体験を実施しているそうです。今回は一週間のインターンシップ受け入れでした。自分はフリーランスプログラマなので、従業員採用のモチベーションも無ければ、技術職ゆえ手伝ってもらえるような仕事もほとんど無いのですが、隠岐島前地域にはエンジニア志望のインターン先が無いということなので、うちで引き取ってみることにしました。普通は技術職のフリーランスインターンする機会はあまり無いと思うので、ある意味離島ならではという気もします(笑)。

というわけで、せっかくなら色々体験してもらって興味の幅を広げつつ、こちらとしてはプログラミング教育の導入部に関するデータを収集させてもらおうと考えてスケジュールを組みました。

1日目: 業界や仕事内容についてのレクチャー、Scratch 入門 + プログラミング教室手伝い
2日目: Web開発入門(HTML + JavaScript)
3日目: Web開発入門(続き)、3Dプリンタによるお土産製作
4日目: Arduino による電子工作入門
5日目: Unity による3Dゲーム製作入門

本当はメインでやっているスマホアプリ開発も入れたかったのですが、インターン生のデバイスWindows + iPhone だったので、開発環境が無く断念しました。自分で書いたプログラムが手元のデバイスで動くのは結構感動するので、インターン向きの内容ではあるんですが条件がなかなか揃いません。

色々とメニューは用意しましたが、付きっきりになるのは仕事に支障が出るので、教材の評価も兼ねて基本的にはWebページや動画、本などの入門教材で自習してもらうことにしました。

1日目

業界や仕事内容について色々話しましたが、あまり興味はなさそうでした(笑)。まずソフトウェア開発というのがどういうことなのか分からない状態だったので、プログラミングを少しでも体験した後のほうが想像しやすかったかもしれません。 その後はプログラミング教室の手伝いをしてもらうために、スクラッチ2.0アイデアブックという本で予習をしてもらいました。

この本はなかなか良書だったようで、特につまづくところも無くスラスラと読みこなしていました。プログラミング教室の間は Scratch で自由にプログラム書いてもらっていましたが、ちゃんと応用してそれっぽい何か動くものを作っていました。

2日目

2日目はWeb開発入門ということで、ビジュアル言語を卒業して、プログラミング学習サイト ドットインストールの HTML 入門と JavaScript 入門の動画を見ながら自習してもらいました。結論から言うと動画ではほとんど理解に結びつかず、後で動画で説明されていた内容について質問してみてもまったく要領を得ませんでした。

動画教材は「とりあえず何か動くものを自分の手で作る」という体験に主眼が置かれていますが、初学者にとっては言語の基本的な文法などを理解していない状態では、何やっているのか分からずにとりあえず指示に従っているだけで、頭には入りにくいようです。他の言語を1つでも学習していれば、言語の差分で見られるのでスラスラ入ってくると思います。

また、Web上の JavaScript 入門は玉石混交で情報が古かったりということが多々あるため、初学者が自分で最適なページを見つけるのはかなり困難だなと感じました。あと、そもそもの話ですが、最近のデジタルネイティブの人はスマホを使えるけど、PCを使えないという噂を聞いていましたが、せいぜい学校の授業で Word、Excel に触るくらいしか経験がなく、ブラウザとYahoo(のページ)の区別がついてなかったので、噂は本当だということが分かりました(笑)。

まあ結論としては、ブラウザの説明から載っている、その時の最新の JavaScript 入門本を一冊読むというのが初学者にとっては良い選択肢かなと思いました。 ただ、Web開発は HTML/CSS など前提となる知識が色々必要でプログラミング始めるまでの道のりが長いので、最初は Processing などセットアップが容易な言語から始めたほうが良かったかもしれません。

3日目

3日目は前日のWeb開発入門のリカバーで直接講義してみました。ホワイトボードを使いながら変数やら文法やらの説明をして、なんとか FizzBuzz 問題を(半分くらい)自力で解いてもらうところまでは行きました。初学者あるあるですが、エラーメッセージの英語を全然読もうとしない(というか読めない)ので、Webで辞書を引いてちゃんと読むように指導しました。

JavaScript でだいぶ頭が疲れたようなので、午後は3Dプリンタで印刷しておいた活イカ活っちゃんストラップの仕上げ作業を体験してもらいました。ルーターでのバリ取り作業などはわりと無心でできるので、午前の作業とのバランスはとれたと思います(笑)。インターン生が自分で完成させたストラップはお持ち帰りいただきました。

4日目

4日目は趣向を変えて電子工作に取り組みました。この日も懲りずに ドットインストールArduino入門を活用してみました。 こちらはJavaScriptと違ってわりとスムーズにこなしているように見えましたが、ブレッドボード上の配線がどうなっているのかとか、コードの各行が意味するところの理解にはつながらなかったようです。結局かなりアフターフォローを入れつつ、光センサと圧電スピーカーを組合せてテルミンもどきみたいなデバイスができあがりました。

f:id:k-aeg:20170209172119j:plain

本当はこれをユニバーサル基板に移植して、CADでエンクロージャ(箱)を設計して、3Dプリンタでプリントしてミュージックデバイスとして完成させるところまでやれたら良かったんですが、そこまでは今回時間がありませんでした。

でもせっかくなので、後で完成させるつもりです。すでにCADでの設計を終えて箱をプリント済みなので、あとは回路をユニバーサル基板に移植して詰めるだけです(笑)。

5日目

最終日は Unity を使って3Dゲームを作りました。Unity がPCにインストールできないというハプニングがあり、午前中を消費してしまいましたが、こちらは公式のチュートリアルが優秀で、あまり手をかけずに自習できました。

tutorial.unity3d.jp

インターン生がFPS(一人称視点のシューティングゲーム)好きなのもあって、Unity なら比較的簡単に FPS が作れそうという体感を得ると、これまでの開発に比べ俄然やる気が見られました。チュートリアルの途中で時間切れになってしまいましたが、まだ続けたそうだったので、プログラミング教室の小学生もそうでしたが、やはり好奇心駆動開発は強いなと思いました(笑)。

まとめ

一口にプログラミング教育と言っても、プログラミングという行為自体の目的が多様化しているのもあり、どこを目指すのかという方向は教育者側では決められないので、各自の興味をきっかけとしてある程度のレベルまでサポートして、自分で学習できるところまでつないであげるのが教育者としての役目かな、と思いました。

一方で、諸外国ではCS(Computer science: 計算機科学)教育に力点を置いて、プログラミングに限らずコンピュータへの理解を深めようという動きが主流になっているのに対して、日本ではプログラミング教育という行為のみが切り出されてクローズアップされている感があり、コンピュータの本質的な理解に結びつかないのではないかという懸念もあります。コンピュータの可能性を最大限に引き出すには、やはりコンピュータ自体への理解が不可欠です。というわけで、プログラミング教室を名乗ってはいますが、プログラミングをきっかけとしてコンピュータに対する理解を深めるという目的も重視していこうと思います。

と、いきなり話が大きくなったりしてまとまりませんでした(笑)。