主页 > IT业界  > 

用AI学安卓游戏开发1——控制小球上下左右移动2

用AI学安卓游戏开发1——控制小球上下左右移动2

业务逻辑:初始化小球随机自有移动,遇到屏幕边缘反弹,摇杆介入后小球停止自有移动,按照摇杆控制方向移动。

download.csdn.net/download/AnalogElectronic/90453667 download.csdn.net/download/AnalogElectronic/90453667

实现效果

核心代码

package com.example.snakegame2 import android.annotation.SuppressLint import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity pose.setContent import androidx pose.foundation.Canvas import androidx pose.foundation.gestures.detectDragGestures import androidx pose.foundation.layout.Arrangement import androidx pose.foundation.layout.Box import androidx pose.foundation.layout.Column import androidx pose.foundation.layout.fillMaxSize import androidx pose.foundation.layout.padding import androidx pose.foundation.layout.size import androidx pose.runtime.Composable import androidx pose.runtime.getValue import androidx pose.runtime.mutableStateOf import androidx pose.runtime.remember import androidx pose.runtime.setValue import androidx pose.ui.Alignment import androidx pose.ui.Modifier import androidx pose.ui.geometry.Offset import androidx pose.ui.geometry.Size import androidx pose.ui.graphics.Color import androidx pose.ui.graphics.drawscope.Stroke import androidx pose.ui.input.pointer.pointerInput import androidx pose.ui.layout.onSizeChanged import androidx pose.ui.unit.dp import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlin.math.cos import kotlin.math.sin import kotlin.random.Random class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { BallControlScreen() } } @SuppressLint("CoroutineCreationDuringComposition") @Composable fun BallControlScreen() { var ballX by remember { mutableStateOf(200f) } var ballY by remember { mutableStateOf(300f) } var dx by remember { mutableStateOf(0f) } var dy by remember { mutableStateOf(0f) } var canvasWidth by remember { mutableStateOf(400f) } var canvasHeight by remember { mutableStateOf(400f) } // 初始化随机方向 val angle = Random.nextFloat() * 360f dx = cos(Math.toRadians(angle.toDouble())).toFloat() dy = sin(Math.toRadians(angle.toDouble())).toFloat() Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, modifier = Modifier .fillMaxSize() ) { // 小球绘制区域 Canvas( modifier = Modifier .size(400.dp) .padding(20.dp) .onSizeChanged { size -> canvasWidth = size.width.toFloat() canvasHeight = size.height.toFloat() }, onDraw = { // 绘制蓝色边界线 drawRect( color = Color.Blue, topLeft = Offset(0f, 0f), size = Size(size.width, size.height), style = Stroke(width = 2f) ) // 绘制小球,背景为白色 drawCircle( color = Color.Red, radius = 20f, center = Offset(ballX, ballY) ) } ) // 虚拟摇杆 Joystick( modifier = Modifier.size(100.dp), onJoystickMoved = { x, y -> // 归一化摇杆输入,确保dx和dy的范围在[-1, 1] dx = x dy = y } ) // 根据摇杆移动更新小球位置 GlobalScope.launch(Dispatchers.Main) { while (true) { // 摇杆控制方向,但不改变速度 ballX += dx * 10 ballY += dy * 10 // 碰撞检测 if (ballX < 20) { ballX = 20f dx = -dx } else if (ballX > canvasWidth - 20) { ballX = canvasWidth - 20 dx = -dx } if (ballY < 20) { ballY = 20f dy = -dy } else if (ballY > canvasHeight - 20) { ballY = canvasHeight - 20 dy = -dy } delay(16) } } } } @Composable fun Joystick( modifier: Modifier = Modifier, onJoystickMoved: (Float, Float) -> Unit = { _, _ -> } ) { var offsetX by remember { mutableStateOf(0f) } var offsetY by remember { mutableStateOf(0f) } Box(modifier = modifier.pointerInput("Joystick") { detectDragGestures( onDragStart = { offsetX = 0f offsetY = 0f onJoystickMoved(0f, 0f) }, onDrag = { change, dragAmount -> val size = size val center = Offset((size.width / 2).toFloat(), (size.height / 2).toFloat()) val position = change.position - center val distance = position.getDistance() val maxDistance = size.width / 2 if (distance > maxDistance) { val normalizedPosition = if (distance > maxDistance) { val ratio = maxDistance / distance Offset(position.x * ratio, position.y * ratio) } else { position } offsetX = normalizedPosition.x / maxDistance offsetY = normalizedPosition.y / maxDistance } else { offsetX = position.x / maxDistance offsetY = position.y / maxDistance } onJoystickMoved(offsetX, offsetY) }, onDragEnd = { offsetX = 0f offsetY = 0f onJoystickMoved(0f, 0f) } ) }) { // 摇杆背景 Canvas(modifier = Modifier.fillMaxSize()) { drawCircle( color = Color.Gray, radius = size.width / 2 ) } // 摇杆帽子 Canvas( modifier = Modifier .size(60.dp) .align(Alignment.Center), onDraw = { drawCircle( color = Color.Blue, radius = size.width / 2, center = Offset( size.width / 2 + (offsetX * (size.width / 2 - 10)), size.height / 2 + (offsetY * (size.height / 2 - 10)) ) ) } ) } } }

当然!以下是对代码的详细解释,包括导入的包和每一行代码的作用:

导入的包 import android.annotation.SuppressLint import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity pose.setContent import androidx pose.foundation.Canvas import androidx pose.foundation.gestures.detectDragGestures import androidx pose.foundation.layout.Arrangement import androidx pose.foundation.layout.Box import androidx pose.foundation.layout.Column import androidx pose.foundation.layout.fillMaxSize import androidx pose.foundation.layout.padding import androidx pose.foundation.layout.size import androidx pose.runtime.Composable import androidx pose.runtime.getValue import androidx pose.runtime.mutableStateOf import androidx pose.runtime.remember import androidx pose.runtime.setValue import androidx pose.ui.Alignment import androidx pose.ui.Modifier import androidx pose.ui.geometry.Offset import androidx pose.ui.geometry.Size import androidx pose.ui.graphics.Color import androidx pose.ui.graphics.drawscope.Stroke import androidx pose.ui.input.pointer.pointerInput import androidx pose.ui.layout.onSizeChanged import androidx pose.ui.unit.dp import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlin.math.cos import kotlin.math.sin import kotlin.random.Random android.annotation.SuppressLint:用于抑制特定的编译器警告。android.os.Bundle:用于传递活动之间的数据。androidx.activity.ComponentActivity:Android 的活动基类,用于创建活动。androidx.activity pose.setContent:用于设置活动的内容为 Jetpack Compose UI。androidx pose.foundation.Canvas:用于绘制自定义图形。androidx pose.foundation.gestures.detectDragGestures:用于检测拖拽手势。androidx pose.foundation.layout.Arrangement:用于布局子组件的排列方式。androidx pose.foundation.layout.Box:用于创建一个容器,可以包含多个子组件。androidx pose.foundation.layout.Column:用于创建垂直排列的布局。androidx pose.foundation.layout.fillMaxSize:用于使组件填充父容器。androidx pose.foundation.layout.padding:用于为组件添加内边距。androidx pose.foundation.layout.size:用于设置组件的大小。androidx pose.runtime.Composable:用于标记一个可组合函数。androidx pose.runtime.getValue:用于从 mutableStateOf 获取值。androidx pose.runtime.mutableStateOf:用于创建一个可变状态。androidx pose.runtime.remember:用于在组合中记住一个值。androidx pose.runtime.setValue:用于设置 mutableStateOf 的值。androidx pose.ui.Alignment:用于对齐组件。androidx pose.ui.Modifier:用于修改组件的属性。androidx pose.ui.geometry.Offset:用于表示一个二维坐标。androidx pose.ui.geometry.Size:用于表示一个大小。androidx pose.ui.graphics.Color:用于表示颜色。androidx pose.ui.graphics.drawscope.Stroke:用于绘制边框。androidx pose.ui.input.pointer.pointerInput:用于处理指针输入。androidx pose.ui.layout.onSizeChanged:用于在组件大小改变时触发回调。androidx pose.ui.unit.dp:用于表示密度无关的像素。kotlinx.coroutines.Dispatchers:用于处理协程的调度。kotlinx.coroutines.GlobalScope:用于创建全局协程。kotlinx.coroutines.Job:用于表示协程的作业。kotlinx.coroutines.delay:用于在协程中延迟执行。kotlinx.coroutines.launch:用于启动协程。kotlin.math.cos:用于计算余弦值。kotlin.math.sin:用于计算正弦值。kotlin.random.Random:用于生成随机数。 主活动类 class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { BallControlScreen() } } } MainActivity:主活动类,继承自 ComponentActivity。onCreate:活动的生命周期方法,用于初始化活动。setContent:设置活动的内容为 Jetpack Compose UI,调用 BallControlScreen 函数。 小球控制屏幕 @SuppressLint("CoroutineCreationDuringComposition") @Composable fun BallControlScreen() { var ballX by remember { mutableStateOf(200f) } var ballY by remember { mutableStateOf(300f) } var dx by remember { mutableStateOf(0f) } var dy by remember { mutableStateOf(0f) } var canvasWidth by remember { mutableStateOf(400f) } var canvasHeight by remember { mutableStateOf(400f) } // 初始化随机方向 val angle = Random.nextFloat() * 360f dx = cos(Math.toRadians(angle.toDouble())).toFloat() dy = sin(Math.toRadians(angle.toDouble())).toFloat() Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, modifier = Modifier .fillMaxSize() ) { // 小球绘制区域 Canvas( modifier = Modifier .size(400.dp) .padding(20.dp) .onSizeChanged { size -> canvasWidth = size.width.toFloat() canvasHeight = size.height.toFloat() }, onDraw = { // 绘制蓝色边界线 drawRect( color = Color.Blue, topLeft = Offset(0f, 0f), size = Size(size.width, size.height), style = Stroke(width = 2f) ) // 绘制小球,背景为白色 drawCircle( color = Color.Red, radius = 20f, center = Offset(ballX, ballY) ) } ) // 虚拟摇杆 Joystick( modifier = Modifier.size(100.dp), onJoystickMoved = { x, y -> // 归一化摇杆输入,确保dx和dy的范围在[-1, 1] dx = x dy = y } ) // 根据摇杆移动更新小球位置 GlobalScope.launch(Dispatchers.Main) { while (true) { // 摇杆控制方向,但不改变速度 ballX += dx * 10 ballY += dy * 10 // 碰撞检测 if (ballX < 20) { ballX = 20f dx = -dx } else if (ballX > canvasWidth - 20) { ballX = canvasWidth - 20 dx = -dx } if (ballY < 20) { ballY = 20f dy = -dy } else if (ballY > canvasHeight - 20) { ballY = canvasHeight - 20 dy = -dy } delay(16) } } } } @SuppressLint("CoroutineCreationDuringComposition"):抑制特定的编译器警告。@Composable:标记一个可组合函数。BallControlScreen:小球控制屏幕的可组合函数。var ballX by remember { mutableStateOf(200f) }:初始化小球的 X 坐标。var ballY by remember { mutableStateOf(300f) }:初始化小球的 Y 坐标。var dx by remember { mutableStateOf(0f) }:初始化小球的水平速度。var dy by remember { mutableStateOf(0f) }:初始化小球的垂直速度。var canvasWidth by remember { mutableStateOf(400f) }:初始化画布的宽度。var canvasHeight by remember { mutableStateOf(400f) }:初始化画布的高度。val angle = Random.nextFloat() * 360f:生成一个随机角度。dx = cos(Math.toRadians(angle.toDouble())).toFloat():将角度转换为水平速度。dy = sin(Math.toRadians(angle.toDouble())).toFloat():将角度转换为垂直速度。Column:创建一个垂直排列的布局。horizontalAlignment = Alignment.CenterHorizontally:水平居中对齐。verticalArrangement = Arrangement.Center:垂直居中排列。modifier = Modifier.fillMaxSize():使组件填充父容器。Canvas:绘制小球和边界线的画布。modifier = Modifier.size(400.dp).padding(20.dp):设置画布的大小和内边距。onSizeChanged:在画布大小改变时更新 canvasWidth 和 canvasHeight。onDraw:绘制蓝色边界线和小球。drawRect:绘制蓝色边界线。drawCircle:绘制小球。Joystick:虚拟摇杆的可组合函数。modifier = Modifier.size(100.dp):设置摇杆的大小。onJoystickMoved:处理摇杆的移动事件。GlobalScope.launch(Dispatchers.Main):启动一个协程,用于更新小球的位置。while (true):无限循环,持续更新小球的位置。ballX += dx * 10:根据摇杆的输入更新小球的 X 坐标。ballY += dy * 10:根据摇杆的输入更新小球的 Y 坐标。if (ballX < 20):检测小球是否碰到左边界。if (ballX > canvasWidth - 20):检测小球是否碰到右边界。if (ballY < 20):检测小球是否碰到上边界。if (ballY > canvasHeight - 20):检测小球是否碰到下边界。delay(16):延迟 16 毫秒,使小球的移动更加平滑。 虚拟摇杆 @Composable fun Joystick( modifier: Modifier = Modifier, onJoystickMoved: (Float, Float) -> Unit = { _, _ -> } ) { var offsetX by remember { mutableStateOf(0f) } var offsetY by remember { mutableStateOf(0f) } Box(modifier = modifier.pointerInput("Joystick") { detectDragGestures( onDragStart = { offsetX = 0f offsetY = 0f onJoystickMoved(0f, 0f) }, onDrag = { change, dragAmount -> val size = size val center = Offset((size.width / 2).toFloat(), (size.height / 2).toFloat()) val position = change.position - center val distance = position.getDistance() val maxDistance = size.width / 2 if (distance > maxDistance) { val normalizedPosition = if (distance > maxDistance) { val ratio = maxDistance / distance Offset(position.x * ratio, position.y * ratio) } else { position } offsetX = normalizedPosition.x / maxDistance offsetY = normalizedPosition.y / maxDistance } else { offsetX = position.x / maxDistance offsetY = position.y / maxDistance } onJoystickMoved(offsetX, offsetY) }, onDragEnd = { offsetX = 0f offsetY = 0f onJoystickMoved(0f, 0f) } ) }) { // 摇杆背景 Canvas(modifier = Modifier.fillMaxSize()) { drawCircle( color = Color.Gray, radius = size.width / 2 ) } // 摇杆帽子 Canvas( modifier = Modifier .size(60.dp) .align(Alignment.Center), onDraw = { drawCircle( color = Color.Blue, radius = size.width / 2, center = Offset( size.width / 2 + (offsetX * (size.width / 2 - 10)), size.height / 2 + (offsetY * (size.height / 2 - 10)) ) ) } ) } } @Composable:标记一个可组合函数。Joystick:虚拟摇杆的可组合函数。modifier: Modifier = Modifier:设置摇杆的修饰符。onJoystickMoved: (Float, Float) -> Unit = { _, _ -> }:处理摇杆的移动事件。var offsetX by remember { mutableStateOf(0f) }:初始化摇杆的水平偏移量。var offsetY by remember { mutableStateOf(0f) }:初始化摇杆的垂直偏移量。Box:创建一个容器,包含摇杆的背景和帽子。modifier = modifier.pointerInput("Joystick"):处理摇杆的指针输入。detectDragGestures:检测拖拽手势。onDragStart:在拖拽开始时重置偏移量。onDrag:在拖拽过程中更新偏移量。onDragEnd:在拖拽结束时重置偏移量。Canvas:绘制摇杆的背景。drawCircle:绘制灰色的摇杆背景。Canvas:绘制摇杆的帽子。drawCircle:绘制蓝色的摇杆帽子。

希望这个详细解释能帮助你更好地理解代码!如果有任何问题或需要进一步优化,请随时告诉我。

标签:

用AI学安卓游戏开发1——控制小球上下左右移动2由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“用AI学安卓游戏开发1——控制小球上下左右移动2