Restructure into themed screens with flag card backs, real font, flip animation and sound
- Replace the bogus DroidSansJapanese.ttf (an HTML page) with M PLUS Rounded 1c, loaded with LoadFontEx and explicit kana codepoints - Theme struct per language with flag-based card backs (Hinomaru, Taegukgi, Trairong) - Card art rendered to textures so the flip squashes the whole card - Synthesized flip/match/mismatch/win/click sounds (new audio package) - Shared ui package for text and buttons; Screen enum replaces i32 ids - Kana <-> romaji pairs drawn from all 46 basic hiragana Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5557de62a3
commit
5806f0498c
11 files changed
+1046
-425
No files matched your search
@@ -0,0 +1,84 @@
|
||||
package ui
|
||||
|
||||
import raylib "vendor:raylib"
|
||||
import assets "../assets"
|
||||
import audio "../audio"
|
||||
import themes "../themes"
|
||||
|
||||
TEXT_SPACING :: 1
|
||||
|
||||
@(private)
|
||||
any_hovered: bool
|
||||
|
||||
// Call at the start of each frame's drawing
|
||||
begin_frame :: proc() {
|
||||
any_hovered = false
|
||||
}
|
||||
|
||||
// Call at the end of each frame's drawing
|
||||
end_frame :: proc() {
|
||||
raylib.SetMouseCursor(any_hovered ? .POINTING_HAND : .DEFAULT)
|
||||
}
|
||||
|
||||
// Mark that something clickable is under the mouse (shows the hand cursor)
|
||||
set_hovered :: proc() {
|
||||
any_hovered = true
|
||||
}
|
||||
|
||||
measure_text :: proc(text: cstring, size: f32, bold := false) -> raylib.Vector2 {
|
||||
return raylib.MeasureTextEx(assets.get_font(bold), text, size, TEXT_SPACING)
|
||||
}
|
||||
|
||||
draw_text :: proc(text: cstring, pos: raylib.Vector2, size: f32, color: raylib.Color, bold := false) {
|
||||
raylib.DrawTextEx(assets.get_font(bold), text, pos, size, TEXT_SPACING, color)
|
||||
}
|
||||
|
||||
// Draws text horizontally centered on center_x with its top at y
|
||||
draw_text_centered :: proc(text: cstring, center_x, y, size: f32, color: raylib.Color, bold := false, shadow := false) {
|
||||
w := measure_text(text, size, bold).x
|
||||
pos := raylib.Vector2{center_x - w / 2, y}
|
||||
if shadow {
|
||||
draw_text(text, pos + {0, size * 0.05}, size, raylib.Fade(themes.BLACK, 0.18), bold)
|
||||
}
|
||||
draw_text(text, pos, size, color, bold)
|
||||
}
|
||||
|
||||
// Draws text centered in a rectangle
|
||||
draw_text_in_rect :: proc(text: cstring, rect: raylib.Rectangle, size: f32, color: raylib.Color, bold := false) {
|
||||
dims := measure_text(text, size, bold)
|
||||
pos := raylib.Vector2{rect.x + (rect.width - dims.x) / 2, rect.y + (rect.height - dims.y) / 2}
|
||||
draw_text(text, pos, size, color, bold)
|
||||
}
|
||||
|
||||
draw_title :: proc(text: cstring, y: f32, color: raylib.Color, size: f32 = themes.TITLE_FONT_SIZE) {
|
||||
draw_text_centered(text, themes.SCREEN_WIDTH / 2, y, size, color, bold = true, shadow = true)
|
||||
}
|
||||
|
||||
// A rounded button with hover, press and shadow states. Returns true when clicked.
|
||||
button :: proc(rect: raylib.Rectangle, text: cstring, color: raylib.Color,
|
||||
text_color := themes.WHITE, font_size: f32 = themes.BUTTON_FONT_SIZE) -> bool {
|
||||
hovered := raylib.CheckCollisionPointRec(raylib.GetMousePosition(), rect)
|
||||
pressed := hovered && raylib.IsMouseButtonDown(.LEFT)
|
||||
if hovered { set_hovered() }
|
||||
|
||||
lift: f32 = 0
|
||||
fill := color
|
||||
if hovered {
|
||||
lift = 2
|
||||
fill = raylib.ColorBrightness(color, 0.12)
|
||||
}
|
||||
if pressed {
|
||||
lift = -1
|
||||
fill = raylib.ColorBrightness(color, -0.08)
|
||||
}
|
||||
|
||||
shadow := raylib.Rectangle{rect.x, rect.y + 4, rect.width, rect.height}
|
||||
raylib.DrawRectangleRounded(shadow, 0.4, 12, raylib.Fade(themes.BLACK, 0.18))
|
||||
body := raylib.Rectangle{rect.x, rect.y - lift, rect.width, rect.height}
|
||||
raylib.DrawRectangleRounded(body, 0.4, 12, fill)
|
||||
draw_text_in_rect(text, body, font_size, text_color, bold = true)
|
||||
|
||||
clicked := hovered && raylib.IsMouseButtonPressed(.LEFT)
|
||||
if clicked { audio.play(.CLICK) }
|
||||
return clicked
|
||||
}
|
||||
Reference in new issue
Block a user