package modes import ( "image/color" "path/filepath" "time" "github.com/hajimehoshi/ebiten/v2" "kidskeyboard/internal/ui" ) type FindKeyMode struct { ctx Context target rune successTicks int errorTicks int lastJingle int } const findChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" func NewFindKeyMode(ctx Context) *FindKeyMode { m := &FindKeyMode{ctx: ctx, lastJingle: -1} m.pickNext() return m } func (m *FindKeyMode) Name() string { return "CTRL+F5 Find Key" } func (m *FindKeyMode) OnEnter() {} func (m *FindKeyMode) OnLeave() {} func (m *FindKeyMode) HandleInput() { if m.successTicks > 0 { return } for _, key := range justPressedKeys() { if !childKey(key) { continue } r, ok := keyRune(key) if ok && r == m.target { m.successTicks = 180 m.errorTicks = 0 m.playJingle() return } m.errorTicks = 18 m.ctx.Audio.PlayError() return } } func (m *FindKeyMode) Update() { if m.errorTicks > 0 { m.errorTicks-- } if m.successTicks > 0 { m.successTicks-- if m.successTicks == 0 { m.pickNext() } } } func (m *FindKeyMode) Draw(screen *ebiten.Image) { screen.Fill(color.Black) w, h := screen.Bounds().Dx(), screen.Bounds().Dy() ui.Text(screen, "CTRL+F5", 20, 20, color.White, 2) var clr color.Color = color.White if m.errorTicks > 0 { clr = color.NRGBA{R: 255, A: 255} } if m.successTicks > 0 { clr = color.NRGBA{G: 255, A: 255} } ui.CenteredText(screen, string(m.target), w/2, h/2, clr, 18) } func (m *FindKeyMode) pickNext() { m.target = rune(findChars[m.ctx.RNG.Intn(len(findChars))]) } func (m *FindKeyMode) playJingle() { const count = 4 next := m.ctx.RNG.Intn(count) if count > 1 { for next == m.lastJingle { next = m.ctx.RNG.Intn(count) } } m.lastJingle = next path := filepath.Join("assets", "sounds", "jingle"+string(rune('1'+next))+".wav") if m.ctx.Audio.PlayWAV(path, true) { return } freq := 520 + float64(next)*120 m.ctx.Audio.PlayToneInterrupt(freq, 180*time.Millisecond, 0.28) }