日々是好日~every day is a good day~

日常の中の非日常の備忘録

【Android Studio】Tach the number 6回目

今日は最後『効果音をつける』です
まず下準備としてProjectタブのresにrawフォルダーを作成します
rawに音源をドラッグ&ドロップしておきます
今回は4つの音源を準備しました

音源はいつも効果音ラボさんの音源を使わせていただいてます
soundeffect-lab.info

import android.graphics.Color
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
import android.os.Handler
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import java.text.SimpleDateFormat
import java.util.*

class MainActivity : AppCompatActivity() {
    private lateinit var sp0: SoundPool
    private var success = 0
    private var mistake = 0
    private var cdstep = 0
    private var cdgo = 0
    private val handler = Handler()
    private var r = Runnable {  }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        gameStart()
    }
    fun gameStart() {
        val btn1: Button = findViewById(R.id.btn1)
        val btn2: Button = findViewById(R.id.btn2)
        val btn3: Button = findViewById(R.id.btn3)
        val btn4: Button = findViewById(R.id.btn4)
        val btn5: Button = findViewById(R.id.btn5)
        val btn6: Button = findViewById(R.id.btn6)
        val btn7: Button = findViewById(R.id.btn7)
        val btn8: Button = findViewById(R.id.btn8)
        val btn9: Button = findViewById(R.id.btn9)
        val btn10: Button = findViewById(R.id.btn10)
        val btn11: Button = findViewById(R.id.btn11)
        val btn12: Button = findViewById(R.id.btn12)
        val btn13: Button = findViewById(R.id.btn13)
        val btn14: Button = findViewById(R.id.btn14)
        val btn15: Button = findViewById(R.id.btn15)
        val btn16: Button = findViewById(R.id.btn16)
        val btn17: Button = findViewById(R.id.btn17)
        val btn18: Button = findViewById(R.id.btn18)
        val btn19: Button = findViewById(R.id.btn19)
        val btn20: Button = findViewById(R.id.btn20)
        val btn21: Button = findViewById(R.id.btn21)
        val btn22: Button = findViewById(R.id.btn22)
        val btn23: Button = findViewById(R.id.btn23)
        val btn24: Button = findViewById(R.id.btn24)
        val btn25: Button = findViewById(R.id.btn25)
        val tv: TextView = findViewById(R.id.tv)
        val tvCD: TextView = findViewById(R.id.tvCD)

        val aa0 = AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_GAME)
            .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
            .build()
        sp0 = SoundPool.Builder().setAudioAttributes(aa0).setMaxStreams(2).build()
        cdstep = sp0.load(this, R.raw.cdstep, 1)
        cdgo = sp0.load(this, R.raw.cdgo, 1)
        mistake = sp0.load(this, R.raw.mistake, 1)
        success = sp0.load(this, R.raw.success, 1)

        val TERM_MILLISECOND: Long = 100
        var count = 0
        val btn = arrayOf(
            btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8, btn9, btn10,
            btn11, btn12, btn13, btn14, btn15, btn16, btn17, btn18, btn19, btn20,
            btn21, btn22, btn23, btn24, btn25
        )
        val btnData = arrayOf(
            "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
            "11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
            "21", "22", "23", "24", "25"
        )
        val list = listOf(
            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
            16, 17, 18, 19, 20, 21, 22, 23, 24
        )
        val num = list.shuffled()

        val dataFormat = SimpleDateFormat("mm:ss.S", Locale.JAPAN)
        var cutime = 0L
        val startTime = 3000L
        tv.text ="   "
        tvCD.textSize = 48f
        tvCD.setTextColor(Color.BLACK)
        tvCD.text = "${startTime / 1000}"
        for (i in 0..24) {
            btn[i].text = btnData[num[i]]
            btn[i].isEnabled = false
        }
        //カウントダウンタイマーのオブジェクトを用意
        val timer = (object : CountDownTimer(startTime, 1000) {
            //途中経過・残り時間
            override fun onTick(p0: Long) {
                //残り時間を表示
                tvCD.text = "${(p0 + 1000) / 1000}" //秒単位
                sp0.play(cdstep, 1.0f, 1.0f, 1, 0, 1.0f)
            }

            //ゲームスタート
            override fun onFinish() {
                sp0.play(cdgo, 1.0f, 1.0f, 1, 0, 1.0f)
                tvCD.textSize = 24f
                tvCD.setTextColor(Color.RED)
                tvCD.text = "START"
                for (i in 0..24) {
                    btn[i].isEnabled = true
                }
                SimpleDateFormat("mm:ss.SS", Locale.US)
                r = object : Runnable {
                    override fun run() {
                        // timeに0.1秒を追加
                        cutime += TERM_MILLISECOND
                        // countTextに時間を表示
                        tv.text = dataFormat.format(cutime)
                        // 0.1秒で再度呼ばれるようにする
                        handler.postDelayed(this, TERM_MILLISECOND)
                    }
                }
                handler.post(r) //タイマー起動
            }
        })
        timer.start()

        for (i in 0..24) {
            btn[i].setOnClickListener {
                if (btn[i].text == btnData[count]) {
                    count++
                    btn[i].isEnabled = false
                    if (count == 25) {
                        sp0.play(success,1.0f, 1.0f, 1, 0, 1.0f)
                        handler.removeCallbacks(r) //タイマーストップ
                        tvCD.text = "STOP"
                        AlertDialog.Builder(this)
                            .setTitle("GAME CLEAR")
                            .setMessage(
                                "TIME : " + tv.text + "\n" +
                                        "もう一度プレイしますか?"
                            )
                            .setPositiveButton("Yes", { dialog, which ->
                                gameStart()
                            })
                            .setNegativeButton("No", { dialog, which ->
                                sp0.release()
                                System.exit(0)
                            })
                            .show()
                    }
                } else {
                    sp0.play(mistake,1.0f, 1.0f, 1, 0, 1.0f)
                    handler.removeCallbacks(r)  //タイマーストップ
                    tvCD.text = "STOP"
                    AlertDialog.Builder(this)
                        .setTitle("GAME OVER")
                        .setMessage("もう一度プレイしますか?")
                        .setPositiveButton("Yes", { dialog, which ->
                            gameStart()
                            
                        })
                        .setNegativeButton("No", { dialog, which ->
                            sp0.release()
                            System.exit(0)
                        })
                        .show()
                }
            }
        }
    }
}

SoundPoolを設定して音源をロード
音を鳴らしたい所で再生
ゲーム終了時にインスタンスを解放する

(再生できなくなっていたので2024.2.5に修正しました)
【注意】音でます
これで完成です