最終更新日
記事公開日

Chat GPTを使ってM5Stack用ミニゲームを作る

M5Stack+Chat GPT

M5Stackは、最初から液晶が搭載されており、マイクロSDカードも使える便利なマイコンです。

他のマイコンに比べて扱いやすいので、ゲームも簡単に作ることができます。

昔はちょっとしたゲームを作るのも大変でした。

容量が少ないので画像や音源を節約しないといけないし、少ないドット数でキャラクターを表現するのにめちゃくちゃ時間が取られていたからです。

それがM5Stackなら「jpg画像」や「mp3音源」をSDカードに保存して、ポンポンポンとあっという間にゲームを完成させることができます。

さらに今はChat GPTの登場により、大まかなプログラムコードだって書いてもらえます。

ということで、今回は【M5Stack】と【ChatGPT】を使い、一日で『じゃんけんミニゲーム』を作ってみました。

《持ち運びできるオリジナルゲーム機を作ってみたい!》

《Scratchではなく、ちゃんとしたプログラミング言語を使ってゲームを作ってみたい!》

という方、ぜひ参考にしてみて下さい。

実際に作成したゲーム

今回作成したのは「じゃんけんゲーム」です。

録音した息子の掛け声(mp3)とグー・チョキ・パーの画像(jpg)を使用しています。

「試される目押し力!確率1/2938!君は10連勝を達成できるか!?」

プログラム(Arduino言語)

※MP3を再生するので、事前に「ESP8266Audio」「ESP8266_Spiram」この2つのライブラリをダウンロードしておく必要があります。

#include <M5Stack.h>

// MP3再生ライブラリ
#include "AudioFileSourceSD.h"
#include "AudioFileSourceID3.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2S.h"

AudioGeneratorMP3 *mp3;
AudioFileSourceSD *file;
AudioOutputI2S *out;
AudioFileSourceID3 *id3;

// 列挙子リスト
enum Hand { GUU, CHOKI, PAR };

// 連続して勝った数
int win_count = 0;

// ボタン判定
bool button_left = false;
bool button_center = false;
bool button_right = false;

// --------------------------------------------------
//                 MP3再生関連
// --------------------------------------------------
void playMP3(const char *filename){
  file = new AudioFileSourceSD(filename);
  id3 = new AudioFileSourceID3(file);
  out = new AudioOutputI2S(0, 1); // Output to builtInDAC
  out->SetOutputModeMono(true);
  out->SetGain(0.1); // 音量(デフォルト:1)
  mp3 = new AudioGeneratorMP3();
  mp3->begin(id3, out);
  while(mp3->isRunning()) {
    if (!mp3->loop()) mp3->stop();
  }
}

// --------------------------------------------------
//           プレイヤー側のじゃんけん画像
// --------------------------------------------------
void player_img(Hand player) {

  switch(player) {

    case GUU:
      M5.Lcd.drawJpgFile(SD, "/janken/guu.jpg", 42, 192, 0, 0, 0, 0, JPEG_DIV_4);
      break;

    case CHOKI:
      M5.Lcd.drawJpgFile(SD, "/janken/choki.jpg", 138, 192, 0, 0, 0, 0, JPEG_DIV_4);
      break;

    case PAR:
      M5.Lcd.drawJpgFile(SD, "/janken/par.jpg", 232, 192, 0, 0, 0, 0, JPEG_DIV_4);
      break;
  }
}

// --------------------------------------------------
//              CPU側のじゃんけん画像
// --------------------------------------------------
void cpu_img(Hand cpu) {

  switch(cpu) {
    
    case GUU:
      M5.Lcd.drawJpgFile(SD, "/janken/re_guu.jpg", 64 ,0);
      break;
    
    case CHOKI:
      M5.Lcd.drawJpgFile(SD, "/janken/re_choki.jpg", 64 ,0);
      break;

    case PAR:
      M5.Lcd.drawJpgFile(SD, "/janken/re_par.jpg", 64 ,0);
      break;
  }
}

// --------------------------------------------------
//                   じゃんけん結果
// --------------------------------------------------
void displayResult(Hand player,Hand cpu) {

  // CPUのじゃんけん抽選
  playMP3("/janken/pon.mp3"); // ポン
  delay(100);

  M5.Lcd.fillScreen(BLACK);
  player_img(player);
  cpu_img(cpu);

  // 引き分け
  if (player == cpu) {

    M5.Lcd.setTextColor(YELLOW);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setCursor(20, 100);
    M5.Lcd.println("DRAW");
    M5.Lcd.setCursor(254, 100);
    M5.Lcd.println("DRAW");

    playMP3("/janken/aiko.mp3"); // 声:あいこ
    M5.Speaker.mute();

  // 勝ち
  } else if ((player == GUU && cpu == CHOKI) ||
             (player == CHOKI && cpu == PAR) ||
             (player == PAR && cpu == GUU)) {

    M5.Lcd.setTextColor(RED);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setCursor(20, 100);
    M5.Lcd.println("WIN!");
    M5.Lcd.setCursor(254, 100);
    M5.Lcd.println("WIN!");

    playMP3("/janken/kati.mp3"); // 声:勝ち
    M5.Speaker.mute();

    // 連続勝利数のカウントアップ
    win_count++;

    // 10連勝達成
    if(win_count==10) {
      delay(500);
      M5.Lcd.fillScreen(BLACK);
      M5.Lcd.setTextColor(WHITE);
      M5.Lcd.setTextSize(5);
      M5.Lcd.setCursor(74, 80);
      M5.Lcd.println("CLEAR!");
      delay(2000);
      win_count==0;
    }

  // 負け
  } else {

    M5.Lcd.setTextColor(BLUE);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setCursor(20, 100);
    M5.Lcd.println("LOSE");
    M5.Lcd.setCursor(254, 100);
    M5.Lcd.println("LOSE");

    // 負けの音
    playMP3("/janken/make.mp3"); // 声:負け
    M5.Speaker.mute();

    win_count = 0;
  }

  // 次の勝負の準備
  delay(2000);
  M5.Lcd.fillScreen(BLACK);

  // 割り込みフラグのリセット
  button_left = false;
  button_center = false;
  button_right = false;

  // プレイヤー側のじゃんけん画像を表示
  player_img(GUU);
  player_img(CHOKI);
  player_img(PAR);

  // 連続勝利数の表示
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setCursor(20, 10);
  M5.Lcd.println("WIN");
  M5.Lcd.setCursor(34, 29);
  M5.Lcd.println(win_count);

  // 声:じゃんけん
  playMP3("/janken/janken.mp3");
}

// --------------------------------------------------
//        左ボタンを押したときの割り込み関数
// --------------------------------------------------
void Interrupt_button_left() {
  button_left = true;
}
// --------------------------------------------------
//       中央ボタンを押したときの割り込み関数
// --------------------------------------------------
void Interrupt_button_center() {
  button_center = true;
}
// --------------------------------------------------
//        右ボタンを押したときの割り込み関数
// --------------------------------------------------
void Interrupt_button_right() {
  button_right = true;
}

// --------------------------------------------------
//           setup
// --------------------------------------------------
void setup() {

  M5.begin();
  M5.Power.begin();
  //WiFi.mode(WIFI_OFF); 
  delay(500);

  // 割り込み処理
  pinMode(GPIO_NUM_39, INPUT);
  attachInterrupt(GPIO_NUM_39, Interrupt_button_left, FALLING);

  pinMode(GPIO_NUM_38, INPUT);
  attachInterrupt(GPIO_NUM_38, Interrupt_button_center, FALLING);

  pinMode(GPIO_NUM_37, INPUT);
  attachInterrupt(GPIO_NUM_37, Interrupt_button_right, FALLING);

  // M5Stackの初期化
  M5.Lcd.fillScreen(BLACK);

  player_img(GUU);
  player_img(CHOKI);
  player_img(PAR);

  // 声:じゃんけん
  playMP3("/janken/janken.mp3");
}

// --------------------------------------------------
//                        loop
// --------------------------------------------------
void loop() {

    for (Hand hand : {GUU, CHOKI, PAR}) {

      // CPUの手を表示
      cpu_img(hand);

      // 割り込み処理によるフラグ判定
      if(button_left) {
        displayResult(GUU,hand);
      }
      else if(button_center) {
        displayResult(CHOKI,hand);
      }
      else if(button_right) {
        displayResult(PAR,hand);
      }

   }

}

使用した画像・音源ファイル

グー・チョキ・パーの画像
  • プレイヤーの「グー」画像(goo.jpg)
  • プレイヤーの「チョキ」画像(choki.jpg)
  • プレイヤーの「パー」画像(par.jpg)
  • 相手の「グー」画像(re_goo.jpg)
  • 相手の「チョキ」画像(re_choki.jpg)
  • 相手の「パー」画像(re_par.jpg)
  • 「じゃんけん」音声(janken.mp3)
  • 「ポン」音声(pon.mp3)
  • 「勝ちだよ」音声(kati.mp3)
  • 「負けだよ」音声(make.mp3)
  • 「あいこだよ」音声(aiko.mp3)

ダウンロード:janken.zip

上記のファイルをマイクロSDカード(16GB以下)に保存して、M5Stackに差し込んでください。

使用マイコン

M5Stack gray

M5Stack gray

BasicやCoreといったM5Stackシリーズであればどれでも動くはずです。

【M5Stackの選び方】BASIC・Gray・FIRE・CORE2・M5Stick・ATOMは何が違うのか?

ゲーム作成の流れ

Chat GPTでベースとなるプログラムを作成する

今回はChat GPTにベースとなるプログラムを作成してもらいました。

Chat GPT(無料で利用できますが、登録が必要です)

もちろん、一から自分で書いても全く問題はありません。

しかしChat GPTに投げれば、ものの数秒でコアとなるベースプログラムを作成してくれます。

プログラムを考える時間・コードを書く時間を減らすことができるので、作業効率を大幅にアップすることができます。

ちなみに、私がChat GPTに出した指示は以下の通りです↓

「じゃんけんゲームのコードを教えて。Arduino言語で。日本語は使わないで。10連勝でエンディングを流したい。対戦相手はコンピューター」

すると、用件に沿ったコードを出力してくれます。

ChatGPTから出力されたコード

※M5Stackで日本語を使うにはライブラリが必要なので、まずは日本語を使わないコードの出力をChat GPTに指示しました。

あとはそのコードをコピペして、M5Stackに書き込むだけ。

ただし、Chat GPTが出力するコードは、そのままではうまく動かない場合がほとんどです。

ボタンを押したときのコマンドが間違えていたり、関数を読み込む前に関数が実行されるコードになっていたりと、100%の完成度とはいきません。

それらを修正して、自分の思い描くゲームへと仕上げていきます。

ゲーム内で使用する画像の準備

RGB565とjpgの画質比較

M5Stackで画像を表示する方法は2つあります。

  1. マイクロSDカードに保存した画像を読み込む
  2. ヘッダファイルとして画像データを読み込む

表示方法SDカード
読み込み
ヘッダファイル
読み込み
フォーマットjpg16bit RGB565
表示速度× 遅い〇 速い
画質〇 キレイ× 荒い

1.マイクロSDカードから画像を読み込む方法

マイクロSDカードから読み込んだ画像

今回のじゃんけんゲームでは、この「マイクロSDカードから画像を読み込む方法」を使用しています。

画像のキレイさ・差し替えの手軽さを重視した結果です。

表示スピードはやや遅くなりますが、今回のじゃんけんゲームでは問題ありません。

M5.Lcd.drawJpgFile(SD, "/janken/guu.jpg", 42, 192, 0, 0, 0, 0, JPEG_DIV_4);

上記のコードでは、SDカードの中にある「janken.guu.jpg」という画像を「座標(0,0)」の位置にサイズ・幅・余白を指定せずに「1/4サイズ」で表示するよう指定しています。

drawJpgFile()

  • 1番目の引数:ファイルデバイス
  • 2番目の引数:ファイルパス
  • 3番目の引数:座標X(左上)
  • 4番目の引数:座標Y(左上)
  • 5番目の引数:最大幅 (px)
  • 6番目の引数:最大高さ (px)
  • 7番目の引数:オフセットX (px)
  • 8番目の引数:オフセットY (px)
  • 9番目の引数:スケール(JPEG_DIV_2 / JPEG_DIV_4 / JPEG_DIV_8)

※SDカードに保存する場合、Photoshopで作成した画像は表示されませんでした。Photoshopで画像を書き出した場合、一度、Windows標準ソフトのペイントなどで保存し直す必要があります。

2.ヘッダファイルから画像を読み込む方法

ヘッダファイルから読み込んだ画像

外部ファイルに画像のバイナリデータ(16bit RGB565フォーマット)を保存し、それを読み込むことでも画像を表示することができます。

画質は荒いですが表示スピードが速いので、簡単な図形などを表示する場合の利用がオススメです。

メインコード

#include <M5Stack.h>
#include "guu.h"

void setup() {
  M5.begin();
}

void loop() {
  M5.Lcd.drawBitmap(0, 0, 16, 16, guu);
}
drawBitmap()
  • 1番目の引数:座標X(左上)
  • 2番目の引数:座標Y(左上)
  • 3番目の引数:幅 (px)
  • 4番目の引数:高さ(px)
  • 5番目の引数:画像データ

※幅・高さは必ず作成した画像データと一致させる必要があります。

guu.h(じゃんけんのグー画像)16×16px

 // RGB565 Dump
const unsigned short guu[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,// row 0, 16 pixels
0x0000,0x0000,0x0000,0xE318,0xA210,0x0000,0x4108,0x2421,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,// row 1, 32 pixels
0x0000,0x0000,0xC739,0xFFFF,0x9EF7,0x6529,0xF7BD,0xFFFF,0x2842,0x8631,0xF7BD,0x694A,0x2000,0xCF7B,0x8631,0x0000,// row 2, 48 pixels
0x0000,0x0000,0xAE73,0xFFFF,0xFFFF,0x518C,0x9EF7,0xFFFF,0x9294,0xF39C,0xFFFF,0xD7BD,0xEF7B,0xFFFF,0xBAD6,0x0000,// row 3, 64 pixels
0x0000,0x0000,0x2C63,0xFFFF,0xFFFF,0xCF7B,0x1CE7,0xFFFF,0x518C,0x9294,0xFFFF,0x96B5,0xF39C,0xFFFF,0xDBDE,0x0000,// row 4, 80 pixels
0x0000,0x0000,0xAE73,0xFFFF,0xFFFF,0x2C63,0xFBDE,0xFFFF,0x518C,0xD39C,0xFFFF,0x75AD,0x9294,0xFFFF,0x9AD6,0x0000,// row 5, 96 pixels
0x0000,0x0000,0x4529,0x518C,0xEF7B,0xAA52,0xAE73,0x1084,0x6529,0x9294,0xFFFF,0xD7BD,0x14A5,0xFFFF,0xDBDE,0x0000,// row 6, 112 pixels
0x0000,0x0000,0xCB5A,0xD7BD,0x3CE7,0xFFFF,0x7DEF,0x5DEF,0x38C6,0xAE73,0xFFFF,0xEF7B,0xAA52,0xFFFF,0x18C6,0x0000,// row 7, 128 pixels
0x0000,0x0C63,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8A52,0xCB5A,0x4D6B,0x2C63,0x4D6B,0x2842,0x2000,// row 8, 144 pixels
0x0000,0x9AD6,0xFFFF,0xFFFF,0xFFFF,0xD39C,0xEF7B,0xCF7B,0x8A52,0x3084,0xF7BD,0xFFFF,0xFFFF,0x38C6,0x518C,0x0000,// row 9, 160 pixels
0x0000,0x5DEF,0xFFFF,0xFFFF,0xFFFF,0x2842,0xAA52,0xD39C,0xD7BD,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEB5A,0x0000,// row 10, 176 pixels
0x0000,0xD7BD,0xFFFF,0xFFFF,0xFFFF,0x4D6B,0x55AD,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xBEF7,0x2000,0x0000,// row 11, 192 pixels
0x0000,0x2842,0xFFFF,0xFFFF,0x9EF7,0x1084,0x7DEF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x2C63,0x0000,0x0000,// row 12, 208 pixels
0x0000,0x0000,0x6D6B,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x518C,0x0000,0x0000,0x0000,// row 13, 224 pixels
0x0000,0x0000,0x0000,0xE739,0x55AD,0x3CE7,0xFFFF,0xFFFF,0xFFFF,0x1CE7,0x75AD,0x694A,0x0000,0x0000,0x0000,0x0000,// row 14, 240 pixels
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xE318,0x4529,0xC318,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,// row 15, 256 pixels
};

表示したい画像サイズで、画像データを作成する必要があります。

例えば、16pxで表示したい場合は16pxのjpgを元に16bit RGB565フォーマットへ変換したデータが必要です。

48pxで表示したい場合は48pxのjpgを元に16bit RGB565フォーマットへ変換したデータが必要となります。

16bit RGB565フォーマットの画像データ作成方法

以下のツールを使用して、画像(BMP/JPEG/PNG)を16bit RGB565フォーマットのデータに変換します↓

画像データImageData化

画像データを16bit RGB565フォーマットに変換

※データ形式は「16Bit RGB565 Dump(little endian)」を選択してください。

PlatformIOを使用している場合は、下記の画像の赤丸のところをクリックすると、新しいファイルを作成できます。

PlatformIOで新規ファイル作成

任意のファイル名(●●●.h)にリネームして、作成した16bit RGB565フォーマットの画像データを張り付けてください。

const unsigned short guu[] = {

// 16bit RGB565フォーマットの画像データを張り付ける

};

コード内に直接画像データを記述する例

ちなみにコード内に16bit RGB565フォーマットの画像データを直接記述することもできますが、ドットアイコンのような小さい画像表示にしか使えません。

48pxまでの画像は表示することができましたが、64px以上となる画像は表示することができませんでした。

#include <M5Stack.h>

// 48pxまでしか表示されない
const unsigned short guu[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,// row 0, 16 pixels
0x0000,0x0000,0x0000,0xE318,0xA210,0x0000,0x4108,0x2421,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,// row 1, 32 pixels
0x0000,0x0000,0xC739,0xFFFF,0x9EF7,0x6529,0xF7BD,0xFFFF,0x2842,0x8631,0xF7BD,0x694A,0x2000,0xCF7B,0x8631,0x0000,// row 2, 48 pixels
0x0000,0x0000,0xAE73,0xFFFF,0xFFFF,0x518C,0x9EF7,0xFFFF,0x9294,0xF39C,0xFFFF,0xD7BD,0xEF7B,0xFFFF,0xBAD6,0x0000,// row 3, 64 pixels
0x0000,0x0000,0x2C63,0xFFFF,0xFFFF,0xCF7B,0x1CE7,0xFFFF,0x518C,0x9294,0xFFFF,0x96B5,0xF39C,0xFFFF,0xDBDE,0x0000,// row 4, 80 pixels
0x0000,0x0000,0xAE73,0xFFFF,0xFFFF,0x2C63,0xFBDE,0xFFFF,0x518C,0xD39C,0xFFFF,0x75AD,0x9294,0xFFFF,0x9AD6,0x0000,// row 5, 96 pixels
0x0000,0x0000,0x4529,0x518C,0xEF7B,0xAA52,0xAE73,0x1084,0x6529,0x9294,0xFFFF,0xD7BD,0x14A5,0xFFFF,0xDBDE,0x0000,// row 6, 112 pixels
0x0000,0x0000,0xCB5A,0xD7BD,0x3CE7,0xFFFF,0x7DEF,0x5DEF,0x38C6,0xAE73,0xFFFF,0xEF7B,0xAA52,0xFFFF,0x18C6,0x0000,// row 7, 128 pixels
0x0000,0x0C63,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8A52,0xCB5A,0x4D6B,0x2C63,0x4D6B,0x2842,0x2000,// row 8, 144 pixels
0x0000,0x9AD6,0xFFFF,0xFFFF,0xFFFF,0xD39C,0xEF7B,0xCF7B,0x8A52,0x3084,0xF7BD,0xFFFF,0xFFFF,0x38C6,0x518C,0x0000,// row 9, 160 pixels
0x0000,0x5DEF,0xFFFF,0xFFFF,0xFFFF,0x2842,0xAA52,0xD39C,0xD7BD,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEB5A,0x0000,// row 10, 176 pixels
0x0000,0xD7BD,0xFFFF,0xFFFF,0xFFFF,0x4D6B,0x55AD,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xBEF7,0x2000,0x0000,// row 11, 192 pixels
0x0000,0x2842,0xFFFF,0xFFFF,0x9EF7,0x1084,0x7DEF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x2C63,0x0000,0x0000,// row 12, 208 pixels
0x0000,0x0000,0x6D6B,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x518C,0x0000,0x0000,0x0000,// row 13, 224 pixels
0x0000,0x0000,0x0000,0xE739,0x55AD,0x3CE7,0xFFFF,0xFFFF,0xFFFF,0x1CE7,0x75AD,0x694A,0x0000,0x0000,0x0000,0x0000,// row 14, 240 pixels
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xE318,0x4529,0xC318,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,// row 15, 256 pixels
};

void setup() {
  M5.begin();
}

void loop() {
  M5.Lcd.drawBitmap(0, 0, 16, 16, guu);
}

ゲーム内で使用する音源の準備

M5Stackで音を鳴らす方法は2つあります。

  1. マイクロSDカードに保存した音を読み込む
  2. ブザー音で作った音階でメロディを流す

1.マイクロSDカードに保存した音を再生する

M5Stackでは、ライブラリを使うことでマイクロSDに保存した「MP3」や「WAV」ファイルを再生することができます。

※事前に下記のライブラリをダウンロードしておかないと、コンパイルの際にエラーが出るので注意してください。

MP3再生に必要なライブラリ

  • ESP8266Audio
  • ESP8266_Spiram

ライブラリのダウンロード・インストール方法(PlatformIOを使用している場合)

※Arduino IDEでもライブラリをインストールすることはできますが、コンパイル・書き込みスピードが全然違うので、ぜひこの機会にPlatformIOの導入を検討してみてください。

PlatformIOでのライブラリのダウンロード・インストール手順(1)
PlatformIOでのライブラリのダウンロード・インストール手順(2)

上記のようにライブラリの検索フォームに「ESP8266Audio」と入力されると、該当するライブラリが表示されます。

「ESP8266Audio」のインストールが終わったら、同様の手順で「ESP8266_Spiram」のインストールも行ってください。

録音した音声をMP3へと変換する手順

今回作成したじゃんけんゲームでは、容量が小さくて軽い「MP3」を音源に使用しました。

  1. スマホアプリの簡単ボイスレコーダーを使って声を録音
  2. スマホからGoogleドライブへ録音した音声(wav)をアップロード
  3. パソコンからGoogleドライブにアクセスして、音声ファイルをダウンロード
  4. Online MP3 Cutterでトリミング・MP3へ変換

MP3を再生するプログラムコードの例

「じゃんけん」「ぽい」という音声をリピートし続けるコードです。

SetGainを0.1に設定することで、音量を小さくしています。

#include <M5Stack.h>

// MP3再生ライブラリ
#include "AudioFileSourceSD.h"
#include "AudioFileSourceID3.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2S.h"

AudioGeneratorMP3 *mp3;
AudioFileSourceSD *file;
AudioOutputI2S *out;
AudioFileSourceID3 *id3;

// --------------------------------------------------
//                 MP3再生関連
// --------------------------------------------------
void playMP3(const char *filename){
  file = new AudioFileSourceSD(filename);
  id3 = new AudioFileSourceID3(file);
  out = new AudioOutputI2S(0, 1); // Output to builtInDAC
  out->SetOutputModeMono(true);
  out->SetGain(0.1); // 音量(デフォルト:1)
  mp3 = new AudioGeneratorMP3();
  mp3->begin(id3, out);
  while(mp3->isRunning()) {
    if (!mp3->loop()) mp3->stop();
  }
}

// --------------------------------------------------
//           setup
// --------------------------------------------------
void setup() {

  M5.begin();
  M5.Power.begin();
  delay(500);

}

// --------------------------------------------------
//                    loop
// --------------------------------------------------
void loop() {

  // 声:じゃんけん
  playMP3("/janken/janken.mp3");  
  
  delay(100);

  // ポン
  playMP3("/janken/pon.mp3");

  // 無音
  M5.Speaker.mute();

  delay(1000);

}

2.ブザー音で作った音階でメロディを流す

ブザーから出る音は周波数を変えることで音階を作ることができます。

ブザーで音を再生するプログラムコードの例

「ドレミファソラシド~」をリピート再生するコードです。

実際の音階とはかけ離れている気もしますが、こんなもんでしょう。

#include <M5Stack.h>

// --------------------------------------------------
//                    音階
// --------------------------------------------------

#define NOTE_D0 -1  // ド
#define NOTE_D1 294 // レ
#define NOTE_D2 330 // ミ
#define NOTE_D3 350 // ファ
#define NOTE_D4 393 // ソ
#define NOTE_D5 441 // ラ
#define NOTE_D6 495 // シ
#define NOTE_D7 556 // ド


#define NOTE_DL1 147 // ド♭
#define NOTE_DL2 165 // レ♭
#define NOTE_DL3 175 // ミ♭
#define NOTE_DL4 196 // ファ♭
#define NOTE_DL5 221 // ソ♭
#define NOTE_DL6 248 // ラ♭
#define NOTE_DL7 278 // シ♭


#define NOTE_DH1 589 // ド#
#define NOTE_DH2 661 // レ#
#define NOTE_DH3 700 // ミ#
#define NOTE_DH4 786 // ファ#
#define NOTE_DH5 882 // ソ#
#define NOTE_DH6 990 // ラ#
#define NOTE_DH7 112 // シ#

// --------------------------------------------------
//           setup
// --------------------------------------------------
void setup() {

  M5.begin();

}

// --------------------------------------------------
//                    loop
// --------------------------------------------------
void loop() {

   M5.Speaker.tone(NOTE_D1, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_D2, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_D3, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_D4, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_D5, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_D6, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_D7, 200); //frequency 3000, with a duration of 200ms
    delay(300);

    delay(1000);

    M5.Speaker.tone(NOTE_DL1, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_DL2, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_DL3, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_DL4, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_DL5, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_DL6, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_DL7, 200); //frequency 3000, with a duration of 200ms
    delay(300);

    delay(1000);

    M5.Speaker.tone(NOTE_DH1, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_DH2, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_DH3, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_DH4, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_DH5, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_DH6, 200); //frequency 3000, with a duration of 200ms
    delay(300);
    M5.Speaker.tone(NOTE_DH7, 200); //frequency 3000, with a duration of 200ms
    delay(300);

    delay(1000);
}

終わり

以上、「Chat GPTを使ってM5Stack用ミニゲームを作る」でした。

面白いゲームのアイディアをお持ちの方、ぜひM5Stack用のミニゲーム作りにチャレンジしてみてください!

この記事のURLをコピー

メールアドレスは公開されませんのでご安心ください。また、* が付いている欄は必須項目となります。

内容に問題なければ、下記の「コメントを送信する」ボタンを押してください。

関連情報

  • 【2024年度版】マイコンおすすめランキングBEST5
運営者プロフィール
コダマ

職業はIT系フリーランス。過去、電子配線業務の経験が10年ある為、はんだづけも得意です。宮崎県在住、30代・2児の父親。

カテゴリー