diff --git a/app/composeApp/src/commonMain/kotlin/kr/tkrmagid/tetrig/ui/GameScreen.kt b/app/composeApp/src/commonMain/kotlin/kr/tkrmagid/tetrig/ui/GameScreen.kt index e8c5e5d..a1daa93 100644 --- a/app/composeApp/src/commonMain/kotlin/kr/tkrmagid/tetrig/ui/GameScreen.kt +++ b/app/composeApp/src/commonMain/kotlin/kr/tkrmagid/tetrig/ui/GameScreen.kt @@ -318,48 +318,59 @@ private fun MiniPiece(type: Char) { @Composable private fun ControlPad(state: GameState, lefty: Boolean, scale: Float, compactHeight: Boolean) { val h = ((if (compactHeight) 130 else 168) * scale).dp - Row( + val gap = (8 * scale).dp + // 아랫줄 3개(하드 드롭·홀드·소프트 드롭)를 정확히 1/3 씩 주려면 그 줄이 + // 화면 전체 폭을 차지해야 한다. 그래서 좌/우 컬럼으로 쪼개지 않고 + // 바깥을 Column 으로 두어 윗줄·아랫줄을 각각 통짜 Row 로 깐다. + Column( Modifier .fillMaxWidth() .height(h) .padding(horizontal = (10 * scale).dp, vertical = (6 * scale).dp), - horizontalArrangement = Arrangement.spacedBy((8 * scale).dp), + verticalArrangement = Arrangement.spacedBy(gap), ) { - val actions: @Composable (Modifier) -> Unit = { m -> - // 회전은 위쪽 한 줄, 아래는 하드 드롭 + 홀드를 반씩 나눈다. - // 두 컬럼의 행 높이 비율(1.4 : 1)을 맞춰야 좌우가 나란히 떨어진다. - Column(m.fillMaxHeight(), verticalArrangement = Arrangement.spacedBy((8 * scale).dp)) { - Row(Modifier.weight(1.4f).fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy((8 * scale).dp)) { - // HOLD 가 아랫줄로 내려가며 빈 한 칸을 회전 두 개가 나눠 갖는다. - // 180° 는 폭을 유지해야 하므로 4등분 중 1칸(weight 1)을 그대로 - // 두고, ↺·↻ 가 1.5 씩 받아 3/8 폭이 된다. + // ── 윗줄: 회전 | 좌우 이동 ── + Row(Modifier.weight(1.4f).fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(gap)) { + val rotates: @Composable (Modifier) -> Unit = { m -> + Row(m.fillMaxHeight(), horizontalArrangement = Arrangement.spacedBy(gap)) { + // 180° 는 폭을 유지해야 해서 4등분 중 1칸을 그대로 두고, + // ↺·↻ 가 1.5 씩 받아 3/8 폭이 된다. CtrlButton("↺", Modifier.weight(1.5f).fillMaxHeight(), scale) { state.rotate("ccw") } CtrlButton("↻", Modifier.weight(1.5f).fillMaxHeight(), scale) { state.rotate("cw") } CtrlButton("180°", Modifier.weight(1f).fillMaxHeight(), scale) { state.rotate("180") } } - Row(Modifier.weight(1f).fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy((8 * scale).dp)) { - CtrlButton("하드 드롭", Modifier.weight(1f).fillMaxHeight(), scale, accent = true) { state.hardDrop() } - CtrlButton("HOLD", Modifier.weight(1f).fillMaxHeight(), scale) { state.hold() } - } } - } - val moves: @Composable (Modifier) -> Unit = { m -> - Column(m.fillMaxHeight(), verticalArrangement = Arrangement.spacedBy((8 * scale).dp)) { - Row(Modifier.weight(1.4f).fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy((8 * scale).dp)) { + val moves: @Composable (Modifier) -> Unit = { m -> + Row(m.fillMaxHeight(), horizontalArrangement = Arrangement.spacedBy(gap)) { HoldCtrl("◀", Modifier.weight(1f).fillMaxHeight(), scale, { state.press(-1) }, { state.release(-1) }) HoldCtrl("▶", Modifier.weight(1f).fillMaxHeight(), scale, { state.press(1) }, { state.release(1) }) } - HoldCtrl("▼ 소프트", Modifier.weight(1f).fillMaxWidth(), scale, { state.setSoft(true) }, { state.setSoft(false) }) + } + if (lefty) { + moves(Modifier.weight(1f)) + rotates(Modifier.weight(1.35f)) + } else { + rotates(Modifier.weight(1.35f)) + moves(Modifier.weight(1f)) } } - // 액션쪽이 한 줄에 버튼 4개라 폭을 더 준다. 1.1 이면 버튼이 세로로 길쭉해져 - // 엄지로 누르기 불편했다. - if (lefty) { - moves(Modifier.weight(1f)) - actions(Modifier.weight(1.35f)) - } else { - actions(Modifier.weight(1.35f)) - moves(Modifier.weight(1f)) + + // ── 아랫줄: 하드 드롭 · 홀드 · 소프트 드롭 3등분 ── + Row(Modifier.weight(1f).fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(gap)) { + val third = Modifier.weight(1f).fillMaxHeight() + val hardDrop: @Composable (Modifier) -> Unit = { m -> + CtrlButton("하드 드롭", m, scale, accent = true) { state.hardDrop() } + } + val hold: @Composable (Modifier) -> Unit = { m -> CtrlButton("HOLD", m, scale) { state.hold() } } + val soft: @Composable (Modifier) -> Unit = { m -> + HoldCtrl("▼ 소프트", m, scale, { state.setSoft(true) }, { state.setSoft(false) }) + } + // 왼손 배치에서는 좌우를 뒤집는다 (소프트가 왼쪽 엄지 쪽으로). + if (lefty) { + soft(third); hold(third); hardDrop(third) + } else { + hardDrop(third); hold(third); soft(third) + } } } } diff --git a/store/shots/03_game.png b/store/shots/03_game.png index 1bd5ba7..500980a 100644 Binary files a/store/shots/03_game.png and b/store/shots/03_game.png differ diff --git a/store/shots/tablet_02_game.png b/store/shots/tablet_02_game.png index b1d646c..e3744ff 100644 Binary files a/store/shots/tablet_02_game.png and b/store/shots/tablet_02_game.png differ