fix: 出牌记录改为米白背景+黑色文字+彩色底色、万能牌→颜色整体着色、自动换行
This commit is contained in:
parent
347e01b5ee
commit
13a1e9432a
@ -218,12 +218,12 @@ class GameEngine(private val rules: GameRules = GameRules.forMode(GameMode.NORMA
|
||||
}
|
||||
CardType.WILD -> {
|
||||
wildColor = chosenColor ?: CardColor.RED
|
||||
message += ",选择 ${wildColor!!.displayName}"
|
||||
message += " → ${wildColor!!.displayName}"
|
||||
}
|
||||
CardType.WILD_DRAW_FOUR -> {
|
||||
wildColor = chosenColor ?: CardColor.RED
|
||||
pendingDraw = if (isStacking) pendingDraw + 4 else 4
|
||||
message += ",下家摸${pendingDraw}张牌,选${wildColor!!.displayName}"
|
||||
message += " → ${wildColor!!.displayName},下家摸${pendingDraw}张牌"
|
||||
}
|
||||
// Flip mode dark side effects
|
||||
CardType.SKIP_ALL -> {
|
||||
@ -238,7 +238,7 @@ class GameEngine(private val rules: GameRules = GameRules.forMode(GameMode.NORMA
|
||||
CardType.WILD_DRAW_TWO -> {
|
||||
wildColor = chosenColor ?: CardColor.RED
|
||||
pendingDraw = 2
|
||||
message += ",下家摸2张,选${wildColor!!.displayName}"
|
||||
message += " → ${wildColor!!.displayName},下家摸2张"
|
||||
}
|
||||
CardType.FLIP -> {
|
||||
flipped = !flipped
|
||||
@ -260,7 +260,7 @@ class GameEngine(private val rules: GameRules = GameRules.forMode(GameMode.NORMA
|
||||
pendingDraw = 4
|
||||
val tempState = state.copy(direction = direction)
|
||||
nextIndex = tempState.nextPlayerIndex()
|
||||
message += "+4反转,选${wildColor!!.displayName}"
|
||||
message += " → ${wildColor!!.displayName},+4反转"
|
||||
}
|
||||
CardType.DISCARD_COLOR -> {
|
||||
val discardColor = card.activeCard(flipped).color
|
||||
@ -274,7 +274,7 @@ class GameEngine(private val rules: GameRules = GameRules.forMode(GameMode.NORMA
|
||||
CardType.WILD_DRAW_COLOR -> {
|
||||
wildColor = chosenColor ?: CardColor.RED
|
||||
nextIndex = advanceIndex(state, nextIndex)
|
||||
message += ",跳过下家并选${wildColor!!.displayName}"
|
||||
message += " → ${wildColor!!.displayName},跳过下家"
|
||||
}
|
||||
CardType.NUMBER -> {
|
||||
// 7-0 rules
|
||||
|
||||
@ -14,7 +14,10 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
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.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.google.gson.Gson
|
||||
@ -26,6 +29,7 @@ import com.unogame.game.GameRules
|
||||
import com.unogame.game.SimpleAI
|
||||
import com.unogame.model.*
|
||||
import com.unogame.ui.components.ColorPickerDialog
|
||||
import com.unogame.ui.components.getBotAvatar
|
||||
import com.unogame.ui.theme.*
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
@ -149,6 +153,8 @@ fun LocalGameScreen(
|
||||
var pendingDrawStateForWild by remember { mutableStateOf<GameState?>(null) }
|
||||
var pendingDrawCardIdxForWild by remember { mutableIntStateOf(-1) }
|
||||
var gameLog by remember { mutableStateOf(listOf<String>()) }
|
||||
// 记录每条日志对应的玩家名,用于行着色
|
||||
var gameLogPlayers by remember { mutableStateOf(listOf<String>()) }
|
||||
var showLogDialog by remember { mutableStateOf(false) }
|
||||
var showSwapTargetPicker by remember { mutableStateOf(false) }
|
||||
var pendingSwapState by remember { mutableStateOf<GameState?>(null) }
|
||||
@ -162,7 +168,10 @@ fun LocalGameScreen(
|
||||
myCards = state.players.find { it.id == myPlayerId }?.cards ?: myCards
|
||||
errorMessage = ""
|
||||
if (state.message.isNotEmpty()) {
|
||||
// 倒序插入,最新在上
|
||||
gameLog = listOf(state.message) + gameLog
|
||||
// 记录该消息对应的操作玩家(消息格式: "玩家名 出了..." 或 "玩家名 摸了...")
|
||||
gameLogPlayers = listOf(state.currentPlayer.name) + gameLogPlayers
|
||||
}
|
||||
if (state.isGameOver) {
|
||||
isGameOver = true
|
||||
@ -329,42 +338,127 @@ fun LocalGameScreen(
|
||||
)
|
||||
}
|
||||
|
||||
// Game log dialog
|
||||
// 出牌记录弹窗
|
||||
if (showLogDialog) {
|
||||
// 卡牌颜色名映射
|
||||
val cardColorMap = mapOf(
|
||||
"红" to UnoRed, "蓝" to UnoBlue,
|
||||
"黄" to Color(0xFFFDD835), "绿" to UnoGreen,
|
||||
"粉" to Color(0xFFE91E63), "紫" to Color(0xFF9C27B0),
|
||||
"青" to Color(0xFF009688), "橙" to Color(0xFFFF9800),
|
||||
"万能" to Color(0xFF616161), "黑" to Color(0xFF424242)
|
||||
)
|
||||
fun parsePlayerName(msg: String): String = msg.substringBefore(" 出了").substringBefore(" 摸了").substringBefore(" 选择").substringBefore(" 无法")
|
||||
fun parseColorText(msg: String): String {
|
||||
val after = msg.substringAfter(" 出了 ", "")
|
||||
if (after.isEmpty()) return ""
|
||||
val colorNames = listOf("万能", "红", "蓝", "黄", "绿", "粉", "紫", "青", "橙", "黑")
|
||||
return colorNames.firstOrNull { after.startsWith(it) } ?: ""
|
||||
}
|
||||
fun parseArrowColor(msg: String): Pair<String, Color>? {
|
||||
val arrowIdx = msg.indexOf(" → ")
|
||||
if (arrowIdx < 0) return null
|
||||
val afterArrow = msg.substring(arrowIdx + 3).trimStart()
|
||||
val cn = listOf("红", "蓝", "黄", "绿", "粉", "紫", "青", "橙", "黑", "万能")
|
||||
for (name in cn) {
|
||||
if (afterArrow.startsWith(name)) {
|
||||
return name to (cardColorMap[name] ?: Color.White)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
val creamBg = Color(0xFFFFF8E1) // 护眼米白
|
||||
val dimText = Color(0xFF555555) // 浅色底上的暗灰文字
|
||||
|
||||
// 关闭
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = { showLogDialog = false },
|
||||
title = { Text("出牌记录", color = GoldAccent, fontWeight = FontWeight.Bold) },
|
||||
title = { Text("出牌记录", color = Color(0xFF333333), fontWeight = FontWeight.Bold) },
|
||||
text = {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.heightIn(max = 400.dp)
|
||||
.heightIn(min = 300.dp, max = 420.dp)
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
if (gameLog.isEmpty()) {
|
||||
Text("暂无记录", color = Color.White.copy(alpha = 0.5f))
|
||||
Text("暂无记录", color = dimText, fontSize = 13.sp)
|
||||
}
|
||||
gameLog.forEachIndexed { index, msg ->
|
||||
Row(modifier = Modifier.padding(vertical = 2.dp)) {
|
||||
Text(
|
||||
"${gameLog.size - index}. ",
|
||||
color = Color.White.copy(alpha = 0.3f),
|
||||
fontSize = 12.sp
|
||||
)
|
||||
Text(
|
||||
msg,
|
||||
color = Color.White.copy(alpha = 0.8f),
|
||||
fontSize = 12.sp
|
||||
)
|
||||
val playerName = gameLogPlayers.getOrElse(index) { parsePlayerName(msg) }
|
||||
val avatar = getBotAvatar(playerName)
|
||||
val colorText = parseColorText(msg)
|
||||
val cardColor = cardColorMap[colorText]
|
||||
val isPlay = " 出了 " in msg
|
||||
val arrowColor = parseArrowColor(msg)
|
||||
val afterPlayer = msg.substringAfter(playerName)
|
||||
|
||||
// 用 AnnotatedString 构建整行,支持自动换行
|
||||
val annotated = buildAnnotatedString {
|
||||
// 序号
|
||||
withStyle(SpanStyle(color = Color(0xFF999999), fontSize = 13.sp)) {
|
||||
append("${gameLog.size - index}. ")
|
||||
}
|
||||
// 玩家名
|
||||
withStyle(SpanStyle(color = avatar.color, fontWeight = FontWeight.Bold, fontSize = 13.sp)) {
|
||||
append(playerName)
|
||||
}
|
||||
if (isPlay && (colorText.isNotEmpty() || arrowColor != null)) {
|
||||
if (arrowColor != null) {
|
||||
val prefix = afterPlayer.substringBefore(" 万能")
|
||||
val cardBlock = afterPlayer.substringAfter(" 出了 ").substringBefore(",")
|
||||
val remain = afterPlayer.substringAfter(prefix + " 出了 " + cardBlock)
|
||||
withStyle(SpanStyle(color = dimText, fontSize = 13.sp)) {
|
||||
append(prefix)
|
||||
append(" 出了 ")
|
||||
}
|
||||
withStyle(SpanStyle(color = Color.Black, fontWeight = FontWeight.Black,
|
||||
fontSize = 13.sp, background = arrowColor.second.copy(alpha = 0.9f))) {
|
||||
append(cardBlock)
|
||||
}
|
||||
if (remain.isNotEmpty()) {
|
||||
withStyle(SpanStyle(color = Color(0xFF777777), fontSize = 12.sp)) {
|
||||
append(remain)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val prefix = afterPlayer.substringBefore(colorText)
|
||||
val cardId = colorText + afterPlayer.substringAfter(colorText).substringBefore(",")
|
||||
val remain = afterPlayer.substringAfter(prefix + cardId)
|
||||
withStyle(SpanStyle(color = dimText, fontSize = 13.sp)) {
|
||||
append(prefix)
|
||||
}
|
||||
withStyle(SpanStyle(color = Color.Black, fontWeight = FontWeight.Black,
|
||||
fontSize = 13.sp, background = (cardColor ?: Color.Gray).copy(alpha = 0.9f))) {
|
||||
append(cardId)
|
||||
}
|
||||
if (remain.isNotEmpty()) {
|
||||
withStyle(SpanStyle(color = Color(0xFF777777), fontSize = 12.sp)) {
|
||||
append(remain)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
withStyle(SpanStyle(color = dimText, fontSize = 13.sp)) {
|
||||
append(afterPlayer)
|
||||
}
|
||||
}
|
||||
}
|
||||
Text(annotated, modifier = Modifier.padding(vertical = 5.dp))
|
||||
// 条目间加细分割线
|
||||
if (index < gameLog.size - 1) {
|
||||
Spacer(modifier = Modifier.height(1.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = { showLogDialog = false }) {
|
||||
Text("关闭", color = GoldAccent)
|
||||
Text("关闭", color = Color(0xFF333333))
|
||||
}
|
||||
},
|
||||
containerColor = DarkSurface
|
||||
containerColor = creamBg
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user