diff --git a/README.md b/README.md index bbe5c8c..2e1c7dd 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,21 @@ screen. **32px tiles** (60% larger than 0.7) occupy 89 legal cells of an 11×11 bounding grid; every tile corner stays inside the actual circle. The square board frame is gone. Directional sprite artwork and user icon are preserved. Package identity: `com.ilias.snake`. -**Version 0.8 (versionCode 8): locally tested and release-built; the new features -still need an on-watch check.** Earlier versions rendered and played on the -user's Watch S4 41mm. Node tests and numeric layout checks are not device tests. +**Version 0.9 (versionCode 9): crown control experiment, unit-tested, needs an +on-watch check.** See docs/CROWN.md for the firmware reasoning. + +## Crown control (new in 0.9) + +- The watch firmware exposes **no crown event to quickapps**; it routes crown + rotation into the scrollable container as scroll deltas. The page is now a + full-screen vertical scroll with the dial centered; `onscroll` fires for both + crown rotation and finger scroll. +- Scroll deltas accumulate; every **40 px of scroll = one 90° turn**, + clockwise = clockwise turn. Reversals are structurally impossible because + turns are relative 90° steps (`rotateDir`-style), never absolute directions. +- The scroller is snapped back to center after every event, so the board never + visibly moves, even though the scroll travel exists. +- Swipes still work exactly as before; both inputs share the two-slot queue. ## Play diff --git a/docs/CROWN.md b/docs/CROWN.md new file mode 100644 index 0000000..06a66d4 --- /dev/null +++ b/docs/CROWN.md @@ -0,0 +1,34 @@ +# Crown control experiment (v0.9) + +Firmware study of the O63 OTA (`upd_miwear.watch.o63.zip`) found how the crown +reaches quickapps: there is **no crown/rotary JS event** (no `onCrown`, +`onRotary`, wheel keyevents in `vela_quickapp.bin`), but the native layer +(`vela_ap.bin`, `inputmanager/lv_touchpad_wheel_interface.c` + the +`crown_scroll` input tag in `lvx_inputmanager.c`) routes crown rotation into +**scroll deltas of the focused scrollable container**. + +So Snake listens to the crown indirectly: + +- the page is wrapped in a full-screen vertical `scroll` component with the + dial centered inside it, +- `onscroll` fires for both crown rotation and finger scroll, +- the page converts each scroll delta into a **queued 90° turn** + (`snake.rotateDir`, already in the codebase): positive delta = + clockwise, negative = counterclockwise, `CROWN_STEP_PX` px of scroll per + turn, +- because turns are 90° relative steps, the crown always turns the snake + left/right regardless of where the head is pointing, and reversals are + structurally impossible (rotateDir never emits a 180° flip), +- the scroll position is actively re-centered (`scrollTo({ top: center })`) + after each event so the board never visually moves; only the idle-swipe + fallback path (when no scroll events arrive, e.g. some firmwares coalesce + crown scroll with the swipe handler) uses `onswipe` as before, +- swipes still work exactly as in 0.8; both input paths feed the same + two-slot turn queue. + +Open questions that need the physical watch: + +- does the Crown S4 emit scroll deltas with sign, and at what px granularity? +- does `onscroll` fire for crown motion at all on this firmware, or only for + touch scroll? If not, the `CROWN_STEP_PX` accumulator still catches the + swipe-path fallback but true crown control would need native access. diff --git a/src/manifest.json b/src/manifest.json index 5ef6c13..a433133 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -2,8 +2,8 @@ "package": "com.ilias.snake", "name": "SNAKE", "icon": "/common/icon.png", - "versionName": "0.8", - "versionCode": 8, + "versionName": "0.9", + "versionCode": 9, "minAPILevel": 1, "deviceTypeList": [ "watch" diff --git a/src/pages/index/index.ux b/src/pages/index/index.ux index 57abf79..4ccb6f7 100644 --- a/src/pages/index/index.ux +++ b/src/pages/index/index.ux @@ -1,6 +1,7 @@