P45 ドラム

Android開発に関するメモランダム

カテゴリー: Androidプログラミング入門 - 独りで学べるスマホアプリの作り方 -  閲覧数:325 配信日:2018-05-14 13:11


コード


▼/sample2/MainActivity.java
package biz.answerlead.sample2;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

import biz.answerlead.sample2.Drum.Type;

/** メイン画面 */
public class MainActivity extends AppCompatActivity implements OnTouchListener {

/** ドラム音管理オブジェクト */
private final Drum drum = new Drum();

/** ドラム画像横幅 */
private static final int DRUM_WIDTH = 1920;

/** ドラム画像縦幅 */
private static final int DRUM_HEIGHT = 1411;

/** 初期化イベント */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// レイアウト設定
setContentView(R.layout.activity_main);

// ドラム描画領域設定
ImageView drum_image = (ImageView) findViewById(R.id.DrumImage);
drum_image.setOnTouchListener(this);
}

/** アプリ開始時、再開時イベント */
@Override
protected void onResume() {
super.onResume();

// 指定ドラム音の読み込み
drum.load(this);
}

/** アプリ中断時イベント */
@Override
protected void onPause() {
super.onPause();

// アプリ未使用時はメモリ節約のため、ドラム音データを開放
drum.release();
}

/** 画面タッチイベント */
@Override
public boolean onTouch(View v, MotionEvent event) {

// 動作ID
int action = event.getActionMasked();

// ポインタID
int index = event.getActionIndex();

// タッチX座標
double touch_x = event.getX(index);

// タッチY座標
double touch_y = event.getY(index);

// 画面横幅
int wx = v.getWidth();

// 画面縦幅
int wy = v.getHeight();

// 動作IDからログ表示用文字列を設定
String action_name;
switch (action) {
case MotionEvent.ACTION_DOWN:
action_name = "ACTION_DOWN";
break;
case MotionEvent.ACTION_MOVE:
action_name = "ACTION_MOVE";
break;
case MotionEvent.ACTION_UP:
action_name = "ACTION_UP";
break;
case MotionEvent.ACTION_POINTER_DOWN:
action_name = "ACTION_POINTER_DOWN";
break;
case MotionEvent.ACTION_POINTER_UP:
action_name = "ACTION_POINTER_UP";
break;
default:
action_name = "OTHER";
break;
}

// ログ出力
Log.v("Touch", String.format(
"A:%20s P:%d/%d X:%5.1f Y:%5.1f",
action_name,
index, event.getPointerCount(),
touch_x, touch_y));

// タッチ開始イベントの場合
if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) {

// 画面と用意した画像の比
double multi;

// 画面の縦横比と用意した画像の縦横比を比べて処理を分岐
if (wx * DRUM_HEIGHT > wy * DRUM_WIDTH) {
// 画面の方が横長な場合は、縦の比率を基準に
multi = (double) DRUM_HEIGHT / wy;
} else {
// 画面の方が縦長な場合は、横の比率を基準に
multi = (double) DRUM_WIDTH / wx;
}

// タッチした座標を画像上での座標に変換
double x = (touch_x - wx / 2.0) * multi + DRUM_WIDTH / 2.0;
double y = (touch_y - wy / 2.0) * multi + DRUM_HEIGHT / 2.0;

// バスドラム部分(円で判定)
if (getDistance(x, y, 960, 960) < 361) {
drum.play(Type.BASS);
}

// ロータム部分
if ((getDistance(x, y, 388, 689) < 261) || (getDistance(x, y, 1532, 689) < 261)) {
drum.play(Type.LOW_TOM);
}

// ハイタム部分
if ((getDistance(x, y, 714, 244) < 196) || (getDistance(x, y, 1206, 244) < 196)) {
drum.play(Type.HI_TOM);
}

// シンバル部分
if ((getDistance(x, y, 288, 127) < 238) || (getDistance(x, y, 1632, 127) < 238)) {
drum.play(Type.CYMBAL);
}

// 座標を情報をデバッグログに表示
Log.d("DEBUG", String.format("画面サイズ(%4d, %4d) 変換前座標(%4.0f, %4.0f) 変換後座標(%4.1f, %4.1f)", wx, wy, touch_x, touch_y, x, y));
}

// 続けてタッチイベントを取得する場合はtrueを返却
// ※falseの場合は1点目のタッチ開始イベントしか掴めない
return true;
}

/** 2点間の距離を求める関数(三平方の定理) */
private double getDistance(double x1, double y1, double x2, double y2) {
return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
}


▼/sample2/Drum.java
package biz.answerlead.sample2;

import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;

/** ドラム音管理クラス */
public class Drum {

   /** 再生音種別 */
   public enum Type {
       CYMBAL,
       HI_TOM,
       LOW_TOM,
       BASS,
   }

   /** 効果音数 */
   private static final int SOUND_NUM = Type.values().length;

   /** 読込み済みフラグ */
   private boolean loaded = false;

   /** 音声管理オブジェクト */
   private final SoundPool sound_pool;

   /** 効果音IDリスト */
   private final Integer[] sound_ids = new Integer[SOUND_NUM];

   /** 初期化処理 */
   public Drum() {

       // 音声管理機能初期化(バージョンにより分岐)
       if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {

           // 5.0未満のSoundPool作成方法
           sound_pool = new SoundPool(SOUND_NUM, AudioManager.STREAM_MUSIC, 0);
       } else {

           // 5.0以降のSoundPool作成方法

           // 再生する効果音がどういうものなのか用途とデータ種別を指定する
           // 今回は最も近い用途としてUSAGE_GAME(ゲーム用)と、
           // CONTENT_TYPE_SONIFICATION(ユーザアクションに合わせて再生されるデータ)を指定
           AudioAttributes attr = new AudioAttributes.Builder()
                   .setUsage(AudioAttributes.USAGE_GAME)
                   .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build();

           // 属性と最大再生音数を指定し、SoundPoolを作成
           sound_pool = new SoundPool.Builder()
                   .setAudioAttributes(attr)
                   .setMaxStreams(SOUND_NUM)
                   .build();
       }
   }

   /** 指定ドラム音データ読込み */
   public void load(Context context) {

       // まだ読込みが完了していなければ
       if (!loaded) {

           // 効果音読込み
           sound_ids[Type.CYMBAL.ordinal()] = sound_pool.load(context, R.raw.cymbal, 1);
           sound_ids[Type.HI_TOM.ordinal()] = sound_pool.load(context, R.raw.hi_tom, 1);
           sound_ids[Type.LOW_TOM.ordinal()] = sound_pool.load(context, R.raw.low_tom, 1);
           sound_ids[Type.BASS.ordinal()] = sound_pool.load(context, R.raw.bass, 1);

           // 読込み済みとする
           loaded = true;
       }
   }

   /** 全てのドラム音データを開放 */
   public void release() {

       // 読込み済み効果音を開放
       for (int i = 0; i < SOUND_NUM; i++) {
           if (sound_ids[i] != null) {
               sound_pool.unload(sound_ids[i]);
               sound_ids[i] = null;
           }
       }

       // 未読込みに戻す
       loaded = false;
   }

   /** 指定音階の再生 */
   public void play(final Type sound) {

       // 指定Typeのインデックスを取得
       final int index = sound.ordinal();

       // 指定音階の有効値チェック、及び指定音階の読込み済みチェック
       if (sound_ids[index] != null) {

           // 音データを再生
           sound_pool.play(
                   sound_ids[index], // 効果音ID
                   1.0f,               // 左音量
                   1.0f,               // 右音量
                   0,                  // 優先度
                   0,                  // ループ回数
                   1                   // 再生速度
           );
       }
   }
}


週間人気ページランキング / 2-16 → 2-22
順位 ページタイトル抜粋 アクセス数
アクセスが、ありませんでした! 0
2025/2/23 1:01 更新
指定期間人気ページランキング / 1970-1-1 → 2025-2-22
順位 ページタイトル抜粋 アクセス数
アクセスが、ありませんでした! 0
2025/2/23 1:01 更新