第16回「液晶ゲームを作ってみよう」



 今回は液晶ディスプレイをArduinoでコントロールして、かんたんなゲームを作ってみます。

 ひと口に液晶ディスプレイ(LCD)と言っても、さまざまな種類がありますね。皆さんがこのページを表示するのに使っているディスプレイは100万ピクセルを超える高解像度なものかもしれません。携帯端末で読んでいるとしても、320×240ピクセル程度の解像度があるでしょう。そうしたLCDは高精細で表現の自由度が高い反面、複雑な制御を必要とします。表示するデータも巨大になりがちで、Arduinoのような8bitマイコンで扱うのは困難です。

 マイコンで扱いやすいのはキャラクターLCDと呼ばれる、文字の表示に特化した小さいモノクロディスプレイです。Arduinoを使うと、ソフトウエアもかんたんです。価格は1000円前後のものが多く、工夫次第でかなりの表現力を発揮します。

 まずはArduinoにキャラクタLCDを接続する際の、基本的な方法について説明します。

秋月電子のキャラクタLCD、SD1602HUOB。ピンが一列に並んでいるので、ブレッドボードに接続しやすい製品です。バックライトの色が異なる2種類(オレンジと緑)があります。
Arduinoと接続する際の回路図です。コントラスト調整用の半固定抵抗(10KΩ)と、バックライトLEDの電流制限抵抗(100Ω程度)が必要です。

 キャラクタLCDにはたくさんの端子があります。ただし、それを全部使う必要はありません。最低限の配線で済ませる場合、電源(5VとGND)以外に6本の線をつなぐだけで動作します。ここでは、最低限バージョンの回路図を示しました。

 間違いやすい点をいくつかあげておきましょう。

 R/Wという端子(SD1602HUOBでは5番ピン)はGNDに接続します。Arduinoへつなぐ方法もありますが、今回はピンを節約するため、GNDへ接続してください。これを忘れると動きません。

 Voという端子は、電圧の高低によって液晶のコントラストを決定するためにあります。適切なコントラストに調整しないと表示がまったく見えないことがあるので、半固定抵抗を回路図のように接続して、電圧を変更できるようにします。正しく動作しているはずなのに何も表示されない場合は、この半固定抵抗を回してみてください。

 キャラクタLCDにはバックライト付きのものと、無いものがあります。通常、バックライトはLEDです。SD1602HUOBの場合は、ユーザーがLCD部とは別に電源を与える必要があります。5Vをそのまま接続すると発熱する可能性があるので、100Ωのカーボン抵抗器を直列に入れました。

 Arduino側のピン番号は、回路図のとおりでなくても構いません。自分にとって都合のいいピンを選んでください。ただし、スケッチ(Arduinoのプログラム)でハードウェアに合った正しいピン番号を指定する必要があります。次に示すスケッチは回路図の通りに接続した場合の例です。これだけで、画面に「hello, world!」が表示されるはずです。

1: #include
2: LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
3:
4: void setup {
5:  lcd.begin(16, 2);
6:  lcd.print("hello, world!");
7: }
8:
9: void loop {}
(行頭の1:から9:は説明に使う行番号です。スケッチとして入力する際は無視してください)

 かんたんにこのスケッチの説明をしましょう。

 1行目の#includeで、ArduinoのLCDライブラリを読み込んでいます。今回使用しているのは、最新版の開発環境「arduino-0017」に付属するライブラリです。これ以前のLCDライブラリとは一部動作が異なります。また、後ほど紹介するスケッチは、このバージョンから使えるようになった便利な機能を利用しますので、arduino-0017が必要です。

 2行目でLCDに接続します。(2, 3, 4, 5, 6, 7)という数値は、LCDが接続されているピン番号を示しています。回路図と違うピンに接続した場合は、変更が必要です。詳細はリファレンスを参照してください。

 4行目から始まるsetupのなかで、2つの処理をしています。まず、使用しているLCDの表示能力が16文字×2行であることの宣言。続いて、メッセージの表示です。

 メッセージをひとつ表示するだけならばloopは不要です。ただし、消してしまうとエラーになるので、空のまま残しておきます。

「hello, world!」が表示できれば、セッティングはまず問題ありません。

aitendoのキャラクタLCD、JHD164A。ハードウェア的には16文字×4行なのですが、ソフトウエアからは32文字×2行に見えます。長いテキストを1行目に表示すると、このように3行目につながって出てきます。コントラスト調整が不要で、Vo端子は未接続でも動作しています
秋月電子の8文字×2行タイプ、ACM0802C-NLW-BBH。ピンが2列なので、ブレッドボードには不向きです
16文字×1行のS-10551D。なんと300円です。
マイクロファンのシールド、CLCD-Boosterを使用すると、Arduinoの上にキャラクタLCDを載せることができます
CLCD-Boosterに16文字×2行の青いLCD、SC1602BBWB-XA-GB-Gを組み合わせたところ。CLCD-Boosterには温度センサと光センサが載っていて、その値を表示するサンプルスケッチが公開されています。それを見ると、文字コードを直接指定して、カタカナを表示する方法がわかるでしょう
バックライトがない、SC1602BS-Bに交換してみました。視認性は良好で、明るいところではバックライト付きのものより見やすいくらいです。500円と安いのも嬉しい点
半固定抵抗を回してコントラストを調整中。文字がクッキリ見えない、あるいは何も見えないときは、この調整を行なってください

 さて、キャラクタLCDを接続し、メッセージを表示するところまでは大丈夫ですね。

 続いては、部品を少し追加し、スケッチを拡張して、ちょっとしたゲームを作ってみます。その際活用するのが、arduino-0017のライブラリで追加された、カスタムキャラクタ機能です。ベテランのパソコンユーザーの方には外字登録といったほうがイメージしやすいかもしれません。文字をデザインして、任意の図形を表示できます。わずか5×7ドットのビットマップですが、アニメーション化することで、案外豊かな表現が可能です。

CLCD-Boosterを利用して作ったハードル飛びゲーム「Hurdleman」。操作系はプッシュスイッチ1つだけです。
次々と現れるハードルを飛び越えてください。理想的なタイミングで飛ぶと10点、ギリギリのタイミングのときは5点がもらえます。1回でも引っかかるとゲームオーバー。きわめて原始的なゲームで、変化がありません。何回飛んでも難しくなったりはしません。
キャラクタLCDの回路に、プッシュスイッチ(タクトスイッチ)を付け加えてください。これがジャンプボタンです。CLCD-Boosterの場合は基板上にあらかじめ実装されているタクトスイッチを使うこともできます(この例ではそうしています)
走っている選手のアニメーションパターン。3コマのループです

 このスケッチは次のURLからダウンロードできます。
http://www.musashinodenpa.com/arduino/lib/Hurdleman.pde

 1つ目のゲームは、これ以上単純なものは思いつかないというくらい単純ですが、アニメーションするキャラクター(走る選手)とスクロールするオブジェクト(迫り来るハードル)という2つの基本的な要素が入っています。

 選手のアニメーションはキャラクタLCDの外字機能で実現しています。arduino-0017のLCDライブラリでは、createCharという命令を使うことでかんたんに利用できます。

 スケッチを見ると、次のようなデータがありますねす。これは、選手のアニメーションパターンの定義です。

B00010, // runner 3
B00010,
B01100,
B00110,
B00100,
B01010,
B10010

 先頭のBはこのデータが2進数であることを表し、続く0と1の組み合わせでパターンを表しています。「1」が走っている人の形に並んでいるように見えますか? このような外字を最高8つまで登録でき、それらを適度なスピードで切り替えながら表示することでアニメーションを実現できます。

 ユーザーの入力を受け付けながら、描画を一定のペースで繰り返すために、MsTimer2ライブラリを使ってタイマー割り込みを利用しています。これは一定時間ごとに処理を呼び出す機能です。refreshという関数に描画系の処理をまとめてあり、この関数を呼び出すたびに画面が更新されます。更新レートについては、このゲームの場合、ゆっくりめの毎秒6フレームで動かしたときに一番いい味になると判断しました。もっと難しくしたい人は、setupのなかで行っているMsTimer2の設定を変更して、高速化してみるといいでしょう。

 それでは、次のゲームに行ってみましょう。ユーザーインタフェイスに少し凝ってみました。

いわゆる「モグラたたき」です。しかし、解像度の問題でモグラには見えないかもしれません。親指用小型ジョイスティック「サムジョイスティック」がコントローラです
サムジョイスティックを左右に動かしてハンマーの位置を決め、モグラのようなものが顔を出したタイミングで、サムジョイスティックを押してハンマーを振り下ろします。
Sparkfunの「Thumb Joystick」と「Breakout Board for Thumb Joystick」を木片の上にネジ留めしました
ブレークアウトボードにL字のピンヘッダをハンダ付けし、そこからArduinoに接続しています
このように配線しました。スケッチはこの回路図を前提にしています。サムジョイスティックの中には2つの可変抵抗とタクトスイッチが入っているだけです。回転式の可変抵抗(ボリューム)と一般的なプッシュスイッチで代用することができます。そのほうがプレイしやすいかもしれません

 このスケッチは次のURLからダウンロードできます。
http://www.musashinodenpa.com/arduino/lib/MoleMole.pde

 ゲームをハードウェアから自作する面白みは、勝手にコントローラを作り出せる点にあるかもしれません。我々はプレステ風のアナログジョイスティックを木の板に乗せて、Wiiリモコン風のインタフェイスをこしらえてみました。使ってみると一長一短です。左右の動きはなかなか快適ですが、親指を押し下げてスイッチを押す操作が固いのです。角度によってはすぐに押すことができず、モグラに逃げられます。内蔵のタクトスイッチを押し込む機構があまり良くないように思えます。このスイッチを使う代わりに、板の下側に引き金式のスイッチを取り付けたらいいかもしれません。そうするとますますWiiリモコンに似てきますね。自分で作ってみることで、大メーカーの製品がいかによく考えられているかが実感できます。

 ソフトウエアの構造はハードルゲームとよく似ています。キャラクター・アニメーションは外字機能、描画系はタイマー割り込みを利用しています。スケッチが少し大きくなっているのは、ゲーム性をあげるための処理が増えたせいです。たとえば、モグラの出現がだんだん速くなります。LIFEの概念を導入し、3回失敗したところでゲームオーバーです。本当は、あるレベルに達すると2匹同時に出現するようにしたいのですが、そこまではできていません。

 このように、キャラクタLCDはかなり簡単に扱うことができます。また、思ったより高速で、工夫しだいでいろいろな表現ができそうです。皆さんも自分だけのゲームマシンを作ってみましょう。