4.4 KiB
4.4 KiB
HanjaKanaMun - Project Plan
Overview
Odin + raylib multilingual memory card game for learning Japanese (Hiragana/Katakana), Korean (Hangul), and Thai scripts.
Commands (see justfile): just run, just check, just test, just package <version>
Current Status
Completed
- Code split into modules under
src/(themes, assets, audio, ui, card, memory, screens) .odinfiles tracked in git (.gitignoreused to ignore*.odin)- Real font: M PLUS Rounded 1c (Medium + ExtraBold, OFL) loaded via
LoadFontExwith kana codepoints - Per-language themes (
themes.Theme) with flag-based card backs: Japan (Hinomaru), Korea (Taegukgi), Thailand (Trairong) - Card flip animation: card art is rendered to textures and squashed horizontally, with lift, shadow and lighting; matched cards pulse
- Sound effects synthesized in code (flip, match, mismatch, win, button click), no audio files needed
- Japanese memory game: kana ↔ romaji pairs, 12 pairs picked at random from the 46 basic hiragana
- ESC goes back one screen (quits from the main menu); no longer closes the app everywhere
- Memory layout fixed (header and Back button no longer overlap cards), real shuffle, moves counted per pair
- Win panel with Play Again / Menu
Pending
- Keyboard support for card selection (1-9, A-L, etc.)
- Korean memory game (needs a Hangul font, e.g. Noto Sans KR; theme and card back already exist)
- Thai memory game (needs e.g. Noto Sans Thai; theme and card back already exist)
- Katakana mode
- Screen transitions
- Score tracking and high scores
- Difficulty levels (number of pairs)
Known Issues / Gotchas
- Font glyphs must be listed: raylib only bakes the codepoints passed to
LoadFontEx. Any new non-ASCII text needs its characters added inassets.build_codepoints, otherwise it renders as?. - Old font failure root cause:
DroidSansJapanese.ttfwas a GitHub HTML page saved from a blob URL, not a font. Always download fonts from raw URLs and check them withfile. - Thai shaping: raylib does no text shaping, so Thai combining vowels/tone marks may be misplaced. Prefer standalone consonants on Thai cards.
- Tests share the memory game's global state, so they must run single-threaded (
just testsetsODIN_TEST_THREADS=1). - The game changes directory to the executable's folder at startup so
assets/is found from anywhere. - Windows builds are cross-compiled: Odin can't link Windows binaries on Linux, so
just windowsbuilds objects with-build-mode:objand links withlld-linkagainst an xwin SDK. The VC runtime is linked statically; only Windows system DLLs are needed. Not yet tested on a real Windows machine.
File Structure
HanjaKanaMun/
├── AGENTS.md # Project plan (this file)
├── README.md
├── justfile # build/run/check/test/package recipes
├── ols.json # ols language server settings (neovim)
├── odinfmt.json # odinfmt formatter settings (4 spaces, LF)
├── .gitea/
│ ├── actions/setup/ # shared CI toolchain setup (apt, Odin, just)
│ └── workflows/
│ ├── gitea-build.yaml # check + test + build on main/develop
│ └── gitea-release.yaml # on tags v*: Linux + Windows packages, package registry upload, Gitea release
├── main.odin # Window/audio setup, screen state machine
├── src/
│ ├── themes/themes.odin # Theme struct, flag colors, Screen/Flag enums, layout constants
│ ├── assets/assets.odin # Font loading (codepoints), get_font
│ ├── audio/audio.odin # Synthesized sound effects, play()
│ ├── ui/ui.odin # Text helpers, buttons, hover cursor
│ ├── card/card.odin # Card struct, flag card-back art, face textures, flip animation
│ ├── memory/memory.odin # Memory game state, logic and drawing
│ └── screens/screens.odin # Main menu and language menus
├── tests/memory_test.odin # Game logic and card animation tests
└── assets/
├── MPLUSRounded1c-Medium.ttf
├── MPLUSRounded1c-ExtraBold.ttf
└── MPLUSRounded1c-OFL.txt
Notes
- NO rm -rf or starting over
- Make small, incremental changes
- Test after each change (
just check,just test, thenjust run) - Keep existing functionality working
- Commit after each working step