package main import ( "runtime" "github.com/gen2brain/raylib-go/raylib" ) // Button represents a clickable button with animation state type Button struct { Bounds rl.Rectangle Text string Color rl.Color Hovered bool Clicked bool Scale float32 Action string } // Screen represents different application screens const ( ScreenMenu = "menu" ScreenThai = "thai" ScreenKorean = "korean" ScreenJapanese = "japanese" ) func main() { // Initialize window screenWidth := int32(800) screenHeight := int32(450) rl.InitWindow(screenWidth, screenHeight, "Learning Raylib in Go") defer rl.CloseWindow() // Set target FPS rl.SetTargetFPS(60) // Button dimensions and positions buttonWidth := int32(200) buttonHeight := int32(50) buttonSpacing := int32(20) startY := int32(screenHeight/2) - (buttonHeight*3 + buttonSpacing*2)/2 // Create buttons thaiBtn := Button{ Bounds: rl.Rectangle{ X: float32(screenWidth/2 - buttonWidth/2), Y: float32(startY), Width: float32(buttonWidth), Height: float32(buttonHeight), }, Text: "Thai", Color: rl.LightGray, Scale: 1.0, Action: ScreenThai, } koreanBtn := Button{ Bounds: rl.Rectangle{ X: float32(screenWidth/2 - buttonWidth/2), Y: float32(startY + buttonHeight + buttonSpacing), Width: float32(buttonWidth), Height: float32(buttonHeight), }, Text: "Korean", Color: rl.LightGray, Scale: 1.0, Action: ScreenKorean, } japaneseBtn := Button{ Bounds: rl.Rectangle{ X: float32(screenWidth/2 - buttonWidth/2), Y: float32(startY + (buttonHeight+buttonSpacing)*2), Width: float32(buttonWidth), Height: float32(buttonHeight), }, Text: "Japanese", Color: rl.LightGray, Scale: 1.0, Action: ScreenJapanese, } buttons := []*Button{&thaiBtn, &koreanBtn, &japaneseBtn} // Current screen state currentScreen := ScreenMenu prevScreen := ScreenMenu // Japanese screen state var japaneseTextures []rl.Texture2D var imageStartY int32 = 0 // Main game loop for !rl.WindowShouldClose() { // Get mouse position mousePos := rl.GetMousePosition() // Handle screen transitions if currentScreen != prevScreen { // Reset button states when changing screens for _, btn := range buttons { btn.Clicked = false btn.Scale = 1.0 } prevScreen = currentScreen } // Update button states and handle clicks for _, btn := range buttons { btn.Hovered = rl.CheckCollisionPointRec(mousePos, btn.Bounds) // Handle click animation if btn.Clicked { btn.Scale += 0.05 if btn.Scale >= 1.1 { btn.Clicked = false } } else if btn.Scale > 1.0 { btn.Scale -= 0.05 if btn.Scale < 1.0 { btn.Scale = 1.0 } } else { btn.Scale = 1.0 } // Handle click - only on menu screen if currentScreen == ScreenMenu && btn.Hovered && rl.IsMouseButtonPressed(rl.MouseLeftButton) { btn.Clicked = true btn.Scale = 0.95 currentScreen = btn.Action } } // Begin drawing rl.BeginDrawing() // Clear background rl.ClearBackground(rl.RayWhite) // Draw appropriate screen switch currentScreen { case ScreenMenu: // Draw title rl.DrawText("Main Menu", int32(screenWidth/2)-50, startY-60, 30, rl.Black) // Draw buttons for _, btn := range buttons { // Calculate scaled bounds for animation scaledWidth := btn.Bounds.Width * btn.Scale scaledHeight := btn.Bounds.Height * btn.Scale scaledX := btn.Bounds.X - (scaledWidth-btn.Bounds.Width)/2 scaledY := btn.Bounds.Y - (scaledHeight-btn.Bounds.Height)/2 // Draw button with animation if btn.Hovered { rl.DrawRectangleRec(rl.Rectangle{X: scaledX, Y: scaledY, Width: scaledWidth, Height: scaledHeight}, rl.DarkGray) } else { rl.DrawRectangleRec(rl.Rectangle{X: scaledX, Y: scaledY, Width: scaledWidth, Height: scaledHeight}, btn.Color) } rl.DrawRectangleLinesEx(rl.Rectangle{X: scaledX, Y: scaledY, Width: scaledWidth, Height: scaledHeight}, 2, rl.Black) // Draw text textWidth := rl.MeasureText(btn.Text, 20) textX := int32(scaledX) + int32(scaledWidth)/2 - textWidth/2 textY := int32(scaledY) + int32(scaledHeight)/2 - 10 rl.DrawText(btn.Text, textX, textY, 20, rl.Black) } case ScreenThai: rl.DrawText("Thai Language Screen", screenWidth/2-100, screenHeight/2-20, 30, rl.Red) 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 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 imagePath := "japanese/images/" hiraganaImages := []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", } // Grid layout columns := 7 imageWidth := int32(64) imageHeight := int32(64) spacing := int32(10) startX := int32(20) 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 for i, texture := range japaneseTextures { if texture.ID != 0 { row := i / columns col := i % columns x := startX + int32(col)*(imageWidth+spacing) y := startY + int32(row)*(imageHeight+spacing) - imageStartY // Draw background for image rl.DrawRectangle(x, y, imageWidth, imageHeight, rl.LightGray) // Draw the texture rl.DrawTexture(texture, int32(x), int32(y), rl.White) // Draw border rl.DrawRectangleLines(x, y, imageWidth, imageHeight, rl.Black) } } // Handle scroll with mouse wheel scroll := rl.GetMouseWheelMove() if scroll != 0 { imageStartY += int32(scroll) * 10 if imageStartY < 0 { imageStartY = 0 } } if rl.IsKeyPressed(rl.KeyEscape) { currentScreen = ScreenMenu // Unload textures when leaving for _, tex := range japaneseTextures { rl.UnloadTexture(tex) } japaneseTextures = nil imageStartY = 0 } // Draw scroll hint rl.DrawText("Use mouse wheel to scroll", screenWidth/2-100, screenHeight-30, 16, rl.Gray) } // Draw FPS counter rl.DrawFPS(10, 10) // End drawing rl.EndDrawing() } } // Required for raylib-go on some platforms func init() { runtime.LockOSThread() }