Enhancements

Implements fat touch detection for playing on mobile phones.
Allows using the whole screen as touch area when not using touch air mode.
Optimize codes to lower minimum required SDK version to 17.
pull/1/head
Tindy X 2021-03-25 21:26:47 +08:00
parent 84b95e9610
commit fb4e41b40e
No known key found for this signature in database
GPG Key ID: C6AD413169968D58
4 changed files with 78 additions and 28 deletions

View File

@ -9,7 +9,7 @@ android {
defaultConfig { defaultConfig {
applicationId "com.github.brokenithm" applicationId "com.github.brokenithm"
minSdkVersion 23 minSdkVersion 17
targetSdkVersion 30 targetSdkVersion 30
versionCode 10100 versionCode 10100
versionName "1.1.0" versionName "1.1.0"

View File

@ -43,11 +43,13 @@ class MainActivity : AppCompatActivity() {
private val numOfGaps = 16 private val numOfGaps = 16
private val buttonWidthToGap = 7.428571f private val buttonWidthToGap = 7.428571f
private val numOfAirBlock = 6 private val numOfAirBlock = 6
private val fatTouchSizeThreshold = 0.034f
private val extraFatTouchSizeThreshold = 0.041f
private var mCurrentDelay = 0f private var mCurrentDelay = 0f
// Buttons // Buttons
private var mCurrentAirHeight = 6 private var mCurrentAirHeight = 6
private var mLastButtons = mutableSetOf<Int>() private var mLastButtons = HashSet<Int>()
private var mTestButton = false private var mTestButton = false
private var mServiceButton = false private var mServiceButton = false
private data class InputEvent(val keys: MutableSet<Int>? = null, val airHeight : Int = 6, val testButton: Boolean = false, val serviceButton: Boolean = false) private data class InputEvent(val keys: MutableSet<Int>? = null, val airHeight : Int = 6, val testButton: Boolean = false, val serviceButton: Boolean = false)
@ -194,9 +196,12 @@ class MainActivity : AppCompatActivity() {
textExpand.callOnClick() textExpand.callOnClick()
view ?: return@setOnTouchListener view.performClick() view ?: return@setOnTouchListener view.performClick()
event ?: return@setOnTouchListener view.performClick() event ?: return@setOnTouchListener view.performClick()
val currentAirAreaHeight = if (mAirSource != 3) 0f else airAreaHeight
val currentButtonAreaHeight = if (mAirSource != 3) 0f else buttonAreaHeight
val totalTouches = event.pointerCount val totalTouches = event.pointerCount
val touchedButtons = mutableSetOf<Int>() val touchedButtons = HashSet<Int>()
var thisAirHeight = 6 var thisAirHeight = 6
var maxTouchedSize = 0f
if (event.action != KeyEvent.ACTION_UP && event.action != MotionEvent.ACTION_CANCEL) { if (event.action != KeyEvent.ACTION_UP && event.action != MotionEvent.ACTION_CANCEL) {
var ignoredIndex = -1 var ignoredIndex = -1
if (event.actionMasked == MotionEvent.ACTION_POINTER_UP) if (event.actionMasked == MotionEvent.ACTION_POINTER_UP)
@ -207,14 +212,14 @@ class MainActivity : AppCompatActivity() {
val x = event.getX(i) + view.left val x = event.getX(i) + view.left
val y = event.getY(i) + view.top val y = event.getY(i) + view.top
when(y) { when(y) {
in 0f..airAreaHeight -> { in 0f..currentAirAreaHeight -> {
thisAirHeight = 0 thisAirHeight = 0
} }
in airAreaHeight..buttonAreaHeight -> { in currentAirAreaHeight..currentButtonAreaHeight -> {
val curAir = ((y - airAreaHeight) / airBlockHeight).toInt() val curAir = ((y - airAreaHeight) / airBlockHeight).toInt()
thisAirHeight = if(mSimpleAir) 0 else thisAirHeight.coerceAtMost(curAir) thisAirHeight = if(mSimpleAir) 0 else thisAirHeight.coerceAtMost(curAir)
} }
in buttonAreaHeight..windowHeight.toFloat() -> { in currentButtonAreaHeight..windowHeight.toFloat() -> {
//val centerButton = (x / buttonBlockWidth).toInt() + 1 //val centerButton = (x / buttonBlockWidth).toInt() + 1
//val leftButton = (centerButton - 1).coerceAtLeast(1) //val leftButton = (centerButton - 1).coerceAtLeast(1)
//val rightButton = (centerButton + 1).coerceAtMost(32) //val rightButton = (centerButton + 1).coerceAtMost(32)
@ -223,9 +228,49 @@ class MainActivity : AppCompatActivity() {
val pointPos = x / buttonBlockWidth val pointPos = x / buttonBlockWidth
var index = pointPos.toInt() var index = pointPos.toInt()
if (index > numOfButtons) index = numOfButtons if (index > numOfButtons) index = numOfButtons
var realIndex = index * 2
if (touchedButtons.contains(realIndex)) realIndex++ var centerButton = index * 2
touchedButtons.add(realIndex) if (touchedButtons.contains(centerButton)) centerButton++
var leftButton = ((index - 1) * 2).coerceAtLeast(0)
if (touchedButtons.contains(leftButton)) leftButton++
var rightButton = ((index + 1) * 2).coerceAtMost(numOfButtons * 2)
if (touchedButtons.contains(rightButton)) rightButton++
var left2Button = ((index - 2) * 2).coerceAtLeast(0)
if (touchedButtons.contains(left2Button)) left2Button++
var right2Button = ((index + 2) * 2).coerceAtMost(numOfButtons * 2)
if (touchedButtons.contains(right2Button)) right2Button++
val currentSize = event.getSize(i)
maxTouchedSize = maxTouchedSize.coerceAtLeast(currentSize)
touchedButtons.add(centerButton)
when ((pointPos - index) * 4) {
in 0f..1f -> {
touchedButtons.add(leftButton)
if (currentSize >= extraFatTouchSizeThreshold) {
touchedButtons.add(left2Button)
touchedButtons.add(rightButton)
}
}
in 1f..3f -> {
if (currentSize >= fatTouchSizeThreshold) {
touchedButtons.add(leftButton)
touchedButtons.add(rightButton)
}
if (currentSize >= extraFatTouchSizeThreshold) {
touchedButtons.add(left2Button)
touchedButtons.add(right2Button)
}
}
in 3f..4f -> {
touchedButtons.add(rightButton)
if (currentSize >= extraFatTouchSizeThreshold) {
touchedButtons.add(leftButton)
touchedButtons.add(right2Button)
}
}
}
/*
if (index > 0) { if (index > 0) {
if ((pointPos - index) * 4 < 1) { if ((pointPos - index) * 4 < 1) {
realIndex = (index - 1) * 2 realIndex = (index - 1) * 2
@ -239,6 +284,7 @@ class MainActivity : AppCompatActivity() {
touchedButtons.add(realIndex) touchedButtons.add(realIndex)
} }
} }
*/
} }
} }
} }
@ -256,7 +302,7 @@ class MainActivity : AppCompatActivity() {
mCurrentAirHeight = thisAirHeight mCurrentAirHeight = thisAirHeight
//mInputQueue.add(InputEvent(touchedButtons, mCurrentAirHeight)) //mInputQueue.add(InputEvent(touchedButtons, mCurrentAirHeight))
if (mDebugInfo) if (mDebugInfo)
textInfo.text = getString(R.string.debug_info, mCurrentAirHeight, touchedButtons.toString(), event.toString()) textInfo.text = getString(R.string.debug_info, mCurrentAirHeight, touchedButtons.toString(), maxTouchedSize, event.toString())
view.performClick() view.performClick()
} }
@ -432,7 +478,7 @@ class MainActivity : AppCompatActivity() {
super.onResume() super.onResume()
if (mSensorManager == null) if (mSensorManager == null)
mSensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager mSensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val gyro = mSensorManager?.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR) val gyro = mSensorManager?.getDefaultSensor(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) Sensor.TYPE_GAME_ROTATION_VECTOR else Sensor.TYPE_ROTATION_VECTOR)
mSensorManager?.registerListener(listener, gyro, 10000) mSensorManager?.registerListener(listener, gyro, 10000)
val accel = mSensorManager?.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION) val accel = mSensorManager?.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)
mSensorManager?.registerListener(listener, accel, 10000) mSensorManager?.registerListener(listener, accel, 10000)
@ -531,10 +577,17 @@ class MainActivity : AppCompatActivity() {
} }
val buffer = ByteArray(256) val buffer = ByteArray(256)
val packet = DatagramPacket(buffer, buffer.size) val packet = DatagramPacket(buffer, buffer.size)
fun InetSocketAddress.toHostString(): String? {
if (hostName != null)
return hostName
if (this.address != null)
return this.address.hostName ?: this.address.hostAddress
return null
}
while (!mExitFlag) { while (!mExitFlag) {
try { try {
socket.receive(packet) socket.receive(packet)
if (packet.address.hostAddress == address.hostString && packet.port == address.port) { if (packet.address.hostAddress == address.toHostString() && packet.port == address.port) {
val data = packet.data val data = packet.data
if (data.size >= 3) { if (data.size >= 3) {
if (data.size >= 100 && data[1] == 'L'.toByte() && data[2] == 'E'.toByte() && data[3] == 'D'.toByte()) { if (data.size >= 100 && data[1] == 'L'.toByte() && data[2] == 'E'.toByte() && data[3] == 'D'.toByte()) {
@ -601,21 +654,17 @@ class MainActivity : AppCompatActivity() {
while (!mExitFlag) { while (!mExitFlag) {
if (mShowDelay) if (mShowDelay)
sendPing(address) sendPing(address)
//while (!mInputQueue.isEmpty() && mInputQueue.peek() == null)
//mInputQueue.pop()
//val buttons = mInputQueue.poll()
val buttons = InputEvent(mLastButtons, mCurrentAirHeight, mTestButton, mServiceButton) val buttons = InputEvent(mLastButtons, mCurrentAirHeight, mTestButton, mServiceButton)
if (buttons != null/* || mLastAirHeight != mCurrentAirHeight*/) { val buffer = applyKeys(buttons/* ?: InputEvent()*/, IoBuffer())
val buffer = applyKeys(buttons/* ?: InputEvent()*/, IoBuffer()) val packet = constructPacket(buffer)
val packet = constructPacket(buffer) try {
try { socket.send(packet)
socket.send(packet) } catch (e: Exception) {
} catch (e: Exception) { e.printStackTrace()
e.printStackTrace() Thread.sleep(100)
Thread.sleep(100) continue
continue
}
} }
//Thread.sleep(2)
Thread.sleep(1) Thread.sleep(1)
} }
socket.close() socket.close()

View File

@ -116,7 +116,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:text="Enable Air" android:text="@string/enable_air"
android:textColor="@color/white" android:textColor="@color/white"
android:visibility="gone" android:visibility="gone"
app:layout_constraintStart_toEndOf="@+id/button_card" app:layout_constraintStart_toEndOf="@+id/button_card"
@ -131,7 +131,7 @@
android:foreground="?android:attr/selectableItemBackground" android:foreground="?android:attr/selectableItemBackground"
android:gravity="center" android:gravity="center"
android:padding="8dp" android:padding="8dp"
android:text="Disable Air" android:text="@string/disable_air"
android:textColor="@color/white" android:textColor="@color/white"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/button_card" app:layout_constraintBottom_toBottomOf="@+id/button_card"

View File

@ -12,7 +12,7 @@
<string name="test">Test</string> <string name="test">Test</string>
<string name="service">Service</string> <string name="service">Service</string>
<string name="show_debug_info">Debug</string> <string name="show_debug_info">Debug</string>
<string name="debug_info">touched: air:%d %s\n%s</string> <string name="debug_info">touched: air:%d %s size:%f\n%s</string>
<string name="current_latency">Current Latency: %f ms</string> <string name="current_latency">Current Latency: %f ms</string>
<string name="press_again_to_exit">Press again to exit</string> <string name="press_again_to_exit">Press again to exit</string>
<string name="show_delay">Show Delay</string> <string name="show_delay">Show Delay</string>
@ -26,4 +26,5 @@
<string name="gyro_air">Gyro Air</string> <string name="gyro_air">Gyro Air</string>
<string name="accel_air">Accel Air</string> <string name="accel_air">Accel Air</string>
<string name="touch_air">Touch Air</string> <string name="touch_air">Touch Air</string>
<string name="enable_air">Enable Air</string>
</resources> </resources>