CURRICULUM.md: full 14-group skill tree drawn from the artistic learning journey — line control through creative systems, with skill dependency graph and notes on how exercises translate into module designs. SPRINT.md: Sprint 2 tickets (AL-010 through AL-015) replacing the Sprint 1 static-stroke prototype with the real scrolling corridor from MODULES.md, including score model migration, difficulty tiers, and session summary screen. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6.4 KiB
ArtLegend — Current Sprint
Sprint goal: Line Corridor MVP. Implement the real scrolling-corridor game from MODULES.md, replace the Sprint 1 prototype, add difficulty tiers, and wire real session data into the Progress screen.
Sprint 1 built a static "draw one stroke" prototype to validate the architecture. Sprint 2 replaces the game logic with the actual design: a continuously scrolling corridor the player tracks with their stylus, scored on Fill and Containment.
Tickets
AL-010 — CorridorScore data model [TODO]
Replace the prototype LineScore with a score model that matches the Corridor Scroll design from MODULES.md.
- Delete
core/modules/LineScore.kt - Create
core/modules/CorridorScore.kt:data class CorridorScore( val fill: Float, // 0..1 — avg coverage of corridor width val wallPenalties: Int, // raw count of wall crossings val overall: Float // weighted: fill * 0.7 − penalty * 0.05, clamped 0..1 ) - Update
GameHost.onSessionCompletesignature:((CorridorScore) -> Unit)? - Update
GameActivityto passfill,wallPenalties,overallvia Intent extras - Update
MainActivity.gameResultLauncherto reconstructCorridorScorefrom Intent - Update
SessionEntity: replacestraightness/anglePrecisionfields withfill: FloatandwallPenalties: Int; bump Room schema version to 2 with a destructive migration (dev only — data is test data) - Update
SessionRepository.save()to write new fields - Update
ProgressScreenSessionCardandSessionBarChartlabels (Overall, Fill, Penalties) - Update
ProgressViewModel— no logic change needed
AL-011 — Scrolling corridor engine [TODO]
Rewrite LineCorridorScreen to implement the scrolling corridor from MODULES.md.
Geometry:
- Corridor scrolls across the screen at a configurable pixel/sec speed
- Corridor is represented as a spine (centerline) moving left-to-right (or at an angle on higher difficulties)
- Player tracks the moving gap by holding their stylus inside it
Rendering:
- Two cyan wall lines scrolling across screen
- Visible lookahead: player can see a few screen-widths ahead
- Stylus trail rendered in yellow (pressure-modulated alpha, same as prototype)
- HUD: session timer (top-right), score preview (fill % running avg, penalty count)
Session lifecycle:
- Session runs for a fixed duration (
sessionDurationparam, default 30s) - When time runs out: compute final score, call
onSessionComplete - Player must hold stylus the entire time — stylus-up counts as not filling
Constructor params:
class LineCorridorScreen(
bridge: StylusInputBridge,
onSessionComplete: (CorridorScore) -> Unit,
corridorWidth: Float = 80f,
scrollSpeed: Float = 180f,
sessionDuration: Float = 30f,
angleChangeEnabled: Boolean = false
)
AL-012 — Real-time containment + fill scoring [TODO]
Implement per-frame scoring logic inside LineCorridorScreen.
Per-frame:
- Compute the corridor bounds at the stylus X position (or nearest corridor segment)
- If stylus is inside bounds: record perpendicular offset → contributes to running fill average
- If stylus crosses a wall: increment
wallPenaltyCount, enforce a brief visual flash (wall turns red for 0.3s) - If stylus is up: does not contribute to fill average (neutral, not a penalty)
At session end:
fill= mean of per-frame fill samples (each sample =1 - |offset| / halfWidth, clamped 0..1)wallPenalties= total crossing countoverall=(fill * 0.7 - wallPenalties * 0.05).coerceIn(0f, 1f)
AL-013 — Difficulty tiers [TODO]
Add selectable difficulty levels that feed into LineCorridorScreen params.
In shared/:
enum class Difficulty { EASY, MEDIUM, HARD }
Difficulty knobs:
| EASY | MEDIUM | HARD | |
|---|---|---|---|
| Corridor width | 90f | 60f | 38f |
| Scroll speed (px/s) | 140f | 220f | 340f |
| Angle changes | None | Gentle (±15° max) | Frequent (±35° max) |
| Session duration | 30s | 30s | 30s |
UI — ModuleDetailScreen:
- Add a
Difficultyselector (three segmented chips: Easy / Medium / Hard) between the module description and the "Start Training" button - Default: EASY
- Pass selected
Difficultyas an Intent extra toGameActivity
In GameActivity:
- Read
Difficultyfrom Intent, buildLineCorridorScreenwith corresponding params - Pass
Difficulty.namethrough to the score result so it can be stored with the session
Add difficulty: String column to SessionEntity (schema version → 3, destructive migration)
AL-014 — Session summary screen [TODO]
Add a dedicated post-game summary in Compose shown after the LibGDX screen closes, before the user returns to the hub.
New route in ArtLegendApp: summary/{moduleType}
SummaryScreen composable:
- Score breakdown: Overall %, Fill %, Wall Penalties
- Streak badge: "X-day streak" (see streak logic below)
- Buttons: "Train Again" (relaunch same module/difficulty), "View Progress", "Back to Hub"
Streak logic (in ProgressViewModel):
- Add
fun streakFor(moduleType: ModuleType): Int— query sessions ordered by timestamp, count consecutive calendar days ending today that have at least one session - Expose as
StateFlow<Int>
Wire-up:
- After
gameResultLauncherreceives a result, navigate tosummary/{moduleType}instead of staying onModuleDetailScreen - Pass
CorridorScoretoSummaryScreenviaArtLegendAppstate (same pattern aslastScorein Sprint 1) ModuleDetailScreenno longer shows the inlineScoreCard— summary screen owns that
AL-015 — Integration smoke test [TODO]
./gradlew :android:assembleDebugpasses with no errors- Hub → Module Detail → difficulty selector renders (Easy selected by default)
- "Start Training" → LibGDX renders scrolling corridor with visible movement
- Stylus held inside corridor: fill HUD increments; crossing a wall: wall flashes red
- Session timer counts down, auto-returns at 0s
- Summary screen shows Fill %, Wall Penalties, Overall %, streak badge
- Progress screen bar chart reflects the session just completed
- All three difficulty tiers launch without crash
Blocked
Nothing blocked currently.
Out of Scope This Sprint
- Angle change corridor segments (HARD difficulty — define the knob values but angle changes can ship as a fast-follow if time allows)
- Sound effects / haptic feedback
- Global XP system
- In-app purchases
- Cloud sync