マイクロビット用ジョイスティック

今回はマイクロビット用のジョイスティックを使って見ましょう。マイクロビット用のジョイスティックとしては以下のようなものがあります。

(1)Micro:bit BBC ゲームパッド拡張ボード

Amazon.co.jp内販売ページ
https://www.amazon.co.jp/gp/product/B07K7K1Y8J/

  • 製品写真

(2)Dolity Arduino BBC Micro:bit用 ジョイスティック

Amazon.co.jp内販売ページ
https://www.amazon.co.jp/gp/product/B07B9BGY3F/

  • 製品写真

 これらのジョイスティックは、それぞれ接続するピンが異なっているため、互換性がありません。また、(2)のジョイスティックは外部に基板を接続できますが、(1)のジョイスティックは外部基板を接続できません。
 (1)のジョイスティックは基板上に電池(バッテリー)があり、充電することができます。これにより外部電源なしで使うことができます。このためゲーム用途だけでなくロボットの制御コントローラーなどに使うこともできます。

 それでは、それぞれのジョイスティックを使ったプログラムを作ってみます。

Micro:bit BBC ゲームパッド拡張ボード
 まず、Micro:bit BBC ゲームパッド拡張ボードを使ってみましょう(以後、これもジョイスティックで呼称を統一)。このジョイスティックを使うには、最初に電池(バッテリー)を基板上に装着します。バッテリー駆動させないのであれば、装着しなくても構いません。バッテリーを装着したら充電します。ジョイスティックの基板にあるPower(電源)に接続します。LEDの点滅回数によって充電量が分かる仕組みになっています。

点滅回数 -
1 約25%
2 約50%
3 約75%
4 約100%
  • バッテリー部分

 なお、このジョイスティックにマイクロビットを接続した場合、マイクロビット側からも電源が供給されますが、バッテリーへの充電はできません。
 ジョイスティックのボタンとスティックのピン番号(端子番号)は以下のようになっています。

名前 ピン番号
ボタンA 5
ボタンB 11
ボタンC 15
ボタンD 14
ボタンE 13
ボタンF 12
ボタンP 8(スティックを押した場合)
スティックX方向 1
スティックY方向 2

 ボタンは押されると1から0になります。スティックはデジタルまたはアナログ値で取得できます。
まず、ボタンが押されたらボタンの名前をマイクロビットのLEDに表示してみましょう。高度なブロックにある「入出力端子」のカテゴリをクリックします。

「デジタルで読み取る」ブロックがありますので、これを利用します。

「論理」のカテゴリにある「もし<真>なら」のブロックを使って入力値を調べます。

ボタンが押されると0になるので、0になったらボタン名を表示します。これをA~F、Pボタンの数だけブロックを配置します。

 JavaScriptコードの場合は以下のようになります。

basic.forever(function () {
    basic.clearScreen()
    if (pins.digitalReadPin(DigitalPin.P5) == 0) {
        basic.showString("A")
    }
    if (pins.digitalReadPin(DigitalPin.P11) == 0) {
        basic.showString("B")
    }
    if (pins.digitalReadPin(DigitalPin.P15) == 0) {
        basic.showString("C")
    }
    if (pins.digitalReadPin(DigitalPin.P14) == 0) {
        basic.showString("D")
    }
    if (pins.digitalReadPin(DigitalPin.P13) == 0) {
        basic.showString("E")
    }
    if (pins.digitalReadPin(DigitalPin.P12) == 0) {
        basic.showString("F")
    }
    if (pins.digitalReadPin(DigitalPin.P8) == 0) {
        basic.showString("P")
    }
})

 プログラムをダウンロードしマイクロビットに転送して動作を確認します。ボタンを押すとボタンに対応した文字がマイクロビットのLEDに表示されます。

スティックの値を読み取る

 今度はスティックの値を読み取ってみましょう。スティックはデジタルではなくアナログで取得することができます。この値は横方向(X)と縦方向(Y)で若干範囲が異なっています。若干の誤差はありますが、以下のような範囲になります。

実際にスティックの値を調べてみましょう。以下のプログラムはスティックのX座標とY座標の値をマイクロビットのLEDに表示します。

 JavaScriptコードの場合は以下のようになります。

basic.forever(function () {
    basic.showString(" X")
    basic.showNumber(pins.analogReadPin(AnalogPin.P1))
    basic.showString(" Y")
    basic.showNumber(pins.analogReadPin(AnalogPin.P2))
    basic.showString("#")
})

 プログラムをダウンロードしマイクロビットに転送して動作を確認します。スティックを動かすとX方向とY方向の値がマイクロビットのLEDに表示されます。

 次にスティックを動かしたらLED上のドットを動かしてみましょう。ドットを動かす場合はスプライト機能を使うと簡単です。スプライト機能は座標だけを指定すれば消去・表示処理を自動で行ってくれます。また、画面の端まで移動した際の処理もブロック1つ加えるだけです。論理ブロックを使わないのでプログラムもすっきりしたものになります。  スティックの上下左右にあわせてドットを動かすプログラムは以下のようになります。

 JavaScriptコードの場合は以下のようになります。

let 自機: game.LedSprite = null
自機 = game.createSprite(2, 2)
basic.forever(function () {
    if (pins.analogReadPin(AnalogPin.P1) < 300) {
        自機.change(LedSpriteProperty.X, -1)
        自機.ifOnEdgeBounce()
    }
    if (pins.analogReadPin(AnalogPin.P1) > 780) {
        自機.change(LedSpriteProperty.X, 1)
        自機.ifOnEdgeBounce()
     }
    if (pins.analogReadPin(AnalogPin.P2) > 700) {
        自機.change(LedSpriteProperty.Y, -1)
        自機.ifOnEdgeBounce()
    }
    if (pins.analogReadPin(AnalogPin.P2) < 380) {
        自機.change(LedSpriteProperty.Y, 1)
        自機.ifOnEdgeBounce()
    }
})

 プログラムをダウンロードしマイクロビットに転送して動作を確認します。マイクロビットに表示されているLEDがスティックに合わせて動きます。

塗りつぶしゲーム

 せっかくのジョイスティックですから、簡単なゲームを作ってみましょう。ゲーム内容は簡単でスティックで自機(点)を動かしてマイクロビットの5×5のLEDを全部点灯させるだけです。要は25個のLEDを全部塗り潰せばゲームクリアということです。

 ゲームのプログラムのジョイスティック処理の部分は前のプログラムと同じです。異なるのはゲームの部分です。まず、塗り潰すLEDの情報を配列に入れることにします。
 なお、配列のどの部分がXY座標に対応しているかは以下の計算式で求めます。

自機のY座標を5で割り小数値を切り捨てた値 + 自機のX座標を5で割ったあまり

 ジョイスティックを動かしてLED部分を塗り潰したら、該当する配列要素を1にします。このため、配列は最初に0を入れておきます。LEDは25個あるので、25個分の0を入れます。JavaScriptコードだと横一列で見やすいのですが、ブロックエディタでは縦長になってしまい、結構画面の場所を取るので見にくいかもしれません。
 ジョイスティックで自機を移動させてLEDを点灯させたら、あとは全部塗り潰したかどうかの判定を行います。配列要素を順番に読み出していきます。1なら合計を1つ増やします。合計が25ならゲームクリアということなので「ゲームオーバー」ブロックを使ってゲームクリア(ゲームオーバー)時の処理を行います。このゲームオーバー時の処理はブロックを配置するだけでGAME OVERの文字とスコアの表示が自動的に行われます。
 あと、もう1つ処理しなければいけないことがあります。それは、塗り潰した部分のLEDを点灯させておくことです。これは配列内の値を読み出して1なら点灯するようにします。なお、消灯は自動的に行われるので点灯処理だけですみます。
 都合のいいことに点灯処理と全部塗り潰したかどうかの判定は同じ繰り返し処理を使うことができます。

 実際のプログラムは以下のようになります。

 JavaScriptコードの場合は以下のようになります。

let y = 0
let x = 0
let 合計 = 0
let 配列: number[] = []
let 自機: game.LedSprite = null
自機 = game.createSprite(2, 2)
配列 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
basic.forever(function () {
    if (pins.analogReadPin(AnalogPin.P1) < 300) {
        自機.change(LedSpriteProperty.X, -1)
        自機.ifOnEdgeBounce()
    }
    if (pins.analogReadPin(AnalogPin.P1) > 780) {
        自機.change(LedSpriteProperty.X, 1)
        自機.ifOnEdgeBounce()
    }
    if (pins.analogReadPin(AnalogPin.P2) > 700) {
        自機.change(LedSpriteProperty.Y, -1)
        自機.ifOnEdgeBounce()
    }
    if (pins.analogReadPin(AnalogPin.P2) < 380) {
        自機.change(LedSpriteProperty.Y, 1)
        自機.ifOnEdgeBounce()
    }
    配列[自機.get(LedSpriteProperty.Y) * 5 + 自機.get(LedSpriteProperty.X)] = 1
    合計 = 0
    for (let counter = 0; counter <= 24; counter++) {
        x = counter % 5
        y = Math.trunc(counter / 5)
        if (配列[counter] == 1) {
            led.plot(x, y)
            合計 += 1
        }
    }
    if (合計 == 25) {
        game.gameOver()
    }
})

 プログラムをダウンロードしマイクロビットに転送して動作を確認します。マイクロビットに表示されているLEDがスティックに合わせて動きます。

ゲームをクリアすると自動的にGAME OVERの文字とスコアを表示します。

 スティックではなくボタンで自機を移動させることもできます。スティックはアナログ入力でしたが、ボタンの場合はデジタル入力になります。このため、使用するブロックは「デジタルで読み取る」ブロックを使います。入力部分を変更するだけでスティックからボタンに対応できます。

 実際のプログラムは以下のようになります。

 JavaScriptコードの場合は以下のようになります。

let y = 0
let x = 0
let 合計 = 0
let 配列: number[] = []
let 自機: game.LedSprite = null
自機 = game.createSprite(2, 2)
配列 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
basic.forever(function () {
    if (pins.digitalReadPin(DigitalPin.P12) == 0) {
        自機.change(LedSpriteProperty.X, -1)
        自機.ifOnEdgeBounce()
    }
    if (pins.digitalReadPin(DigitalPin.P14) == 0) {
        自機.change(LedSpriteProperty.X, 1)
        自機.ifOnEdgeBounce()
    }
    if (pins.digitalReadPin(DigitalPin.P13) == 0) {
        自機.change(LedSpriteProperty.Y, -1)
        自機.ifOnEdgeBounce()
    }
    if (pins.digitalReadPin(DigitalPin.P15) == 0) {
        自機.change(LedSpriteProperty.Y, 1)
        自機.ifOnEdgeBounce()
    }
    配列[自機.get(LedSpriteProperty.Y) * 5 + 自機.get(LedSpriteProperty.X)] = 1
    合計 = 0
    for (let counter = 0; counter <= 24; counter++) {
        x = counter % 5
        y = Math.trunc(counter / 5)
        if (配列[counter] == 1) {
            led.plot(x, y)
            合計 += 1
        }
    }
    if (合計 == 25) {
        game.gameOver()
    }
})

Dolity Arduino BBC Micro:bit用 ジョイスティック

 それでは次にもう1つの「Dolity Arduino BBC Micro:bit用 ジョイスティック」を使ってみます。基本的な作り方は同じですが、使用できるボタンとピン番号が異なっています。
 ジョイスティックのボタンとスティックのピン番号(端子番号)は以下のようになっています。ボタンはデジタル値で、スティックはアナログ値で読み取ることができます。

名前 ピン番号
UPボタン(上ボタン) 10
DOWNボタン(下ボタン) 8
LEFTボタン(左ボタン) 11
RIGHTボタン(右ボタン) 9
MODEボタン(モードボタン) 6
SELECTボタン(セレクトボタン) 7
スティックX方向 4
スティックY方向 3
スティックZ方向 5

 押されたボタンに応じてLEDにアイコンや文字を表示するプログラムは以下のようになります。

 JavaScriptコードの場合は以下のようになります。

basic.forever(function () {
    basic.clearScreen()
    if (pins.digitalReadPin(DigitalPin.P10) == 0) {
        basic.showArrow(ArrowNames.North)
    }
    if (pins.digitalReadPin(DigitalPin.P8) == 0) {
        basic.showArrow(ArrowNames.South)
    }
    if (pins.digitalReadPin(DigitalPin.P11) == 0) {
        basic.showArrow(ArrowNames.West)
    }
    if (pins.digitalReadPin(DigitalPin.P9) == 0) {
        basic.showArrow(ArrowNames.East)
    }
    if (pins.digitalReadPin(DigitalPin.P7) == 0) {
        basic.showString("S")
    }
    if (pins.digitalReadPin(DigitalPin.P6) == 0) {
        basic.showString("M")
    }
})

 なお、このジョイスティックは押されたボタンに応じてLEDに特定のパターンが表示されます(2台購入してテストしてみましたが、2台とも同じ)。このため、上記のプログラムを実行した場合、プログラムで表示したパターンとジョイスティックのパターンがミックスされて表示されます。

 今度はスティックの値を読み取ってみましょう。スティックはデジタルではなくアナログで取得することができます。この値は横方向(X)と縦方向(Y)で若干範囲が異なっています。若干の誤差はありますが、以下のような範囲になります。

実際にスティックの値を調べてみましょう。以下のプログラムはスティックのX座標とY座標の値をマイクロビットのLEDに表示します。

 JavaScriptコードの場合は以下のようになります。

basic.forever(function () {
    basic.showString(" X")
    basic.showNumber(pins.analogReadPin(AnalogPin.P4))
    basic.showString(" Y")
    basic.showNumber(pins.analogReadPin(AnalogPin.P3))
    basic.showString("#")
})

ゲームの制御部分を変更して動かす

 それでは最後に、塗り潰しゲームをこのジョイスティックで動かすように変更してみます。制御部分の端子番号と数値を変えるだけですので簡単です。
実際のプログラムは以下のようになります。

 JavaScriptコードの場合は以下のようになります。

let y = 0
let x = 0
let 合計 = 0
let 配列: number[] = []
let 自機: game.LedSprite = null
自機 = game.createSprite(2, 2)
配列 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
basic.forever(function () {
    if (pins.analogReadPin(AnalogPin.P4) < 250) {
        自機.change(LedSpriteProperty.X, -1)
        自機.ifOnEdgeBounce()
    }
    if (pins.analogReadPin(AnalogPin.P4) > 850) {
        自機.change(LedSpriteProperty.X, 1)
        自機.ifOnEdgeBounce()
    }
    if (pins.analogReadPin(AnalogPin.P3) > 850) {
        自機.change(LedSpriteProperty.Y, -1)
        自機.ifOnEdgeBounce()
    }
    if (pins.analogReadPin(AnalogPin.P3) < 250) {
        自機.change(LedSpriteProperty.Y, 1)
        自機.ifOnEdgeBounce()
    }
    配列[自機.get(LedSpriteProperty.Y) * 5 + 自機.get(LedSpriteProperty.X)] = 1
    合計 = 0
    for (let counter = 0; counter <= 24; counter++) {
        x = counter % 5
        y = Math.trunc(counter / 5)
        if (配列[counter] == 1) {
            led.plot(x, y)
            合計 += 1
        }
    }
    if (合計 == 25) {
        game.gameOver()
    }
})

 このジョイスティックでもボタンで自機を動かすようにしてみるとよいでしょう。

著者 古籏一浩
プログラミングをベースにして面白そうなものはとりあえずやってみるというスタンス。複雑なものよりシンプルで楽しめるものが好み。最近は30年前に移植したゲーム(mz-700版 SPACE HARRIER)の話などを書いたりしています。
著者サイト:http://www.openspc2.org/