diff --git a/ui/Components.slint b/ui/Components.slint index d376613..ff6b035 100644 --- a/ui/Components.slint +++ b/ui/Components.slint @@ -1,17 +1,19 @@ import { LineEdit } from "std-widgets.slint"; export component Button inherits Rectangle { + in property scale; + in property text; in property enabled: true; callback clicked; - width: 100px; - height: 36px; + width: 100px * scale; + height: 36px * scale; background: !root.enabled ? #555555 // 禁用状态 : touch.pressed ? #444444 // 按下 : #2C2C2C; // 默认 - border-radius: 6px; + border-radius: 6px * scale; touch := TouchArea { enabled: root.enabled; @@ -23,41 +25,43 @@ export component Button inherits Rectangle { Text { text: root.text; color: #FFFFFF; - font-size: 14px; + font-size: 14px * scale; vertical-alignment: center; horizontal-alignment: center; } } export component LabeledInput inherits VerticalLayout { + in property scale; + in property input-type: InputType.text; in property label-text; in-out property value <=> input.text; in property placeholder; - spacing: 6px; + spacing: 6px * scale; // 标签文本 Text { text: root.label-text; - font-size: 12px; + font-size: 12px * scale; font-weight: 500; color: #555555; } // 输入框背景和实体 Rectangle { - height: 36px; + height: 36px * scale; background: #FFFFFF; - border-radius: 6px; - border-width: 1px; + border-radius: 6px * scale; + border-width: 1px * scale; border-color: input.has-focus ? #888888 : #E0E0E0; // 聚焦时边框变深 input := LineEdit { width: 100%; height: 100%; - font-size: 14px; + font-size: 14px * scale; placeholder-text: root.placeholder; input-type: root.input-type; } diff --git a/ui/ConnectPage.slint b/ui/ConnectPage.slint index 1f1f8e1..16f0a33 100644 --- a/ui/ConnectPage.slint +++ b/ui/ConnectPage.slint @@ -4,13 +4,15 @@ import { } from "std-widgets.slint"; import { Button, LabeledInput } from "Components.slint"; -export component ConnectPage inherits Window { +export component ConnectPage inherits Rectangle { + in property scale; + in property is-connecting; callback request-connect(string, string, string); - width: 1920px; - height: 1080px; + width: 100%; + height: 100%; // 背景渐变 (从左上角的米色到右下角的淡粉色) Rectangle { @@ -19,29 +21,29 @@ export component ConnectPage inherits Window { // 中心卡片 Rectangle { - width: 600px; - height: 600px; // 根据内容高度调整 + width: 600px * scale; + height: 600px * scale; // 根据内容高度调整 background: #FDFBF8; // 略微区别于背景的米白色 - border-radius: 20px; + border-radius: 20px * scale; // 简单的阴影模拟 - drop-shadow-blur: 20px; + drop-shadow-blur: 20px * scale; drop-shadow-color: #00000015; - drop-shadow-offset-y: 4px; + drop-shadow-offset-y: 4px * scale; VerticalLayout { - padding: 40px; - spacing: 20px; + padding: 40px * scale; + spacing: 20px * scale; alignment: center; // 标题区域 VerticalLayout { - spacing: 8px; + spacing: 8px * scale; alignment: center; Text { text: "UNO"; - font-size: 96px; + font-size: 96px * scale; font-weight: 700; color: #222222; horizontal-alignment: center; @@ -49,7 +51,7 @@ export component ConnectPage inherits Window { Text { text: "连接至服务器以开始游戏"; - font-size: 14px; + font-size: 14px * scale; color: #666666; horizontal-alignment: center; } @@ -57,32 +59,36 @@ export component ConnectPage inherits Window { // 占位间隔 Rectangle { - height: 10px; + height: 10px * scale; } // 表单区域 address-input := LabeledInput { + scale: root.scale; label-text: "服务器地址"; value: "localhost"; } port-input := LabeledInput { + scale: root.scale; label-text: "服务器端口"; value: "10001"; input-type: InputType.number; } name-input := LabeledInput { + scale: root.scale; label-text: "玩家昵称"; value: "Player"; } // 底部按钮区域 (增加一点顶部间距) HorizontalLayout { - padding-top: 10px; + padding-top: 10px * scale; alignment: center; Button { + scale: root.scale; text: is-connecting ? "正在连接..." : "连接"; enabled: !is-connecting; clicked => { diff --git a/ui/GamePage.slint b/ui/GamePage.slint index 5bbc644..e373d12 100644 --- a/ui/GamePage.slint +++ b/ui/GamePage.slint @@ -34,28 +34,30 @@ export struct HandCard { // 玩家头像组件 component PlayerAvatar inherits Rectangle { + in property scale; + in property player-name; in property card-count; in property has-uno; in property is-current-turn; - width: 100px; - height: 130px; + width: 100px * scale; + height: 130px * scale; background: transparent; VerticalLayout { - spacing: 4px; + spacing: 4px * scale; alignment: center; // UNO 标志占位区域 (固定高度) HorizontalLayout { alignment: center; Rectangle { - width: 50px; - height: 20px; + width: 50px * scale; + height: 20px * scale; background: has-uno ? #FF5722 : transparent; - border-radius: 4px; + border-radius: 4px * scale; Text { text: "UNO!"; - font-size: 11px; + font-size: 11px * scale; font-weight: 700; color: has-uno ? #FFFFFF : transparent; horizontal-alignment: center; @@ -68,15 +70,15 @@ component PlayerAvatar inherits Rectangle { HorizontalLayout { alignment: center; Rectangle { - width: 60px; - height: 60px; + width: 60px * scale; + height: 60px * scale; background: is-current-turn ? #FFD54F : #E0E0E0; - border-radius: 30px; - border-width: is-current-turn ? 3px : 0px; + border-radius: 30px * scale; + border-width: is-current-turn ? 3px * scale : 0px; border-color: #FF9800; Text { text: "👤"; - font-size: 28px; + font-size: 28px * scale; horizontal-alignment: center; vertical-alignment: center; } @@ -86,7 +88,7 @@ component PlayerAvatar inherits Rectangle { // 玩家名称 Text { text: player-name; - font-size: 12px; + font-size: 12px * scale; font-weight: 500; color: #333333; horizontal-alignment: center; @@ -95,7 +97,7 @@ component PlayerAvatar inherits Rectangle { // 剩余手牌数 Text { text: "剩余: " + card-count + " 张"; - font-size: 10px; + font-size: 10px * scale; color: #666666; horizontal-alignment: center; } @@ -104,22 +106,24 @@ component PlayerAvatar inherits Rectangle { // 卡牌背面组件 (起牌堆) component CardBack inherits Rectangle { + in property scale; + in property card-width: 100; in property card-height: 150; - width: card-width * 1px; - height: card-height * 1px; + width: card-width * 1px * scale; + height: card-height * 1px * scale; background: #2C2C2C; - border-radius: 10px; - border-width: 2px; + border-radius: 10px * scale; + border-width: 2px * scale; border-color: #444444; Rectangle { width: parent.width * 0.75; height: parent.height * 0.83; background: #1a1a1a; - border-radius: 8px; + border-radius: 8px * scale; Text { text: "UNO"; - font-size: 20px; + font-size: 20px * scale; font-weight: 700; color: #888888; horizontal-alignment: center; @@ -130,16 +134,18 @@ component CardBack inherits Rectangle { // 弃牌堆卡牌组件 component DiscardCard inherits Rectangle { + in property scale; + in property card-image; in property card-width: 100; in property card-height: 150; - width: card-width * 1px; - height: card-height * 1px; + width: card-width * 1px * scale; + height: card-height * 1px * scale; background: transparent; - border-radius: 10px; - drop-shadow-blur: 12px; + border-radius: 10px * scale; + drop-shadow-blur: 12px * scale; drop-shadow-color: #00000040; - drop-shadow-offset-y: 4px; + drop-shadow-offset-y: 4px * scale; Image { width: 100%; height: 100%; @@ -150,6 +156,8 @@ component DiscardCard inherits Rectangle { // 方向环背景组件 - 只绘制环线 component DirectionRingBackground inherits Rectangle { + in property scale; + in property current-color: CardColor.Red; in property ring-width: 500; in property ring-height: 280; @@ -157,8 +165,8 @@ component DirectionRingBackground inherits Rectangle { property ring-color-dim: current-color == CardColor.Red ? #E57373 : current-color == CardColor.Blue ? #64B5F6 : current-color == CardColor.Green ? #81C784 : current-color == CardColor.Yellow ? #FFF176 : #BDBDBD; property a: ring-width / 2; property b: ring-height / 2; - width: ring-width * 1px; - height: ring-height * 1px; + width: ring-width * 1px * scale; + height: ring-height * 1px * scale; background: transparent; // 底层光晕环 @@ -166,28 +174,28 @@ component DirectionRingBackground inherits Rectangle { width: 100%; height: 100%; stroke: ring-color-dim; - stroke-width: 8px; + stroke-width: 8px * scale; fill: transparent; opacity: 0.3; MoveTo { - x: ring-width / 2 + a; - y: ring-height / 2; + x: (ring-width / 2 + a) * scale; + y: (ring-height / 2) * scale; } ArcTo { - x: ring-width / 2 - a; - y: ring-height / 2; - radius-x: a; - radius-y: b; + x: (ring-width / 2 - a) * scale; + y: (ring-height / 2) * scale; + radius-x: a * scale; + radius-y: b * scale; sweep: true; large-arc: true; } ArcTo { - x: ring-width / 2 + a; - y: ring-height / 2; - radius-x: a; - radius-y: b; + x: (ring-width / 2 + a) * scale; + y: (ring-height / 2) * scale; + radius-x: a * scale; + radius-y: b * scale; sweep: true; large-arc: true; } @@ -198,28 +206,28 @@ component DirectionRingBackground inherits Rectangle { width: 100%; height: 100%; stroke: ring-color; - stroke-width: 3px; + stroke-width: 3px * scale; fill: transparent; opacity: 0.9; MoveTo { - x: ring-width / 2 + a; - y: ring-height / 2; + x: (ring-width / 2 + a) * scale; + y: (ring-height / 2) * scale; } ArcTo { - x: ring-width / 2 - a; - y: ring-height / 2; - radius-x: a; - radius-y: b; + x: (ring-width / 2 - a) * scale; + y: (ring-height / 2) * scale; + radius-x: a * scale; + radius-y: b * scale; sweep: true; large-arc: true; } ArcTo { - x: ring-width / 2 + a; - y: ring-height / 2; - radius-x: a; - radius-y: b; + x: (ring-width / 2 + a) * scale; + y: (ring-height / 2) * scale; + radius-x: a * scale; + radius-y: b * scale; sweep: true; large-arc: true; } @@ -228,6 +236,8 @@ component DirectionRingBackground inherits Rectangle { // 方向环光点组件 - 使用内置动画实现平滑移动 component DirectionRingOrbs inherits Rectangle { + in property scale; + in property direction: GameDirection.Clockwise; in property current-color: CardColor.Red; in property ring-width: 500; @@ -248,55 +258,55 @@ component DirectionRingOrbs inherits Rectangle { // 实际角度 = 基础角度 * 方向系数 property actual-angle: base-angle * dir-sign; - width: ring-width * 1px; - height: ring-height * 1px; + width: ring-width * 1px * scale; + height: ring-height * 1px * scale; background: transparent; // 光点1 Rectangle { - x: parent.width / 2 - 9px + cos(actual-angle * 1deg) * a * 1px; - y: parent.height / 2 - 9px + sin(actual-angle * 1deg) * b * 1px; - width: 18px; - height: 18px; + x: (parent.width / 2 - 9px * scale) + cos(actual-angle * 1deg) * a * 1px * scale; + y: (parent.height / 2 - 9px * scale) + sin(actual-angle * 1deg) * b * 1px * scale; + width: 18px * scale; + height: 18px * scale; background: ring-color; - border-radius: 9px; - drop-shadow-blur: 8px; + border-radius: 9px * scale; + drop-shadow-blur: 8px * scale; drop-shadow-color: ring-color; } // 光点2 Rectangle { - x: parent.width / 2 - 9px + cos((actual-angle + 90) * 1deg) * a * 1px; - y: parent.height / 2 - 9px + sin((actual-angle + 90) * 1deg) * b * 1px; - width: 18px; - height: 18px; + x: (parent.width / 2 - 9px * scale) + cos((actual-angle + 90) * 1deg) * a * 1px * scale; + y: (parent.height / 2 - 9px * scale) + sin((actual-angle + 90) * 1deg) * b * 1px * scale; + width: 18px * scale; + height: 18px * scale; background: ring-color; - border-radius: 9px; - drop-shadow-blur: 8px; + border-radius: 9px * scale; + drop-shadow-blur: 8px * scale; drop-shadow-color: ring-color; } // 光点3 Rectangle { - x: parent.width / 2 - 9px + cos((actual-angle + 180) * 1deg) * a * 1px; - y: parent.height / 2 - 9px + sin((actual-angle + 180) * 1deg) * b * 1px; - width: 18px; - height: 18px; + x: (parent.width / 2 - 9px * scale) + cos((actual-angle + 180) * 1deg) * a * 1px * scale; + y: (parent.height / 2 - 9px * scale) + sin((actual-angle + 180) * 1deg) * b * 1px * scale; + width: 18px * scale; + height: 18px * scale; background: ring-color; - border-radius: 9px; - drop-shadow-blur: 8px; + border-radius: 9px * scale; + drop-shadow-blur: 8px * scale; drop-shadow-color: ring-color; } // 光点4 Rectangle { - x: parent.width / 2 - 9px + cos((actual-angle + 270) * 1deg) * a * 1px; - y: parent.height / 2 - 9px + sin((actual-angle + 270) * 1deg) * b * 1px; - width: 18px; - height: 18px; + x: (parent.width / 2 - 9px * scale) + cos((actual-angle + 270) * 1deg) * a * 1px * scale; + y: (parent.height / 2 - 9px * scale) + sin((actual-angle + 270) * 1deg) * b * 1px * scale; + width: 18px * scale; + height: 18px * scale; background: ring-color; - border-radius: 9px; - drop-shadow-blur: 8px; + border-radius: 9px * scale; + drop-shadow-blur: 8px * scale; drop-shadow-color: ring-color; } @@ -308,17 +318,19 @@ component DirectionRingOrbs inherits Rectangle { // 手牌卡牌组件 component HandCardItem inherits Rectangle { + in property scale; + in property card-image; in property is-selected: false; callback clicked; - width: 120px; - height: 180px; - y: is-selected ? -25px : 0px; + width: 120px * scale; + height: 180px * scale; + y: is-selected ? -25px * scale : 0px; background: transparent; - border-radius: 10px; - drop-shadow-blur: is-selected ? 16px : 6px; + border-radius: 10px * scale; + drop-shadow-blur: is-selected ? 16px * scale : 6px * scale; drop-shadow-color: is-selected ? #00000040 : #00000025; - drop-shadow-offset-y: is-selected ? 6px : 3px; + drop-shadow-offset-y: is-selected ? 6px * scale : 3px * scale; animate y { duration: 150ms; easing: ease-out; @@ -340,14 +352,15 @@ component HandCardItem inherits Rectangle { // UNO 圆形按钮组件 component UnoButton inherits Rectangle { + in property scale; callback clicked; - width: 90px; - height: 90px; + width: 90px * scale; + height: 90px * scale; background: touch.pressed ? #D32F2F : #F44336; - border-radius: 45px; - drop-shadow-blur: 12px; + border-radius: 45px * scale; + drop-shadow-blur: 12px * scale; drop-shadow-color: #F4433660; - drop-shadow-offset-y: 4px; + drop-shadow-offset-y: 4px * scale; touch := TouchArea { clicked => { root.clicked(); @@ -356,7 +369,7 @@ component UnoButton inherits Rectangle { Text { text: "UNO!"; - font-size: 20px; + font-size: 20px * scale; font-weight: 700; color: #FFFFFF; horizontal-alignment: center; @@ -366,18 +379,19 @@ component UnoButton inherits Rectangle { // 颜色选择按钮组件 component ColorButton inherits Rectangle { + in property scale; in property btn-color; in property color-name; callback clicked; - width: 80px; - height: 80px; + width: 80px * scale; + height: 80px * scale; background: touch.pressed ? btn-color.darker(20%) : btn-color; - border-radius: 12px; - border-width: 3px; + border-radius: 12px * scale; + border-width: 3px * scale; border-color: btn-color.darker(30%); - drop-shadow-blur: 8px; + drop-shadow-blur: 8px * scale; drop-shadow-color: btn-color.with-alpha(0.4); - drop-shadow-offset-y: 3px; + drop-shadow-offset-y: 3px * scale; touch := TouchArea { clicked => { root.clicked(); @@ -386,7 +400,7 @@ component ColorButton inherits Rectangle { Text { text: color-name; - font-size: 14px; + font-size: 14px * scale; font-weight: 600; color: #FFFFFF; horizontal-alignment: center; @@ -396,6 +410,7 @@ component ColorButton inherits Rectangle { // 颜色选择弹窗组件 component ColorPickerDialog inherits Rectangle { + in property scale; in property show: false; callback color-selected(CardColor); callback cancel; @@ -421,13 +436,13 @@ component ColorPickerDialog inherits Rectangle { Rectangle { x: (parent.width - self.width) / 2; y: (parent.height - self.height) / 2; - width: 600px; - height: 280px; + width: 600px * scale; + height: 280px * scale; background: #FFFFFF; - border-radius: 20px; - drop-shadow-blur: 30px; + border-radius: 20px * scale; + drop-shadow-blur: 30px * scale; drop-shadow-color: #00000040; - drop-shadow-offset-y: 10px; + drop-shadow-offset-y: 10px * scale; // 阻止点击弹窗内容时关闭 TouchArea { @@ -435,14 +450,14 @@ component ColorPickerDialog inherits Rectangle { } VerticalLayout { - padding: 30px; - spacing: 25px; + padding: 30px * scale; + spacing: 25px * scale; alignment: center; // 标题 Text { text: "选择颜色"; - font-size: 24px; + font-size: 24px * scale; font-weight: 700; color: #333333; horizontal-alignment: center; @@ -450,9 +465,10 @@ component ColorPickerDialog inherits Rectangle { // 颜色按钮网格 HorizontalLayout { - spacing: 20px; + spacing: 20px * scale; alignment: center; ColorButton { + scale: root.scale; btn-color: #F44336; color-name: "红色"; clicked => { @@ -461,6 +477,7 @@ component ColorPickerDialog inherits Rectangle { } ColorButton { + scale: root.scale; btn-color: #2196F3; color-name: "蓝色"; clicked => { @@ -469,6 +486,7 @@ component ColorPickerDialog inherits Rectangle { } ColorButton { + scale: root.scale; btn-color: #4CAF50; color-name: "绿色"; clicked => { @@ -477,6 +495,7 @@ component ColorPickerDialog inherits Rectangle { } ColorButton { + scale: root.scale; btn-color: #FFEB3B; color-name: "黄色"; clicked => { @@ -489,6 +508,7 @@ component ColorPickerDialog inherits Rectangle { HorizontalLayout { alignment: center; Button { + scale: root.scale; text: "取消"; clicked => { root.cancel(); @@ -500,7 +520,8 @@ component ColorPickerDialog inherits Rectangle { } // 主游戏页面 -export component GamePage inherits Window { +export component GamePage inherits Rectangle { + in property scale; // 其他玩家列表 in property <[OtherPlayer]> other-players; @@ -530,8 +551,8 @@ export component GamePage inherits Window { callback request-play-card(int, CardColor); callback request-draw-card; callback request-uno; - width: 1920px; - height: 1080px; + width: 100%; + height: 100%; // 背景渐变 Rectangle { @@ -540,25 +561,26 @@ export component GamePage inherits Window { // 主布局 VerticalLayout { - padding: 30px; - spacing: 20px; + padding: 30px * scale; + spacing: 20px * scale; // ===== 顶部:其他玩家区域 ===== Rectangle { - height: 150px; + height: 150px * scale; background: #FDFBF8; - border-radius: 16px; - drop-shadow-blur: 10px; + border-radius: 16px * scale; + drop-shadow-blur: 10px * scale; drop-shadow-color: #00000010; - drop-shadow-offset-y: 2px; + drop-shadow-offset-y: 2px * scale; HorizontalLayout { - padding-top: 10px; - padding-bottom: 15px; - padding-left: 15px; - padding-right: 15px; - spacing: 40px; + padding-top: 10px * scale; + padding-bottom: 15px * scale; + padding-left: 15px * scale; + padding-right: 15px * scale; + spacing: 40px * scale; alignment: center; for player[index] in other-players: PlayerAvatar { + scale: root.scale; player-name: player.name; card-count: player.card-count; has-uno: player.has-uno; @@ -574,14 +596,15 @@ export component GamePage inherits Window { // 中心容器:包含环和两个牌堆 Rectangle { - width: 560px; - height: 320px; + width: 560px * scale; + height: 320px * scale; x: (parent.width - self.width) / 2; y: (parent.height - self.height) / 2; background: transparent; // 方向环背景 - 在牌堆下面 DirectionRingBackground { + scale: root.scale; x: (parent.width - self.width) / 2; y: (parent.height - self.height) / 2; ring-width: 560; @@ -591,11 +614,12 @@ export component GamePage inherits Window { // 起牌堆 - 左侧 Rectangle { - x: 80px; - y: (parent.height - 200px) / 2; - width: 130px; - height: 200px; + x: 80px * scale; + y: (parent.height - 200px * scale) / 2; + width: 130px * scale; + height: 200px * scale; CardBack { + scale: root.scale; card-width: 130; card-height: 200; } @@ -613,15 +637,17 @@ export component GamePage inherits Window { // 弃牌堆 - 右侧 DiscardCard { - x: parent.width - 130px - 80px; - y: (parent.height - 200px) / 2; + scale: root.scale; + x: parent.width - 130px * scale - 80px * scale; + y: (parent.height - 200px * scale) / 2; card-width: 130; card-height: 200; card-image: root.discard-top-card; } // 方向环光点 - 在牌堆上面 - DirectionRingOrbs { + DirectionRingOrbs { + scale: root.scale; x: (parent.width - self.width) / 2; y: (parent.height - self.height) / 2; ring-width: 560; @@ -634,23 +660,24 @@ export component GamePage inherits Window { // ===== 底部:当前玩家区域 ===== Rectangle { - height: 320px; + height: 320px * scale; background: #FDFBF8; - border-radius: 16px; - drop-shadow-blur: 10px; + border-radius: 16px * scale; + drop-shadow-blur: 10px * scale; drop-shadow-color: #00000010; - drop-shadow-offset-y: -2px; + drop-shadow-offset-y: -2px * scale; HorizontalLayout { - padding: 20px; - padding-left: 40px; - padding-right: 40px; - spacing: 30px; + padding: 20px * scale; + padding-left: 40px * scale; + padding-right: 40px * scale; + spacing: 30px * scale; alignment: space-between; // 当前玩家头像 - 靠左,垂直居中与UNO按钮对齐 VerticalLayout { alignment: center; PlayerAvatar { + scale: root.scale; player-name: current-player-name; card-count: current-player-card-count; has-uno: current-player-has-uno; @@ -661,17 +688,18 @@ export component GamePage inherits Window { // 手牌区域 VerticalLayout { horizontal-stretch: 1; - spacing: 10px; + spacing: 10px * scale; alignment: center; // 出牌按钮 (放在手牌上方) Rectangle { - height: 50px; + height: 50px * scale; background: transparent; HorizontalLayout { alignment: center; - padding-bottom: 10px; + padding-bottom: 10px * scale; Button { + scale: root.scale; text: "出牌"; enabled: is-current-player-turn && selected-card-index >= 0 && hand-cards[selected-card-index].can-be-played; clicked => { @@ -693,20 +721,21 @@ export component GamePage inherits Window { // 手牌列表 - 上方留出空间给选中效果 Rectangle { - height: 210px; + height: 210px * scale; background: transparent; // 手牌容器,向下偏移以给选中卡牌留空间,居中显示 Rectangle { x: (parent.width - self.width) / 2; - y: 25px; + y: 25px * scale; width: hand-cards-layout.preferred-width; - height: 180px; + height: 180px * scale; hand-cards-layout := HorizontalLayout { alignment: center; - spacing: -35px; // 卡牌重叠效果 + spacing: -35px * scale; // 卡牌重叠效果 for card[index] in hand-cards: HandCardItem { + scale: root.scale; card-image: card.image-path; is-selected: index == selected-card-index; clicked => { @@ -729,6 +758,7 @@ export component GamePage inherits Window { VerticalLayout { alignment: center; UnoButton { + scale: root.scale; clicked => { root.request-uno(); } @@ -740,6 +770,7 @@ export component GamePage inherits Window { // 颜色选择弹窗 (覆盖在最上层) ColorPickerDialog { + scale: root.scale; show: root.show-color-picker; color-selected(color) => { root.show-color-picker = false; diff --git a/ui/MainWindow.slint b/ui/MainWindow.slint index 95fdde3..c9666c9 100644 --- a/ui/MainWindow.slint +++ b/ui/MainWindow.slint @@ -1,6 +1,12 @@ import { ConnectPage } from "ConnectPage.slint"; import { StartPage } from "StartPage.slint"; -import { GamePage, OtherPlayer, HandCard, CardColor, GameDirection } from "GamePage.slint"; +import { + GamePage, + OtherPlayer, + HandCard, + CardColor, + GameDirection, +} from "GamePage.slint"; enum PageType { ConnectPage, @@ -35,17 +41,23 @@ export component MainWindow inherits Window { callback request-draw-card; callback request-uno; - width: 1920px; - height: 1080px; + preferred-width: 1920px; + preferred-height: 1080px; + min-width: 960px; + min-height: 600px; title: "UNO!"; + property scale: min(self.width / 1920px, self.height / 1080px); + if root.active-page == PageType.ConnectPage: connect-page := ConnectPage { + scale: root.scale; is-connecting: root.is-connecting; request-connect(server-address, server-port, player-name) => { root.request-connect(server-address, server-port, player-name); } } if root.active-page == PageType.StartPage: start-page := StartPage { + scale: root.scale; is-ready: root.is-ready; is-restart: root.is-restart; request-start => { @@ -53,6 +65,7 @@ export component MainWindow inherits Window { } } if root.active-page == PageType.GamePage: game-page := GamePage { + scale: root.scale; other-players: root.other-players; current-player-name: root.current-player-name; current-player-card-count: root.current-player-card-count; diff --git a/ui/StartPage.slint b/ui/StartPage.slint index 172b317..1239dd7 100644 --- a/ui/StartPage.slint +++ b/ui/StartPage.slint @@ -1,13 +1,14 @@ import {Button} from "Components.slint"; -export component StartPage inherits Window { +export component StartPage inherits Rectangle { + in property scale; in property is-ready; in property is-restart; callback request-start; - width: 1920px; - height: 1080px; + width: 100%; + height: 100%; // 背景渐变 (从左上角的米色到右下角的淡粉色) Rectangle { @@ -16,29 +17,29 @@ export component StartPage inherits Window { // 中心卡片 Rectangle { - width: 600px; - height: 600px; // 根据内容高度调整 + width: 600px * scale; + height: 600px * scale; // 根据内容高度调整 background: #FDFBF8; // 略微区别于背景的米白色 - border-radius: 20px; + border-radius: 20px * scale; // 简单的阴影模拟 - drop-shadow-blur: 20px; + drop-shadow-blur: 20px * scale; drop-shadow-color: #00000015; - drop-shadow-offset-y: 4px; + drop-shadow-offset-y: 4px * scale; VerticalLayout { - padding: 40px; - spacing: 20px; + padding: 40px * scale; + spacing: 20px * scale; alignment: center; // 标题区域 VerticalLayout { - spacing: 8px; + spacing: 8px * scale; alignment: center; Text { text: "UNO"; - font-size: 96px; + font-size: 96px * scale; font-weight: 700; color: #222222; horizontal-alignment: center; @@ -46,7 +47,7 @@ export component StartPage inherits Window { Text { text: is-restart ? "游戏结束,重新准备以重新开始游戏" : "连接成功,所有玩家准备后开始游戏"; - font-size: 14px; + font-size: 14px * scale; color: #666666; horizontal-alignment: center; } @@ -54,15 +55,16 @@ export component StartPage inherits Window { // 占位间隔 Rectangle { - height: 10px; + height: 10px * scale; } // 底部按钮区域 (增加一点顶部间距) HorizontalLayout { - padding-top: 10px; + padding-top: 10px * scale; alignment: center; Button { + scale: root.scale; enabled: !is-ready; text: is-ready ? "已准备" : "准备"; clicked => {