音ゲー作成までの道のり１

#メトロノームの作成とその大まかな構成

先日よりandroidでの音ゲーを作成するために、メトロノームを作成している。
そのメトロノームの大まかな構成は、
・BPMを自分で設定できる
・動作は４拍子固定
・1拍ずつ音と対応したランプが光る。
といったものです。


##プログラムの作成
上記の構成を元にアプリのGUIを作成した。
<img width="232" alt="rhythm.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376689/37310c95-719d-42be-58a5-3c023a881b98.png">


```xml:mainactivity.xml
     <ImageView
        android:id="@+id/image1"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginStart="67dp"
        android:layout_marginLeft="67dp"
        android:layout_marginTop="200dp"
        android:layout_marginEnd="24dp"
        android:layout_marginRight="24dp"
        app:layout_constraintEnd_toStartOf="@+id/image2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/en" />

    <ImageView
        android:id="@+id/image2"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginLeft="24dp"
        android:layout_marginTop="200dp"
        android:layout_marginEnd="24dp"
        android:layout_marginRight="24dp"
        app:layout_constraintEnd_toStartOf="@+id/image3"
        app:layout_constraintStart_toEndOf="@+id/image1"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/en" />

    <ImageView
        android:id="@+id/image3"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginLeft="24dp"
        android:layout_marginTop="200dp"
        android:layout_marginEnd="24dp"
        android:layout_marginRight="24dp"
        app:layout_constraintEnd_toStartOf="@+id/image4"
        app:layout_constraintStart_toEndOf="@+id/image2"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/en" />

    <ImageView
        android:id="@+id/image4"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginLeft="24dp"
        android:layout_marginTop="200dp"
        android:layout_marginEnd="67dp"
        android:layout_marginRight="67dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/image3"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/en" />

    <EditText
        android:id="@+id/BpM"
        android:layout_width="192dp"
        android:layout_height="50dp"
        android:layout_marginTop="95dp"
        android:layout_marginEnd="54dp"
        android:layout_marginRight="54dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="120"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="BPM:"
        android:textSize="26sp"
        app:layout_constraintEnd_toStartOf="@+id/BpM"
        app:layout_constraintTop_toTopOf="parent" />


    <Button
        android:id="@+id/strat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="67dp"
        android:layout_marginLeft="67dp"
        android:layout_marginBottom="102dp"
        android:text="Start"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/End"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="68dp"
        android:layout_marginRight="68dp"
        android:layout_marginBottom="102dp"
        android:text="END"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
```
次に作成したプログラムを下記に記載する。

```java:MainActivity.java

import androidx.appcompat.app.AppCompatActivity;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.InputType;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {
    ImageView Image1,Image2,Image3,Image4;
    int i,Delay;
    float X_Data,Y_Data,Z_Data;
    TextView text1;
    private Timer timer;
    private CountUpTimerTask timerTask;
    private Handler handler = new Handler();
    
    SoundPool soundPool;
    int mp3;
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);

        Image1 = findViewById(R.id.image1);
        Image2 = findViewById(R.id.image2);
        Image3 = findViewById(R.id.image3);
        Image4 = findViewById(R.id.image4);
        Button startButton = findViewById(R.id.strat);
        Button endButton = findViewById(R.id.End);
        EditText et = findViewById(R.id.BpM);

        Image1.setImageResource(R.drawable.en);
        Image2.setImageResource(R.drawable.en);
        Image3.setImageResource(R.drawable.en);
        Image4.setImageResource(R.drawable.en);

        //EditTextに数字しか入力できないようにする
        et.setInputType(InputType.TYPE_CLASS_NUMBER);

        //入力された値をint型に変換
        String bpm = ((EditText)findViewById(R.id.BpM)).getText().toString();
        int BPM = Integer.parseInt((bpm));

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
        } else {
            AudioAttributes attr = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .build();
            soundPool = new SoundPool.Builder()
                    .setAudioAttributes(attr)
                    .setMaxStreams(5)
                    .build();
        }


        mp3 = soundPool.load(this,R.raw.pop,1);

        //STARTButton
        startButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                i=0;

                String bpm = ((EditText)findViewById(R.id.BpM)).getText().toString();
                int BPM = Integer.parseInt((bpm));
                Delay = 60000/BPM;
                Image1.setImageResource(R.drawable.en);
                Image2.setImageResource(R.drawable.en);
                Image3.setImageResource(R.drawable.en);
                Image4.setImageResource(R.drawable.en);

               if(null != timer){
                   timer.cancel();
                   timer = null;
               }

               timer = new Timer();

               timerTask = new CountUpTimerTask();

               timer.schedule(timerTask,0,Delay);
            }

        });

        //ENDButton
        endButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(null != timer){
                    timer.cancel();
                    timer=null;
                }


                Image1.setImageResource(R.drawable.en);
                Image2.setImageResource(R.drawable.en);
                Image3.setImageResource(R.drawable.en);
                Image4.setImageResource(R.drawable.en);
            }
        });
    }

    class CountUpTimerTask extends TimerTask{
        @Override
        public void run(){
            handler.post(new Runnable() {
                @Override
                public void run() {
                    if (i == 0) {
                        Image1.setImageResource(R.drawable.eng);
                        Image4.setImageResource(R.drawable.en);
                        soundPool.play(mp3,2 , 2, 0, 0, 1f);
                        i++;
                    }
                    else if (i == 1) {
                        Image1.setImageResource(R.drawable.en);
                        Image2.setImageResource(R.drawable.eng);
                        soundPool.play(mp3,2 , 2, 0, 0, 1f);
                        i++;
                    }
                    else if (i == 2) {
                        Image2.setImageResource(R.drawable.en);
                        Image3.setImageResource(R.drawable.eng);
                        soundPool.play(mp3,2 , 2, 0, 0, 1f);
                        i++;
                    }
                    else {
                        Image3.setImageResource(R.drawable.en);
                        Image4.setImageResource(R.drawable.eng);
                        soundPool.play(mp3,2 , 2, 0, 0, 1f);
                        i = 0;
                    }
                }
            });
        }
    }
}
```
##プログラムの欠点と次に追加するもの
このプログラムでは、androidのせいなのかプログラムのせいか分からないのだが、動作途中に少しラグが発生する。そこを改善できればしたいと思う。
次に追加するものは、androidを様々な方向に振るとその都度音が出るようにしたいと思っており、現在加速度センサの変化をメトロノームの中に組み込めるかどうかを試みている。