チーム1763

課題名

瞬間音感マスター

研究者名

Tatsuya Kaneko
Yuki Uehara

使用器具

PSoc基盤
Miniprog 
シリアル通信用ケーブル
ジャンパー線 2本
スピーカー

概要

瞬間的に流れた音の音階を当てるゲームであり、出題者と回答者の二人で対戦をする。

<操作方法>
1.回答者ははじめに流れる音階(起動音)を記憶しておく。

2.出題者がキーボードで音を選択しその音を鳴らす。
 出題者が下記キーから一つキーを押し、エンターキーで出題する音を登録すると
 スピーカーよりその音階の音が発生する。
 (a:ド s:レ d:ミ f:ファ g:ソ h:ラ j:シ k:ド に対応する)
  ※小文字のLを入力するとゲームが終了する
  ※何文字か押した後エンターを押すと、はじめに押したキーに対応した音階のみが発生する
  ※音は一瞬しか流れないので回答者はよく聞くこと。

3.回答者はその音をよく聴き、答えだと思う音階に対応したキーを押す。


4.正解か不正解か(true or false)、その時点での正解数(score)、ライフ(life)をLCD画面に表示する。
 正解の場合は正解音を鳴らし、不正解の場合は不正解音を鳴らす。

5.2回間違える前に5回正解したらゲームクリアとなる。
 2回間違えるとゲームオーバーとなる。
 クリアするとクリア音が流れ、LCD上に「GAME CLEAR」と表示される。
 不正解するとゲームオーバー音が流れ、LCD上にメッセージと正解数が表示される。

6.ゲームを再開するときはリセットボタンを押す

ソースコード&配線

#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules
#include <stdlib.h>
#include <stdio.h>
#pragma interrupt_handler myISR

int PW=125;
int SILENT=0,D=229,D1=217, L=204,L1=102,M=182,M1=91,F=172,S=153,R=136,C=121,DD=115;
int SCORE=0,LIFE=2,CLEAR=5;
int TC = 0;
int version=0;
int wait=0;


void myISR(void)
{
TC+=1;
if(version==0){
PWM16_1_WritePulseWidth(PW);
if(TC==30){
UART_CPutString("Please remember the following sound!");
UART_CPutString("\r\n\r\n");
}
else if(TC==50)
PWM16_1_WritePeriod(D);
else if(TC==60)
PWM16_1_WritePeriod(L);
else if(TC==70)
PWM16_1_WritePeriod(M);
else if(TC==80)
PWM16_1_WritePeriod(F);
else if(TC==90)
PWM16_1_WritePeriod(S);
else if(TC==100)
PWM16_1_WritePeriod(R);
else if(TC==110)
PWM16_1_WritePeriod(C);
else if(TC==120)
PWM16_1_WritePeriod(DD);
else if(TC==130)
PWM16_1_WritePeriod(SILENT);
else if(TC==140)
UART_CPutString("\r\nSet the Answer Tone.\r\n");
}

else if(version==1){
PWM16_1_WritePulseWidth(PW);
if(TC==5)
PWM16_1_WritePeriod(C);
else if(TC==7)
PWM16_1_WritePeriod(SILENT);
else if(TC==8)
PWM16_1_WritePeriod(S);
else if(TC==14)
PWM16_1_WritePeriod(SILENT);
}

else if(version==2){
PWM16_1_WritePulseWidth(PW);
if(TC==5)
PWM16_1_WritePeriod(D);
else if(TC==6)
PWM16_1_WritePeriod(SILENT);
else if(TC==7)
PWM16_1_WritePeriod(D);
else if(TC==12)
PWM16_1_WritePeriod(SILENT);
}

else if(version==3){
PWM16_1_WritePulseWidth(PW);
if(TC == 2)
PWM16_1_WritePeriod(L1);
else if(TC == 3)
PWM16_1_WritePeriod(SILENT);
else if(TC == 4)
PWM16_1_WritePeriod(L1);
else if(TC == 5)
PWM16_1_WritePeriod(SILENT);
else if(TC == 6)
PWM16_1_WritePeriod(L1);
else if(TC == 7)
PWM16_1_WritePeriod(SILENT);
else if(TC == 8)
PWM16_1_WritePeriod(L1);
else if(TC == 14)
PWM16_1_WritePeriod(SILENT);
else if(TC == 15)
PWM16_1_WritePeriod(C);
else if(TC == 22)
PWM16_1_WritePeriod(DD);
else if(TC == 28)
PWM16_1_WritePeriod(SILENT);
else if(TC == 30)
PWM16_1_WritePeriod(L1);
else if(TC == 31)
PWM16_1_WritePeriod(SILENT);
else if(TC == 34)
PWM16_1_WritePeriod(DD);
else if(TC == 36)
PWM16_1_WritePeriod(L1);
else if(TC == 46)
PWM16_1_WritePeriod(SILENT);
}

else if(version==4){
PWM16_1_WritePulseWidth(PW);
if(TC == 2)
PWM16_1_WritePeriod(R);
else if(TC == 3)
PWM16_1_WritePeriod(S);
else if(TC == 5)
PWM16_1_WritePeriod(R);
else if(TC == 12)
PWM16_1_WritePeriod(SILENT);
else if(TC == 13)
PWM16_1_WritePeriod(S);
else if(TC == 15)
PWM16_1_WritePeriod(F);
else if(TC == 17)
PWM16_1_WritePeriod(M);
else if(TC == 19)
PWM16_1_WritePeriod(L);
else if(TC == 21)
PWM16_1_WritePeriod(D1);
else if(TC == 26)
PWM16_1_WritePeriod(L);
else if(TC == 32)
PWM16_1_WritePeriod(SILENT);
}
}

void main(void)
{
// M8C_EnableGInt ; // Uncomment this line to enable Global Interrupts
  // Insert your main routine code here.
  
  char *strPtr_1;
  char *strPtr_2;
  int answer;          // 正解の音
  int choice;          // 回答した音
  int score = SCORE;   // スコア
  char score_char[20]; // スコアの文字列化
  int life = LIFE;     // ライフ
  char life_char[20];  // ライフの文字列化
  
  UART_CmdReset();
  UART_IntCntl(UART_ENABLE_RX_INT);
  Counter8_WritePeriod(155);
  Counter8_WriteCompareValue(77);
  Counter8_Start();
  UART_Start(UART_PARITY_NONE);
  LCD_Start();
  
  
  // ゲームスタートの初期画面
  // UART側に出題を要求する
  UART_CPutString("\r\nGAME START!\r\n");
  UART_CPutString("\r\n\r\n");
  
  // LCD
  LCD_PrCString("GAME START!");
  
  M8C_EnableGInt;
  PWM16_1_Start();
  Timer16_1_EnableInt();
  Timer16_1_Start();
  while(TC<145)
  {};
  while(1){
    // 1つ目のループ 出題(鳴らす音を選ぶ)
    while(1){
      if(UART_bCmdCheck()){
        if(strPtr_1 = UART_szGetParam()){
          wait=0;
          // コマンド入力と音の発生、正解をanswerに記憶
          if(*strPtr_1 == 'a'){
            PWM16_1_WritePeriod(D);
            while(wait<30000){
              wait++;
            }
            PWM16_1_WritePeriod(SILENT);
            answer = 1;
          }
          else if(*strPtr_1 == 's'){
            PWM16_1_WritePeriod(L);
              while(wait<30000){
                wait++;
              }
            PWM16_1_WritePeriod(SILENT);
            answer = 2;
          }
          else if(*strPtr_1 == 'd'){
            PWM16_1_WritePeriod(M);
            while(wait<30000){
              wait++;
            }
            PWM16_1_WritePeriod(SILENT);
            answer = 3;
          }
          else if(*strPtr_1 == 'f'){
            PWM16_1_WritePeriod(F);
            while(wait<30000){
              wait++;
            }
            PWM16_1_WritePeriod(SILENT);
            answer = 4;
          }
          else if(*strPtr_1 == 'g'){
            PWM16_1_WritePeriod(S);
            while(wait<30000){
              wait++;
            }
            PWM16_1_WritePeriod(SILENT);
            answer = 5;
          }
          else if(*strPtr_1 == 'h'){
            PWM16_1_WritePeriod(R);
            while(wait<30000){
              wait++;
            }
            PWM16_1_WritePeriod(SILENT);
            answer = 6;
          }
          else if(*strPtr_1 == 'j'){
            PWM16_1_WritePeriod(C);
            while(wait<30000){
              wait++;
            }
            PWM16_1_WritePeriod(SILENT);
            answer = 7;
          }
          else if(*strPtr_1 == 'k'){
            PWM16_1_WritePeriod(DD);
            while(wait<30000){
              wait++;
            }
            PWM16_1_WritePeriod(SILENT);
            answer = 8;
          }
          // 無音(SILENT)を選択した場合、ゲーム終了
          else if(*strPtr_1 == 'l'){
            PWM16_1_WritePeriod(SILENT);
            UART_CPutString("Thank you for playing!\r\n");
            break;
          }

         UART_CmdReset();
        
          // 回答を要求する表示
          // UART
          UART_CPutString("Inputed your Answer from [a, s, d, f, g, h, j, k] => ");
          // LCD
          LCD_Control(0x01);
          LCD_Position(0,0);
          LCD_PrCString("Input Answer");
          
          // 出題し、回答を要求したところで、1つ目のループを抜ける
          break;
        }
      }
    }
    
    // 2つ目のループ 回答(鳴っている音を選ぶ)
    while(1){
      if(strPtr_2 = UART_szGetParam()){
        UART_PutString(strPtr_2);
        PWM16_1_WritePeriod(SILENT);
        
        // コマンド入力、回答をchoiceに記憶
        if(*strPtr_2 == 'a'){
          choice = 1;
        }
        else if(*strPtr_2 == 's'){
          choice = 2;
        }
        else if(*strPtr_2 == 'd'){
          choice = 3;
        }
        else if(*strPtr_2 == 'f'){
          choice = 4;
        }
        else if(*strPtr_2 == 'g'){
          choice = 5;
        }
        else if(*strPtr_2 == 'h'){
          choice = 6;
        }
        else if(*strPtr_2 == 'j'){
          choice = 7;
        }
        else if(*strPtr_2 == 'k'){
          choice = 8;
        }
        
        //LCDの初期化
        LCD_Control(0x01);
        LCD_Position(0,0);
        
        // 正解の場合
        if(choice == answer){
          version=1;
          TC=0;
          score++;
          
          //5問正解
          if(score == CLEAR) {
            TC=0;
            version=3;
             M8C_EnableGInt;
             PWM16_1_Start();
             Timer16_1_EnableInt();
             Timer16_1_Start();
             while(TC<30)
             {};
             csprintf(score_char, "%d", score);
             UART_CPutString("\r\nscore : ");
             UART_PutString(score_char);
             UART_CPutString("\r\nGAME CLEAR!!!");
             break;
          }
          
          // 正解の表示
            // UART
            UART_CPutString("\r\nTrue!");
            // LCD
            LCD_PrCString("True!");
            // 出力のために、int型変数をchar型配列にコピー
            csprintf(score_char, "%d", score);
            csprintf(life_char, "%d", life);
            if(version==1){
              M8C_EnableGInt;
              PWM16_1_Start();
              Timer16_1_EnableInt();
              Timer16_1_Start();
              while(TC<15)
             {}
            }
        }
        
        // 不正解の場合
        else {
          life--;
          
          // 不正解の表示
          if(life != 0) {
            version=2;
            TC=0;
            // UART
            UART_CPutString("\r\nFalse");
            // LCD
            LCD_PrCString("False");
            // 出力のために、int型変数をchar型配列にコピー
            csprintf(score_char, "%d", score);
            csprintf(life_char, "%d", life);
            if(version==12){
              M8C_EnableGInt;
              PWM16_1_Start();
              Timer16_1_EnableInt();
              Timer16_1_Start();
              while(TC<13)
              {};
            }
            LCD_Position(1,0);
          }
          
          // ゲームオーバーの場合(ライフが0になった場合)
          else {
            version=4;
            TC=0;
            csprintf(score_char, "%d", score);
            // UART
            UART_CPutString("\r\n\r\nGAME OVER.\r\nscore : ");
            UART_PutString(score_char);
            // LCD
            LCD_Position(0,0);
            LCD_PrCString("GAME OVER.");
            LCD_Position(1,0);
            LCD_PrCString("Score : ");
            LCD_PrString(score_char);
            
            if(version==4){
              M8C_EnableGInt;
              PWM16_1_Start();
              Timer16_1_EnableInt();
              Timer16_1_Start();
              while(TC<48)
              {};
            }
            break;
          }
        }
        
        // スコアの表示
        // UART
        UART_CmdReset();
        UART_CPutString("\r\nscore : ");
        UART_PutString(score_char);
        // LCD
        LCD_Position(0,7);
        LCD_PrCString("Score: ");
        LCD_PrString(score_char);
        
        // ライフの表示
        // UART
        UART_CPutString("\r\nlife : ");
        UART_PutString(life_char);
        // LCD
        LCD_Position(1,7);
        LCD_PrCString("Life : ");
        LCD_PrString(life_char);
        
        // 次の出題をUART側に要求して、2つ目のループを抜ける
        UART_CPutString("\r\n\r\nSet the Answer Tone.\r\n");
        break;
      }
    }
  }    
}

1763.png

考察

ラボ timer_pwm2 pwm_uart2を基に音階を作成し、ゲーム内容に関しては、チーム1568の内容を参考して作成した。
ゲーム感覚で楽しめるように、2回間違える前に5回正解したらクリアとなるようにし、また割込み処理をすることによって、
正解したとき、不正解のとき、ゲームクリアのとき、ゲームオーバーのときに音楽を流せるようにした。
音楽が流れる時間を約1秒ほどにして、瞬間的に音階を聞き分けないといけないように難易度を少し高くした。
「l」を選択すると「Thank you for playing!」と表示してゲームを終了できる。

改善点としては、一人で遊べるモードも追加することが挙げられる。
その方法としてはスタートボタンを押すとコンピュータ側が自動的に音を鳴らしてくれるようにし、ゲームが終わるまで回答者が余計なボタンを押すことなくスムーズに遊べるようにするといったことが考えられる。

  • 最終更新:2017-12-19 16:22:18

このWIKIを編集するにはパスワード入力が必要です

認証パスワード