【Android Studio】ゲームアプリ開発入門 第11回「効果音の再生」
ここまでの記事はこちら
今回はゲームには欠かせない効果音の再生を実装します。
効果音は
- オレンジ・ピンクボールに当たった時のヒット音
- 黒いトゲトゲに当たった時のゲームオーバー音
の2種類です。
それでは始めていきましょう!
解説
1. 音声ファイルの用意
音声ファイルのダウンロード
まずは使用する音声ファイルをこちらからダウンロードしてください。(2つのファイルが入っています。)
Catch the Ball(効果音)
簡単に作ったものなので音質は良くないですが、ご自由にお使いください。
rawフォルダの用意
効果音などの音声ファイルは raw フォルダに置きます。
raw フォルダはプロジェクト作成時には無いので、フォルダを作ってから音声ファイルを置きます。
Step 1
Android Studio 画面左側のプロジェクト構造にある res フォルダを選択した状態にします。
Step 2
res フォルダの上で右クリック → New → Folder → Raw Resources Folder をクリックします。
Step3
そのまま「Finish」を押します。
Step 4
作成された raw フォルダの上で右クリックして、Macの場合は「Open in → Finder」、Windowsの場合は「Open in → Explorer」を選択します。
Step 5
raw フォルダに先ほどダウンロードした音声ファイルを置きます。
これで音声ファイルを使う準備は完了です!
2. SoundPlayerクラスの作成
音声を管理するために SoundPlayer クラスを作成します。
パッケージ名の上で右クリック → New → Java Class をクリックします。
SoundPlayer と入力して Enter キーを押します。
3. 音声ファイル再生の準備
音声ファイルを読み込んで再生するための用意をしていきます。
SoundPlayer.java に以下のコードを書いてください。
R.raw.hit 部分に音声ファイルが認識されないエラーが表示された場合は Android Studio を再起動してください。
16行目 : SoundPool
ゲームの効果音など短い音を再生する時は SoundPool クラスを使います。
soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
2 はSOUND_POOL_MAX(最大同時再生数)です。
STREAM_MUSIC は音声ファイルの種類です。他にも STREAM_ALARM, STREAM_RING などがあります。
0 は再生品質です。ここはデフォルトの0にしておきます。
18・19行目 : load
load で音声ファイルを読み込みます。
soundPool.load(context, R.raw.hit, 1);
R.raw.correct は音声ファイルの ID です。
1 は再生品質です。ここもデフォルト値にしておきます。
22~24行目
オレンジ・ピンクボールに当たった時に音を再生するメソッドです。
public void playHitSound() {
soundPool.play(hitSound, 1.0f, 1.0f, 1, 0, 1.0f);
}
MainActivity.java から playHitSound メソッドを呼ぶことで音を鳴らします。
黒いトゲトゲに当たった時は 26 行目 playOverSound メソッドを呼びます。
play メソッド
play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)
soundID | サウンドID |
leftVolume(左の音量) | 0.0 ~ 1.0 |
rightVolume(右の音量) | 0.0 ~ 1.0 |
priority(優先度) | 0が最小値 |
loop(ループ・繰り返し) | 0: ループなし -1: ループする |
rate(再生速度) | 0.5(遅) ~ 2.0(速) |
SoundPoolの非推奨について
API 21(Lollipop)から new SoundPool~ の書き方は非推奨になっています。
このアプリは低い API にも対応させていること、非推奨でもプログラムに影響がないことから、そのままにしています。
非推奨を解決したい場合は以下のように書き直してください。
4. 効果音を再生する
まずは MainActivity.java に SoundPlayer クラスを用意します。
MainActivity.java を開いて、5・12行目を追加します。
次に、それぞれのボールの衝突判定をしている箇所で playHitSound メソッドと playOverSound メソッドを呼び出します。
10・20・33行目を追加します。
33行目の soundPlayer.playOverSound(); について
動画では if (timer != null) { より上に書いていますが、一度だけ再生されるように if (timer != null) { 内に書いて下さい。
5. アプリを実行する
アプリを実行して、効果音が再生されるかを確認してください。
テスト動画(音が出ます)
次に行うこと
次回はこのゲームアプリの総仕上げです。
画面の大きさが変わってもゲームを楽しめるようにボックスとボールの動くスピードを調整していきましょう。
saraさん。いつもandroidアプリ開発の学習のために参考にさせてもらっています。ありがとうございます。
質問があります。
効果音を読み取るloadメソッドで
>soundPool.load(context, R.raw.hit, 1);
という箇所がありますが、第一引数のcontextが分かりません。soundplayer内の個々の記述のみが不明だったので詳しく解説いただけると幸いです。
自分なりに調べたところ、contextというのは現在のクラスを取得するという理解をしましたが、このアプリ内、およびクラス内ではどんな機能として果たしているのか、分かりませんでした。
SoundPool クラスの load メソッドを見てみると、このように書いてあることが確認できると思います。
public int load(Context context, int resId, int priority) {
AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
context は現在のクラス(アクティビティ)なので、ここではアクティビティのリソースにアクセスして音声ファイルを開いていることが分かります。
MainActivity.java で SoundPlayer クラスを使うためのコードを書きました。
soundPlayer = new SoundPlayer(this);
この this が context、つまり MainActivity にあたります。
ですので
soundPool.load(context, R.raw.hit, 1);
では、MainActivity のリソースから hit.wav ファイルを開いていることになります。
ご返信ありがとうございます。
SoundPlayerにて、contextと指定することでMainActivity内のthis指定と繋げているイメージでしょうか?何となくわかった気がします。
>MainActivity のリソースから hit.wav ファイルを開いていることになります。
ここがいまいち理解できなかったです。
リソースというとrawフォルダのことかと思うのですが、resフォルダに保存されているのでは?と思いました。
> リソースというとrawフォルダのことかと思うのですが、resフォルダに保存されているのでは?と思いました。
res は Resource(リソース)の略なので res フォルダ内にあるファイルは全てリソースになります。
ですので、res フォルダ内の raw フォルダにある音声ファイルもリソース内にあることになります。
また、res フォルダ内にある全てのファイルには自動的に id が付けられて、R クラスで管理されています。
ですので
soundPool.load(context, R.raw.hit, 1);
の R.raw.hit は R クラスに作成された hit.wav の id を意味しています。
その id を使って
public int load(Context context, int resId, int priority) {
AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
では音声ファイルを用意してます。
コードが呼ばれる順番
soundPlayer = new SoundPlayer(this);
↓
public SoundPlayer(Context context) {
↓
soundPool.load(context, R.raw.hit, 1);
↓
public int load(Context context, int resId, int priority) {
で追いかけていくとわかりやすいかもしれません。
R クラスの中身については以下の記事の中盤に画像を載せているので、よろしければご確認ください
https://codeforfun.jp/java-for-android-6/
ご返信ありがとうございます。
恐らく、理解できたと思います。どのActivityからもresフォルダにアクセスすることは可能だけれども、今回はMainActivityからresフォルダを開くということですかね。少し、自分の勘違いがあったかもしれません。
コードの順番の説明分かりやすかったです。確かに、追いかけていくとrawフォルダから音声ファイルを取り出せることになりますね。
コメントの承認が遅くなってしまいすみません。
>> どのActivityからもresフォルダにアクセスすることは可能だけれども、今回はMainActivityからresフォルダを開くということ
その通りです!
SoundPlayer クラスを MainActivity で用意しているので MainActivity 経由で res フォルダにアクセスしている感じですね。
もし結果画面で効果音を再生するなら ResultAvtivty.java に
soundPlayer = new SoundPlayer(this);
と書くことになるので、今度は ResultActivity からres フォルダにアクセスすることになります。
この辺りはイメージが難しいですが、たくさんコードを書いていけばだんだん繋がりが見えてくると思います
ありがとうございました!
仰る通りで、イメージが難しいのですが沢山のコードを書くことでつながりが見えてくるのかなと思いました。
アプリ開発の勉強に参考にさせていただいておりますます。
rawに音楽のデータを入れると勝手にTextデータと認識されてしまい、
wavデータになりません。どうすればいいのか解決方法教えていただけますでしょうか。
当サイトを見つけて頂きありがとうございます!
お時間空いてしまったので解決済みかもしれませんが Android Studio の再起動をお試しください。
再起動でも解決できない場合は、具体的なエラーメッセージやスクリーンショットを添付いただければと思います。