Compare commits
5 Commits
74ac78aaaa
...
v2.0.3
| Author | SHA1 | Date | |
|---|---|---|---|
| 43c8ccd6d2 | |||
| f8c6bfab49 | |||
| 5e674fa686 | |||
| fe13a61c09 | |||
| da0f355b98 |
@@ -181,14 +181,33 @@ private fun BoardWithPanels(state: GameState, ghostOn: Boolean, l: Layout, stack
|
||||
BoardCanvas(state, ghostOn)
|
||||
}
|
||||
Column(Modifier.width(panelW)) {
|
||||
SidePanel("HOLD", listOfNotNull(state.game.hold), s, 1, l.isTiny)
|
||||
Spacer(Modifier.height((8 * s).dp))
|
||||
SidePanel("NEXT", state.game.peekNext(if (l.isTiny) 3 else 5), s, if (l.isTiny) 3 else 5, l.isTiny)
|
||||
SidePanels(state, s, l.isTiny)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HOLD / NEXT 패널.
|
||||
*
|
||||
* `game.hold` 와 `game.peekNext()` 는 Compose 가 관찰하지 못하는 평범한 엔진
|
||||
* 필드라, 값이 바뀌어도 그것만으로는 재구성이 일어나지 않는다. BoardCanvas 와
|
||||
* 똑같이 여기서 `state.version` 을 읽어 구독해야 한다. 이 구독이 없으면 게임이
|
||||
* 시작될 때의 넥스트 큐가 끝까지 그대로 멈춰 있는다.
|
||||
*
|
||||
* 보드 전체가 아니라 패널만 따로 떼어 둔 이유는, 재구성 범위를 이 서브트리로
|
||||
* 좁혀 매 프레임 BoxWithConstraints 측정까지 다시 돌지 않게 하기 위해서다.
|
||||
*/
|
||||
@Composable
|
||||
private fun SidePanels(state: GameState, s: Float, tiny: Boolean) {
|
||||
@Suppress("UNUSED_EXPRESSION")
|
||||
state.version
|
||||
val nextCount = if (tiny) 3 else 5
|
||||
SidePanel("HOLD", listOfNotNull(state.game.hold), s, 1, tiny)
|
||||
Spacer(Modifier.height((8 * s).dp))
|
||||
SidePanel("NEXT", state.game.peekNext(nextCount), s, nextCount, tiny)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoardCanvas(state: GameState, ghostOn: Boolean) {
|
||||
@Suppress("UNUSED_EXPRESSION")
|
||||
@@ -307,15 +326,20 @@ private fun ControlPad(state: GameState, lefty: Boolean, scale: Float, compactHe
|
||||
horizontalArrangement = Arrangement.spacedBy((8 * scale).dp),
|
||||
) {
|
||||
val actions: @Composable (Modifier) -> Unit = { m ->
|
||||
// 회전은 위쪽 한 줄, 아래는 하드 드롭 + 홀드를 반씩 나눈다.
|
||||
// 두 컬럼의 행 높이 비율(1.4 : 1)을 맞춰야 좌우가 나란히 떨어진다.
|
||||
Column(m.fillMaxHeight(), verticalArrangement = Arrangement.spacedBy((8 * scale).dp)) {
|
||||
Row(Modifier.weight(1f).fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy((8 * scale).dp)) {
|
||||
CtrlButton("HOLD", Modifier.weight(2f).fillMaxHeight(), scale) { state.hold() }
|
||||
Row(Modifier.weight(1.4f).fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy((8 * scale).dp)) {
|
||||
// HOLD 가 아랫줄로 내려가며 빈 한 칸을 회전 두 개가 나눠 갖는다.
|
||||
// 180° 는 폭을 유지해야 하므로 4등분 중 1칸(weight 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) { state.rotate("ccw") }
|
||||
CtrlButton("↻", Modifier.weight(1f).fillMaxHeight(), scale) { state.rotate("cw") }
|
||||
CtrlButton("하드\n드롭", Modifier.weight(1f).fillMaxHeight(), scale, accent = true) { state.hardDrop() }
|
||||
CtrlButton("하드 드롭", Modifier.weight(1f).fillMaxHeight(), scale, accent = true) { state.hardDrop() }
|
||||
CtrlButton("HOLD", Modifier.weight(1f).fillMaxHeight(), scale) { state.hold() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -328,11 +352,13 @@ private fun ControlPad(state: GameState, lefty: Boolean, scale: Float, compactHe
|
||||
HoldCtrl("▼ 소프트", Modifier.weight(1f).fillMaxWidth(), scale, { state.setSoft(true) }, { state.setSoft(false) })
|
||||
}
|
||||
}
|
||||
// 액션쪽이 한 줄에 버튼 4개라 폭을 더 준다. 1.1 이면 버튼이 세로로 길쭉해져
|
||||
// 엄지로 누르기 불편했다.
|
||||
if (lefty) {
|
||||
moves(Modifier.weight(1f))
|
||||
actions(Modifier.weight(1.1f))
|
||||
actions(Modifier.weight(1.35f))
|
||||
} else {
|
||||
actions(Modifier.weight(1.1f))
|
||||
actions(Modifier.weight(1.35f))
|
||||
moves(Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,5 +10,5 @@ kotlin.code.style=official
|
||||
kotlin.daemon.jvmargs=-Xmx2g
|
||||
|
||||
# 버전은 CI/로컬에서 -PappVersionName -PappVersionCode 로 덮어쓸 수 있다.
|
||||
appVersionName=2.0.1
|
||||
appVersionCode=3
|
||||
appVersionName=2.0.3
|
||||
appVersionCode=5
|
||||
|
||||
@@ -60,7 +60,9 @@ git tag -a "v$new_name" -m "TETRIG v$new_name"
|
||||
TOKEN="${GITEA_TOKEN:-$(node -e 'console.log(require(process.env.HOME+"/.config/ejclaw/secrets.json").credentials["git.tkrmagid.kr"].token)' 2>/dev/null || true)}"
|
||||
[ -n "$TOKEN" ] || { echo "GITEA_TOKEN 이 없습니다"; exit 1; }
|
||||
|
||||
git push "$GITEA_HOST/$REPO.git" HEAD:main --tags
|
||||
# 토큰을 URL 에 넣어 푸시한다. 그냥 호스트만 주면 자격증명 헬퍼가 없어
|
||||
# "could not read Username" 으로 죽는다. URL 은 로그에 남지 않게 변수로만 쓴다.
|
||||
git push "https://oauth2:${TOKEN}@${GITEA_HOST#https://}/$REPO.git" HEAD:main --tags
|
||||
|
||||
echo "Gitea 릴리스 생성..."
|
||||
REL_ID=$(curl -sS -X POST "$GITEA_HOST/api/v1/repos/$REPO/releases" \
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 59 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 61 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 64 KiB |
Reference in New Issue
Block a user