チーム2146

課題名

距離センサーによる得点ゲーム

研究者名

Ryunosuke Ema
Reishi Ohashi

遊び方

距離センサーによって画面上のプレイヤー(アルファベットのO)を操作し、得点(アルファベットのP)を取る。まず初めに、キーボード上でsとEnterを入力することでゲームがスタートする。その後に約30秒のカウントダウンが開始されるため、制限時間内にできるだけ多くの得点を獲得できるように、距離センサーに手をかざしてプレイヤーを操作する。得点を獲得すると点数が1ずつ加算され基板上のモニターにそのスコアが16進数で表示される。制限時間になると、画面上にFINISHと表示される。再度プレイする場合は、もう一度sとEnterを入力する。

使用器具

PSoC MiniProg
PSoC基盤
距離センサー
ジャンパー線
シリアル通信ケーブル

ユーザーモジュール

2022-01-11_153043.png

ソースコード

#define WIDTH 107 // フィールドの画面幅
#define LIMIT 30 // 制限時間[s]
#include <m8c.h>
#include "PSoCAPI.h"
#include <stdlib.h>
#pragma interrupt_handler myISR

int PW = 125; // Pulse Width
int TC = 0; // Time Count
int isPlay = 0; // ゲームをプレイ中であるか

void main(void)
{
  unsigned int adc_data; // 距離センサーのデータが入る

  int i;
   int cpos; // プレイヤーの位置
   int r; // ポイントの位置
   int score = 0;

  char* strPtr; // シリアルポートから受け取った文字を格納する変数

  // モジュールの初期化等
   M8C_EnableGInt;
   PWM16_1_Start();
   Timer16_1_EnableInt();
   Timer16_1_Start();
   PWM16_1_WritePulseWidth(PW);

  PGA_Start(PGA_HIGHPOWER);
   LCD_Start();
   LCD_InitBG(LCD_SOLID_BG);
   ADCINC_Start(ADCINC_HIGHPOWER);
   ADCINC_GetSamples(0);

  UART_CmdReset();
   UART_IntCntl(UART_ENABLE_RX_INT);
   Counter8_WritePeriod(155);
   Counter8_WriteCompareValue(77);
   Counter8_Start();
   UART_Start(UART_PARITY_NONE);

  //距離センサーを利用して乱数列を生成
   if (ADCINC_fIsDataAvailable() == 0) {
       adc_data = ADCINC_wClearFlagGetData();
       srand(adc_data);
   }

  // 1からWIDTHまでの乱数を生成
   r = rand() % WIDTH + 1;

  // スコア表示はLCDで行う
   LCD_Position(0, 0);
   LCD_PrCString("SCORE : ----");

  // 端末上で下記を表示
   UART_CPutString("\r\nSTART -> S\r\n");

  // ここでゲームの処理を行う
   while (1) {
       // ゲームが実行中の時
       if (isPlay) {
           // 制限時間が過ぎていたら
           if (TC > LIMIT) {
               // 終了表示と、リトライの表示
               UART_CPutString("\r\nFINISH!!\r\n");
               UART_CPutString("\r\nRETRY -> S\r\n");
               TC = 0;
               isPlay = 0;
               score = 0;
               continue;
           }
           // 制限時間中であれば、距離センサーから取得した値によって
           // プレイヤーの位置を変更する。
           while (ADCINC_fIsDataAvailable() == 0) {};
           adc_data = ADCINC_wClearFlagGetData();

          cpos = adc_data / 30; // 30は縮尺

          // プレイヤーの位置と、ポイントの位置が合っていた場合
           // スコアの追加とポイントの位置の変更を行う
           if (cpos == r) {
               score += 1;

              LCD_Position(0, 0);
               LCD_PrCString("SCORE : ");
               LCD_PrHexInt(score); // 値は16進数
               r = rand() % WIDTH + 1;
           }

          // プレイヤー, ポイント の順で配置される場合
           if (cpos < r) {
               UART_CPutString("l"); // 左端
               for (i = 0; i < cpos; i++) {
                   UART_CPutString(" ");
               }
               UART_CPutString("O"); // プレイヤー
               for (i = cpos; i < r; i++) {
                   UART_CPutString(" ");
               }
               UART_CPutString("P"); // ポイント
               for (i = r; i <= WIDTH; i++) {
                   UART_CPutString(" ");
               }
               UART_CPutString("l\r\n"); // 右端
           }
           // ポイント, プレイヤー の順で配置される場合
           else {
               UART_CPutString("l");
               for (i = 0; i <= r; i++) {
                   UART_CPutString(" ");
               }
               UART_CPutString("P");
               for (i = r; i < cpos; i++) {
                   UART_CPutString(" ");
               }
               UART_CPutString("O");
               for (i = cpos; i < WIDTH; i++) {
                   UART_CPutString(" ");
               }
               UART_CPutString("l\r\n");
           }
       }

      // ゲームがプレイ中でない場合
       else {
           if (UART_bCmdCheck()) {
               // sが入力されたらスタート(リスタート時も含め)
               if (strPtr = UART_szGetParam()) {
                   if (*strPtr == 's')
                       isPlay = 1;
               }
               UART_CmdReset();
           }
       }
   }
}

void myISR(void){
  if(isPlay){
       TC += 1;
   }
}

反省点と考察

・終了するときに謎の文字列が表示されてしまうバグを取り除くことが出来なかった。
・点数表示を基板上のモニターにする際に16進数表記以外の方法がわからないため、1つの得点を100点にしたかったもののできなかった。
・センサーの仕様上、センサーとの距離が極端に近い場合、遠い場合の判定(画面上左端と右端)がかなり難しくなってしまった。
・プログラムの仕様上、空白以外に表示する文字が1つ増えただけでも場合分けが大量に必要になってしまうため、取ったら得点がマイナスになる障害物を作成したかったものの追加できなかった。
・BGMが存在していないため、やや寂しいゲームとなってしまった。

参考文献


  • 最終更新:2022-01-15 12:31:00

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

認証パスワード