284 lines
7.8 KiB
Go
284 lines
7.8 KiB
Go
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()
|
|
}
|