HMCL-dev / HMCL-PE

Hello Minecraft! Launcher for Android
GNU General Public License v3.0
742 stars 96 forks source link

陀螺仪卡顿、陀螺仪在逆向横屏时反转 #155

Open WuDi-ZhanShen opened 1 year ago

WuDi-ZhanShen commented 1 year ago

我看到您的src/main/java/com/tungsten/hmclpe/control/ViewManager.java中的onSensorEvent()函数了。

这个应该是从CSDN上抄的吧?我在写安卓MC陀螺仪控制视角功能的时候,跟您抄了同一份CSDN代码嘿嘿嘿,表现出来效果也是很卡顿。

当时不太理解,后来才意识到NS2S的这个数字过于庞大,dT这个数字又过于小,以至于在乘乘除除的过程中原本的values[0]和values[1]数据严重失真。

MD,狗CSDN误我!其实根本不需要转换纳秒为秒,也不需要获取两次SensorEvent的间隔时间,更不需要使用angle数组来记录当前的角度....直接使用values[0]和values[1]原始数据作为pointer的水平移动量和竖直移动量即可。在您使用的FASTEST采样率下,直接使用原始数据会非常非常的流畅。

原始数据大体上会比使用您当前的处理方法处理后的数据大10倍左右(因设备陀螺仪最大采样率而异),所以您可以对灵敏度也稍作调节,以使得灵敏度合适。

还有就是逆向横屏(180度横屏)时陀螺仪反转问题,因为逆向横屏后会颠倒游戏的UI画面,但是不影响陀螺仪回报的数据。为此,我个人的处理方法是,显示一个按钮,点击后即可获取当前屏幕是横屏还是逆向横屏,并在逆向横屏时为陀螺仪数据乘上-1。

获取设备方向的办法是: getWindowManager().getDefaultDisplay().getRotation() 这个函数会返回0、1、2、3中的一个数字,分别代表四个方向。请注意,onConfigurationChanges()函数并不会在横屏和逆向横屏切换时触发,所以软件是无法主动得知横屏和逆向横屏的切换的,如果每秒都检测一次的话又太低效率,因此我只能想到提供一个按钮给用户,在用户切换横屏状态后点击按钮,我就获取当前屏幕方向并由此给陀螺仪数据乘-1。

听起来是很笨的方法,不过确实想不到更好的了。。但是我最近刚刚听说了安卓系统源码里有一个隐藏的RotationWatcher.aidl接口文件,正在研究可否反射此隐藏接口函数来监听横屏与逆向横屏的切换。等我研究出结果了会第一时间告知您!

最后,希望您有空可以试用一下我的安卓MC的陀螺仪视角控制APP,能提点意见就最好啦,祝您生活愉快虎年大吉!

Tungstend commented 1 year ago

感谢,这部分代码抄过来有很长一段时间了,最初是没有问题的,因此我就没有研究过陀螺仪了,最近我也发现了它很卡顿,但由于其他的更新任务就没有详细研究,另外HMCL-PE 已经停更,这个bug也懒得修了,我将会在我的新启动器上修复此问题

WuDi-ZhanShen commented 1 year ago

感谢您的回复!我很喜欢HMCL-PE!

WuDi-ZhanShen commented 1 year ago

感谢,这部分代码抄过来有很长一段时间了,最初是没有问题的,因此我就没有研究过陀螺仪了,最近我也发现了它很卡顿,但由于其他的更新任务就没有详细研究,另外HMCL-PE 已经停更,这个bug也懒得修了,我将会在我的新启动器上修复此问题

您好!我已经找到了监听屏幕方向在横屏和逆向横屏之间切换的方法,注册一个监听android.intent.action.CONFIGURATION_CHANGED系统广播的广播接收器即可。 registerReceiver(mBroadcastReceiver, new IntentFilter("android.intent.action.CONFIGURATION_CHANGED"));

在接收到这个广播之后,使用 int rotation = windowManager.getDefaultDisplay().getRotation(); 即可获得当前设备的方向,rotation的值可能有0,1,2,3,对应于设备的四个方向。

artdeell commented 1 year ago

Or you can do what pojav does, and move away from using the gyroscope directly We switched to Game Rotation Vector and it is way more reliable than just the gyroscope

WuDi-ZhanShen commented 1 year ago

Or you can do what pojav does, and move away from using the gyroscope directly We switched to Game Rotation Vector and it is way more reliable than just the gyroscope

Thanks! But how can we determine if the current screen orientation is either "landscape" or "reverseLandscape"? While the gyroscope sensor's report data is independent of the current screen orientation, the game's user interface, on the other hand, is dependent on it. So whatever method we use, the current screen orientation still must be known.

artdeell commented 1 year ago

Or you can do what pojav does, and move away from using the gyroscope directly We switched to Game Rotation Vector and it is way more reliable than just the gyroscope

Thanks! But how can we determine if the current screen orientation is either "landscape" or "reverseLandscape"? While the gyroscope sensor's report data is independent of the current screen orientation, the game's user interface, on the other hand, is dependent on it. So whatever method we use, the current screen orientation still must be known.

For that, you can use the orientation sensor (directly)

WuDi-ZhanShen commented 1 year ago

Or you can do what pojav does, and move away from using the gyroscope directly We switched to Game Rotation Vector and it is way more reliable than just the gyroscope

Thanks! But how can we determine if the current screen orientation is either "landscape" or "reverseLandscape"? While the gyroscope sensor's report data is independent of the current screen orientation, the game's user interface, on the other hand, is dependent on it. So whatever method we use, the current screen orientation still must be known.

For that, you can use the orientation sensor (directly)

Even when the orientation sensor reports a degree of 350, the screen orientation may still be in landscape mode instead of reverseLandscape, which depends on the system setting "frozen_rotation". As such, I am looking for a more reliable way to determine the current screen orientation, and I found a possible solution.

WuDi-ZhanShen commented 1 year ago

Or you can do what pojav does, and move away from using the gyroscope directly We switched to Game Rotation Vector and it is way more reliable than just the gyroscope

Thanks! But how can we determine if the current screen orientation is either "landscape" or "reverseLandscape"? While the gyroscope sensor's report data is independent of the current screen orientation, the game's user interface, on the other hand, is dependent on it. So whatever method we use, the current screen orientation still must be known.

For that, you can use the orientation sensor (directly)

Another possible solution without orientation sensor is to reflect the android.view.RotationWatcher, but it's very difficult to do reflrction on Android version up to 9 .

artdeell commented 1 year ago

Well then the only option remaining is Game Rotation Vector, it's in sync with android orientation.

WuDi-ZhanShen commented 1 year ago

Well then the only option remaining is Game Rotation Vector, it's in sync with android orientation.

Does pojav need to retrieve the current orientation each time a Game Rotation Vector is sent? I am not very familiar with pojav, but if this were the case, it could be inefficient.

artdeell commented 1 year ago

Well then the only option remaining is Game Rotation Vector, it's in sync with android orientation.

Does pojav need to retrieve the current orientation each time a Game Rotation Vector is sent? I am not very familiar with pojav, but if this were the case, it could be inefficient.

No, GRV is synchronized with the current app's rotation