package main import ( . "lcthw.dev/go/ttarpit/debug" "time" "fmt" "github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2/encoding" "lcthw.dev/go/ttarpit/game" "lcthw.dev/go/ttarpit/builder" ) type UI struct { Screen tcell.Screen DefaultStyle tcell.Style DeadStyle tcell.Style } func (ui *UI) DrawText(x int, y int, text string) { for i, cell := range text { ui.Screen.SetContent(x+i, y, cell, nil, tcell.StyleDefault) } } func (ui *UI) StyleText(x int, y int, text string, style tcell.Style) { for i, cell := range text { ui.Screen.SetContent(x+i, y, cell, nil, style) } } func (ui *UI) Render(data *game.Game, build *builder.Builder) { if data.HP <= 0 { ui.Screen.SetStyle(ui.DeadStyle) ui.Screen.Sync() ui.Screen.Clear() ui.DrawText(0, 10, fmt.Sprintf("YOU DIED!")) } else { ui.Screen.SetStyle(ui.DefaultStyle) ui.Screen.Clear() } time_since := time.Until(data.EndTime) ui.DrawText(0, 0, "Welcome to Turing's Tarpit") ui.DrawText(0, 2, fmt.Sprintf("HP: %d", data.HP)) ui.DrawText(0, 3, fmt.Sprintf("Errors: %d", data.Errors)) ui.DrawText(0, 4, fmt.Sprintf("Deadline: %s", time_since.Round(time.Second))) green := tcell.StyleDefault.Background(tcell.ColorGreen).Foreground(tcell.ColorBlack) red := tcell.StyleDefault.Background(tcell.ColorRed).Foreground(tcell.ColorBlack) yellow := tcell.StyleDefault.Background(tcell.ColorYellow).Foreground(tcell.ColorBlack) switch build.BuildState { case builder.START: ui.StyleText(0, 5, "Build: READY", green) case builder.RUNNING: ui.StyleText(0, 5, "Build: RUNNING", yellow) case builder.PASSED: ui.StyleText(0, 5, "Build: PASSED", green) case builder.FAILED: ui.StyleText(0, 5, "Build: FAILED", red) } for i := len(data.ErrorLog) - 1 ; i >= 0; i-- { errinfo := data.ErrorLog[i] ui.DrawText(0, 8 + (i % 10), errinfo.Raw) } ui.Screen.Show() } func (ui *UI) HandleKeys(ev *tcell.EventKey) bool { switch ev.Key() { case tcell.KeyEscape: return false } switch ev.Rune() { case 'q': return false } return true } func (ui *UI) HandleEvents() bool { switch ev := ui.Screen.PollEvent().(type) { case *tcell.EventResize: ui.Screen.Sync() case *tcell.EventKey: return ui.HandleKeys(ev) } return true } func (ui *UI) Exit() { ui.Screen.Fini() } func (ui *UI) RenderLoop(g *game.Game, build *builder.Builder) { go func () { for { ui.Render(g, build) time.Sleep(100 * time.Millisecond) } }() for ui.HandleEvents() { ui.Render(g, build) } } func MakeUI() *UI { var err error encoding.Register() ui := new(UI) ui.Screen, err = tcell.NewScreen() if err != nil { Log.Fatal(err) } err = ui.Screen.Init() if err != nil { Log.Fatal(err) } ui.DefaultStyle = tcell.StyleDefault. Background(tcell.ColorBlack). Foreground(tcell.ColorWhite) ui.DeadStyle = tcell.StyleDefault. Background(tcell.ColorDarkRed). Foreground(tcell.ColorWhite) ui.Screen.SetStyle(ui.DefaultStyle) ui.Screen.Clear() return ui }