package game import ( tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) var inkPalette = []string{"#ff6b6b", "#feca57", "#1dd1a1", "#54a0ff", "#ff9ff3", "#48dbfb", "#f368e0", "#ffffff"} var charPalette = []rune{'█', '▓', '▒', '░', '#', '*', '.', '@', 'o', '+'} type state int const ( stateIntro state = iota stateCanvas ) type Model struct { canvas *Canvas id string label string state state renderer *lipgloss.Renderer inkColorIdx int charIdx int width, height int } func NewModel(canvas *Canvas, id, label string, renderer *lipgloss.Renderer) Model { return Model{canvas: canvas, id: id, label: label, state: stateIntro, renderer: renderer} } func (m Model) Init() tea.Cmd { return nil } func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.WindowSizeMsg: m.width, m.height = msg.Width, msg.Height return m, nil case canvasUpdatedMsg: // Someone (possibly this session) changed the shared state -- // nothing to do here but re-render; View() always reads a fresh // snapshot from the canvas. return m, nil case tea.KeyMsg: if m.state == stateIntro { m.state = stateCanvas return m, nil } return m.handleKey(msg) } return m, nil } func (m Model) handleKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) { switch msg.String() { case "ctrl+c", "q": return m, tea.Quit case "up", "k": m.canvas.MoveCursor(m.id, 0, -1) case "down", "j": m.canvas.MoveCursor(m.id, 0, 1) case "left", "h": m.canvas.MoveCursor(m.id, -1, 0) case "right", "l": m.canvas.MoveCursor(m.id, 1, 0) case " ", "enter": if cur, ok := m.canvas.CursorsSnapshot()[m.id]; ok { m.canvas.Paint(cur.X, cur.Y, charPalette[m.charIdx], inkPalette[m.inkColorIdx]) } case "backspace", "delete": if cur, ok := m.canvas.CursorsSnapshot()[m.id]; ok { m.canvas.Paint(cur.X, cur.Y, ' ', "") } case "[": m.charIdx = (m.charIdx - 1 + len(charPalette)) % len(charPalette) case "]": m.charIdx = (m.charIdx + 1) % len(charPalette) case "1", "2", "3", "4", "5", "6", "7", "8": m.inkColorIdx = int(msg.String()[0] - '1') case "c": m.canvas.Clear() } return m, nil }