我正在尝试为 Android 构建一个基本的贪吃蛇游戏。除了食物更新之外,一切都运转良好。它是随机工作的,有时,当你从食物旁边经过时,它会被认为正在吃它,有时食物只是在上次吃完食物后几秒钟后才出现在屏幕上,有时,只是什么也没发生!
整个项目上传于:https://github.com/tauqirnizami/SnakeGame
视图模型文件:
var foodCoordinates: Pair<Int, Int> = Pair(14, 13)
var score = 0L
var direction = 0
var giantFoodCoordinates: Pair<Int, Int>? = null
var giantFoodCounter: Int = 0
class SnakeViewModel() : ViewModel() {
/*Pair(length/y-coordinate, width/x-coordinate)*/
var coordinates = mutableStateListOf(Pair(16, 17), Pair(17, 17), Pair(18, 17))
private set
private var delayInMillis: Long = 500L
private var gameGoing by mutableStateOf(true)
private fun delayChange() {/*TODO*/
delayInMillis = if (score == 0L) 500 else if (score <= 500) 500 / score else 0
}
init {
viewModelScope.launch(Dispatchers.Default) {
delay(1000L)
while (gameGoing) {
delay(delayInMillis)
delayChange()
coordinatesUpdation()
}
}
}
private suspend fun coordinatesUpdation() {
// Compute the new head position based on the direction
val head = coordinates.first()
val newHead = when (direction) {
0 -> Pair(if (head.first > 1) head.first - 1 else gridLength, head.second) // UP
1 -> Pair(if (head.first < gridLength) head.first + 1 else 1, head.second) // DOWN
2 -> Pair(head.first, if (head.second > 1) head.second - 1 else gridWidth) // LEFT
else -> Pair(head.first, if (head.second < gridWidth) head.second + 1 else 1) // RIGHT
}
// Update the coordinates with the new head and shift the body
coordinates.add(0, newHead)
coordinates.removeLast()
//Eating Food
if (newHead == foodCoordinates) {
foodCoordinates = food(giantFoodCoordinates)
score++
giantFoodCounter++
val tail = coordinates.last()
coordinates.add(tail)
}
if (coordinates.drop(1).any { it == newHead }) {
gameGoing = false
}
if (giantFoodCounter % 8 == 0 && giantFoodCounter!=0) {
giantFoodCoordinates = food(foodCoordinates)
viewModelScope.launch(Dispatchers.Default) {
delay((if (score < 30) 15 else if (score < 100) 10 else if (score < 300) 6 else 4) * 1000L)
giantFoodCoordinates = null
giantFoodCounter = 0
}
}
if (newHead == giantFoodCoordinates) {
giantFoodCounter = 0
score += 5
var tail = coordinates.last()
coordinates.add(tail)
tail = coordinates.last()
coordinates.add(tail)
tail = coordinates.last()
coordinates.add(tail)
tail = coordinates.last()
coordinates.add(tail)
tail = coordinates.last()
coordinates.add(tail)
}
}
private fun food(otherFood: Pair<Int, Int>?): Pair<Int, Int> {
var a: Pair<Int, Int>
do {
a = Pair((1..gridLength).random(), (1..gridWidth).random())
} while (coordinates.any { it == a } || otherFood == a)
return a
}
}
和可组合文件:
val gridWidth: Int = 20
val gridLength: Int = 35
@Composable
fun DisplayGrid(
modifier: Modifier,
snakeViewModel: SnakeViewModel
) {
val colors = generateColorGrid(coordinates = snakeViewModel.coordinates)
ColorGrid(colors, gridWidth, modifier = modifier, cellSize = 18.dp)
}
@Composable
fun Screen(
modifier: Modifier = Modifier,
snakeViewModel: SnakeViewModel = SnakeViewModel()
) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
) {
DisplayGrid(modifier, snakeViewModel = snakeViewModel)
Row(
modifier = Modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
//Buttns and score display
}
}
}
fun generateColorGrid(coordinates: List<Pair<Int, Int>>): List<Color> {
val coloursList: MutableList<Color> = mutableListOf()
for (i in 1..gridLength) {
for (j in 1..gridWidth) {
if (coordinates.any { it == Pair(i, j) }) {
coloursList.add(Color.White)
} else if (Pair(j, i) == foodCoordinates) {
coloursList.add(Color.LightGray)
} else if (Pair(j, i) == giantFoodCoordinates) {
coloursList.add(Color.DarkGray)
} else {
coloursList.add(Color.Yellow)
}
}
}
return coloursList
}
@Composable
fun ColorGrid(colors: List<Color>, width: Int, cellSize: Dp, modifier: Modifier = Modifier) {
LazyVerticalGrid(
columns = GridCells.Fixed(width),
modifier = modifier
) {
items(colors) { color ->
Box(
modifier = Modifier
.size(cellSize) // Sets the size of each cell
.background(color)
)
}
}
}
我知道我的代码看起来很疯狂,但我这样编写只是为了尽可能防止延迟并使其尽可能优化。 bcz 屏幕已经每秒更新多次,我想尽可能多地进行优化。
我认为这可能是由于坐标更新()函数需要太多时间才能正确执行,因此我尝试将坐标更新()函数中的所有 if else 块放入一个单独的函数中,并在单独的协程中运行这个新函数,但这造成了更大的危害,因为现在我们同时读取和更新“坐标”变量!
一切正常,只是将食物显示在错误的位置:
Pair(j, i)
应该是Pair(i, j)
。