Android点球大战应用如何跟踪屏幕触摸实现足球跟随触摸移动
点球大战Android应用触摸跟踪与射门功能实现方案
一、先修正现有布局问题
你当前的activity_main.xml中守门员ImageView缺少ID和闭合标签,先修正为以下代码:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/rootLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/main_bg" tools:context=".MainActivity"> <ImageView android:id="@+id/ball" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ball" app:layout_editor_absoluteX="150dp" app:layout_editor_absoluteY="500dp" tools:ignore="MissingConstraints" /> <ImageView android:id="@+id/goalkeeper" android:layout_width="150dp" android:layout_height="150dp" android:src="@drawable/goalkeeper" app:layout_editor_absoluteX="125dp" app:layout_editor_absoluteY="300dp" tools:ignore="MissingConstraints" /> </androidx.constraintlayout.widget.ConstraintLayout>
这里额外给根布局加了ID方便后续事件绑定,也给守门员加了ID方便后续扑救逻辑调用。
二、实现触摸跟踪与射门逻辑
核心是重写触摸事件回调,分三个状态处理手指动作:
ACTION_DOWN:手指按下时校验触摸点是否在足球区域,避免误触ACTION_MOVE:手指移动时实时更新足球的坐标,实现跟随效果ACTION_UP:手指抬起时触发射门动画与得分判定逻辑
完整的MainActivity.kt代码如下:
import android.animation.ObjectAnimator import android.os.Bundle import android.view.MotionEvent import android.view.View import android.view.animation.DecelerateInterpolator import androidx.appcompat.app.AppCompatActivity class MainActivity : AppCompatActivity() { // 足球默认初始位置,用于射门结束后重置 private var defaultBallX = 0f private var defaultBallY = 0f // 触摸偏移量,避免手指挡住足球 private val touchOffset = 100f override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 全屏配置 window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_FULLSCREEN // 页面加载完成后记录足球初始位置 findViewById<View>(R.id.ball).post { defaultBallX = findViewById<View>(R.id.ball).x defaultBallY = findViewById<View>(R.id.ball).y } } override fun onTouchEvent(event: MotionEvent): Boolean { val ball = findViewById<View>(R.id.ball) when (event.action) { // 手指按下 MotionEvent.ACTION_DOWN -> { // 判断按下位置是否在足球范围内,避免误触 val touchX = event.rawX val touchY = event.rawY val isTouchOnBall = touchX >= ball.x && touchX <= ball.x + ball.width && touchY >= ball.y && touchY <= ball.y + ball.height return isTouchOnBall // 只有按到足球才消费后续事件 } // 手指移动 MotionEvent.ACTION_MOVE -> { // 更新足球位置,加偏移避免手指挡住球 ball.x = event.rawX - ball.width/2 ball.y = event.rawY - ball.height/2 - touchOffset return true } // 手指抬起,触发射门 MotionEvent.ACTION_UP -> { shootBall(ball) return true } } return super.onTouchEvent(event) } // 射门逻辑实现 private fun shootBall(ball: View) { // 计算射门终点,这里示例是往屏幕顶部(球门方向)飞 val endY = -ball.height.toFloat() // 也可以根据手指抬起时的速度调整射门速度,这里简化处理 val animatorY = ObjectAnimator.ofFloat(ball, "y", ball.y, endY) animatorY.duration = 500 animatorY.interpolator = DecelerateInterpolator() animatorY.start() // 此处可扩展: // 1. 加守门员随机扑救的动画 // 2. 判断足球最终位置是否在球门范围内,计算得分 // 3. 射门结束后延迟重置足球到初始位置 ball.postDelayed({ ball.x = defaultBallX ball.y = defaultBallY }, 1000) } }
三、可选优化点
- 可以用
VelocityTracker计算手指抬起时的滑动速度,动态调整射门的速度和方向,体验更真实 - 增加碰撞检测,判断足球是否和守门员碰撞,判定是否扑救成功
- 给足球移动加旋转动画,模拟真实足球滚动效果
内容的提问来源于stack exchange,提问作者Yama Lomama
相关产品推荐
相关产品推荐

