@import '@/uni.scss'; // ===================================== // 扫雷游戏 - 暗色毛玻璃风格 // 与项目整体设计语言保持一致 // ===================================== .container { min-height: 100vh; background: $bg-dark; color: $text-dark-main; font-size: $font-md; position: relative; overflow: hidden; } // 背景装饰 - 使用项目统一的光球效果 .bg-dark-grid { position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 0; pointer-events: none; &::before { content: ''; position: absolute; top: -100rpx; right: -100rpx; width: 600rpx; height: 600rpx; background: radial-gradient(circle, rgba($brand-primary, 0.2) 0%, transparent 70%); filter: blur(60rpx); border-radius: 50%; animation: float 10s ease-in-out infinite; } &::after { content: ''; position: absolute; bottom: 100rpx; left: -150rpx; width: 500rpx; height: 500rpx; background: radial-gradient(circle, rgba($brand-secondary, 0.15) 0%, transparent 70%); filter: blur(50rpx); border-radius: 50%; animation: float 15s ease-in-out infinite reverse; } } @keyframes float { 0%, 100% { transform: translateY(0) scale(1); } 50% { transform: translateY(-30rpx) scale(1.05); } } // ===================================== // 暗色毛玻璃卡片 - 项目统一风格 // ===================================== .glass-card { background: $bg-dark-card; backdrop-filter: blur(20rpx); border: 1px solid $border-dark; box-shadow: $shadow-card; border-radius: $radius-lg; position: relative; z-index: 1; } // ===================================== // 加载屏幕 // ===================================== .loading-screen { position: fixed; inset: 0; display: flex; justify-content: center; align-items: center; z-index: 100; background: rgba(0, 0, 0, 0.9); } .loading-content { display: flex; flex-direction: column; align-items: center; gap: $spacing-lg; } .loading-spinner { font-size: 80rpx; animation: pulse 1.5s ease-in-out infinite; } .loading-text { color: $text-dark-sub; font-size: $font-md; letter-spacing: 4rpx; } // ===================================== // 匹配大厅 // ===================================== .lobby-screen { position: relative; width: 100%; min-height: 100vh; display: flex; flex-direction: column; z-index: 5; } .bg-decoration { position: absolute; top: 0; left: 0; right: 0; height: 50vh; background: linear-gradient(180deg, rgba($brand-primary, 0.1) 0%, transparent 100%); z-index: -1; } .lobby-content { flex: 1; display: flex; flex-direction: column; align-items: center; padding: $spacing-xl $spacing-lg; padding-top: calc(80rpx + env(safe-area-inset-top)); z-index: 10; } .game-title { font-size: $font-xxl + 8rpx; font-weight: 900; color: $text-dark-main; text-shadow: 0 4rpx 20rpx rgba($brand-primary, 0.4); margin-bottom: $spacing-xxl; letter-spacing: 6rpx; } // ===================================== // 匹配卡片 // ===================================== .match-box { width: 100%; padding: $spacing-xxl $spacing-lg; display: flex; flex-direction: column; align-items: center; margin-bottom: $spacing-lg; } // 扫描器动画 .scanner-box { position: relative; width: 200rpx; height: 200rpx; margin-bottom: $spacing-xl; display: flex; justify-content: center; align-items: center; // 外圈脉冲 &::before { content: ''; position: absolute; inset: 0; border: 2rpx solid rgba($brand-primary, 0.4); border-radius: 50%; animation: pulse-ring 2s ease-out infinite; } // 内圈旋转 &::after { content: ''; position: absolute; inset: 20rpx; border: 3rpx dashed rgba($brand-primary, 0.6); border-radius: 50%; animation: rotate 6s linear infinite; } } @keyframes pulse-ring { 0% { transform: scale(1); opacity: 1; } 100% { transform: scale(1.4); opacity: 0; } } @keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } // 扫描线 .scanner-line { position: absolute; width: 100%; height: 3rpx; background: linear-gradient(90deg, transparent, $brand-primary, transparent); animation: scan 2s linear infinite; top: 0; } @keyframes scan { 0% { top: 0%; opacity: 0; } 50% { opacity: 1; } 100% { top: 100%; opacity: 0; } } .match-spinner { font-size: 90rpx; z-index: 10; filter: drop-shadow(0 0 20rpx rgba($brand-primary, 0.4)); animation: bounce 2s ease-in-out infinite; } @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-15rpx); } } .match-status { font-size: $font-lg; font-weight: 700; color: $brand-primary; margin-bottom: $spacing-xl; } .match-info { width: 100%; } .timer-row { display: flex; justify-content: center; align-items: baseline; gap: $spacing-md; margin-bottom: $spacing-lg; } .timer-label { font-size: $font-sm; color: $text-dark-sub; } .timer-value { font-size: 56rpx; font-weight: 900; color: $text-dark-main; } .status-tip { text-align: center; margin-bottom: $spacing-xl; height: 40rpx; text { font-size: $font-sm; } } .tip-normal { color: $color-success; } .tip-warning { color: $color-warning; } .tip-error { color: $color-error; animation: blink 1s ease-in-out infinite; } @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .cancel-btn { height: 88rpx; font-size: $font-md; background: transparent; border: 1px solid $border-dark; border-radius: $radius-round; color: $text-dark-sub; display: flex; justify-content: center; align-items: center; transition: all $transition-normal $ease-out; &:active { background: rgba(255, 255, 255, 0.05); } } // ===================================== // 开始匹配区域 // ===================================== .start-box { width: 100%; display: flex; flex-direction: column; align-items: center; } .game-intro-card { width: 100%; padding: $spacing-xl; margin-bottom: $spacing-xxl; display: flex; flex-direction: column; gap: $spacing-lg; } .intro-item { display: flex; align-items: center; gap: $spacing-lg; } .intro-icon { font-size: 40rpx; } .intro-text { font-size: $font-md; color: $text-dark-main; font-weight: 500; } // 按钮使用全局定义 .start-btn { width: 380rpx; height: 100rpx; font-size: $font-lg; margin-bottom: $spacing-xxl; } .btn-text { color: $text-inverse; } // ===================================== // 日志区域 - 终端风格 // ===================================== .log-section { width: 100%; flex: 1; display: flex; flex-direction: column; min-height: 200rpx; } .log-header { padding: $spacing-md $spacing-lg; border-bottom: 1px solid $border-dark; display: flex; justify-content: space-between; align-items: center; } .log-title { font-size: $font-xxs; color: $text-dark-sub; text-transform: uppercase; letter-spacing: 4rpx; } .online-indicator { width: 12rpx; height: 12rpx; background: $color-success; border-radius: 50%; box-shadow: 0 0 10rpx $color-success; } .mini-logs { flex: 1; padding: $spacing-md; } .log-item { font-size: $font-xs; line-height: 1.8; margin-bottom: $spacing-xs; display: flex; gap: $spacing-sm; } .log-time { color: rgba(255, 255, 255, 0.3); flex-shrink: 0; } .log-content { word-break: break-all; } .log-system .log-content { color: $accent-cyan; } // ===================================== // 动画特效库 // ===================================== // 飘字上浮动画 @keyframes floatUp { 0% { transform: translate(-50%, 0); opacity: 0; } 20% { opacity: 1; } 80% { opacity: 1; } 100% { transform: translate(-50%, -60rpx); opacity: 0; } } .float-label { position: absolute; pointer-events: none; font-weight: 900; font-size: 36rpx; z-index: 100; animation: floatUp 1s ease-out forwards; text-shadow: 0 0 10rpx rgba(0, 0, 0, 0.8), 2rpx 2rpx 0 #000; white-space: nowrap; &.text-heal { color: $color-success; } &.text-damage { color: $color-error; } &.text-item { color: $color-warning; } &.global { position: fixed; font-size: 48rpx; z-index: 9999; } } // 屏幕震动 @keyframes screenShake { 0%, 100% { transform: translate(0); } 10% { transform: translate(-8rpx, 6rpx); } 20% { transform: translate(8rpx, -6rpx); } 30% { transform: translate(-6rpx, -6rpx); } 40% { transform: translate(6rpx, 6rpx); } 50% { transform: translate(-6rpx, 4rpx); } 60% { transform: translate(6rpx, -4rpx); } 70% { transform: translate(-4rpx, 6rpx); } 80% { transform: translate(4rpx, -6rpx); } 90% { transform: translate(-2rpx, 2rpx); } } .screen-shake { animation: screenShake 0.4s ease-in-out; } // 玩家受伤红闪 @keyframes damageFlash { 0%, 100% { box-shadow: none; background: $bg-dark-card; } 25%, 75% { background: rgba($color-error, 0.2); box-shadow: 0 0 20rpx rgba($color-error, 0.4), inset 0 0 15rpx rgba($color-error, 0.2); } 50% { background: rgba($color-error, 0.4); box-shadow: 0 0 30rpx rgba($color-error, 0.6), inset 0 0 20rpx rgba($color-error, 0.3); } } .player-damaged { animation: damageFlash 0.6s ease-in-out, shake 0.4s ease-in-out; } // 玩家治疗绿闪 @keyframes healGlow { 0%, 100% { box-shadow: none; } 50% { box-shadow: 0 0 20rpx rgba($color-success, 0.6), inset 0 0 10rpx rgba($color-success, 0.3); } } .player-healed { animation: healGlow 0.6s ease-in-out; } // 倒计时紧急脉冲 @keyframes urgentPulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.5; transform: scale(1.1); } } .urgent { animation: urgentPulse 0.5s ease-in-out infinite; color: $color-error !important; } .log-empty { height: 100%; display: flex; align-items: center; justify-content: center; color: rgba(255, 255, 255, 0.2); font-size: $font-sm; font-style: italic; } // ===================================== // 游戏主界面 // ===================================== .game-screen { min-height: 100vh; display: flex; flex-direction: column; } .game-header { display: flex; justify-content: space-between; align-items: center; padding: $spacing-md $spacing-lg; background: $bg-dark-card; backdrop-filter: blur(20rpx); padding-top: calc($spacing-md + env(safe-area-inset-top)); border-bottom: 1px solid $border-dark; } .header-actions { display: flex; gap: $spacing-md; } .header-title { font-size: $font-lg; font-weight: 800; color: $text-dark-main; } .round-badge { background: rgba($brand-primary, 0.2); color: $brand-primary; padding: $spacing-xs $spacing-md; border-radius: $radius-round; font-size: $font-xs; font-weight: bold; } .game-layout { display: flex; flex-direction: column; flex: 1; } .btn-icon { width: 56rpx; height: 56rpx; display: flex; justify-content: center; align-items: center; font-size: $font-lg; background: rgba(255, 255, 255, 0.05); border-radius: $radius-md; &.active { background: rgba($brand-primary, 0.2); } } // ===================================== // 对手栏 // ===================================== .opponents-bar { height: 150rpx; background: rgba(0, 0, 0, 0.2); border-bottom: 1px solid $border-dark; } .opponents-list { display: flex; padding: $spacing-md; gap: $spacing-md; } .player-card { // 默认样式 (通用) background: $bg-dark-card; border: 1px solid $border-dark; border-radius: $radius-lg; padding: $spacing-sm; display: flex; align-items: center; position: relative; transition: all $transition-normal; // 对手样式 (紧凑纵向) &.opponent { min-width: 140rpx; height: 120rpx; flex-direction: column; justify-content: center; gap: 6rpx; .avatar { margin-right: 0; width: 60rpx; height: 60rpx; font-size: 36rpx; margin-bottom: 4rpx; } .player-info { align-items: center; width: 100%; } .username { font-size: 20rpx; // 更小的字体 max-width: 120rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: center; } .status-icons { position: absolute; top: 6rpx; right: 6rpx; flex-direction: column; // 图标纵向排列以节省横向空间 gap: 2rpx; .icon { font-size: 18rpx; background: rgba(0, 0, 0, 0.5); border-radius: 50%; padding: 2rpx; } } } // "我"的样式 (保持横向,但更精致) &.me { background: rgba($brand-primary, 0.1); border-color: rgba($brand-primary, 0.3); min-width: 280rpx; height: 140rpx; padding: $spacing-md; .avatar { width: 80rpx; height: 80rpx; font-size: 44rpx; } .username { font-size: $font-sm; } } &.active-turn { border-color: $brand-primary; box-shadow: 0 0 20rpx rgba($brand-primary, 0.3); } &.damaged { animation: damageFlash 0.6s ease-in-out, shake 0.5s ease-in-out; } &.healed { animation: healGlow 0.6s ease-in-out; } @keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5rpx); } 75% { transform: translateX(5rpx); } } .avatar { font-size: 44rpx; margin-right: $spacing-md; display: flex; align-items: center; justify-content: center; background: rgba(255, 255, 255, 0.1); border-radius: 50%; width: 80rpx; height: 80rpx; &.lg { width: 100rpx; height: 100rpx; font-size: 64rpx; } } .player-info { display: flex; flex-direction: column; gap: 4rpx; } .username { font-size: $font-sm; color: $text-dark-main; font-weight: 600; } .hp-bar { display: flex; gap: 2rpx; } .heart { font-size: 18rpx; } .status-icons { display: flex; gap: 4rpx; .icon { font-size: 16rpx; } } } // ===================================== // 棋盘区域 // ===================================== .board-area { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: $spacing-md; } .turn-indicator { display: flex; gap: $spacing-md; margin-bottom: $spacing-md; } .turn-badge { padding: $spacing-sm $spacing-lg; background: $bg-dark-card; border: 1px solid $border-dark; border-radius: $radius-round; font-size: $font-md; font-weight: 600; color: $text-dark-sub; &.my-turn { background: rgba($brand-primary, 0.15); border-color: $brand-primary; color: $brand-primary; } } .timer-badge { padding: $spacing-sm $spacing-md; background: $bg-dark-card; border-radius: $radius-round; font-size: $font-md; font-weight: 700; color: $text-dark-main; &.urgent { color: $color-error; animation: blink 0.5s ease-in-out infinite; } } .timer-progress-bg { width: 660rpx; height: 6rpx; background: rgba(255, 255, 255, 0.1); border-radius: 3rpx; margin-bottom: $spacing-md; overflow: hidden; } .timer-progress-fill { height: 100%; border-radius: 3rpx; transition: width 1s linear; &.bg-green { background: $color-success; } &.bg-yellow { background: $color-warning; } &.bg-red { background: $color-error; } } .grid-board { display: grid; gap: 6rpx; width: 660rpx; height: 660rpx; padding: $spacing-sm; background: $bg-dark-card; border-radius: $radius-lg; border: 1px solid $border-dark; // 确保格子始终保持正方形 aspect-ratio: 1 / 1; } .grid-cell { background: rgba(255, 255, 255, 0.08); border-radius: $radius-sm; display: flex; justify-content: center; align-items: center; transition: all $transition-fast; position: relative; // 确保每个格子都是正方形 aspect-ratio: 1 / 1; width: 100%; height: auto; &:active { transform: scale(0.95); } &.revealed { background: rgba(0, 0, 0, 0.3); } &.type-bomb { background: rgba($color-error, 0.2); } &.has-magnifier { border: 2rpx dashed rgba($accent-cyan, 0.5); } // --- 新增特效样式 --- &.explosion { animation: explode 0.5s ease-out; } // 道具特效 - 移植自 Explosion.css &.item-medkit { animation: itemReveal 0.5s ease-out, pulseGlowGreen 2s infinite; background-color: rgba(16, 185, 129, 0.2) !important; } &.item-revive { animation: itemReveal 0.5s ease-out, pulseGlowGreen 1.5s infinite; background-color: rgba(16, 185, 129, 0.3) !important; border: 1px solid #10b981; } &.item-knife { animation: itemReveal 0.5s ease-out, glint 1s infinite; background-color: rgba(239, 68, 68, 0.1) !important; } &.item-lightning { animation: itemReveal 0.4s ease-out, glint 0.5s infinite; background-color: rgba(239, 68, 68, 0.2) !important; } &.item-poison { animation: itemReveal 0.6s ease-out, pulseGlowPurple 3s infinite; background-color: rgba(139, 92, 246, 0.2) !important; } &.item-shield { animation: itemReveal 0.5s ease-out, pulseGlowBlue 2s infinite; background-color: rgba(59, 130, 246, 0.2) !important; border-radius: 50% !important; } &.item-skip { animation: itemReveal 0.5s ease-out, pulseGlowGold 2s infinite; background-color: rgba(245, 158, 11, 0.2) !important; opacity: 0.8; } &.item-magnifier { animation: itemReveal 0.5s ease-out, float 2s ease-in-out infinite; background-color: rgba(59, 130, 246, 0.1) !important; } &.item-bomb_timer { animation: itemReveal 0.5s ease-out, pulseGlowRed 0.5s infinite, shake 0.2s infinite; background-color: rgba(239, 68, 68, 0.3) !important; } &.item-curse { animation: itemReveal 0.7s ease-out, pulseGlowPurple 1s infinite; background-color: rgba(139, 92, 246, 0.3) !important; filter: grayscale(0.5) contrast(1.5); } &.item-chest { animation: itemReveal 0.5s ease-out, pulseGlowGold 3s infinite; background-color: rgba(245, 158, 11, 0.3) !important; } // 补充缺失的动画 Keyframes @keyframes explode { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.5); opacity: 0.8; box-shadow: 0 0 20rpx #ef4444, 0 0 40rpx #fb923c; } 100% { transform: scale(1); opacity: 1; box-shadow: 0 0 10rpx rgba(239, 68, 68, 0.4); } } @keyframes itemReveal { 0% { transform: scale(0.5) rotate(-20deg); opacity: 0; } 60% { transform: scale(1.2) rotate(10deg); } 100% { transform: scale(1) rotate(0); opacity: 1; } } @keyframes pulseGlowGreen { 0%, 100% { box-shadow: 0 0 5rpx #10b981; } 50% { box-shadow: 0 0 20rpx #10b981, 0 0 30rpx #34d399; } } @keyframes pulseGlowBlue { 0%, 100% { box-shadow: 0 0 5rpx #3b82f6; } 50% { box-shadow: 0 0 20rpx #3b82f6, 0 0 30rpx #60a5fa; } } @keyframes pulseGlowPurple { 0%, 100% { box-shadow: 0 0 5rpx #8b5cf6; } 50% { box-shadow: 0 0 20rpx #8b5cf6, 0 0 30rpx #a78bfa; } } @keyframes pulseGlowRed { 0%, 100% { box-shadow: 0 0 5rpx #ef4444; } 50% { box-shadow: 0 0 20rpx #ef4444, 0 0 30rpx #f87171; } } @keyframes pulseGlowGold { 0%, 100% { box-shadow: 0 0 5rpx #f59e0b; } 50% { box-shadow: 0 0 20rpx #f59e0b, 0 0 30rpx #fbbf24; } } @keyframes glint { 0% { filter: brightness(1); } 50% { filter: brightness(1.8) contrast(1.2); } 100% { filter: brightness(1); } } .cell-icon { font-size: 32rpx; } .cell-num { font-size: $font-lg; font-weight: 900; } .magnifier-mark { display: flex; justify-content: center; align-items: center; position: relative; .magnifier-content { font-size: 28rpx; opacity: 0.8; } .magnifier-badge { position: absolute; top: 2rpx; right: 2rpx; font-size: 16rpx; } } // ===================================== // 底部面板 // ===================================== .bottom-panel { padding: $spacing-sm; padding-bottom: calc($spacing-sm + env(safe-area-inset-bottom)); background: rgba(0, 0, 0, 0.4); display: flex; gap: $spacing-md; border-top: 1px solid $border-dark; height: 180rpx; // 减小高度 } .game-logs { flex: 1; height: 100%; padding: $spacing-sm; background: rgba(0, 0, 0, 0.3); border-radius: $radius-md; } .log-line { font-size: $font-xxs; line-height: 1.6; color: $text-dark-sub; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; &.log-system { color: $accent-cyan; } &.log-effect { color: $brand-primary; } } // ===================================== // 弹窗 // ===================================== .modal-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.8); backdrop-filter: blur(10rpx); display: flex; justify-content: center; align-items: center; z-index: 1000; } .modal-content { width: 520rpx; padding: $spacing-xxl $spacing-xl; display: flex; flex-direction: column; align-items: center; gap: $spacing-lg; } .modal-emoji { font-size: 100rpx; } .modal-title { font-size: 40rpx; font-weight: 900; color: $text-dark-main; margin-top: $spacing-md; } .result-details { margin: $spacing-lg 0; padding: $spacing-md; background: rgba($bg-dark-card, 0.5); border-radius: $radius-md; width: 100%; .detail-text { font-size: $font-md; color: $text-dark-sub; text-align: center; line-height: 1.6; } } // ===================================== // 玩法说明弹窗 // ===================================== .guide-modal { width: 90%; max-width: 640rpx; max-height: 80vh; display: flex; flex-direction: column; } .guide-header { display: flex; justify-content: space-between; align-items: center; padding: $spacing-lg; border-bottom: 1px solid $border-dark; } .guide-title { font-size: $font-lg; font-weight: 800; color: $text-dark-main; } .close-btn { width: 56rpx; height: 56rpx; display: flex; justify-content: center; align-items: center; font-size: $font-lg; color: $text-dark-sub; background: rgba(255, 255, 255, 0.05); border-radius: 50%; } .guide-body { padding: $spacing-lg; max-height: 60vh; } .section-title { display: block; font-size: $font-md; font-weight: 700; color: $brand-primary; margin-bottom: $spacing-md; } .guide-grid { display: flex; flex-direction: column; gap: $spacing-md; } .guide-item { display: flex; align-items: flex-start; gap: $spacing-md; padding: $spacing-sm; background: rgba(255, 255, 255, 0.03); border-radius: $radius-md; .icon { font-size: 32rpx; flex-shrink: 0; } .desc { display: flex; flex-direction: column; gap: 4rpx; } .name { font-size: $font-sm; font-weight: 600; color: $text-dark-main; } .detail { font-size: $font-xs; color: $text-dark-sub; line-height: 1.5; } } // ===================================== // 飘字动画 // ===================================== .float-label { position: absolute; font-size: $font-md; font-weight: 900; pointer-events: none; animation: floatUp 1s ease-out forwards; z-index: 100; text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.8); &.global { position: fixed; } &.text-damage { color: $color-error; } &.text-heal { color: $color-success; } &.text-effect { color: $accent-cyan; } } @keyframes floatUp { 0% { opacity: 1; transform: translateY(0) scale(1); } 100% { opacity: 0; transform: translateY(-60rpx) scale(0.8); } } // ===================================== // 屏幕震动 & 通用动画 // ===================================== .screen-shake { animation: screenShake 0.4s ease-in-out; } @keyframes screenShake { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-8rpx); } 40% { transform: translateX(8rpx); } 60% { transform: translateX(-4rpx); } 80% { transform: translateX(4rpx); } } .fadeInUp { animation: fadeInUp 0.5s ease-out both; } @keyframes fadeInUp { from { opacity: 0; transform: translateY(40rpx); } to { opacity: 1; transform: translateY(0); } } .pulse { animation: pulse 2s ease-in-out infinite; } @keyframes pulse { 0%, 100% { transform: scale(1); opacity: 0.9; } 50% { transform: scale(1.03); opacity: 1; } } }