Add restart

This commit is contained in:
Christian Basler
2025-03-12 07:52:02 +01:00
parent 370dc2a2a2
commit 63f6fca83f
4 changed files with 101 additions and 27 deletions

View File

@@ -2,6 +2,7 @@ package ch.dissem.yaep.ui.common
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.aspectRatio
@@ -30,7 +31,6 @@ import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType import androidx.compose.ui.unit.TextUnitType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ch.dissem.yaep.domain.Clue import ch.dissem.yaep.domain.Clue
import ch.dissem.yaep.domain.Game
import ch.dissem.yaep.domain.Grid import ch.dissem.yaep.domain.Grid
import ch.dissem.yaep.domain.HorizontalClue import ch.dissem.yaep.domain.HorizontalClue
import ch.dissem.yaep.domain.ItemClass import ch.dissem.yaep.domain.ItemClass
@@ -58,11 +58,13 @@ class DisplayClue<C : Clue>(val clue: C) {
} }
@Composable @Composable
fun App(modifier: Modifier = Modifier, game: Game = remember { generateGame() }) { fun App(modifier: Modifier = Modifier) {
var game by remember { mutableStateOf(generateGame()) }
val horizontalClues = remember(game) { game.horizontalClues.map { DisplayClue(it) } } val horizontalClues = remember(game) { game.horizontalClues.map { DisplayClue(it) } }
val verticalClues = remember(game) { game.verticalClues.map { DisplayClue(it) } } val verticalClues = remember(game) { game.verticalClues.map { DisplayClue(it) } }
val timer = remember(game) { GameTimer() } val timer = remember(game) { GameTimer() }
val time by timer.elapsedTime.collectAsState("00:00") val time by timer.elapsedTime.collectAsState("00:00")
var isSolved by remember(game) { mutableStateOf(false) }
LaunchedEffect(game) { LaunchedEffect(game) {
game.onStart { game.onStart {
timer.start() timer.start()
@@ -70,10 +72,12 @@ fun App(modifier: Modifier = Modifier, game: Game = remember { generateGame() })
game.onSolved { game.onSolved {
timer.stop() timer.stop()
isSolved = true
} }
} }
Row(modifier = modifier) { Box(modifier = modifier) {
Row(modifier = Modifier.blurOnFinished(isSolved)) {
PuzzleGrid( PuzzleGrid(
modifier = Modifier modifier = Modifier
.aspectRatio(1f) .aspectRatio(1f)
@@ -97,6 +101,10 @@ fun App(modifier: Modifier = Modifier, game: Game = remember { generateGame() })
Text(time, fontSize = TextUnit(4f, TextUnitType.Em)) Text(time, fontSize = TextUnit(4f, TextUnitType.Em))
} }
} }
EndOfGame(isSolved = isSolved) {
game = generateGame()
}
}
} }
@Composable @Composable
@@ -114,9 +122,10 @@ fun PuzzleGrid(
) { ) {
val allOptions = row.options val allOptions = row.options
for (item in row) { for (item in row) {
var selection by remember { mutableStateOf(item.selection) } var selection by remember(item) { mutableStateOf(item.selection) }
val options = val options = remember(item) {
remember { allOptions.map { Toggleable(it, item.options.contains(it)) } } allOptions.map { Toggleable(it, item.options.contains(it)) }
}
LaunchedEffect(item) { LaunchedEffect(item) {
item.optionsRemovedListeners.add { removed -> item.optionsRemovedListeners.add { removed ->
options options

View File

@@ -0,0 +1,65 @@
package ch.dissem.yaep.ui.common
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.BlurEffect
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.sp
@Composable
fun EndOfGame(
modifier: Modifier = Modifier,
isSolved: Boolean,
onRestart: () -> Unit
) {
AnimatedVisibility(
visible = isSolved,
modifier = modifier,
enter = fadeIn(),
exit = fadeOut()
) {
val background = MaterialTheme.colorScheme.background
Box(modifier = Modifier
.fillMaxSize()
.drawBehind {
drawRect(color = background.copy(alpha = 0.8f))
}
) {
Column(
modifier = Modifier
.align(Alignment.Center)
) {
Text(
text = "You won",
fontSize = 128.sp,
textAlign = TextAlign.Center,
)
Button(
modifier = Modifier.align(CenterHorizontally),
onClick = onRestart
) {
Text("Restart")
}
}
}
}
}
fun Modifier.blurOnFinished(isSolved: Boolean): Modifier = graphicsLayer {
if (isSolved) {
this.renderEffect = BlurEffect(8f, 8f)
}
}

View File

@@ -1,5 +1,5 @@
[versions] [versions]
agp = "8.8.2" agp = "8.9.0"
jdk = "21" jdk = "21"
android-compileSdk = "35" android-compileSdk = "35"
android-minSdk = "24" android-minSdk = "24"

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME