diff --git a/app/src/main/java/com/android_tetris/AboutUsScreen.kt b/app/src/main/java/com/android_tetris/AboutUsScreen.kt index a30254865f1ca0d18850044d3d4d0695b57c42ee..43a781c77acb69157dbea197a849633c5bbd6b01 100644 --- a/app/src/main/java/com/android_tetris/AboutUsScreen.kt +++ b/app/src/main/java/com/android_tetris/AboutUsScreen.kt @@ -1,263 +1,427 @@ package com.android_tetris +import android_tetris.ui.theme.* +import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.* import androidx.compose.foundation.layout.* -import androidx.compose.material.Button -import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.withStyle -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.android_tetris.ui.theme.* +import androidx.compose.animation.core.* +import androidx.compose.foundation.background +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.selection.DisableSelection +import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.material.* +import androidx.compose.material.icons.filled.* +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontFamily +import com.android_tetris.ui.theme.getBitmap +import com.android_tetris.ui.theme.topBarView_More + +@ExperimentalComposeUiApi +@ExperimentalAnimationApi @Composable fun AboutUsScreen() { - Column( - modifier = Modifier - .fillMaxSize() - .background(color = Color.Black) - ) { - val biggerMargin = 16.dp - val innerMargin = 10.dp - val smallerMargin = 5.dp - - Text( - buildAnnotatedString { - withStyle(style = SpanStyle(color = Rainbow1)) { - append("A") - } - withStyle(style = SpanStyle(color = Rainbow2)) { - append("b") - } - withStyle(style = SpanStyle(color = Rainbow3)) { - append("o") - } - withStyle(style = SpanStyle(color = Rainbow4)) { - append("u") - } - withStyle(style = SpanStyle(color = Rainbow5)) { - append("t") - } - withStyle(style = SpanStyle(color = Rainbow6)) { - append(" u") - } - withStyle(style = SpanStyle(color = Rainbow7)) { - append("s") - } - }, - // text = "bout us", - fontSize = 48.sp, - fontWeight = FontWeight.Bold, - color = Color.White, - modifier = Modifier - .padding(top = 10.dp) - .align(alignment = Alignment.CenterHorizontally) - ) - Text( - text = "* Click the heart! *", - fontSize = 16.sp, - color = Color.White.copy(0.7f), - modifier = Modifier - .align(alignment = Alignment.CenterHorizontally) - ) - // 水墨渲染图片 - Row( + Box(modifier = Modifier + //.fillMaxSize() + .verticalScroll(rememberScrollState()) + .background(color = Color.Black) + ){ + Column( modifier = Modifier - .padding(biggerMargin) - .height(200.dp) - .fillMaxWidth() + .fillMaxSize() + .background(color = Color.Black) ) { - InkColorCanvas() - } + val biggerMargin = 16.dp + val innerMargin = 10.dp + val smallerMargin = 5.dp - /* TODO: 开发心路历程 */ - Box(Modifier.padding( - bottom = biggerMargin, - start = biggerMargin, - end = biggerMargin - )) { - Column() { - Text( - text = "开发者信息:", - fontSize = 28.sp, - fontWeight = FontWeight.Bold, - color = Color.White, - modifier = Modifier - .padding(top = 10.dp) - ) + topBarView_More() // 添加TopBar + Text( + buildAnnotatedString { + withStyle(style = SpanStyle(color = Rainbow1)) { + append("A") + } + withStyle(style = SpanStyle(color = Rainbow2)) { + append("b") + } + withStyle(style = SpanStyle(color = Rainbow3)) { + append("o") + } + withStyle(style = SpanStyle(color = Rainbow4)) { + append("u") + } + withStyle(style = SpanStyle(color = Rainbow5)) { + append("t") + } + withStyle(style = SpanStyle(color = Rainbow6)) { + append(" u") + } + withStyle(style = SpanStyle(color = Rainbow7)) { + append("s") + } + }, + // text = "bout us", + fontSize = 48.sp, + fontWeight = FontWeight.Bold, + color = Color.White, + modifier = Modifier + .padding(top = 10.dp) + .align(alignment = Alignment.CenterHorizontally) + ) + BlinkTag { + Column(modifier = Modifier.align(alignment = Alignment.CenterHorizontally)){ + Row { + Icon( + tint = PastelRainbowYellow, + painter = painterResource(id = R.drawable.ic_star), + contentDescription = null // decorative element + ) + Text( + text = " Click the heart! ", + color = Color.White, + modifier = it + .padding(8.dp) + ) + } + } + } + + // 水墨渲染图片 + Row( + modifier = Modifier + .padding(biggerMargin) + .height(200.dp) + .fillMaxWidth() + ) { + InkColorCanvas() + } + + // Contribute information + Row( + modifier = Modifier + .padding(biggerMargin) + .height(500.dp) + .fillMaxWidth() + ){ + Parallax() + } + + //Launch Rocket + Row{ Text( - text = """小组成员:王雨潇、张煜玮、西鹏飞 - |使用 Kotlin 语言和 Jetpack Compose 框架开发 - | - """.trimMargin(), - fontSize = 16.sp, + text = "Our Faith", color = Color.White, + fontSize = 40.sp, + fontFamily = FontFamily.Cursive, modifier = Modifier - .padding(top = 10.dp) + .alpha(0.8f) + .padding(start = 5.dp) ) - - Text( - text = """compose_version = 1.0.0-beta08 - |kotlin_version = 1.5.10 - |Running in SDK 30, minSdk = 21 - | - """.trimMargin(), - fontSize = 16.sp, - color = Color.White.copy(0.7f), + Spacer(modifier = Modifier.width(150.dp)) + Image( + painter = painterResource(id = R.drawable.moon), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .width(70.dp) + .height(70.dp) ) - - Row( - Modifier.fillMaxWidth() + } + Row( + modifier = Modifier + .padding(biggerMargin) + .height(400.dp) + .fillMaxWidth() + ){ + val animationState = remember{ mutableStateOf(false)} + BoxWithConstraints( + modifier = Modifier + .fillMaxSize() + .background(color = Color.Black) ) { - Text( - text = "留言板:", - fontSize = 28.sp, - fontWeight = FontWeight.Bold, - color = Color.White + Rocket( + isRocketEnabled = animationState.value, + maxWidth = maxWidth, + maxHeight = maxHeight + ) + LaunchButton( + animationState = animationState.value, + onToggleAnimationState = { animationState.value = !animationState.value } ) - - Button( - onClick = { infoStorage.currentScreen = 1 }, - modifier = Modifier.offset(x = 96.dp) - ) { - Text(text = "Back to Settings") - } } } - } - /* TODO: 成员介绍滚动条 */ - Image( - bitmap = getBitmap(resource = R.drawable.film_edge), - contentDescription = "filmEdgeImage", - modifier = Modifier.fillMaxWidth() - ) - Box( - modifier = Modifier - .background(Color.Black) - .horizontalScroll(rememberScrollState()) - .padding(smallerMargin) - ) { - Row { - Box( - modifier = Modifier - //.verticalScroll(rememberScrollState()) - .width(169.dp) - .height(128.dp) - ) { - Column( + //Message Board + Text( + text = "Message Board", + color = Color.White, + fontSize = 40.sp, + fontFamily = FontFamily.Cursive, + modifier = Modifier + .alpha(0.8f) + .padding(start = 5.dp) + ) + Image( + bitmap = getBitmap(resource = R.drawable.film_edge), + contentDescription = "filmEdgeImage", + modifier = Modifier.fillMaxWidth() + ) + Box( + modifier = Modifier + .background(Color.Black) + .horizontalScroll(rememberScrollState()) + .padding(smallerMargin) + ) { + Row { + Box( modifier = Modifier - .border(innerMargin, Color.Black) - .background(brush = gradient) - .padding(biggerMargin) - ) { - Text( - text = "WYX:\n好羡慕隔壁做深度学习的啊……\n\n" + .width(200.dp) + .height(200.dp) + ){ + ImageCard( //调用函数 + painter = painterResource(id = R.drawable.meme_yx), + contentDescription = "WYX", + title = "王雨潇:\n" + + " 好羡慕隔壁做深度学习的啊……" ) } - } - - Box( - modifier = Modifier - //.verticalScroll(rememberScrollState()) - .width(169.dp) - .height(128.dp) - ) { - Column( + Spacer(modifier = Modifier.width(20.dp)) + Box( modifier = Modifier - .border(innerMargin, Color.Black) - .background(brush = gradient) - .padding(biggerMargin) - ) { - Text( - text = "ZYW:\n感谢我两边大佬在开发过程中对我的帮助\n\n" + .width(200.dp) + .height(200.dp) + ){ + ImageCard( //调用函数 + painter = painterResource(id = R.drawable.meme_yw), + contentDescription ="ZYW" , + title = "张煜玮:\n" + + " 感谢我两边大佬在开发过程中对我的帮助~" ) } - } - - Box( - modifier = Modifier - //.verticalScroll(rememberScrollState()) - .width(169.dp) - .height(128.dp) - ) { - Column( + Spacer(modifier = Modifier.width(20.dp)) + Box( modifier = Modifier - .border(innerMargin, Color.Black) - .background(brush = gradient) - .padding(biggerMargin) - ) { - Text( - text = "XPF:\n狂啃kotlin,玩转Compose(实则摸鱼靠队友)的15天\n\n" + .width(200.dp) + .height(200.dp) + ){ + ImageCard( //调用函数 + painter = painterResource(id = R.drawable.meme_pf), + contentDescription = "XPF", + title = "西鹏飞:\n" + + " 狂啃kotlin,玩转Compose(实则摸鱼靠队友)的15天" ) } } + } + Image( + bitmap = getBitmap(resource = R.drawable.film_edge), + contentDescription = "filmEdgeImage", + modifier = Modifier.fillMaxWidth() + ) - // 表情包 - Box( - modifier = Modifier - //.verticalScroll(rememberScrollState()) - .height(128.dp) - ) { - Column( + //contact us + Spacer(modifier = Modifier.height(10.dp)) + Text( + text = "Contact us", + color = Color.White, + fontSize = 40.sp, + fontFamily = FontFamily.Cursive, + modifier = Modifier + .alpha(0.8f) + .padding(start = 5.dp) + ) + Text( + text=" The messages below can be coped! ", + color = Color.White, + fontSize = 12.sp, + fontFamily = FontFamily.Serif, + ) + Box( + modifier = Modifier + .background(Color.Black) + .horizontalScroll(rememberScrollState()) + .padding(smallerMargin) + ){ + Row{ + Card( modifier = Modifier - .fillMaxSize() - .border(innerMargin, Color.Black) - .background(brush = gradient) - .padding(biggerMargin) - ) { - Image( - bitmap = getBitmap(resource = R.drawable.meme_1), - contentDescription = "meme_1" - ) - } - } + .width(300.dp) + .height(220.dp) + .border( + width = 5.dp, + color = Rainbow7, + shape = RoundedCornerShape(15.dp) + ), + shape = RoundedCornerShape(15.dp), + elevation = 5.dp + ){ + Box(modifier = Modifier + .background(Color.White) + .fillMaxSize()){ + Column(modifier = Modifier.padding(10.dp)){ + Row { + Icon( + tint = Rainbow7, + painter = painterResource(id = R.drawable.ic_fork), + contentDescription = null // decorative element + ) + Spacer(modifier = Modifier.width(20.dp)) + Text( + text = "Fork", + color = Rainbow7, + fontWeight=FontWeight.Bold, + fontSize=20.sp + ) + } + SelectionContainer { + Column { + DisableSelection { // 不可以选择的部分 + Text("ProjectAddress_1:",color = Color.Black,fontSize=15.sp) + } + Text("https://gitee.com/yxwang2023/android_tetris\n",color = Color.Black,fontSize=15.sp) + DisableSelection { // 不可以选择的部分 + Text("ProjectAddress_2:",color = Color.Black,fontSize=15.sp) + } + Text("https://github.com/zyw-stu/Andriod_Tetris\n",color = Color.Black,fontSize=15.sp) + } + } + }//Column + }//Box - // 表情包 - Box( - modifier = Modifier - //.verticalScroll(rememberScrollState()) - .height(128.dp) - ) { - Column( + } // Fork card + Spacer(modifier = Modifier.width(20.dp)) + Card( modifier = Modifier - .fillMaxSize() - .border(innerMargin, Color.Black) - .background(brush = gradient) - .padding(biggerMargin) - ) { - Image( - bitmap = getBitmap(resource = R.drawable.meme_2), - contentDescription = "meme_2" - ) - } - } + .width(300.dp) + .height(220.dp) + .border( + width = 5.dp, + color = Rainbow6, + shape = RoundedCornerShape(15.dp) + ), + shape = RoundedCornerShape(15.dp), + elevation = 5.dp + ){ + Box(modifier = Modifier + .background(Color.White) + .fillMaxSize()){ + Column(modifier = Modifier.padding(10.dp)){ + Row { + Icon( + tint = Rainbow6, + painter = painterResource(id = R.drawable.ic_mail), + contentDescription = null // decorative element + ) + Spacer(modifier = Modifier.width(20.dp)) + Text( + text = "Email", + color = Rainbow6, + fontWeight=FontWeight.Bold, + fontSize=20.sp + ) + } + SelectionContainer { + Column { + DisableSelection { // 不可以选择的部分 + Text("王雨潇",fontSize=15.sp) + } + Text("19281171@bjtu.edu.cn\n",fontSize=15.sp) + DisableSelection { // 不可以选择的部分 + Text("张煜玮",fontSize=15.sp) + } + Text("19291255@bjtu.edu.cn\n",fontSize=15.sp) + DisableSelection { // 不可以选择的部分 + Text("西鹏飞",fontSize=15.sp) + } + Text("19281142@bjtu.edu.cn\n",fontSize=15.sp) + } + } + }//Column + }//Box + + } // Fork card + Spacer(modifier = Modifier.width(20.dp)) + Card( + modifier = Modifier + .width(300.dp) + .height(220.dp) + .border( + width = 5.dp, + color = Rainbow5, + shape = RoundedCornerShape(15.dp) + ), + shape = RoundedCornerShape(15.dp), + elevation = 5.dp + ){ + Box(modifier = Modifier + .background(Color.White) + .fillMaxSize()){ + Column(modifier = Modifier.padding(10.dp)){ + Row { + Icon( + tint = Rainbow5, + painter = painterResource(id = R.drawable.ic___mayun), + contentDescription = null // decorative element + ) + Spacer(modifier = Modifier.width(20.dp)) + Text( + text = "Gitee", + color = Rainbow5, + fontWeight=FontWeight.Bold, + fontSize=20.sp + ) + } + SelectionContainer { + Column { + Column { + DisableSelection { // 不可以选择的部分 + Text("王雨潇",fontSize=15.sp) + } + Text("https://gitee.com/yxwang2023\n",fontSize=15.sp) + DisableSelection { // 不可以选择的部分 + Text("张煜玮",fontSize=15.sp) + } + Text("https://gitee.com/bigfishhhh\n",fontSize=15.sp) + DisableSelection { // 不可以选择的部分 + Text("西鹏飞",fontSize=15.sp) + } + Text("https://gitee.com/pengfei_xi\n",fontSize=15.sp) + } + } + }//Column + }//Box + + } // Fork card + }// Fork card } + + } - Image( - bitmap = getBitmap(resource = R.drawable.film_edge), - contentDescription = "filmEdgeImage", - modifier = Modifier.fillMaxWidth() - ) } -} +}} + + + -@Preview -@Composable -fun PreviewAboutUs() { - ComposeTetrisTheme(ComposeTetrisTheme.Theme.Light) { - AboutUsScreen() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/android_tetris/MainActivity.kt b/app/src/main/java/com/android_tetris/MainActivity.kt index 53b7e1657f366c02cebf30a9a9291d4acc174463..8d96eea544bdb8e90b9a4e2d003d8410269fc2f9 100644 --- a/app/src/main/java/com/android_tetris/MainActivity.kt +++ b/app/src/main/java/com/android_tetris/MainActivity.kt @@ -5,10 +5,13 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.annotation.RequiresApi +import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.runtime.InternalComposeApi import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.lifecycle.ViewModel import androidx.lifecycle.viewmodel.compose.viewModel import com.android_tetris.ui.theme.ComposeTetrisTheme @@ -30,11 +33,13 @@ class ThemeViewModel : ViewModel() { @RequiresApi(Build.VERSION_CODES.R) var infoStorage = ScreenToScreenInfo() +@ExperimentalComposeUiApi +@ExperimentalAnimationApi class MainActivity : ComponentActivity() { + @OptIn(InternalComposeApi::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - var viewModel : ThemeViewModel = viewModel() if(isSystemInDarkTheme()) viewModel.Theme = ComposeTetrisTheme.Theme.Dark diff --git a/app/src/main/java/com/android_tetris/TetrisGameScreen.kt b/app/src/main/java/com/android_tetris/TetrisGameScreen.kt index a742540674653fb1e69f4963c0e50c7e227fb705..b457c117431e3e5f4742839c46905cb3e17c7811 100644 --- a/app/src/main/java/com/android_tetris/TetrisGameScreen.kt +++ b/app/src/main/java/com/android_tetris/TetrisGameScreen.kt @@ -64,9 +64,6 @@ fun TetrisGameScreen() { }, onSound = { tetrisViewModel.dispatch(Action.Sound) - }, - onSettings = { - tetrisViewModel.dispatch(Action.Settings) } ) ) diff --git a/app/src/main/java/com/android_tetris/TetrisSettingScreen.kt b/app/src/main/java/com/android_tetris/TetrisSettingScreen.kt index bfe0cb67eecee9aafd865fc4dbacc32daaa84a37..6518946f0f747834fb7a8f6fccf3c4505d2dd96b 100644 --- a/app/src/main/java/com/android_tetris/TetrisSettingScreen.kt +++ b/app/src/main/java/com/android_tetris/TetrisSettingScreen.kt @@ -1,300 +1,460 @@ package com.android_tetris +import android_tetris.ui.theme.AnimateSun +import android_tetris.ui.theme.DropDownAnimate +import android_tetris.ui.theme.PlanetMoon +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.spring +import androidx.compose.foundation.* +import androidx.compose.foundation.gestures.awaitFirstDown import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.constraintlayout.compose.ConstraintLayout import androidx.compose.ui.unit.* import androidx.lifecycle.viewmodel.compose.viewModel import com.android_tetris.ui.theme.* -import com.android_tetris.ui.theme.RadioSelectionButton -import com.android_tetris.ui.theme.RectangularButton +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch + +@ExperimentalAnimationApi +@InternalComposeApi @Composable fun SettingsScreen() { - Column( + Box( modifier = Modifier .fillMaxSize() - .background(color = MaterialTheme.colors.background) - .padding(24.dp) - ) { - val biggerMargin = 16.dp - val smallerMargin = 5.dp - - Row() { - Text( - text = "Game Settings", - fontSize = 36.sp, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colors.surface, - modifier = Modifier.padding(top = smallerMargin, bottom = smallerMargin) + .verticalScroll(rememberScrollState()) + ){ + val animatedOffset = remember { Animatable(0f) } + val animatedScales = remember { Animatable(1f) } + val animatedRound = remember { Animatable(30f) } + val animatedCheckBox = remember { Animatable(0f) } + val animatedBitmap = remember { Animatable(0f) } + val animatedText = remember { Animatable(1f) } + val animatedColor = remember { + androidx.compose.animation.Animatable( + Color( + 206, + 199, + 250, + 121 + ) ) - Spacer(modifier = Modifier.width(30.dp)) - if(MaterialTheme.colors.surface == LightGrey) { - Column() { - Spacer(modifier = Modifier.height(smallerMargin)) - PlanetMoon() - } - } - else AnimateSun(Modifier.size(50.dp)) // 显示动画小太阳 } - - ConstraintLayout( + val mutableState: MutableState = remember { mutableStateOf(true) } + Box( modifier = Modifier - .wrapContentWidth(align = Alignment.CenterHorizontally) + //.fillMaxWidth() + .background(color = MaterialTheme.colors.background) ) { - val (difficultySwitch, - themeSwitch, - switchBGM) = createRefs() - - Row(modifier = Modifier.constrainAs(difficultySwitch) { - start.linkTo(parent.start) - top.linkTo(parent.top) - }) { - Text( - text = "Switch difficulty", - style = MaterialTheme.typography.body1.merge(), - color = MaterialTheme.colors.surface, - modifier = Modifier.padding(smallerMargin) - ) + Box { - // Switch difficulty 难度选择框 - val difficultyOptions = listOf("Easy", "Normal", "Hard") - val difficultyDownSpeed = listOf(700L, 500L, 300L) - var select = 1 + Column( + verticalArrangement = Arrangement.Center, + modifier = Modifier.pointerInput(Unit) { + coroutineScope { + while (true) { + val offset = awaitPointerEventScope { + awaitFirstDown().position + } + // Launch a new coroutine for animation so the touch detection thread is not + // blocked. + launch { + if (mutableState.value) { + animatedScales.animateTo( + 1.3f, + animationSpec = spring(stiffness = Spring.StiffnessLow) + ) + animatedText.animateTo( + 1f, + animationSpec = spring(stiffness = Spring.StiffnessLow) + ) + animatedRound.animateTo( + 10f, + animationSpec = spring(stiffness = Spring.StiffnessLow) + ) + animatedBitmap.animateTo( + 10f, + animationSpec = spring(stiffness = Spring.StiffnessLow) + ) + animatedCheckBox.animateTo( + 10f, + animationSpec = spring(stiffness = Spring.StiffnessLow) + ) + animatedColor.animateTo(Color(206, 170, 209, 121)) + } else { + animatedScales.animateTo( + 1f, + animationSpec = spring(stiffness = Spring.StiffnessLow) + ) + animatedText.animateTo( + -2f, + animationSpec = spring(stiffness = Spring.StiffnessLow) + ) + animatedRound.animateTo( + 30f, + animationSpec = spring(stiffness = Spring.StiffnessLow) + ) + animatedBitmap.animateTo( + 0f, + animationSpec = spring(stiffness = Spring.StiffnessLow) + ) + animatedCheckBox.animateTo( + 0f, + animationSpec = spring(stiffness = Spring.StiffnessLow) + ) + animatedColor.animateTo(Color(206, 199, 250, 121)) + } - when(infoStorage.difficulty) { - difficultyDownSpeed[0] -> select = 0 - difficultyDownSpeed[1] -> select = 1 - difficultyDownSpeed[2] -> select = 2 - } + mutableState.value = !mutableState.value + animatedOffset.animateTo( + offset.x, + animationSpec = spring(stiffness = Spring.StiffnessLow) + ) - Column( - modifier = Modifier.fillMaxWidth() - ) { - RadioSelectionButton( - label = "Easy", - modifier = Modifier, - isSelected = ("Easy" == difficultyOptions[select]), - onPress = { - select = 0 - infoStorage.difficulty = difficultyDownSpeed[select] - }, - isDarkTheme = (MaterialTheme.colors.primary == PlayButtonColorNight2) - ) - RadioSelectionButton( - label = "Normal", - modifier = Modifier, - isSelected = ("Normal" == difficultyOptions[select]), - onPress = { - select = 1 - infoStorage.difficulty = difficultyDownSpeed[select] - }, - isDarkTheme = (MaterialTheme.colors.primary == PlayButtonColorNight2) - ) - RadioSelectionButton( - label = "Hard", - modifier = Modifier, - isSelected = ("Hard" == difficultyOptions[select]), - onPress = { - select = 2 - infoStorage.difficulty = difficultyDownSpeed[select] - }, - isDarkTheme = (MaterialTheme.colors.primary == PlayButtonColorNight2) - ) - } - } // end of Row(modifier = Modifier.constrainAs(difficultySwitch) - - Row(modifier = Modifier.constrainAs(themeSwitch) { - start.linkTo(parent.start) - top.linkTo(difficultySwitch.bottom, margin = biggerMargin) - }) { - var viewModel : ThemeViewModel = viewModel() - - Text( - text = "Switch theme", - style = MaterialTheme.typography.body1.merge(), - color = MaterialTheme.colors.surface, - modifier = Modifier.padding(smallerMargin) - ) + } - Column(modifier = Modifier.fillMaxWidth()) { - RectangularButton( - label = "Daytime mode", - modifier = Modifier - .padding( - horizontal = biggerMargin, - vertical = smallerMargin - )) { - viewModel.Theme = ComposeTetrisTheme.Theme.Light + } + } + }) { + Box(contentAlignment = Alignment.Center) { + LoginPageTopBlurImage(animatedBitmap, animatedOffset, animatedScales) + LoginPageTopRotaAndScaleImage(animatedColor, animatedScales, animatedOffset) } + Column( + modifier = Modifier + .fillMaxSize() + .background(color = MaterialTheme.colors.background) + .padding(24.dp) + ) { + val biggerMargin = 16.dp + val smallerMargin = 5.dp - RectangularButton( - label = "Night mode", - modifier = Modifier.padding( - horizontal = biggerMargin, - vertical = smallerMargin - )) { - viewModel.Theme = ComposeTetrisTheme.Theme.Dark - } - } - } // end of Row(modifier = Modifier.constrainAs(themeSwitch) - - Row(modifier = Modifier - .fillMaxWidth() - .constrainAs(switchBGM) { - start.linkTo(parent.start) - top.linkTo(themeSwitch.bottom, margin = biggerMargin) - }) { - Text( - text = "Choose the BGM", - style = MaterialTheme.typography.body1.merge(), - color = MaterialTheme.colors.surface, - modifier = Modifier.padding(smallerMargin) - ) - RectangularButton( - label = "Next Music", - modifier = Modifier - .padding(horizontal = biggerMargin), - ) { - /* TODO: 等这里有音乐再说 */ - } - } // end of Row(modifier = Modifier.constrainAs(switchBGM) - } + //"Setting" + Row() { + Text( + text = "Game Settings", + fontSize = 36.sp, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colors.surface, + modifier = Modifier.padding(top = smallerMargin, bottom = smallerMargin) + ) + Spacer(modifier = Modifier.width(30.dp)) + if(MaterialTheme.colors.surface == LightGrey) { + Column() { + Spacer(modifier = Modifier.height(smallerMargin)) + PlanetMoon() + } + } + else AnimateSun(Modifier.size(50.dp)) // 显示动画小太阳 + } - Text( - text = "Player Profile", - fontSize = 36.sp, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colors.surface, - modifier = Modifier.padding( - top = biggerMargin, - bottom = smallerMargin - ) - ) + ConstraintLayout( + modifier = Modifier + .wrapContentWidth(align = Alignment.CenterHorizontally) + ) { + val (difficultySwitch, + themeSwitch, + switchBGM) = createRefs() - ConstraintLayout( - modifier = Modifier - .wrapContentWidth(align = Alignment.CenterHorizontally) - ) { - val (playerName, - historyScore, - rules, - backButton) = createRefs() - - Row(modifier = Modifier.constrainAs(playerName) { - start.linkTo(parent.start) - top.linkTo(parent.top) - }) { - Text( - text = "Player name", - style = MaterialTheme.typography.body1.merge(), - color = MaterialTheme.colors.surface, - modifier = Modifier.padding(smallerMargin) - ) - TextField( - value = infoStorage.playerName, - onValueChange = { - infoStorage.playerName = it - }, - label = { - Text("What's your name? ", - color = MaterialTheme.colors.surface) - }, - maxLines = 1, - modifier = Modifier - .fillMaxWidth() - ) - } + Row(modifier = Modifier.constrainAs(difficultySwitch) { + start.linkTo(parent.start) + top.linkTo(parent.top) + }) { + Column{ + Spacer(modifier = Modifier.height(5.dp)) + Icon( + tint = PastelRainbowGreen, + painter = painterResource(id = R.drawable.ic___difficulty), + contentDescription = null // decorative element + ) + } + // Switch difficulty 难度选择框 + Text( + text = "Switch difficulty", + style = MaterialTheme.typography.body1.merge(), + color = MaterialTheme.colors.surface, + modifier = Modifier.padding(smallerMargin) + ) - Row(modifier = Modifier.constrainAs(historyScore) { - start.linkTo(playerName.start) - top.linkTo(playerName.bottom, margin = biggerMargin) - }) { - /* TODO: 尝试从储存中捕获最高分 */ - val highest = infoStorage.highestScore - - Text( - text = "Highest score", - style = MaterialTheme.typography.body1.merge(), - color = MaterialTheme.colors.surface, - modifier = Modifier.padding(smallerMargin) - ) + val difficultyOptions = listOf("Easy", "Normal", "Hard") + val difficultyDownSpeed = listOf(700L, 500L, 300L) + var select = 1 - Text( - text = "$highest", - fontSize = 24.sp, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colors.surface, - modifier = Modifier.padding(horizontal = biggerMargin) - ) - } + when(infoStorage.difficulty) { + difficultyDownSpeed[0] -> select = 0 + difficultyDownSpeed[1] -> select = 1 + difficultyDownSpeed[2] -> select = 2 + } - Row(modifier = Modifier - .constrainAs(rules) { - start.linkTo(historyScore.start) - top.linkTo(historyScore.bottom, margin = biggerMargin) - }) { - Column( - modifier = Modifier.fillMaxHeight() - ) { - Text( - text = "How to play", - style = MaterialTheme.typography.body1.merge(), - color = MaterialTheme.colors.surface, - modifier = Modifier.padding(smallerMargin) - ) - } + Column( + modifier = Modifier.fillMaxWidth() + ) { + RadioSelectionButton( + label = "Easy", + modifier = Modifier, + isSelected = ("Easy" == difficultyOptions[select]), + onPress = { + select = 0 + infoStorage.difficulty = difficultyDownSpeed[select] + }, + isDarkTheme = (MaterialTheme.colors.primary == PlayButtonColorNight2) + ) + RadioSelectionButton( + label = "Normal", + modifier = Modifier, + isSelected = ("Normal" == difficultyOptions[select]), + onPress = { + select = 1 + infoStorage.difficulty = difficultyDownSpeed[select] + }, + isDarkTheme = (MaterialTheme.colors.primary == PlayButtonColorNight2) + ) + RadioSelectionButton( + label = "Hard", + modifier = Modifier, + isSelected = ("Hard" == difficultyOptions[select]), + onPress = { + select = 2 + infoStorage.difficulty = difficultyDownSpeed[select] + }, + isDarkTheme = (MaterialTheme.colors.primary == PlayButtonColorNight2) + ) + } + } // end of Row(modifier = Modifier.constrainAs(difficultySwitch) - DropDownAnimate( - text = " * Click to expand * ", - modifier = Modifier.padding(smallerMargin) - ) { - Text( - text = "Press \"Rotate\" to rotate the block\n" + - "Press \"◀\" and \"▶\" to move the block horizontally\n" + - "Press \"▼\" to speed up the block fall\n" + - "Press \"✔\" directly to drop the current block\n", - fontSize = 14.sp, - color = MaterialTheme.colors.surface, - modifier = Modifier - .padding(smallerMargin) - .fillMaxSize() - ) - } - } - Row(modifier = Modifier - .fillMaxSize() - .constrainAs(backButton) { - start.linkTo(rules.start) - top.linkTo(rules.bottom) - bottom.linkTo(parent.bottom, margin = smallerMargin) - }) { - RectangularButton( - label = "Back", - modifier = Modifier.padding( - top = 4 * biggerMargin, - bottom = 0.dp, - start = 0.dp - )) { - infoStorage.currentScreen = 0 - } - Spacer(modifier = Modifier.width(biggerMargin)) - RectangularButton( - label = "About us", - modifier = Modifier.padding( - top = 4 * biggerMargin, - bottom = 0.dp, - start = 0.dp - )) { - infoStorage.currentScreen = 2 + + //主题选择 + Row(modifier = Modifier.constrainAs(themeSwitch) { + start.linkTo(parent.start) + top.linkTo(difficultySwitch.bottom, margin = biggerMargin) + }) { + Column{ + Spacer(modifier = Modifier.height(5.dp)) + Icon( + tint = PastelRainbowYellow, + painter = painterResource(id = R.drawable.ic____theme), + contentDescription = null // decorative element + ) + } + var viewModel : ThemeViewModel = viewModel() + Text( + text = "Switch theme", + style = MaterialTheme.typography.body1.merge(), + color = MaterialTheme.colors.surface, + modifier = Modifier.padding(smallerMargin) + ) + + Column(modifier = Modifier.fillMaxWidth()) { + RectangularButton( + label = "Daytime mode", + modifier = Modifier + .padding( + horizontal = biggerMargin, + vertical = smallerMargin + )) { + viewModel.Theme = ComposeTetrisTheme.Theme.Light + } + + RectangularButton( + label = "Night mode", + modifier = Modifier.padding( + horizontal = biggerMargin, + vertical = smallerMargin + )) { + viewModel.Theme = ComposeTetrisTheme.Theme.Dark + } + } + } // end of Row(modifier = Modifier.constrainAs(themeSwitch) + + + + //音乐选择 + Row(modifier = Modifier + .fillMaxWidth() + .constrainAs(switchBGM) { + start.linkTo(parent.start) + top.linkTo(themeSwitch.bottom, margin = biggerMargin) + }) { + Column{ + Spacer(modifier = Modifier.height(5.dp)) + Icon( + tint = Rainbow5, + painter = painterResource(id = R.drawable.ic___music), + contentDescription = null // decorative element + ) + } + Text( + text = "Choose the BGM", + style = MaterialTheme.typography.body1.merge(), + color = MaterialTheme.colors.surface, + modifier = Modifier.padding(smallerMargin) + ) + RectangularButton( + label = "Next Music", + modifier = Modifier + .padding(horizontal = biggerMargin), + ) { + /* TODO: 等这里有音乐再说 */ + } + } // end of Row(modifier = Modifier.constrainAs(switchBGM) + + } + + + //个人主页 + Text( + text = "Player Profile", + fontSize = 36.sp, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colors.surface, + modifier = Modifier.padding( + top = biggerMargin, + bottom = smallerMargin + ) + ) + + ConstraintLayout( + modifier = Modifier + .wrapContentWidth(align = Alignment.CenterHorizontally) + ) { + val (playerName, + historyScore, + rules, + backButton) = createRefs() + + //Player Name + Row(modifier = Modifier.constrainAs(playerName) { + start.linkTo(parent.start) + top.linkTo(parent.top) + }) { + Column{ + Spacer(modifier = Modifier.height(5.dp)) + Icon( + tint = Rainbow3, + painter = painterResource(id = R.drawable.ic_____name), + contentDescription = null // decorative element + ) + } + + Text( + text = "Player name", + style = MaterialTheme.typography.body1.merge(), + color = MaterialTheme.colors.surface, + modifier = Modifier.padding(smallerMargin) + ) + var text by rememberSaveable { mutableStateOf("") } + + TextField( + //value = infoStorage.playerName, + value=text, + onValueChange = { + //infoStorage.playerName = it + text=it + }, + label = { + Text("\uD83C\uDF08 What's your name? ", + color = MaterialTheme.colors.surface) + }, + maxLines = 1, + modifier = Modifier + .fillMaxWidth() + ) + } + + + + // Highest Score + Row(modifier = Modifier.constrainAs(historyScore) { + start.linkTo(playerName.start) + top.linkTo(playerName.bottom, margin = biggerMargin) + }) { + Column{ + Spacer(modifier = Modifier.height(5.dp)) + Icon( + tint = PastelRainbowRed, + painter = painterResource(id = R.drawable.ic_____score), + contentDescription = null // decorative element + ) + } + /* TODO: 尝试从储存中捕获最高分 */ + val highest = infoStorage.highestScore + Text( + text = "Highest score", + style = MaterialTheme.typography.body1.merge(), + color = MaterialTheme.colors.surface, + modifier = Modifier.padding(smallerMargin) + ) + + Text( + text = "$highest", + fontSize = 24.sp, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colors.surface, + modifier = Modifier.padding(horizontal = biggerMargin) + ) + } + + + Row(modifier = Modifier + .constrainAs(rules) { + start.linkTo(historyScore.start) + top.linkTo(historyScore.bottom, margin = biggerMargin) + }) { + + Column{ + Spacer(modifier = Modifier.height(5.dp)) + Icon( + tint = PastelRainbowOrange, + painter = painterResource(id = R.drawable.ic_____zhinan), + contentDescription = null // decorative element + ) + } + Text( + text = "Help", + style = MaterialTheme.typography.body1.merge(), + color = MaterialTheme.colors.surface, + modifier = Modifier.padding(smallerMargin) + ) + + + DropDownAnimate( + text = " * Click to expand *", + modifier = Modifier.padding(smallerMargin) + ) { + Text( + text = "Press \"Rotate\" to rotate the block\n" + + "Press \"◀\" and \"▶\" to move the block horizontally\n" + + "Press \"▼\" to speed up the block fall\n" + + "Press \"✔\" directly to drop the current block\n", + fontSize = 14.sp, + color = MaterialTheme.colors.surface, + modifier = Modifier + .padding(smallerMargin) + .fillMaxSize() + ) + } + } + + + } + } } } } } } + diff --git a/app/src/main/java/com/android_tetris/ui/TetrisBody.kt b/app/src/main/java/com/android_tetris/ui/TetrisBody.kt index cc744655859cdb8f549e7c98d0f7a7685e4b2ca0..45ce18370873543ab95b2997a48f06b74fe5d98e 100644 --- a/app/src/main/java/com/android_tetris/ui/TetrisBody.kt +++ b/app/src/main/java/com/android_tetris/ui/TetrisBody.kt @@ -1,20 +1,32 @@ package com.android_tetris.ui -import androidx.compose.foundation.Canvas + +import android.widget.Toast +import androidx.compose.animation.animateColor +import androidx.compose.animation.core.* import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* -import androidx.compose.material.MaterialTheme -import androidx.compose.runtime.Composable +import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.android_tetris.infoStorage +import com.android_tetris.ui.theme.BodyBackground import com.android_tetris.ui.theme.ComposeTetrisTheme +import com.android_tetris.ui.theme.Rainbow7 + @Preview(widthDp = 360, heightDp = 700) @Composable @@ -31,46 +43,148 @@ fun PreviewTetrisBody() { } } + @Composable fun TetrisBody( tetrisScreen: @Composable (() -> Unit), tetrisButton: @Composable (() -> Unit), ) { + var sizeState by remember { + mutableStateOf(400.dp) + } + val size by animateDpAsState( + targetValue = sizeState, + tween( //增大的较为平缓 + durationMillis = 3000, + delayMillis = 300, + easing = LinearOutSlowInEasing + ) + ) + //改变颜色状态 + val infiniteTransition= rememberInfiniteTransition() + val color by infiniteTransition.animateColor( + initialValue = BodyBackground, + targetValue = Rainbow7, + animationSpec = infiniteRepeatable( + tween(durationMillis = 2000), + repeatMode = RepeatMode.Reverse + ) + ) + Column( modifier = Modifier .fillMaxSize() + //.background(color = BodyBackground) .background(color = MaterialTheme.colors.background) .padding(bottom = 30.dp) ) { - Box( - Modifier - .align(alignment = Alignment.CenterHorizontally) + + //顶部导航 + TopAppBar( + modifier = Modifier .fillMaxWidth() - .weight(weight = 1f) - .padding(start = 40.dp, top = 50.dp, end = 40.dp, bottom = 10.dp), + .height(48.dp), + backgroundColor = MaterialTheme.colors.primarySurface, + elevation = 4.dp, + contentPadding = AppBarDefaults.ContentPadding ) { + Row(modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically) { - //绘制边框 - val borderPadding = 8.dp - Canvas(modifier = Modifier.fillMaxSize()) { - drawScreenBorder( - leftTop = Offset(x = 0f, y = 0f), - width = size.width, - height = size.height, - borderPadding = borderPadding, + // 转到setting界面 + Icon( + imageVector = Icons.Filled.Settings, + contentDescription = "menu按钮", + tint = Color.White, + modifier = Modifier + .clickable { + //点击了按钮 + infoStorage.currentScreen = 1 + //Toast.makeText(context, "Clicked on Icon Button", Toast.LENGTH_SHORT).show() + } + .padding(start = 12.dp, end = 12.dp) + .fillMaxHeight() ) - } + Text(text = "Setting",fontSize = 17.sp,color = Color.White) + + //转到About us 界面 + Icon( + imageVector = Icons.Filled.Person, + contentDescription = "menu按钮", + tint = Color.White, + modifier = Modifier + .clickable { + //点击了按钮 + infoStorage.currentScreen = 2 + //Toast.makeText(context, "Clicked on Icon Button", Toast.LENGTH_SHORT).show() + } + .padding(start = 12.dp, end = 12.dp) + .fillMaxHeight() + ) + Text(text = "More",fontSize = 17.sp,color = Color.White) + - //游戏屏幕 - Row( + // 增大屏幕 + val context = LocalContext.current + Icon( + imageVector = Icons.Filled.KeyboardArrowUp, + contentDescription = "menu按钮", + tint = Color.White, + modifier = Modifier + .clickable { + //点击了按钮 + + if(sizeState<460.dp){ + sizeState += 15.dp + } + else{ + Toast.makeText(context, "The screen is maximized!", Toast.LENGTH_SHORT).show() + } + + } + .padding(start = 12.dp, end = 12.dp) + .fillMaxHeight() + ) + Text(text = "Big",fontSize = 17.sp,color = Color.White) + + //减小屏幕 + Icon( + imageVector = Icons.Filled.KeyboardArrowDown, + contentDescription = "menu按钮", + tint = Color.White, + modifier = Modifier + .clickable { + //点击了按钮 + if(sizeState>370.dp){ + sizeState -= 15.dp + } + else{ + Toast.makeText(context, "The screen is minimized!", Toast.LENGTH_SHORT).show() + } + + } + .padding(start = 12.dp, end = 12.dp) + .fillMaxHeight() + ) + Text(text = "Small",fontSize = 17.sp,color = Color.White) + + } + } + Box( + modifier = Modifier + .size(size) + .background(color), + contentAlignment = Alignment.Center + ) { + Column( modifier = Modifier .matchParentSize() - .padding(all = borderPadding) + .padding(10.dp) ) { + //游戏屏幕 tetrisScreen() } } - //控制按钮 tetrisButton() } diff --git a/app/src/main/java/com/android_tetris/ui/TetrisButton.kt b/app/src/main/java/com/android_tetris/ui/TetrisButton.kt index 9976cc539ba297e1e6276a161ae7fc4ed0f7aa55..cb8533af7c5cd4d33ba4d98e697326cd10e0aa46 100644 --- a/app/src/main/java/com/android_tetris/ui/TetrisButton.kt +++ b/app/src/main/java/com/android_tetris/ui/TetrisButton.kt @@ -55,12 +55,6 @@ fun TetrisButton( ) { playListener.onSound() } - ControlButton( - label = "Settings", - modifier = Modifier.padding(start = controlPadding) - ) { - playListener.onSettings() - } } ConstraintLayout( modifier = Modifier diff --git a/app/src/main/java/com/android_tetris/ui/theme/Animation.kt b/app/src/main/java/com/android_tetris/ui/theme/Animation.kt index 1a46ffd281da8d20278c01122a6cc1da3f0eca4c..798800d6a4b467f8010348a0b9d9c2b178181eb8 100644 --- a/app/src/main/java/com/android_tetris/ui/theme/Animation.kt +++ b/app/src/main/java/com/android_tetris/ui/theme/Animation.kt @@ -1,6 +1,8 @@ package com.android_tetris.ui.theme import android.graphics.* +import android.view.MotionEvent +import androidx.compose.animation.ExperimentalAnimationApi import com.android_tetris.R import androidx.compose.animation.core.* import androidx.compose.foundation.Canvas @@ -9,30 +11,42 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.awaitFirstDown import androidx.compose.foundation.layout.* -import androidx.compose.material.Icon -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowDropDown import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.BiasAlignment +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.rotate import androidx.compose.ui.draw.scale import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.* import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.drawscope.Fill import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.drawscope.drawIntoCanvas +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.input.pointer.pointerInteropFilter +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.res.imageResource import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.android_tetris.ui.theme.* import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import kotlin.math.cos @@ -360,4 +374,359 @@ fun DropDownAnimate( content() } } +} + +// 3D android +const val maxAngle = 50f +val maxTranslation = 140.dp.value + +@ExperimentalAnimationApi +@ExperimentalComposeUiApi +@Preview +@Composable +fun Parallax() { + var angle by remember { mutableStateOf(Pair(0f, 0f)) } + var start by remember { mutableStateOf(Pair(-1f, -1f)) } + var viewSize by remember { mutableStateOf(Size.Zero) } + Box(modifier =Modifier//.fillMaxSize() + //.verticalScroll(rememberScrollState()) + .background(color = Color.Black) + + ){ + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .width(450.dp) + .height(470.dp) + .background(Color.Black) + .onGloballyPositioned { coordinates -> + viewSize = Size( + width = coordinates.size.width.toFloat(), + height = coordinates.size.height.toFloat() + ) + } + .pointerInteropFilter { m -> + when (m.action) { + MotionEvent.ACTION_UP -> { + start = Pair(-1f, -1f) + } + MotionEvent.ACTION_DOWN -> { + start = Pair(m.rawX, m.rawY) + } + MotionEvent.ACTION_MOVE -> { + if (viewSize != Size.Zero) { + val end = Pair(m.rawX, m.rawY) + val newAngle = getRotationAngles(start, end, viewSize) + var x: Float = angle.first + newAngle.first + var y: Float = angle.second + newAngle.second + + if (x > maxAngle) x = maxAngle + else if (x < -maxAngle) x = -maxAngle + + if (y > maxAngle) y = maxAngle + else if (y < -maxAngle) y = -maxAngle + + angle = Pair(x, y) + start = end + } + } + } + true + } + ) { + Box(contentAlignment = Alignment.TopCenter) { + Text( + text = "Contribute Information", + color = Color.White, + fontSize = 40.sp, + fontFamily = FontFamily.Cursive, + modifier = Modifier + .alpha(0.8f) + .padding(start = 5.dp) + ) + } + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .weight(1f) + .size(400.dp) + ) { + Card( + shape = RoundedCornerShape(12.dp), + backgroundColor = Color.White, + elevation = 0.dp, + modifier = Modifier + .graphicsLayer( + transformOrigin = TransformOrigin(0.5f, 0.5f), + rotationY = animateFloatAsState(-angle.first).value, + rotationX = animateFloatAsState(angle.second).value, + cameraDistance = 16.dp.value + ) + .width(320.dp) + .aspectRatio(1f) + ) { + Image( + imageVector = ImageVector.vectorResource(id = R.drawable.back), + contentDescription = "Parallax Background", + modifier = Modifier.fillMaxSize() + ) + Box(contentAlignment = Alignment.BottomStart) { + Text( + text = "compose_version = 1.0.0-beta08\n"+ + "kotlin_version = 1.5.10\n"+ + "Running in SDK 30, minSdk = 21", + color = Color.Black, + fontSize = 12.sp, + fontFamily = FontFamily.Serif, + modifier = Modifier + .alpha(0.8f) + .padding(start = 12.dp) + ) + } + Box(contentAlignment = Alignment.TopCenter) { + Text( + text = "Contributers: 王雨潇、张煜玮、西鹏飞\n" + + "Language: Kotlin\n"+ + "Framework: Jetpack compose", + color = Color.DarkGray, + fontSize = 14.sp, + fontFamily = FontFamily.Serif, + modifier = Modifier + .alpha(0.8f) + .padding(start = 12.dp) + ) + } + } + + Box( + modifier = Modifier + .graphicsLayer( + transformOrigin = TransformOrigin(0.5f, 0.5f), + rotationY = animateFloatAsState(-angle.first).value, + rotationX = animateFloatAsState(angle.second).value, + cameraDistance = 16.dp.value, + translationX = -getTranslation(angle.first, maxTranslation), + translationY = -getTranslation(angle.second, maxTranslation) + ) + .size(320.dp) + .align(Alignment.Center) + ){ + Image(imageVector = ImageVector.vectorResource(id = R.drawable.front), contentDescription = "Parallax Background") + } + + } + Box(contentAlignment = Alignment.BottomEnd) { + Text( + text = "Made in Augest, 2021", + color = Color.White, + fontSize = 25.sp, + fontFamily = FontFamily.Cursive, + modifier = Modifier + .alpha(0.8f) + .padding(start = 5.dp) + ) + } + } + + } + +} + +/** + * This method converts the current touch input to rotation values based on the original point + * at which the touch event started. + * + * @param start : coordinates of first touch event + * @param end : coordinates of final touch event + */ +fun getRotationAngles( + start: Pair, + end: Pair, + size: Size +): Pair { + /** + * 1. get the magnitude of drag event, based on screen's width & height & acceleration + * 2. get the direction/angle of the drag event + */ + val acceleration = 3 + val distances = getDistances(end, start) + val rotationX = (distances.first / size.width) * maxAngle * acceleration + val rotationY = (distances.second / size.height) * maxAngle * acceleration + return Pair(rotationX, rotationY) +} + +fun getDistances(p1: Pair, p2: Pair): Pair { + return Pair( + p2.first - p1.first, + p2.second - p1.second + ) +} + +fun getTranslation(angle: Float, maxDistance: Float): Float { + return (angle/90f) * maxDistance +} + + + +// rocker launch +@Composable +fun Rocket( + isRocketEnabled: Boolean, + maxWidth: Dp, + maxHeight: Dp +) { + val resource: Painter + val modifier: Modifier + val rocketSize = 100.dp + if(!isRocketEnabled){ + resource = painterResource(id = R.drawable.rocket_intial) + modifier = Modifier.offset( + y = maxHeight - rocketSize, + ) + } + else{ + val infiniteTransition = rememberInfiniteTransition() + val engineState = infiniteTransition.animateFloat( + initialValue = 0f, + targetValue = 1f, + animationSpec = infiniteRepeatable( + animation = tween( + durationMillis = 500, + easing = LinearEasing + ) + ) + ) + val xPositionState = infiniteTransition.animateFloat( + initialValue = 0f, + targetValue = 1f, + animationSpec = infiniteRepeatable( + animation = tween( + durationMillis = 2000, + easing = LinearEasing + ) + ) + ) + if (engineState.value <= .5f) { + resource = painterResource(id = R.drawable.rocket1) + } else { + resource = painterResource(id = R.drawable.rocket2) + } + modifier = Modifier.offset( + x = (maxWidth - rocketSize) * xPositionState.value, + y = (maxHeight - rocketSize) - (maxHeight - rocketSize) * xPositionState.value, + ) + } + Image( + modifier = modifier + .width(rocketSize) + .height(rocketSize), + painter = resource, + contentDescription = "A Rocket", + ) +} + + +@ExperimentalAnimationApi +@Composable +fun LaunchButton( + animationState: Boolean, + onToggleAnimationState: () -> Unit, +){ + Column{ + Text( + text = " Shoot for the moon,\n" + + " even if you miss,\n" + + " you'll land among the star.\n" + + " ——Les Brown", + color = Color.White, + fontSize = 30.sp, + fontFamily = FontFamily.Cursive, + modifier = Modifier + .alpha(0.8f) + .padding(start = 5.dp) + ) + Spacer(modifier = Modifier.height(15.dp)) + Row{ + MultiColorSmoothText( + text =" 追寻月之所向,\n" + + " 纵使交错而过,\n" + + " 也将置身于繁星之间。\n", + modifier = Modifier.padding(5.dp), + style = MaterialTheme.typography.h6, + duration = 1200 + ) + Icon( + tint = PastelRainbowYellow, + painter = painterResource(id = R.drawable.ic_moonstar), + contentDescription = null // decorative element + ) + } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.Center + ){ + if(animationState){ + Button( + onClick = onToggleAnimationState, + colors = ButtonDefaults.buttonColors(backgroundColor = Rainbow1, contentColor = Color.White) + ) { + Text("STOP") + } + + } + else{ + Button( + onClick = onToggleAnimationState, + ) { + Text("LAUNCH") + } + } + } + } +} + + +//ImageCard +@Composable +fun ImageCard( + painter: Painter, + contentDescription: String, + title: String, + modifier:Modifier=Modifier +) { + Card( + modifier = modifier.fillMaxWidth(), + shape = RoundedCornerShape(10.dp), //形状 + elevation = 5.dp + ) { + Box(modifier = Modifier.height(200.dp)) { + Image( + painter = painter, + contentDescription = contentDescription, + contentScale = ContentScale.Crop + ) + Box(modifier = Modifier + .fillMaxSize() + .background( + Brush.verticalGradient( // 黑色透明背景 + colors = listOf( + Color.Transparent, + Color.Black + ), + startY = 300f + ) + ) + ) + Box( + modifier = Modifier + .fillMaxSize() + .padding(12.dp), + contentAlignment = Alignment.BottomStart + ) { + Text(title, style = TextStyle(color = Color.White, fontSize = 16.sp)) + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/android_tetris/ui/theme/Color.kt b/app/src/main/java/com/android_tetris/ui/theme/Color.kt index e3c66ee2c9b369aa7a2d66dd3cd9cdd423b682e6..7b105676aafb86bd9568ebe829b0c0affc266327 100644 --- a/app/src/main/java/com/android_tetris/ui/theme/Color.kt +++ b/app/src/main/java/com/android_tetris/ui/theme/Color.kt @@ -40,9 +40,47 @@ val BrickAlpha = Color.Black.copy(alpha = 0.2f) val BrickFill = Color.Black.copy(alpha = 0.9f) val Rainbow1 = Color(0xFFF8BBD0) val Rainbow2 = Color(0xFFE1BEE7) -val Rainbow3 = Color(0xFFD1C4E9) +val Rainbow3 = Color(0xFFD1C4E9) // val Rainbow4 = Color(0xFFBBDEFB) -val Rainbow5 = Color(0xFFB2EBF2) +val Rainbow5 = Color(0xFFB2EBF2) // val Rainbow6 = Color(0xFFB2DFDB) val Rainbow7 = Color(0xFFC8E6C9) -val gradient = Brush.verticalGradient(0f to Color.Gray, 1000f to Color.White) \ No newline at end of file +val gradient = Brush.verticalGradient(0f to Color.Gray, 1000f to Color.White) + + +// 彩虹字体 +val RainbowRed = Color(0xFFDA034E) +val RainbowOrange = Color(0xFFFF9800) +val RainbowYellow = Color(0xFFFFEB3B) +val RainbowGreen = Color(0xFF4CAF50) +val RainbowBlue = Color(0xFF2196F3) +val RainbowIndigo = Color(0xFF3F51B5) +val RainbowViolet = Color(0xFF9C27B0) + +val SkittlesRainbow = listOf( + RainbowRed, + RainbowOrange, + RainbowYellow, + RainbowGreen, + RainbowBlue, + RainbowIndigo, + RainbowViolet +) + +val PastelRainbowRed = Color(0xFFFF80AB) // +val PastelRainbowOrange = Color(0xFFFF9E80) +val PastelRainbowYellow = Color(0xFFFFFF8D) // +val PastelRainbowGreen = Color(0xFFA7FFEB) // +val PastelRainbowBlue = Color(0xFF82B1FF) +val PastelRainbowIndigo = Color(0xFF8C9EFF) +val PastelRainbowViolet = Color(0xFFEA80FC) + +val PastelRainbow = listOf( + PastelRainbowRed, + PastelRainbowOrange, + PastelRainbowYellow, + PastelRainbowGreen, + PastelRainbowBlue, + PastelRainbowIndigo, + PastelRainbowViolet +) \ No newline at end of file diff --git a/app/src/main/java/com/android_tetris/ui/theme/Login.kt b/app/src/main/java/com/android_tetris/ui/theme/Login.kt new file mode 100644 index 0000000000000000000000000000000000000000..6789bf77a0027d234504af18daa9ad00ed310ee6 --- /dev/null +++ b/app/src/main/java/com/android_tetris/ui/theme/Login.kt @@ -0,0 +1,556 @@ +package com.android_tetris.ui.theme + + +import android.graphics.* +import android.graphics.Color +import android.graphics.LinearGradient +import android.graphics.Matrix +import android.graphics.Paint +import android.graphics.Path +import android.graphics.Shader +import androidx.compose.animation.core.* +import androidx.compose.foundation.* +import androidx.compose.foundation.gestures.* +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.rotate +import androidx.compose.ui.draw.scale +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.drawscope.drawIntoCanvas +import androidx.compose.ui.graphics.nativeCanvas +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.unit.dp +import androidx.compose.ui.graphics.* +import androidx.compose.ui.text.TextStyle +import androidx.compose.runtime.Composable +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Outline +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.res.imageResource +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.LayoutDirection +import com.android_tetris.R + + + +/** + * 登陆背景模糊头缩放部图片 + */ +@Composable +fun LoginPageTopBlurImage( + animatedBitmap: Animatable, + animatedOffset: Animatable, + animatedScales: Animatable +) { + Column() { + topBarView_Set() // 添加set界面顶部导航栏 + Image( + bitmap = BitmapBlur.doBlur( + getBitmap(resource = R.drawable.mn_2).asAndroidBitmap(),//界面上方背景图 + animatedBitmap.value.toInt(), false + ).asImageBitmap(), + contentDescription = "", + contentScale = ContentScale.FillWidth, + modifier = Modifier + .fillMaxWidth() + .height(250.dp) + .clip( + QureytoImageShapes(160f, animatedOffset.value) + ) + .scale(animatedScales.value, animatedScales.value) + ) + } +} + +//登陆页面头部旋转缩放的图片 + +@Composable +fun LoginPageTopRotaAndScaleImage( + animatedColor: Animatable, + animatedScales: Animatable, + animatedOffset: Animatable +) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .padding(0.dp) + .clip(CicleImageShape()) + .background(animatedColor.value) + .width((130 * animatedScales.value).dp) + .height((130 * animatedScales.value).dp) + ) { + Image( + bitmap = getBitmap(R.drawable.mn_3), // 用户头像 + contentDescription = "w", + contentScale = ContentScale.FillBounds, + modifier = Modifier + .height(80.dp) + .width(80.dp) + .background(color = Color(0XFF0DBEBF), shape = CircleShape) + .padding(3.dp) + .clip( + CircleShape + ) + .shadow(elevation = 150.dp, clip = true) + .rotate( + animatedOffset.value + ) + ) + } +} + +/** + * 登陆页面顶部文字 + */ +@Composable +fun LoginPageTopTextBox( + animatedOffset: Animatable, + animatedScales: Animatable +) { + Box( + contentAlignment = Alignment.Center, modifier = Modifier + .fillMaxWidth() + .padding(top = 20.dp) + ) { + Column(horizontalAlignment = Alignment.CenterHorizontally) { + Canvas( + modifier = Modifier + .fillMaxWidth() + .draggable(state = DraggableState { + + }, orientation = Orientation.Horizontal, onDragStarted = { + }, onDragStopped = { + + }), + ) { + drawIntoCanvas { canvas -> + val paint = androidx.compose.ui.graphics.Paint() + paint.style = PaintingStyle.Fill + paint.color = androidx.compose.ui.graphics.Color.Green + val textPaint = Paint() + textPaint.strokeWidth = 2f + textPaint.style = Paint.Style.FILL + textPaint.color = Color.BLACK + textPaint.textSize = 52f + + + //测量文字宽度 + val rect = Rect() + textPaint.getTextBounds("BomposeUnit 登陆", 0, 6, rect) + val colors = intArrayOf( + Color.BLACK, + Color.argb( + 250, + 121, + animatedOffset.value.toInt(), + 206 + ), + Color.argb( + 250, + 121, + 206, + animatedOffset.value.toInt() + ) + ) + val positions = floatArrayOf(0.2f, 11f, 0.2f) + + + //让渐变动起来从而感觉到文字闪动起来了 + val transMatrix = Matrix() + transMatrix.postTranslate( + -rect.width() + rect.width() * 2 * (animatedScales.value * 1.5f), + 0f + ) + //设置渐变 + val linearGradient = LinearGradient( + 0f, + 0f, + rect.width().toFloat(), + 0f, + colors, + positions, + Shader.TileMode.CLAMP + ) + //设置矩阵变换 + linearGradient.setLocalMatrix(transMatrix) + + textPaint.shader = linearGradient + //1.坐标变换 + canvas.nativeCanvas.drawText( + "BomposeUnit 登陆", + size.width / 3.5f, + size.height / 2.5f, + textPaint + ) + val secontextPath = navePath() + + + val rect1 = Rect() + textPaint.getTextBounds("更多精彩,更多体验 ~", 0, 6, rect1) + secontextPath.moveTo(340f, 100f) + //0-110 + if (animatedOffset.value == 0f) { + secontextPath.quadTo(350f, 10f, 710f, 100f) + + } + secontextPath.quadTo(animatedOffset.value, 10f, 710f, 100f) + + textPaint.textSize = 32f + textPaint.letterSpacing = 0.3f + //canvas.nativeCanvas.drawPath(secontextPath,textPaint) + canvas.nativeCanvas.drawTextOnPath( + "更多精彩,更多体验 ~", + secontextPath, + 0f, + 0f, + textPaint + ) + } + + } + } + } +} + + +//登陆页面输入框 + +@Composable +fun LoginPageInput( + inputUserName: MutableState, + animatedColor: Animatable, + animatedRound: Animatable, + inputPassworld: MutableState +) { + Box( + contentAlignment = Alignment.Center, modifier = Modifier + .fillMaxWidth() + .padding(top = 60.dp) + ) { + TextField( + value = inputUserName.value, + onValueChange = { + inputUserName.value = it.trim() + }, + // shape = AnimalRoundedCornerShape(animatedRound.value), + colors = TextFieldDefaults.textFieldColors( + unfocusedIndicatorColor = androidx.compose.ui.graphics.Color.Transparent, + focusedIndicatorColor = androidx.compose.ui.graphics.Color.Transparent, + backgroundColor = androidx.compose.ui.graphics.Color.Transparent + ), + modifier = Modifier + .height(48.dp) + .border( + 1.2.dp, + //animatedColor.value.copy(alpha = 1f) + Color( + animatedColor.value.red, + animatedColor.value.green, + animatedColor.value.blue, + 1f + ), + //shape = RoundedCornerShape(18.dp) + AnimalRoundedCornerShape(animatedRound.value) + ), + leadingIcon = { + Icon( + bitmap = getBitmap(R.drawable.nicheng), + contentDescription = "" + ) + }) + } +} + + +fun navePath(): Path { + return Path() +} +@Composable +fun getBitmap(resource: Int): ImageBitmap { + return ImageBitmap.Companion.imageResource(resource) +} +@Stable +class CicleImageShape(val circle: Float = 0f) : Shape { + override fun createOutline( + size: Size, + layoutDirection: LayoutDirection, + density: Density + ): Outline { + val minWidth = Math.min(size.width - circle, size.width - circle) + val rect = androidx.compose.ui.geometry.Rect(circle, circle, minWidth, minWidth) + val path = androidx.compose.ui.graphics.Path() + path.addOval(rect) + return Outline.Generic(path) + } +} + +// 动态圆角输入框 +@Stable +class AnimalRoundedCornerShape(private val value: Float = 30f) : Shape { + override fun createOutline( + size: Size, + layoutDirection: LayoutDirection, + density: Density + ): Outline { + val path = androidx.compose.ui.graphics.Path() + path.lineTo(value, 0f) + path.cubicTo(value, 0f, 0f, 0f, 0f, value) + path.lineTo(0f, size.height - value) + path.cubicTo(0f, size.height - value, 0f, size.height, value, size.height) + path.quadraticBezierTo(size.width / 2, size.height - value, size.width - value, size.height) + path.quadraticBezierTo(size.width, size.height, size.width, size.height - value) + path.lineTo(size.width, value) + path.quadraticBezierTo(size.width, 0f, size.width - value, 0f) + path.quadraticBezierTo(size.width / 2, value, value, 0f) + path.lineTo(value, 0f) + return Outline.Generic(path) + } + +} + +//形状裁剪 +@Stable +class QureytoImageShapes(var hudu: Float = 100f, var controller:Float=0f) : Shape { + + override fun createOutline( + size: Size, + layoutDirection: LayoutDirection, + density: Density + ): Outline { + val path = androidx.compose.ui.graphics.Path() + path.moveTo(0f, 0f) + path.lineTo(0f, size.height - hudu) + if(controller==0f){ + controller =size.width / 2f + } + path.quadraticBezierTo(controller, size.height, size.width, size.height - hudu) + path.lineTo(size.width, 0f) + path.close() + return Outline.Generic(path) + } +} + +// 模糊效果 +object BitmapBlur { + fun doBlur(sentBitmap: Bitmap, radiu: Int = 1, canReuseInBitmap: Boolean): Bitmap { + var radius: Int = radiu + val bitmap: Bitmap = if (canReuseInBitmap) { + sentBitmap + } else { + sentBitmap.copy(sentBitmap.config, true) + } + if (radius < 1) { + radius = 0 + } + val w = bitmap.width + val h = bitmap.height + val pix = IntArray(w * h) + bitmap.getPixels(pix, 0, w, 0, 0, w, h) + val wm = w - 1 + val hm = h - 1 + val wh = w * h + val div = radius + radius + 1 + val r = IntArray(wh) + val g = IntArray(wh) + val b = IntArray(wh) + var rsum: Int + var gsum: Int + var bsum: Int + var x: Int + var y: Int + var i: Int + var p: Int + var yp: Int + var yi: Int + var yw: Int + val vmin = IntArray(Math.max(w, h)) + var divsum = div + 1 shr 1 + divsum *= divsum + val dv = IntArray(256 * divsum) + i = 0 + while (i < 256 * divsum) { + dv[i] = i / divsum + i++ + } + yi = 0 + yw = yi + val stack = Array(div) { + IntArray( + 3 + ) + } + var stackpointer: Int + var stackstart: Int + var sir: IntArray + var rbs: Int + val r1 = radius + 1 + var routsum: Int + var goutsum: Int + var boutsum: Int + var rinsum: Int + var ginsum: Int + var binsum: Int + y = 0 + while (y < h) { + bsum = 0 + gsum = bsum + rsum = gsum + boutsum = rsum + goutsum = boutsum + routsum = goutsum + binsum = routsum + ginsum = binsum + rinsum = ginsum + i = -radius + while (i <= radius) { + p = pix[yi + Math.min(wm, Math.max(i, 0))] + sir = stack[i + radius] + sir[0] = p and 0xff0000 shr 16 + sir[1] = p and 0x00ff00 shr 8 + sir[2] = p and 0x0000ff + rbs = r1 - Math.abs(i) + rsum += sir[0] * rbs + gsum += sir[1] * rbs + bsum += sir[2] * rbs + if (i > 0) { + rinsum += sir[0] + ginsum += sir[1] + binsum += sir[2] + } else { + routsum += sir[0] + goutsum += sir[1] + boutsum += sir[2] + } + i++ + } + stackpointer = radius + x = 0 + while (x < w) { + r[yi] = dv[rsum] + g[yi] = dv[gsum] + b[yi] = dv[bsum] + rsum -= routsum + gsum -= goutsum + bsum -= boutsum + stackstart = stackpointer - radius + div + sir = stack[stackstart % div] + routsum -= sir[0] + goutsum -= sir[1] + boutsum -= sir[2] + if (y == 0) { + vmin[x] = Math.min(x + radius + 1, wm) + } + p = pix[yw + vmin[x]] + sir[0] = p and 0xff0000 shr 16 + sir[1] = p and 0x00ff00 shr 8 + sir[2] = p and 0x0000ff + rinsum += sir[0] + ginsum += sir[1] + binsum += sir[2] + rsum += rinsum + gsum += ginsum + bsum += binsum + stackpointer = (stackpointer + 1) % div + sir = stack[stackpointer % div] + routsum += sir[0] + goutsum += sir[1] + boutsum += sir[2] + rinsum -= sir[0] + ginsum -= sir[1] + binsum -= sir[2] + yi++ + x++ + } + yw += w + y++ + } + x = 0 + while (x < w) { + bsum = 0 + gsum = bsum + rsum = gsum + boutsum = rsum + goutsum = boutsum + routsum = goutsum + binsum = routsum + ginsum = binsum + rinsum = ginsum + yp = -radius * w + i = -radius + while (i <= radius) { + yi = Math.max(0, yp) + x + sir = stack[i + radius] + sir[0] = r[yi] + sir[1] = g[yi] + sir[2] = b[yi] + rbs = r1 - Math.abs(i) + rsum += r[yi] * rbs + gsum += g[yi] * rbs + bsum += b[yi] * rbs + if (i > 0) { + rinsum += sir[0] + ginsum += sir[1] + binsum += sir[2] + } else { + routsum += sir[0] + goutsum += sir[1] + boutsum += sir[2] + } + if (i < hm) { + yp += w + } + i++ + } + yi = x + stackpointer = radius + y = 0 + while (y < h) { + + // Preserve alpha channel: ( 0xff000000 & pix[yi] ) + pix[yi] = + -0x1000000 and pix[yi] or (dv[rsum] shl 16) or (dv[gsum] shl 8) or dv[bsum] + rsum -= routsum + gsum -= goutsum + bsum -= boutsum + stackstart = stackpointer - radius + div + sir = stack[stackstart % div] + routsum -= sir[0] + goutsum -= sir[1] + boutsum -= sir[2] + if (x == 0) { + vmin[y] = Math.min(y + r1, hm) * w + } + p = x + vmin[y] + sir[0] = r[p] + sir[1] = g[p] + sir[2] = b[p] + rinsum += sir[0] + ginsum += sir[1] + binsum += sir[2] + rsum += rinsum + gsum += ginsum + bsum += binsum + stackpointer = (stackpointer + 1) % div + sir = stack[stackpointer] + routsum += sir[0] + goutsum += sir[1] + boutsum += sir[2] + rinsum -= sir[0] + ginsum -= sir[1] + binsum -= sir[2] + yi += w + y++ + } + x++ + } + bitmap.setPixels(pix, 0, w, 0, 0, w, h) + return bitmap + } +} + + diff --git a/app/src/main/java/com/android_tetris/ui/theme/RainbowSpark.kt b/app/src/main/java/com/android_tetris/ui/theme/RainbowSpark.kt new file mode 100644 index 0000000000000000000000000000000000000000..b502bd0f399ee889c64acf0161d514b474fb5396 --- /dev/null +++ b/app/src/main/java/com/android_tetris/ui/theme/RainbowSpark.kt @@ -0,0 +1,215 @@ +package com.android_tetris.ui.theme + + +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.animateColor +import androidx.compose.animation.core.* +import androidx.compose.foundation.layout.* +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle + + +@ExperimentalAnimationApi +@Composable +fun MultiColorText( + modifier: Modifier = Modifier, + text: String, + style: TextStyle = LocalTextStyle.current, + rainbow: List = SkittlesRainbow, + startColor: Int = 0, +) { + Row(modifier) { + var index = startColor + for (letter in text) { + Text(letter.toString(), color = rainbow.get(index), style = style) + index++ + if (index == rainbow.size) index = 0 + } + + } +} + +@ExperimentalAnimationApi +@Composable +fun SnappyRainbowText( + modifier: Modifier = Modifier, + text: String, + style: TextStyle = LocalTextStyle.current, + rainbow: List = SkittlesRainbow +) { + require(rainbow.size > 0) + val infiniteTransition = rememberInfiniteTransition() + val colorIndex by infiniteTransition.animateValue( + initialValue = 0, + targetValue = rainbow.size - 1, + typeConverter = Int.VectorConverter, + animationSpec = infiniteRepeatable( + animation = tween(), + repeatMode = RepeatMode.Restart + ) + ) + MultiColorText( + text = text, + style = style, + modifier = modifier, + startColor = colorIndex, + rainbow = rainbow + ) +} + +@ExperimentalAnimationApi +@Composable +fun SmoothRainbowText( + modifier: Modifier = Modifier, + text: String, + style: TextStyle = LocalTextStyle.current, + rainbow: List = PastelRainbow, + startColor: Int = 0, + duration: Int = 1200 +) { + Row(modifier) { + var index = startColor + for (letter in text) { + MultiColorSmoothText( + text = letter.toString(), + style = style, + rainbow = rainbow, + startIndex = index, + duration = duration + ) + index++ + if (index == rainbow.size) index = 0 + + } + + } +} + +@ExperimentalAnimationApi +@Composable +fun TwoColorSmoothText( + modifier: Modifier = Modifier, + text: String, + style: TextStyle = LocalTextStyle.current, + startColor: Color, + endColor: Color +) { + val infiniteTransition = rememberInfiniteTransition() + val color by infiniteTransition.animateColor( + initialValue = startColor, + targetValue = endColor, + animationSpec = infiniteRepeatable( + animation = tween(durationMillis = 1000), + repeatMode = RepeatMode.Restart + ) + ) + Text(text = text, color = color, style = style, modifier = modifier) +} + +@ExperimentalAnimationApi +@Composable +fun MultiColorSmoothText( + modifier: Modifier = Modifier, + text: String, + style: TextStyle = LocalTextStyle.current, + rainbow: List = PastelRainbow, + startIndex: Int = 0, + duration: Int +) { + val infiniteTransition = rememberInfiniteTransition() + val interval = duration / rainbow.size + val color by infiniteTransition.animateColor( + initialValue = rainbow[0], + targetValue = rainbow.last(), + animationSpec = infiniteRepeatable( + animation = keyframes { + durationMillis = duration + delayMillis = startIndex * interval / 2 + var i = 0 + for (color in rainbow) { + color at i + i += interval + } + }, + repeatMode = RepeatMode.Restart + ) + ) + Text(text = text, color = color, style = style, modifier = modifier) +} + +@ExperimentalAnimationApi +@Composable +fun ThemedBlinkText( + modifier: Modifier = Modifier, + text: String, + style: TextStyle = LocalTextStyle.current +) { + LocalContentBlinkTag { + Text( + text = text, + modifier = modifier, + style = style + ) + } +} + +@ExperimentalAnimationApi +@Composable +fun LocalContentBlinkTag( + durationMillis: Int = 500, + content: @Composable () -> Unit +) { + val infiniteTransition = rememberInfiniteTransition() + val alpha: Float by infiniteTransition.animateFloat( + initialValue = 1f, + targetValue = 0f, + animationSpec = infiniteRepeatable( + animation = tween(durationMillis = durationMillis), + repeatMode = RepeatMode.Reverse + ) + ) + CompositionLocalProvider(LocalContentAlpha provides alpha) { + content() + } +} + +@ExperimentalAnimationApi +@Composable +fun BlinkTag( + modifier: Modifier = Modifier, + duration: Int = 500000, + content: @Composable (modifier: Modifier) -> Unit +) { + val infiniteTransition = rememberInfiniteTransition() + val alpha: Float by infiniteTransition.animateFloat( + initialValue = 1f, + targetValue = 0f, + animationSpec = infiniteRepeatable( + animation = keyframes { + durationMillis = duration + 1f at (duration*0.8).toInt() + 0f at duration + }, + repeatMode = RepeatMode.Reverse + ) + ) + content(modifier = modifier.alpha(alpha)) +} + +@ExperimentalAnimationApi +@Composable +fun BlinkText( + modifier: Modifier = Modifier, + text: String, + color: Color = Color.Unspecified, + style: TextStyle = LocalTextStyle.current, + durationMillis: Int = 1000, +) { + BlinkTag(modifier = modifier, duration = durationMillis) { + Text(modifier = it, text = text, style = style, color = color) + } +} diff --git a/app/src/main/java/com/android_tetris/ui/theme/TopBar.kt b/app/src/main/java/com/android_tetris/ui/theme/TopBar.kt new file mode 100644 index 0000000000000000000000000000000000000000..8217cce59fef909713b7dd6b60c309552381377f --- /dev/null +++ b/app/src/main/java/com/android_tetris/ui/theme/TopBar.kt @@ -0,0 +1,108 @@ +package com.android_tetris.ui.theme + + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.filled.Person +import androidx.compose.material.icons.filled.Settings +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.android_tetris.infoStorage + +@Composable +fun topBarView_Set(){ + TopAppBar( + modifier = Modifier + .fillMaxWidth() + .height(48.dp), + backgroundColor = MaterialTheme.colors.primarySurface, + elevation = 4.dp, + contentPadding = AppBarDefaults.ContentPadding + ) { + Row(modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically) { + Icon( + imageVector = Icons.Filled.Home, + contentDescription = "menu按钮", + tint = Color.White, + modifier = Modifier + .clickable { + //点击了按钮 + infoStorage.currentScreen = 0 + //Toast.makeText(context, "Clicked on Icon Button", Toast.LENGTH_SHORT).show() + } + .padding(start = 12.dp, end = 12.dp) + .fillMaxHeight() + ) + Text(text = "Home",fontSize = 17.sp,color = Color.White) + Icon( + imageVector = Icons.Filled.Person, + contentDescription = "menu按钮", + tint = Color.White, + modifier = Modifier + .clickable { + //点击了按钮 + infoStorage.currentScreen = 2 + //Toast.makeText(context, "Clicked on Icon Button", Toast.LENGTH_SHORT).show() + } + .padding(start = 12.dp, end = 12.dp) + .fillMaxHeight() + ) + Text(text = "More",fontSize = 17.sp,color = Color.White) + } + } +} + +@Preview +@Composable +fun topBarView_More(){ + TopAppBar( + modifier = Modifier + .fillMaxWidth() + .height(48.dp), + backgroundColor = MaterialTheme.colors.primarySurface, + elevation = 4.dp, + contentPadding = AppBarDefaults.ContentPadding + ) { + Row(modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically) { + Icon( + imageVector = Icons.Filled.Home, + contentDescription = "menu按钮", + tint = Color.White, + modifier = Modifier + .clickable { + //点击了按钮 + infoStorage.currentScreen = 0 + //Toast.makeText(context, "Clicked on Icon Button", Toast.LENGTH_SHORT).show() + } + .padding(start = 12.dp, end = 12.dp) + .fillMaxHeight() + ) + Text(text = "Home",fontSize = 17.sp,color = Color.White) + Icon( + imageVector = Icons.Filled.Settings, + contentDescription = "menu按钮", + tint = Color.White, + modifier = Modifier + .clickable { + //点击了按钮 + infoStorage.currentScreen = 1 + //Toast.makeText(context, "Clicked on Icon Button", Toast.LENGTH_SHORT).show() + } + .padding(start = 12.dp, end = 12.dp) + .fillMaxHeight() + ) + Text(text = "Setting",fontSize = 17.sp,color = Color.White) + } + } +} + diff --git a/app/src/main/res/drawable/back.xml b/app/src/main/res/drawable/back.xml new file mode 100644 index 0000000000000000000000000000000000000000..0050e7c6e170a238d8c5428058afb75d865537e1 --- /dev/null +++ b/app/src/main/res/drawable/back.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/front.xml b/app/src/main/res/drawable/front.xml new file mode 100644 index 0000000000000000000000000000000000000000..3a448d85a332eb399744dd4acfb06316f83f710c --- /dev/null +++ b/app/src/main/res/drawable/front.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic______fenge.xml b/app/src/main/res/drawable/ic______fenge.xml new file mode 100644 index 0000000000000000000000000000000000000000..65958f77fc1a90eb9ed53b59d013d2aa05a90dc3 --- /dev/null +++ b/app/src/main/res/drawable/ic______fenge.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_____name.xml b/app/src/main/res/drawable/ic_____name.xml new file mode 100644 index 0000000000000000000000000000000000000000..9a9a9719d1205901bd9f90641dd524de4950f063 --- /dev/null +++ b/app/src/main/res/drawable/ic_____name.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_____score.xml b/app/src/main/res/drawable/ic_____score.xml new file mode 100644 index 0000000000000000000000000000000000000000..05c24616d0c7a558213d128d0b3ace06b93bf97d --- /dev/null +++ b/app/src/main/res/drawable/ic_____score.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_____zhinan.xml b/app/src/main/res/drawable/ic_____zhinan.xml new file mode 100644 index 0000000000000000000000000000000000000000..c1d73e68592eba915811fd67b4baddd810c59be5 --- /dev/null +++ b/app/src/main/res/drawable/ic_____zhinan.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic____theme.xml b/app/src/main/res/drawable/ic____theme.xml new file mode 100644 index 0000000000000000000000000000000000000000..827f037460353902be28868e53ec837b1e69a027 --- /dev/null +++ b/app/src/main/res/drawable/ic____theme.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic___difficulty.xml b/app/src/main/res/drawable/ic___difficulty.xml new file mode 100644 index 0000000000000000000000000000000000000000..f2baf219715fe567612ab4c9175d9ee84651530d --- /dev/null +++ b/app/src/main/res/drawable/ic___difficulty.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic___mayun.xml b/app/src/main/res/drawable/ic___mayun.xml new file mode 100644 index 0000000000000000000000000000000000000000..ba2f1f08a138c3d3d53958f15932bf7438296dce --- /dev/null +++ b/app/src/main/res/drawable/ic___mayun.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic___music.xml b/app/src/main/res/drawable/ic___music.xml new file mode 100644 index 0000000000000000000000000000000000000000..79181e3bf740e516dfbf4a57023f0daafad72a9f --- /dev/null +++ b/app/src/main/res/drawable/ic___music.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_fork.xml b/app/src/main/res/drawable/ic_fork.xml new file mode 100644 index 0000000000000000000000000000000000000000..1e9452cfd53edfe726d4a733814ba6b793c34719 --- /dev/null +++ b/app/src/main/res/drawable/ic_fork.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_mail.xml b/app/src/main/res/drawable/ic_mail.xml new file mode 100644 index 0000000000000000000000000000000000000000..622ba4b6f57bf727974b52b8bfa21e62012e8397 --- /dev/null +++ b/app/src/main/res/drawable/ic_mail.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_moonstar.xml b/app/src/main/res/drawable/ic_moonstar.xml new file mode 100644 index 0000000000000000000000000000000000000000..64215499b168fb81dbac0093d9a7984459dbf14b --- /dev/null +++ b/app/src/main/res/drawable/ic_moonstar.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/ic_star.xml b/app/src/main/res/drawable/ic_star.xml new file mode 100644 index 0000000000000000000000000000000000000000..64466908d7aac530d800a9baba59b1dee0eabcea --- /dev/null +++ b/app/src/main/res/drawable/ic_star.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable/icon_tetris.jpg b/app/src/main/res/drawable/icon_tetris.jpg index c067089d9c4ef1562ffa129d222f2a6d1d4ecc27..44cac007146a373ca2969ee642d81805cc794a5d 100644 Binary files a/app/src/main/res/drawable/icon_tetris.jpg and b/app/src/main/res/drawable/icon_tetris.jpg differ diff --git a/app/src/main/res/drawable/meme_pf.jpg b/app/src/main/res/drawable/meme_pf.jpg new file mode 100644 index 0000000000000000000000000000000000000000..593acf59e553904d6c3292f06889da6958f46a6a Binary files /dev/null and b/app/src/main/res/drawable/meme_pf.jpg differ diff --git a/app/src/main/res/drawable/meme_yw.jpg b/app/src/main/res/drawable/meme_yw.jpg new file mode 100644 index 0000000000000000000000000000000000000000..568c6a54775611e9c4337587350b10e66a8b5fe4 Binary files /dev/null and b/app/src/main/res/drawable/meme_yw.jpg differ diff --git a/app/src/main/res/drawable/meme_yx.jpg b/app/src/main/res/drawable/meme_yx.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b24b468b86318a1ed9d49aeb3b7c2643c3018998 Binary files /dev/null and b/app/src/main/res/drawable/meme_yx.jpg differ diff --git a/app/src/main/res/drawable/mn_1.webp b/app/src/main/res/drawable/mn_1.webp new file mode 100644 index 0000000000000000000000000000000000000000..08068c1a680beb11d62173468b15eadd0fa0c88c Binary files /dev/null and b/app/src/main/res/drawable/mn_1.webp differ diff --git a/app/src/main/res/drawable/mn_2.webp b/app/src/main/res/drawable/mn_2.webp new file mode 100644 index 0000000000000000000000000000000000000000..b2e56d80feb5529f377cf7ba388a4e091eb8e73b Binary files /dev/null and b/app/src/main/res/drawable/mn_2.webp differ diff --git a/app/src/main/res/drawable/mn_3.webp b/app/src/main/res/drawable/mn_3.webp new file mode 100644 index 0000000000000000000000000000000000000000..7e6781eaea0338a938e87ff3bc8703d281bf6eb2 Binary files /dev/null and b/app/src/main/res/drawable/mn_3.webp differ diff --git a/app/src/main/res/drawable/moon.jpg b/app/src/main/res/drawable/moon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2a794803190ef3036db6df5e4e6fedbc4aeb2008 Binary files /dev/null and b/app/src/main/res/drawable/moon.jpg differ diff --git a/app/src/main/res/drawable/nicheng.png b/app/src/main/res/drawable/nicheng.png new file mode 100644 index 0000000000000000000000000000000000000000..2a8d2d9bdb15b855059c502efe60553be0cd0631 Binary files /dev/null and b/app/src/main/res/drawable/nicheng.png differ diff --git a/app/src/main/res/drawable/rocket1.png b/app/src/main/res/drawable/rocket1.png new file mode 100644 index 0000000000000000000000000000000000000000..c9e7d99abf0e3c3f990f3943ed1cbf2f56884387 Binary files /dev/null and b/app/src/main/res/drawable/rocket1.png differ diff --git a/app/src/main/res/drawable/rocket2.png b/app/src/main/res/drawable/rocket2.png new file mode 100644 index 0000000000000000000000000000000000000000..bac7e36b03a4303baa2c30b7b2861d4d1b4535f7 Binary files /dev/null and b/app/src/main/res/drawable/rocket2.png differ diff --git a/app/src/main/res/drawable/rocket_intial.png b/app/src/main/res/drawable/rocket_intial.png new file mode 100644 index 0000000000000000000000000000000000000000..3b7454e3c06ae258e6a393ef4090c78a9f8d39e0 Binary files /dev/null and b/app/src/main/res/drawable/rocket_intial.png differ diff --git a/daemon/7.0/registry.bin b/daemon/7.0/registry.bin index 5f402583cf684e4822d18656fefdaa2e7428ebb4..99b6f24dbf31f3c7a0a7460cd973c6ed5a67e4ae 100644 Binary files a/daemon/7.0/registry.bin and b/daemon/7.0/registry.bin differ diff --git a/daemon/7.0/registry.bin.lock b/daemon/7.0/registry.bin.lock index 516d7ca94b114e9e86c5ae5c9fbd17c9624e7a2e..63c6264fa72dcb1bfd60d40eae5cfb293fc1e317 100644 Binary files a/daemon/7.0/registry.bin.lock and b/daemon/7.0/registry.bin.lock differ