5672|17

9850

帖子

24

TA的资源

版主

楼主
 

虚拟架子鼓------Android程序开发 [复制链接]

 
 

Android程序使用Android Studio开发的

界面显示2根鼓棒,移动SensorTile相应的鼓棒会上下左右摆

检测到鼓棒快速落下鼓棒时,判断落下的角度播放相应鼓声

之前没接触过Android3D开发

在网上找了一个“OpenGL ES2.03D茶壶”的例程

例程里通过导入3D茶壶的.obj文件,并对其进行操作

我用3DMAX自己画了一根鼓棒,第一次用3DMax,用着还挺顺手

https://bbs.eeworld.com.cn/forum.php?mod=viewthread&tid=523174&highlight=3DMAX

 

画好鼓棒后导出.obj文件,加入Android项目里

打开ch_t.obj能看到一些像坐标一样的东西

 

为了让鼓棒看起来更像样,在百度里找了一张木文图片

Android里作为鼓棒的皮肤使用

做好的界面效果如下

 

 

 

背景是空白的看起来不是很漂亮,理想的效果是把架子鼓也画上去做成Real Drum的效果

落棒时显示敲打的特效,奈何水平有限,研究了很长时间也没做出来

 

只好以后有时间再弄

 

说到Real Drum,还要说声感谢,Real Drum并没有对它的APK文件加密处理

apk改成.zip文件后就能读到里边的资源文件

例如图片和.ogg音频

找到对应的文件,把它也加入到Android项目里

 

MainActivity.java文件里加入3D鼓棒和蓝牙接收的代码,再把数据提取、落棒检测、鼓棒控制和声音播放部分实现APP就基本开发完成

 

蓝牙开发和其它BLE设备开发一样,检测手机是否支持BLE,开启蓝牙

        if (!getPackageManager().hasSystemFeature(

                PackageManager.FEATURE_BLUETOOTH_LE)) {

            finish();

        }

        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

        mBluetoothAdapter = bluetoothManager.getAdapter();

        if (mBluetoothAdapter == null) {

            finish();

            return;

        }

        mBluetoothAdapter.enable();

 

onResumeonPause函数里加入启用扫描和关闭扫描的代码

 

    protected void onResume() {

        super.onResume();

        if (DEBUG) {

        } else {

            mGLSurfaceView.onResume();

        }

        scanLeDevice(true);

        Log.i(TAG, "startLeScan");

    }

 

    @Override

    protected void onPause() {

        super.onPause();

        if (DEBUG) {

        } else {

            mGLSurfaceView.onPause();

        }

        scanLeDevice(false);

        Log.i(TAG, "stopLeScan");

    }

 

 

在扫描状态设置函数里设置回调函数

 

    private void scanLeDevice(final boolean enable) {

        if (enable) {

            mScanning = true;

            mBluetoothAdapter.startLeScan(leScanCallback);

        } else {

            mScanning = false;

            mBluetoothAdapter.stopLeScan(leScanCallback);

        }

    }

 

声明回调函数,实现相应的方法

    private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {

        @Override

        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {

//            final float x = 360 -  (getShort(scanRecord,2) + 10000) /20000.00f * 360;

//            final float y =360 -  (getShort(scanRecord,4) ) / 100.00f;

//            final float z =360 - (getShort(scanRecord,6) + 10000) /20000.00f * 360;

            //读取数据标识,因为没有使用CRC校验,防止受其它蓝牙数据影响

            //str“airdrum”时认为数据有校

            String s = new String(Arrays.copyOfRange(scanRecord, 2+6+6,2+6+6+7));

            if(!s.equals("airdrum"))

            {

                return;

            }

            //获得鼓棒ID

            Long drumId = getLong(scanRecord,2);

            //不包含这个ID的大鼓棒就添加它

            if(!drumIds.contains((drumId)))

            {

                drumIds.add(drumId);

            }

            final float count = getShort(scanRecord, 6+2);

            final float r2 = 180 + getShort(scanRecord, 6+4) / 100.00f;//r2的范围是-180~+180 180后得到0~360数据

            final float r0 = getUShort(scanRecord, 6+6) / 100.00f;//r0的范围是0~360

            System.out.println("r2:\t"+ r2+"\tr0:\t"+ r0 + "\tangle:" + getAngle(r0,firstR0)+"\tfirstr0:"+getAngle(r0,firstR0)+90);

            if (count > oldCount) {

                //第一次落棒

                if (first) {

                    first = false;

                    //第一次落棒时保存第一次落棒的位置

                    firstR2 = r2;

                    firstR0 = r0;

                    sp.play(start, 1.0f, 0.3f, 0, 0, 1.0f);

                } else {

                    float angleR0 = getMinAngle(r0,firstR0);

                    float angleR2 = getMinAngle(r2,firstR2);

                    //右鼓

                    if (angleR0 > 15) {

                        //

                        if (angleR2 > 25) {

                            sp.play(closehh, 1.0f, 0.3f, 0, 0, 1.0f);

                        } else {//

                            sp.play(snare, 1.0f, 0.3f, 0, 0, 1.0f);

                        }

                    } else if (angleR0 < -15) {//左鼓

                        //

                        if (angleR2 > 25) {

                            sp.play(closehh, 1.0f, 0.3f, 0, 0, 1.0f);

                        } else {//

                            sp.play(snare, 1.0f, 0.3f, 0, 0, 1.0f);

                        }

                    } else {//中鼓

                        //

                        if (angleR2 > 25) {

                            sp.play(openhh, 1.0f, 0.3f, 0, 0, 1.0f);

                        } else {//

                            sp.play(kick, 1.0f, 0.3f, 0, 0, 1.0f);

                        }

                    }

                }

            }

            oldCount = count;

            final float angleZ = getAngle(r0,firstR0)+90;;

            float z = angleZ > 360 ? angleZ - 360:angleZ;

            final float angleY = z > 180 ? r2:-r2;

            if (Looper.myLooper() == Looper.getMainLooper()) {

                if (DEBUG) {

                    final String str = String.format("%.2f          %.2f          %.2f", count, r2, r0);

                    textView1.setText(str);

                } else {

                    mGLSurfaceView.setXYZ(0,0,angleY , angleZ);

                }

            } else {

                runOnUiThread(new Runnable() {

                    @Override

                    public void run() {

                        if (DEBUG) {

                            final String str = String.format("%.2f          %.2f          %.2f", count, r2, r0);

                            textView1.setText(str);

                        } else {

                            mGLSurfaceView.setXYZ(0,0, angleY,angleZ);

                        }

                    }

                });

            }

        }

    };

 

 

现在单鼓棒功能已经实现,完整的代码已经放在github

https://github.com/int8cn/AirDrum

 

 

 

 

最新回复

牛人真多啊!!!学习学习     详情 回复 发表于 2024-8-13 17:48
点赞 关注
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 

回复
举报

1902

帖子

0

TA的资源

版主

沙发
 
牛人真多啊学习一下下了哦,
 
 
 

回复

111

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
虾哥,你的sensor是固定在鼓棒的什么位置?

如果花式空抛 (鼓槌离手,空中翻腾)的话,鼓会有声音么?

点评

正准备焊接SensorTile小板,焊好后想放在离手近一些的位置 你说的离手不敢试,摔坏了就不能演示了,按照我写的落棒检测代码应该不会有声音  详情 回复 发表于 2017-4-28 17:01
 
 
 

回复

9850

帖子

24

TA的资源

版主

4
 
alberthink 发表于 2017-4-28 16:32
虾哥,你的sensor是固定在鼓棒的什么位置?

如果花式空抛 (鼓槌离手,空中翻腾)的话,鼓会有声音么?

正准备焊接SensorTile小板,焊好后想放在离手近一些的位置
你说的离手不敢试,摔坏了就不能演示了,按照我写的落棒检测代码应该不会有声音
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

回复

111

帖子

0

TA的资源

一粒金砂(中级)

5
 
虾哥,由于你的鼓槌是基于广播来传递数据,所以程序扫描LE设备并筛选的部分应避免将过多不必要的数据记录到log中(严重时可能会导致程序崩溃),如果我理解的没错,你的代码里面是把所有的扫描都存log,然后再作名称的比较的。这个风险有些大,特别是随着周围LE广播设备越来越多的场景。

点评

收一条判断一条 没有记录log啊 手机的配置处理一条广播的时间应该非常短 尤其哪些不符合规则的数据判断几个字节不对就直接返回了 影响应该不大  详情 回复 发表于 2017-4-28 18:12
 
 
 

回复

9850

帖子

24

TA的资源

版主

6
 


收一条判断一条 没有记录log啊
手机的配置处理一条广播的时间应该非常短
尤其哪些不符合规则的数据判断几个字节不对就直接返回了
影响应该不大
 
 
 

回复

2774

帖子

8

TA的资源

版主

7
 
看不懂,一个头两个大!

点评

你说的应该是“Log.i()"吧?这个是调试用的,相当于system.out.print....  详情 回复 发表于 2017-4-28 20:34
 
 
 

回复

2721

帖子

0

TA的资源

纯净的硅(中级)

8
 
我电脑装了android studio编译时卡的很

点评

我的也是,这个软件非常占内存,打开后硬盘一直在读写,你要是再开一个虚拟机…………  详情 回复 发表于 2017-4-28 20:35
 
 
 

回复

183

帖子

4

TA的资源

一粒金砂(高级)

9
 
非常棒!
 
 
 

回复

9850

帖子

24

TA的资源

版主

10
 
strong161 发表于 2017-4-28 19:35
看不懂,一个头两个大!

你说的应该是“Log.i()"吧?这个是调试用的,相当于system.out.print....

点评

哈哈,APP搞不来,所以基本上看不下去,所以也就看不懂了!  详情 回复 发表于 2017-4-28 21:56
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

回复

9850

帖子

24

TA的资源

版主

11
 
suoma 发表于 2017-4-28 19:45
我电脑装了android studio编译时卡的很

我的也是,这个软件非常占内存,打开后硬盘一直在读写,你要是再开一个虚拟机…………
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

回复

2774

帖子

8

TA的资源

版主

12
 
littleshrimp 发表于 2017-4-28 20:34
你说的应该是“Log.i()"吧?这个是调试用的,相当于system.out.print....

哈哈,APP搞不来,所以基本上看不下去,所以也就看不懂了!
 
 
 

回复

661

帖子

29

TA的资源

版主

13
 
厉害,看了下代码,也实际运行了一下,看你蓝牙部分还么有写全,蓝牙是准备移植ST的SDK还是自己写呢?

点评

蓝牙已经写完了 直接接收广播 不连接  详情 回复 发表于 2017-4-29 13:57
个人签名QQ:252669569
 
 
 

回复

9850

帖子

24

TA的资源

版主

14
 


蓝牙已经写完了 直接接收广播 不连接

点评

恩,这个厉害,那SensorTile端的代码也改了吗?  详情 回复 发表于 2017-4-29 14:01
 
 
 

回复

661

帖子

29

TA的资源

版主

15
 
littleshrimp 发表于 2017-4-29 13:57
蓝牙已经写完了 直接接收广播 不连接

恩,这个厉害,那SensorTile端的代码也改了吗?

点评

Sensortile端使用BEACON方式直接将数据更新到广播包里  详情 回复 发表于 2017-4-29 15:28
个人签名QQ:252669569
 
 
 

回复

9850

帖子

24

TA的资源

版主

16
 


Sensortile端使用BEACON方式直接将数据更新到广播包里
 
 
 

回复

419

帖子

0

TA的资源

纯净的硅(中级)

17
 
非常好,内容很详细,图文并茂,学习了。!!!!!
 
 
 

回复

7

帖子

0

TA的资源

一粒金砂(中级)

18
 

牛人真多啊!!!学习学习

 

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表