Add Thai and Korean character image displays with scrolling grids

This commit is contained in:
2026-05-09 00:27:26 +02:00
parent 2ab3aa60d2
commit 47247e1b2b
166 changed files with 407 additions and 63 deletions
+147
View File
@@ -0,0 +1,147 @@
package main
import (
"fmt"
"os"
"runtime"
"github.com/gen2brain/raylib-go/raylib"
)
// Korean Hangul Jamo - Choseong (Initial consonants)
var koreanChoseong = []struct {
character string
name string
}{
{"ㄱ", "Giyeok"}, {"ㄲ", "SsangGiyeok"}, {"ㄴ", "Nieun"}, {"ㄷ", "Dieut"}, {"ㄸ", "SsangDieut"},
{"ㄹ", "Rieul"}, {"ㅁ", "Mieum"}, {"ㅂ", "Pieup"}, {"ㅃ", "SsangPieup"}, {"ㅅ", "Siot"},
{"ㅆ", "SsangSiot"}, {"ㅇ", "Ieung"}, {"ㅈ", "Jieut"}, {"ㅉ", "SsangJieut"}, {"ㅊ", "Chieut"},
{"ㅋ", "Kieuk"}, {"ㅌ", "Tieut"}, {"ㅍ", "Pieup"}, {"ㅎ", "Hieut"},
}
// Korean Hangul Jamo - Jungseong (Medial vowels)
var koreanJungseong = []struct {
character string
name string
}{
{"ㅏ", "A"}, {"ㅐ", "Ae"}, {"ㅑ", "Ya"}, {"ㅒ", "Yae"}, {"ㅓ", "Eo"},
{"ㅔ", "E"}, {"ㅕ", "Yeo"}, {"ㅖ", "Ye"}, {"ㅗ", "O"}, {"ㅘ", "Wa"},
{"ㅙ", "Wae"}, {"ㅚ", "Oe"}, {"ㅛ", "Yo"}, {"ㅜ", "U"}, {"ㅝ", "Wo"},
{"ㅞ", "We"}, {"ㅟ", "Wi"}, {"ㅠ", "Yu"}, {"ㅡ", "Eu"}, {"ㅢ", "Ui"},
{"ㅣ", "I"},
}
// Korean Hangul Jamo - Jongseong (Final consonants)
var koreanJongseong = []struct {
character string
name string
}{
{"", "None"}, {"ㄱ", "Giyeok"}, {"ㄲ", "SsangGiyeok"}, {"ㄱㅅ", "Giyeok-Siot"}, {"ㄴ", "Nieun"},
{"ㄵ", "Nieun-Cieut"}, {"ㄶ", "Nieun-Hieut"}, {"ㄷ", "Dieut"}, {"ㄹ", "Rieul"}, {"ㄺ", "Rieul-Giyeok"},
{"ㄻ", "Rieul-Mieum"}, {"ㄼ", "Rieul-Pieup"}, {"ㄽ", "Rieul-Siot"}, {"ㄾ", "Rieul-Tieut"}, {"ㄿ", "Rieul-Phup"},
{"ㅀ", "Rieul-Hieut"}, {"ㅁ", "Mieum"}, {"ㅂ", "Pieup"}, {"ㅄ", "Pieup-Siot"}, {"ㅅ", "Siot"},
{"ㅆ", "SsangSiot"}, {"ㅇ", "Ieung"}, {"ㅈ", "Jieut"}, {"ㅊ", "Chieut"}, {"ㅋ", "Kieuk"},
{"ㅌ", "Tieut"}, {"ㅍ", "Pieup"}, {"ㅎ", "Hieut"},
}
// Common Hangul syllables
var koreanSyllables = []struct {
character string
name string
}{
{"가", "Ga"}, {"각", "Gak"}, {"간", "Gan"}, {"갈", "Gal"}, {"감", "Gam"},
{"갑", "Gap"}, {"강", "Gang"}, {"개", "Gae"}, {"객", "Gaek"}, {"건", "Geon"},
{"걸", "Geol"}, {"검", "Geom"}, {"겁", "Geop"}, {"게", "Ge"}, {"격", "Gyeok"},
{"견", "Gyeon"}, {"결", "Gyeol"}, {"겸", "Gyeom"}, {"겹", "Gyeop"}, {"경", "Gyeong"},
{"계", "Gye"}, {"고", "Go"}, {"곡", "Gok"}, {"곤", "Gon"}, {"골", "Gol"},
{"공", "Gong"}, {"과", "Gwa"}, {"관", "Gwan"}, {"괄", "Gwal"}, {"광", "Gwang"},
{"귀", "Gwi"}, {"규", "Gyu"}, {"균", "Gyun"}, {"굴", "Gul"}, {"굼", "Gum"},
{"국", "Guk"}, {"군", "Gun"}, {"굽", "Gup"}, {"굿", "Gut"}, {"그", "Geu"},
}
func main() {
// Initialize raylib for font rendering
runtime.LockOSThread()
rl.InitWindow(1, 1, "Korean Generator")
defer rl.CloseWindow()
// Create directory for images
if err := os.MkdirAll("images", 0755); err != nil {
panic(err)
}
// Load a font that supports Korean
font := rl.GetFontDefault()
fontPaths := []string{
"/System/Library/Fonts/AppleGothic.ttc",
"/System/Library/Fonts/AppleMyungjo.ttc",
"/Library/Fonts/AppleGothic.ttc",
"/usr/share/fonts/truetype/noto/NotoSansKR-Regular.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
}
for _, path := range fontPaths {
if _, err := os.Stat(path); err == nil {
font = rl.LoadFont(path)
if font != (rl.Font{}) {
break
}
}
}
if font == (rl.Font{}) {
font = rl.GetFontDefault()
fmt.Println("Using default font")
} else {
fmt.Println("Loaded Korean font")
}
// All Korean characters
allKorean := append(koreanChoseong, koreanJungseong...)
allKorean = append(allKorean, koreanJongseong...)
allKorean = append(allKorean, koreanSyllables...)
// Create image for each character
for _, k := range allKorean {
// Skip empty character
if k.character == "" {
continue
}
// Create a render texture
texture := rl.LoadRenderTexture(256, 256)
rl.BeginTextureMode(texture)
rl.ClearBackground(rl.White)
// Draw the Korean character
charWidth := rl.MeasureText(k.character, 128)
charX := int32((256 - charWidth) / 2)
charY := int32(80)
rl.DrawText(k.character, charX, charY, 128, rl.Black)
// Draw name at the bottom
nameWidth := rl.MeasureText(k.name, 24)
nameX := int32((256 - nameWidth) / 2)
nameY := int32(200)
rl.DrawText(k.name, nameX, nameY, 24, rl.Blue)
rl.EndTextureMode()
// Convert render texture to image
img := rl.LoadImageFromTexture(texture.Texture)
// Save as PNG
filename := "images/" + k.character + "_" + k.name + ".png"
rl.ExportImage(*img, filename)
// Cleanup
rl.UnloadImage(img)
rl.UnloadRenderTexture(texture)
fmt.Println("Generated:", filename)
}
fmt.Println("Finished generating all Korean images!")
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
View File
Binary file not shown.
+134 -63
View File
@@ -25,6 +25,17 @@ const (
ScreenJapanese = "japanese" ScreenJapanese = "japanese"
) )
// LanguageScreenState holds the state for each language screen
type LanguageScreenState struct {
Textures []rl.Texture2D
ImageFiles []string
ImagePath string
ScrollY int32
Loaded bool
Title string
Color rl.Color
}
func main() { func main() {
// Initialize window // Initialize window
screenWidth := int32(800) screenWidth := int32(800)
@@ -87,10 +98,84 @@ func main() {
// Current screen state // Current screen state
currentScreen := ScreenMenu currentScreen := ScreenMenu
prevScreen := ScreenMenu prevScreen := ScreenMenu
// Japanese screen state // Language screen states
var japaneseTextures []rl.Texture2D languageStates := map[string]*LanguageScreenState{
var imageStartY int32 = 0 ScreenThai: {
ImagePath: "thai/images/",
ImageFiles: []string{
"ก_Ko Kai.png", "ข_Kho Khai.png", "ฃ_Kho Khuat.png", "ค_Kho Khwai.png", "ฅ_Kho Khon.png",
"ฆ_Kho Rakhang.png", "ง_Ngo Ngai.png", "จ_Cho Chan.png", "ฉ_Cho Ching.png", "ช_Cho Chang.png",
"ซ_So So.png", "ฌ_Cho Che.png", "ญ_Yo Ying.png", "ฎ_Do Dek.png", "ฏ_To Tao.png",
"ฐ_To Thong.png", "ฑ_To Thung.png", "ฒ_To Thahan.png", "ณ_No Nen.png", "ด_Do Dek.png",
"ต_To Tao.png", "ถ_To Thung.png", "ท_To Thahan.png", "ธ_Tho Thong.png", "น_No Nu.png",
"บ_Bo Baimai.png", "ป_Po Pla.png", "ผ_Pho Phung.png", "ฝ_Fo Fa.png", "พ_Pho Phan.png",
"ฟ_Fo Fan.png", "ภ_Pho Samphao.png", "ม_Mo Ma.png", "ย_Yo Yak.png", "ร_Ro Rua.png",
"ล_Lo Ling.png", "ว_Wo Waen.png", "ศ_So Sala.png", "ษ_So Ruezi.png", "ส_So Suan.png",
"ห_Ho Hip.png", "ฬ_Lo Chula.png", "อ_O Ang.png", "ฮ_Ho Nokhuk.png",
"ะ_Sara A.png", "ั_Sara Aa.png", "า_Sara Aa.png", "ำ_Sara Am.png", "ิ_Sara I.png",
"ี_Sara Ii.png", "ึ_Sara Ue.png", "ื_Sara Uee.png", "ุ_Sara U.png", "ู_Sara Uu.png",
"เ_Sara E.png", "แ_Sara Ae.png", "โ_Sara O.png", "ใ_Sara Ai Mai Malai.png", "ไ_Sara Ai Mai Muang.png",
"ๅ_Sara Ue.png", "ๆ_Sara Uee.png",
"_Zero.png", "๑_One.png", "๒_Two.png", "๓_Three.png", "๔_Four.png",
"๕_Five.png", "๖_Six.png", "๗_Seven.png", "๘_Eight.png", "๙_Nine.png",
},
ScrollY: 0,
Title: "Thai Characters",
Color: rl.Red,
},
ScreenKorean: {
ImagePath: "korean/images/",
ImageFiles: []string{
"ㄱ_Giyeok.png", "ㄲ_SsangGiyeok.png", "ㄴ_Nieun.png", "ㄷ_Dieut.png", "ㄸ_SsangDieut.png",
"ㄹ_Rieul.png", "ㅁ_Mieum.png", "ㅂ_Pieup.png", "ㅃ_SsangPieup.png", "ㅅ_Siot.png",
"ㅆ_SsangSiot.png", "ㅇ_Ieung.png", "ㅈ_Jieut.png", "ㅉ_SSangJieut.png", "ㅊ_Chieut.png",
"ㅋ_Kieuk.png", "ㅌ_Tieut.png", "ㅍ_Pieup.png", "ㅎ_Hieut.png",
"ㅏ_A.png", "ㅐ_Ae.png", "ㅑ_Ya.png", "ㅒ_Yae.png", "ㅓ_Eo.png",
"ㅔ_E.png", "ㅕ_Yeo.png", "ㅖ_Ye.png", "ㅗ_O.png", "ㅘ_Wa.png",
"ㅙ_Wae.png", "ㅚ_Oe.png", "ㅛ_Yo.png", "ㅜ_U.png", "ㅝ_Wo.png",
"ㅞ_We.png", "ㅟ_Wi.png", "ㅠ_Yu.png", "ㅡ_Eu.png", "ㅢ_Ui.png", "ㅣ_I.png",
"ㄱㅅ_Giyeok-Siot.png", "ㄵ_Nieun-Cieut.png", "ㄶ_Nieun-Hieut.png",
"ㄺ_Rieul-Giyeok.png", "ㄻ_Rieul-Mieum.png", "ㄼ_Rieul-Pieup.png", "ㄽ_Rieul-Siot.png",
"ㄾ_Rieul-Tieut.png", "ㄿ_Rieul-Phup.png", "ㅀ_Rieul-Hieut.png",
"ㅄ_Pieup-Siot.png",
"가_Ga.png", "각_Gak.png", "간_Gan.png", "갈_Gal.png", "감_Gam.png",
"갑_Gap.png", "강_Gang.png", "개_Gae.png", "객_Gaek.png", "건_Geon.png",
"걸_Geol.png", "검_Geom.png", "겁_Geop.png", "게_Ge.png", "격_Gyeok.png",
"견_Gyeon.png", "결_Gyeol.png", "겸_Gyeom.png", "겹_Gyeop.png", "경_Gyeong.png",
"계_Gye.png", "고_Go.png", "곡_Gok.png", "곤_Gon.png", "골_Gol.png",
"공_Gong.png", "과_Gwa.png", "관_Gwan.png", "괄_Gwal.png", "광_Gwang.png",
"귀_Gwi.png", "규_Gyu.png", "균_Gyun.png", "굴_Gul.png", "굼_Gum.png",
"국_Guk.png", "군_Gun.png", "굽_Gup.png", "굿_Gut.png", "그_Geu.png",
},
ScrollY: 0,
Title: "Korean Characters",
Color: rl.Blue,
},
ScreenJapanese: {
ImagePath: "japanese/images/",
ImageFiles: []string{
"あ_a.png", "い_i.png", "う_u.png", "え_e.png", "お_o.png",
"か_ka.png", "き_ki.png", "く_ku.png", "け_ke.png", "こ_ko.png",
"さ_sa.png", "し_shi.png", "す_su.png", "せ_se.png", "そ_so.png",
"た_ta.png", "ち_chi.png", "つ_tsu.png", "て_te.png", "と_to.png",
"な_na.png", "に_ni.png", "ぬ_nu.png", "ね_ne.png", "の_no.png",
"は_ha.png", "ひ_hi.png", "ふ_fu.png", "へ_he.png", "ほ_ho.png",
"ま_ma.png", "み_mi.png", "む_mu.png", "め_me.png", "も_mo.png",
"や_ya.png", "ゆ_yu.png", "よ_yo.png",
"ら_ra.png", "り_ri.png", "る_ru.png", "れ_re.png", "ろ_ro.png",
"わ_wa.png", "ゐ_wi.png", "ゑ_we.png", "を_wo.png", "ん_n.png",
"が_ga.png", "ぎ_gi.png", "ぐ_gu.png", "げ_ge.png", "ご_go.png",
"ざ_za.png", "じ_ji.png", "ず_zu.png", "ぜ_ze.png", "ぞ_zo.png",
"だ_da.png", "ぢ_di.png", "づ_du.png", "で_de.png", "ど_do.png",
"ば_ba.png", "び_bi.png", "ぶ_bu.png", "べ_be.png", "ぼ_bo.png",
"ぱ_pa.png", "ぴ_pi.png", "ぷ_pu.png", "ぺ_pe.png", "ぽ_po.png",
},
ScrollY: 0,
Title: "Hiragana Characters",
Color: rl.Green,
},
}
// Main game loop // Main game loop
for !rl.WindowShouldClose() { for !rl.WindowShouldClose() {
@@ -104,6 +189,39 @@ func main() {
btn.Clicked = false btn.Clicked = false
btn.Scale = 1.0 btn.Scale = 1.0
} }
// Reset language screen state when switching to it
if currentScreen != ScreenMenu {
state := languageStates[currentScreen]
if !state.Loaded {
// Load textures
for _, imgName := range state.ImageFiles {
texture := rl.LoadTexture(state.ImagePath + imgName)
if texture.ID != 0 {
state.Textures = append(state.Textures, texture)
} else {
state.Textures = append(state.Textures, rl.Texture2D{})
}
}
state.Loaded = true
}
state.ScrollY = 0
} else {
// Unload textures when leaving language screens
for _, lang := range []string{ScreenThai, ScreenKorean, ScreenJapanese} {
if lang != currentScreen {
state := languageStates[lang]
for _, tex := range state.Textures {
if tex.ID != 0 {
rl.UnloadTexture(tex)
}
}
state.Textures = nil
state.Loaded = false
}
}
}
prevScreen = currentScreen prevScreen = currentScreen
} }
@@ -169,43 +287,13 @@ func main() {
rl.DrawText(btn.Text, textX, textY, 20, rl.Black) rl.DrawText(btn.Text, textX, textY, 20, rl.Black)
} }
case ScreenThai: default:
rl.DrawText("Thai Language Screen", screenWidth/2-100, screenHeight/2-20, 30, rl.Red) // Language screens
rl.DrawText("Press ESC to return to menu", screenWidth/2-120, screenHeight/2+30, 20, rl.Black) state := languageStates[currentScreen]
if rl.IsKeyPressed(rl.KeyEscape) {
currentScreen = ScreenMenu
}
case ScreenKorean:
rl.DrawText("Korean Language Screen", screenWidth/2-120, screenHeight/2-20, 30, rl.Blue)
rl.DrawText("Press ESC to return to menu", screenWidth/2-120, screenHeight/2+30, 20, rl.Black)
if rl.IsKeyPressed(rl.KeyEscape) {
currentScreen = ScreenMenu
}
case ScreenJapanese:
rl.DrawText("Hiragana Characters", 20, 20, 30, rl.Green)
rl.DrawText("Press ESC to return to menu", screenWidth-200, 20, 20, rl.Black)
// Load and display Hiragana images in a grid // Draw title
imagePath := "japanese/images/" rl.DrawText(state.Title, 20, 20, 30, state.Color)
hiraganaImages := []string{ rl.DrawText("Press ESC to return to menu", screenWidth-200, 20, 20, rl.Black)
"あ_a.png", "い_i.png", "う_u.png", "え_e.png", "お_o.png",
"か_ka.png", "き_ki.png", "く_ku.png", "け_ke.png", "こ_ko.png",
"さ_sa.png", "し_shi.png", "す_su.png", "せ_se.png", "そ_so.png",
"た_ta.png", "ち_chi.png", "つ_tsu.png", "て_te.png", "と_to.png",
"な_na.png", "に_ni.png", "ぬ_nu.png", "ね_ne.png", "の_no.png",
"は_ha.png", "ひ_hi.png", "ふ_fu.png", "へ_he.png", "ほ_ho.png",
"ま_ma.png", "み_mi.png", "む_mu.png", "め_me.png", "も_mo.png",
"や_ya.png", "ゆ_yu.png", "よ_yo.png",
"ら_ra.png", "り_ri.png", "る_ru.png", "れ_re.png", "ろ_ro.png",
"わ_wa.png", "ゐ_wi.png", "ゑ_we.png", "を_wo.png", "ん_n.png",
"が_ga.png", "ぎ_gi.png", "ぐ_gu.png", "げ_ge.png", "ご_go.png",
"ざ_za.png", "じ_ji.png", "ず_zu.png", "ぜ_ze.png", "ぞ_zo.png",
"だ_da.png", "ぢ_di.png", "づ_du.png", "で_de.png", "ど_do.png",
"ば_ba.png", "び_bi.png", "ぶ_bu.png", "べ_be.png", "ぼ_bo.png",
"ぱ_pa.png", "ぴ_pi.png", "ぷ_pu.png", "ぺ_pe.png", "ぽ_po.png",
}
// Grid layout // Grid layout
columns := 7 columns := 7
@@ -215,25 +303,13 @@ func main() {
startX := int32(20) startX := int32(20)
startY := int32(60) startY := int32(60)
// Load images on first frame
if len(japaneseTextures) == 0 {
for _, imgName := range hiraganaImages {
texture := rl.LoadTexture(imagePath + imgName)
if texture != (rl.Texture2D{}) {
japaneseTextures = append(japaneseTextures, texture)
} else {
japaneseTextures = append(japaneseTextures, rl.Texture2D{})
}
}
}
// Draw images in grid // Draw images in grid
for i, texture := range japaneseTextures { for i, texture := range state.Textures {
if texture.ID != 0 { if texture.ID != 0 {
row := i / columns row := i / columns
col := i % columns col := i % columns
x := startX + int32(col)*(imageWidth+spacing) x := startX + int32(col)*(imageWidth+spacing)
y := startY + int32(row)*(imageHeight+spacing) - imageStartY y := startY + int32(row)*(imageHeight+spacing) - state.ScrollY
// Draw background for image // Draw background for image
rl.DrawRectangle(x, y, imageWidth, imageHeight, rl.LightGray) rl.DrawRectangle(x, y, imageWidth, imageHeight, rl.LightGray)
@@ -249,20 +325,15 @@ func main() {
// Handle scroll with mouse wheel // Handle scroll with mouse wheel
scroll := rl.GetMouseWheelMove() scroll := rl.GetMouseWheelMove()
if scroll != 0 { if scroll != 0 {
imageStartY += int32(scroll) * 10 state.ScrollY += int32(scroll) * 10
if imageStartY < 0 { if state.ScrollY < 0 {
imageStartY = 0 state.ScrollY = 0
} }
} }
// Handle ESC key
if rl.IsKeyPressed(rl.KeyEscape) { if rl.IsKeyPressed(rl.KeyEscape) {
currentScreen = ScreenMenu currentScreen = ScreenMenu
// Unload textures when leaving
for _, tex := range japaneseTextures {
rl.UnloadTexture(tex)
}
japaneseTextures = nil
imageStartY = 0
} }
// Draw scroll hint // Draw scroll hint
+126
View File
@@ -0,0 +1,126 @@
package main
import (
"fmt"
"os"
"runtime"
"github.com/gen2brain/raylib-go/raylib"
)
// Thai consonants (44 characters)
var thaiConsonants = []struct {
character string
name string
}{
{"ก", "Ko Kai"}, {"ข", "Kho Khai"}, {"ฃ", "Kho Khuat"}, {"ค", "Kho Khwai"}, {"ฅ", "Kho Khon"},
{"ฆ", "Kho Rakhang"}, {"ง", "Ngo Ngai"}, {"จ", "Cho Chan"}, {"ฉ", "Cho Ching"}, {"ช", "Cho Chang"},
{"ซ", "So So"}, {"ฌ", "Cho Che"}, {"ญ", "Yo Ying"}, {"ฎ", "Do Dek"}, {"ฏ", "To Tao"},
{"ฐ", "To Thong"}, {"ฑ", "To Thung"}, {"ฒ", "To Thahan"}, {"ณ", "No Nen"}, {"ด", "Do Dek"},
{"ต", "To Tao"}, {"ถ", "To Thung"}, {"ท", "To Thahan"}, {"ธ", "Tho Thong"}, {"น", "No Nu"},
{"บ", "Bo Baimai"}, {"ป", "Po Pla"}, {"ผ", "Pho Phung"}, {"ฝ", "Fo Fa"}, {"พ", "Pho Phan"},
{"ฟ", "Fo Fan"}, {"ภ", "Pho Samphao"}, {"ม", "Mo Ma"}, {"ย", "Yo Yak"}, {"ร", "Ro Rua"},
{"ล", "Lo Ling"}, {"ว", "Wo Waen"}, {"ศ", "So Sala"}, {"ษ", "So Ruezi"}, {"ส", "So Suan"},
{"ห", "Ho Hip"}, {"ฬ", "Lo Chula"}, {"อ", "O Ang"}, {"ฮ", "Ho Nokhuk"},
}
// Thai vowels (32 characters)
var thaiVowels = []struct {
character string
name string
}{
{"ะ", "Sara A"}, {"ั", "Sara Aa"}, {"า", "Sara Aa"}, {"ำ", "Sara Am"}, {"ิ", "Sara I"},
{"ี", "Sara Ii"}, {"ึ", "Sara Ue"}, {"ื", "Sara Uee"}, {"ุ", "Sara U"}, {"ู", "Sara Uu"},
{"เ", "Sara E"}, {"แ", "Sara Ae"}, {"โ", "Sara O"}, {"ใ", "Sara Ai Mai Malai"}, {"ไ", "Sara Ai Mai Muang"},
{"ๅ", "Sara Ue"}, {"ๆ", "Sara Uee"},
}
// Thai numbers
var thaiNumbers = []struct {
character string
name string
}{
{"", "Zero"}, {"๑", "One"}, {"๒", "Two"}, {"๓", "Three"}, {"๔", "Four"},
{"๕", "Five"}, {"๖", "Six"}, {"๗", "Seven"}, {"๘", "Eight"}, {"๙", "Nine"},
}
func main() {
// Initialize raylib for font rendering
runtime.LockOSThread()
rl.InitWindow(1, 1, "Thai Generator")
defer rl.CloseWindow()
// Create directory for images
if err := os.MkdirAll("images", 0755); err != nil {
panic(err)
}
// Load a font that supports Thai
font := rl.GetFontDefault()
fontPaths := []string{
"/System/Library/Fonts/Ayuthaya.ttc",
"/System/Library/Fonts/Thonburi.ttc",
"/Library/Fonts/Ayuthaya.ttc",
"/usr/share/fonts/truetype/noto/NotoSansThai-Regular.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
}
for _, path := range fontPaths {
if _, err := os.Stat(path); err == nil {
font = rl.LoadFont(path)
if font != (rl.Font{}) {
break
}
}
}
if font == (rl.Font{}) {
font = rl.GetFontDefault()
fmt.Println("Using default font")
} else {
fmt.Println("Loaded Thai font")
}
// All Thai characters
allThai := append(thaiConsonants, thaiVowels...)
allThai = append(allThai, thaiNumbers...)
// Create image for each character
for _, t := range allThai {
// Create a render texture
texture := rl.LoadRenderTexture(256, 256)
rl.BeginTextureMode(texture)
rl.ClearBackground(rl.White)
// Draw the Thai character
charWidth := rl.MeasureText(t.character, 128)
charX := int32((256 - charWidth) / 2)
charY := int32(80)
rl.DrawText(t.character, charX, charY, 128, rl.Black)
// Draw name at the bottom
nameWidth := rl.MeasureText(t.name, 24)
nameX := int32((256 - nameWidth) / 2)
nameY := int32(200)
rl.DrawText(t.name, nameX, nameY, 24, rl.Blue)
rl.EndTextureMode()
// Convert render texture to image
img := rl.LoadImageFromTexture(texture.Texture)
// Save as PNG
filename := "images/" + t.character + "_" + t.name + ".png"
rl.ExportImage(*img, filename)
// Cleanup
rl.UnloadImage(img)
rl.UnloadRenderTexture(texture)
fmt.Println("Generated:", filename)
}
fmt.Println("Finished generating all Thai images!")
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Some files were not shown because too many files have changed in this diff Show More