micro:bitでゲームを作る

今人気の子供マイコン micro:bit で遊ぼう。

ニンジャそっちのけで micro:bit で遊んでいたメンターの小川です。
なにをして遊んでいたか紹介します。

micro:bitとは

micro:bit

イギリス生まれの子供マイコンです。
Scratchでプログラムしたり、PythonやJavaScriptで本格的なプログラミングもできます。
本体には5×5のLEDやボタンが付いているので、それでゲームを作ることもできます。
モーターを動かすボードにmicro:bitを挿せば、ロボットも作れます。

必要なもの

・パソコン
・マイクロB USBケーブル (スマホとかでよく使うやつです)
・micro:bit

プログラムの動かしかた

1. 以下のURLをクリックし、エディタを開きます
https://www.coderdojo-hiroshima.com/user_upload/microbit/PythonEditor/editor.html
2. 下のソースコードを貼り付けます
3. 「Download」をクリックして、HEXファイルをダウンロードします
4. micro:bitをコンピュータに接続します。 このとき「MICROBIT」というドライブが認識されます
5. 「MICROBIT」ドライブに先ほどダウンロードしたHEXファイルをドロップします
6. 書き込みが終わると、自動的にプログラムが実行されます

ゲームの内容

なにかボタンを押すとゲームが始まります。
画面の一番下にニンジャがおり、AボタンとBボタンで左右に動かせます。
画面の上からシュリケンが迫ってくるので、ニンジャを操作してよけてください。
当たると爆発四散します。

問題点

難易度がずっと同じ。
だんだんスピードを速くするなどして難易度を上げる工夫が必要。

シュリケンがランダムで出現するが、完全にランダムなので横一直線に並んだりして絶対によけられない状況が発生する。
必ず抜けられるようシュリケンの配置を調整するアルゴリズムを考える必要がある。

ニンジャの方には「ダメなランダム」と指摘を頂きました。

ソースコード

今回はPythonで作ってみました。
なにをやっているか詳しく知りたい人は、メンター小川に訊いてください。

from microbit import *
import random

# ニンジャの画像
NINJA_IMAGE = \
    Image(
        "99999:"
        "99990:"
        "90090:"
        "99990:"
        "99990")

# 爆発の画像
EXPLOSION_IMAGES = [
    Image(
        "00900:"
        "09090:"
        "90909:"
        "09090:"
        "00900"),
    Image(
        "90909:"
        "00000:"
        "09090:"
        "00000:"
        "90909"),
]

# ステージの幅
STAGE_WIDTH = 5
#ステージの高さ
STAGE_HEIGHT = 5
# シュリケンの出現率 (値が大きいほど出現率が低くなる)
SHURIKEN_RATE = 5
# 背景の明るさ
BACKGROUND_BRIGHTNESS = 0
# シュリケンの明るさ
SHURIKEN_BRIGHTNESS = 3
# プレイヤーの明るさ
PLAYER_BRIGHTNESS = 9
# スクロールする間隔
SCROLL_INTERVAL = 10

# 二次元配列から画像を作成する
def create_image(img):
    s = ':'.join([''.join([str(pixel) for pixel in line]) for line in img])
    return Image(s)

# ボタンが押されるのを待つ
def wait_for_button_press():
    # ボタンが押された回数をクリアする
    button_a.get_presses()
    button_b.get_presses()

    # なにかボタンが押されるまで待つ
    while button_a.get_presses() == 0 and button_b.get_presses() == 0:
        sleep(16)

# ゲームを実行する
def run_game():
    tick = 0
    player_pos = STAGE_WIDTH // 2
    backstage_pos = 0
    backstage = [[BACKGROUND_BRIGHTNESS] * STAGE_WIDTH] * STAGE_HEIGHT

    while True:
        # 押されたボタンによってプレイヤーを左右に動かす
        player_pos -= button_a.get_presses()
        player_pos += button_b.get_presses()
        if player_pos < 0:
            player_pos = 0
        if player_pos >= STAGE_WIDTH:
            player_pos = STAGE_WIDTH - 1

        if tick % SCROLL_INTERVAL == 0: # ステージをスクロールさせるのをゆっくりにする
            # ステージをスクロールさせる
            backstage_pos -= 1
            if backstage_pos < 0:
                backstage_pos = STAGE_HEIGHT - 1
            # ステージにシュリケンを出す
            backstage[backstage_pos] = [
                SHURIKEN_BRIGHTNESS if random.randint(0, SHURIKEN_RATE - 1) == 0 else BACKGROUND_BRIGHTNESS
                    for _ in range(STAGE_WIDTH)]

        # 表示するステージを作る
        stage = [line[:] for line in backstage[backstage_pos:]]
        stage.extend([line[:] for line in backstage[0:backstage_pos]])

        # プレイヤーにシュリケンが当たったか判定する
        if stage[-1][player_pos] != BACKGROUND_BRIGHTNESS:
            # 当たったのでゲームオーバー
            display.show(EXPLOSION_IMAGES * 2)
            break

        # ステージを表示する
        stage[-1][player_pos] = PLAYER_BRIGHTNESS
        display.show(create_image(stage))

        tick += 1

        sleep(16)

while True:
    display.show(NINJA_IMAGE)
    wait_for_button_press()
    run_game()

ソースコード (初心者向け)

上のソースコードは内包表記などの中級者向けの考え方を使っているので、
基本的な命令だけを使ったソースコードを以下に示します。

from microbit import *
import random

# ニンジャの画像
NINJA_IMAGE = \
    Image(
        "99999:"
        "99990:"
        "90090:"
        "99990:"
        "99990")

# 爆発の画像
EXPLOSION_IMAGES = [
    Image(
        "00900:"
        "09090:"
        "90909:"
        "09090:"
        "00900"),
    Image(
        "90909:"
        "00000:"
        "09090:"
        "00000:"
        "90909"),
]

# ステージの幅
STAGE_WIDTH = 5
#ステージの高さ
STAGE_HEIGHT = 5
# シュリケンの出現率 (値が大きいほど出現率が低くなる)
SHURIKEN_RATE = 5
# 背景の明るさ
BACKGROUND_BRIGHTNESS = 0
# シュリケンの明るさ
SHURIKEN_BRIGHTNESS = 3
# プレイヤーの明るさ
PLAYER_BRIGHTNESS = 9
# スクロールする間隔
SCROLL_INTERVAL = 10

# 二次元配列から画像を作成する
def create_image(img):
    img_str = []
    for line in img:
        line_str = []
        for pixel in line:
            line_str.append(str(pixel))
        img_str.append(''.join(line_str))
    s = ':'.join(img_str)
    return Image(s)

# ボタンが押されるのを待つ
def wait_for_button_press():
    # ボタンが押された回数をクリアする
    button_a.get_presses()
    button_b.get_presses()

    # なにかボタンが押されるまで待つ
    while button_a.get_presses() == 0 and button_b.get_presses() == 0:
        sleep(16)

# ゲームを実行する
def run_game():
    tick = 0
    player_pos = 2
    backstage_pos = 0
    backstage = [
        [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]
    ]

    while True:
        # 押されたボタンによってプレイヤーを左右に動かす
        player_pos -= button_a.get_presses()
        player_pos += button_b.get_presses()
        if player_pos < 0:
            player_pos = 0
        if player_pos >= STAGE_WIDTH:
            player_pos = STAGE_WIDTH - 1

        if tick == 0: # ステージをスクロールさせるのをゆっくりにする
            # ステージをスクロールさせる
            backstage_pos -= 1
            if backstage_pos < 0:
                backstage_pos = STAGE_HEIGHT - 1
            # ステージにシュリケンを出す
            new_line = []
            for _ in range(STAGE_WIDTH):
                if random.randint(0, SHURIKEN_RATE - 1) == 0:
                    new_line.append(SHURIKEN_BRIGHTNESS)
                else:
                    new_line.append(BACKGROUND_BRIGHTNESS)
            backstage[backstage_pos] = new_line

        # 表示するステージを作る
        stage = []
        for line in backstage[backstage_pos:]:
            stage.append(line[:])
        for line in backstage[0:backstage_pos]:
            stage.append(line[:])

        # プレイヤーにシュリケンが当たったか判定する
        if stage[-1][player_pos] != BACKGROUND_BRIGHTNESS:
            # 当たったのでゲームオーバー
            display.show(EXPLOSION_IMAGES * 2)
            break

        # ステージを表示する
        stage[-1][player_pos] = PLAYER_BRIGHTNESS
        display.show(create_image(stage))

        tick += 1
        if tick >= SCROLL_INTERVAL:
            tick = 0

        sleep(16)

while True:
    display.show(NINJA_IMAGE)
    wait_for_button_press()
    run_game()

ソースコードを改造する

ソースコードを改造するには、Pythonとmicro:bitの知識が必要になります。
以下に参考になるものを紹介します。

・書籍:10才からはじめるプログラミング図鑑:たのしくまなぶスクラッチ&Python超入門
ScratchのブロックがPythonの命令とどう対応しているか書いてあります。
Scratchをすでに習得しているなら入門しやすいと思います。

・micro:bit – MicroPython ドキュメント
プログラムからLEDやボタンを使うための命令が載っています。
http://www5f.biglobe.ne.jp/~inachi/microbit/micropython/index.html

ABOUTこの記事をかいた人

小川 久史

CoderDojo広島メンター。ソフトからハードまで、つくることならなんでもござれ。ニンジャの好奇心を刺激する術を模索中。