Untitled

mail@pastecode.io avatar
unknown
plain_text
16 days ago
5.9 kB
3
Indexable
Never
@Composable
fun AppNavigation(
    modifier: Modifier = Modifier,
) {
    val viewModel: GameViewModel = hiltViewModel()
    val navController = rememberNavController()
    NavHost(
        navController = navController,
        startDestination = "mainMenu",
        modifier = modifier,
    ) {
        composable(
            route = "mainMenu",
            enterTransition = {EnterTransition.None} ,
            exitTransition = {ExitTransition.None} ,
        ) {
            MainMenu(
                viewModel = viewModel,
                navController = navController,
            )
        }
        composable(
            route = "gameScreen",
            enterTransition = {EnterTransition.None} ,
            exitTransition = {ExitTransition.None} ,
        ) {
            GameScreen(
                viewModel = viewModel,
                navController = navController
            )
        }
        composable(
            route = "gameOverScreen",
            enterTransition = {EnterTransition.None} ,
            exitTransition = {ExitTransition.None} ,
        ) {
            GameOverScreen(
                viewModel = viewModel,
                navController = navController,
            )
        }
    }
}


@Composable
fun GameOverScreen(
    viewModel: GameViewModel,
    navController: NavHostController,
    modifier: Modifier = Modifier,
) {
    val gameState by viewModel.gameState.collectAsStateWithLifecycle()
    val avgReactionTime = rememberSaveable { gameState?.avgReactionTime ?: 0L }

    Scaffold(
        containerColor = Color.Black,
        modifier = modifier
            .fillMaxSize()
    ) { innerPadding ->
        GameOverScreenContent(
            avgReactionTime = avgReactionTime,
            onRestartClicked = {
                viewModel.startNewGame()
                navController.navigate("gameScreen") {
                    popUpTo("gameOverScreen") { inclusive = true }
                }
            },
            modifier = modifier
                .padding(innerPadding)
        )
    }
}

@Composable
fun GameOverScreenContent(
    avgReactionTime: Long,
    onRestartClicked: () -> Unit,
    modifier: Modifier = Modifier,
) {
    Column(
        modifier = modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Text(
            text = "Average Reaction Time: $avgReactionTime ms",
            style = Typography.titleLarge,
            color = Color.White
        )
        UniversalButton(
            text = "Restart",
            onClick = onRestartClicked
        )
    }
}


@Composable
fun GameScreen(
    viewModel: GameViewModel,
    navController: NavHostController,
    modifier: Modifier = Modifier
) {
    val gameState by viewModel.gameState.collectAsState()

    LaunchedEffect(Unit) {
        viewModel.startNewGame()
    }

    if (gameState?.status == GameStatus.GAME_OVER) {
        navController.navigate(route = "gameOverScreen") {
            popUpTo("gameScreen") { inclusive = true }
        }
    } else {
        Scaffold(
            modifier = modifier.fillMaxSize(),
            containerColor = Color.Black
        ) { innerPadding ->
            GameScreenContent(
                gameState = gameState,
                onDotClicked = { index -> viewModel.onDotClicked(index) },
                modifier = modifier.padding(innerPadding)
            )
        }
    }
}



@Composable
fun GameScreenContent(
    gameState: GameState?,
    onDotClicked: (Int) -> Unit,
    modifier: Modifier = Modifier,
) {
    Box(
        modifier = modifier
            .statusBarsPadding()
            .fillMaxSize()
            .background(Color.Black)
    ) {
        gameState?.let { state ->
            Column(
                modifier = modifier.fillMaxSize()
            ) {
                Text(
                    text = "Score: ${state.score}",
                    modifier = Modifier
                        .align(Alignment.End)
                        .padding(end = 16.dp, top = 16.dp),
                    color = Color.White,
                    fontSize = 24.sp
                )

                Box(
                    modifier = modifier
                        .fillMaxSize()
                        .padding(16.dp),
                    contentAlignment = Alignment.Center
                ) {
                    val gridSize = sqrt(state.dots.size.toFloat()).toInt()

                    Column(
                        verticalArrangement = Arrangement.spacedBy(20.dp),
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        for (y in 0 until gridSize) {
                            Row(
                                horizontalArrangement = Arrangement.spacedBy(20.dp),
                                verticalAlignment = Alignment.CenterVertically
                            ) {
                                for (x in 0 until gridSize) {
                                    val index = y * gridSize + x
                                    if (index < state.dots.size) {
                                        val dot = state.dots[index]
                                        Box(
                                            modifier = Modifier
                                                .size(dot.size.dp)
                                                .clip(CircleShape)
                                                .background(dot.color)
                                                .clickable { onDotClicked(index) }
                                        )
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Leave a Comment