検索
連載

ハラハラドキドキ「うさぎさん危機一髪ゲーム」を作ろう!アイデア・ハック!! Arduinoで遊ぼう(4)(2/3 ページ)

頭の中のアイデアを「Arduino(アルドゥイーノ)」で実現!! 筆者と一緒にモノづくりの喜びや難しさを体験・体感してみよう。第4回のテーマは“子どもと一緒に作って遊べるゲーム”だ。スイッチとブザーを組み合わせて、「うさぎさん危機一髪ゲーム」を作る! 後半には、電磁石を使ってうさぎさんを落下させるオプション機能についても解説する。

Share
Tweet
LINE
Hatena

Arduinoでメロディーを奏でよう!

 それでは、Arduinoの統合開発環境「Arduino IDE」で、スケッチ(プログラム)を作成していきましょう(スケッチ1)。


#include "pitches.h"
 
//-----------------------
// 定数の定義
//-----------------------
const int BZ = 2;                //ブザー(TMP36)の出力ピン
 
const int nos = 5;               //スイッチの数
const int SW[nos] = {3,4,5,6,7}; //各スイッチの入力ピン番号
//const int BOM = 10;            //電磁石ピンの出力ピン(オプション)
 
//スイッチの回路は負論理なので、ONがLOWになる
const int SW_ON = LOW;
const int SW_OFF = HIGH;
 
//-----------------------
// グローバル変数の定義
//-----------------------
int G_old_val[nos] = {SW_OFF, SW_OFF, SW_OFF, SW_OFF, SW_OFF}; //前回のスイッチの値
int G_sw_val;
 
void setup() {
    pinMode(BZ, OUTPUT);        //ブザーを出力モードに設定
 
    //スイッチを全て入力モードに設定
    for(int i = 0; i < nos; i++){
      pinMode(SW[i], INPUT);
    }
//    pinMode(BOM, OUTPUT);       //電磁石ピンを出力モードに設定(オプション)
 
    randomSeed(analogRead(A0)); //乱数の初期設定に未接続ピンのノイズを利用
//  digitalWrite(BOM, HIGH);    //電磁石の電流を流す(オプション)
    bz_start();                 //ゲームスタート音楽
}
 
void loop() {
    int int_swNumber = -1;      //何も押してないときの番号を設定
    int int_rand = random(nos); //ランダムでハズレスイッチ番号を決定する
 
    //スイッチ1〜5の状態を取得
    for(int i = 0; i < nos; i++){
       G_sw_val = digitalRead(SW[i]);    //スイッチの状態を読み取る
       if(G_sw_val == SW_ON && G_old_val[i] == SW_OFF){
          int_swNumber = i;              //スイッチの番号を取得
       }
       G_old_val[i] = G_sw_val;          //スイッチの値を保存
    }
 
    //スイッチの入力があったとき
    if(int_swNumber != -1){
            //ハズレスイッチ番号が押されたら、ゲーム終了
            if(int_rand == int_swNumber){
                bz_ending();                //エンディング音楽
//        digitalWrite(BOM, LOW);           //電磁石の電流をカット
            } //クリア音を流す
            else{
                bz_levelup();
            }
    }
}
スケッチ1 「うさぎさん危機一髪ゲーム」。乱数でハズレスイッチ番号を決めて、ゲームの判定をしている

 1行目の#includeで、「pitches.h」を読み込んでいます。これは、音階を宣言したファイルで、Arduinoのサンプルスケッチ「toneMelody」に入っています。この音階を使用して、ゲーム用のメロディーを作りました。

 31行目のrandomSeed()は、乱数を発生するための初期処理です。使用していないアナログ入力ピン(A0)のノイズを引数にすることで、random()使用時に毎回違う値を取得できるようになります。

 36行目から始まるloop()の中で、ゲームの判定を行います。int_swNumber変数にスイッチが押されていないときの番号「−1」をセットした後(37行目)、ランダム関数でハズレスイッチ番号を選んでいます(38行目)。

 41〜47行目は、スイッチ1〜5までの入力値を見て、スイッチの状態をチェックしています。スイッチが押されていた場合は、int_swNumberにスイッチ番号を取得します(44行目)。

 スイッチが押されていたときは、50〜59行目が実行され、アタリ/ハズレの判定を行い、それぞれに該当するメロディーを呼び出します。

 今回、toneMelody()とゲームスタートを含む3曲分の楽譜を、ユーザー関数として作成しました。Arudino IDEには、音を鳴らすためのtone()が用意されています。tone()は引数に、出力するピン番号、周波数を指定して、メロディーを奏でることができます。

 toneMelody()と、ゲームスタートのbz_start()でメロディーの作り方を見てみましょう(スケッチ2)。

//-----------------------------------
// 指定した音階と長さでブザーを鳴らす
// note:音階  duration:長さ
//-----------------------------------
void toneMelody(int note, int duration){
  int noteDuration = 1000 / duration;    //音の長さを決める
  tone(BZ, note);                        //ブザーを指定周波数
  delay(noteDuration);                   //指定時間 鳴らす
 
  //音の切れ目を作る
  noteDuration = noteDuration * 0.1;    //長さを決めている
  noTone(BZ);                           //ブザーへの出力を止める
  delay(noteDuration);                  //指定時間保つ
}
 
//-----------------------
// スタート
//-----------------------
void bz_start(){
  int melody[] = {NOTE_G5, NOTE_G5, 0, NOTE_G5, NOTE_F5, NOTE_G5, NOTE_AS5};
  int noteDurations[] = {8,8,8,4,8,4,4};
  for (int i = 0; i < 7; i++) {
    toneMelody(melody[i], noteDurations[i]);
  }
スケッチ2 ゲーム開始時に流す曲。誰もが知っている懐かしいメロディーをマネてみた

 toneMelody()は、引数に音階と音の長さを指定して呼び出します。実際に鳴らす音の長さは計算で求めます。durationが「8」の場合は、1000÷8=125、つまり125ミリ秒間だけ音が鳴ります(5行目)。

 tone()の引数に、出力するピン、周波数を指定し、delay()で出力する時間を指定しています(7〜8行目)。音と音が連続すると曲が歯切れよく聞こえないので、noTone()で音を止めます(12〜13行目)。

 bz_start()には、音階と長さを記録してあります。要するに、これが楽譜です。20行目のmelody配列の要素は、「pitches.h」に宣言されている音階です。「pitches.h」には、B0〜DS8まで8オクターブの音(周波数)が定義されています。noteDurations配列には、melodyに入れた音の長さを要素として宣言します。

 for文で配列の要素をループして、toneMelody()を呼び出せばブザーが鳴ります。

 レベルアップとエンディングの音階は、ファイルに入っているのでダウンロードして確認してください。

>>スケッチ(mono04_game.zip)のダウンロードはこちら

Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る