From dcc8a3a4f93eb5b7dcc965e63ad2ea6057a8ee6b Mon Sep 17 00:00:00 2001 From: citrons Date: Wed, 29 Jan 2025 21:57:36 -0600 Subject: keyboard and mouse handling --- football/main.go | 237 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 188 insertions(+), 49 deletions(-) (limited to 'football/main.go') diff --git a/football/main.go b/football/main.go index a6cd954..f6332c1 100644 --- a/football/main.go +++ b/football/main.go @@ -2,9 +2,13 @@ package main import ( "citrons.xyz/talk/tui" + "zgo.at/termfo/keys" "math/rand" "log" + "os" "strings" + "strconv" + "fmt" "time" ) @@ -13,14 +17,20 @@ type ball struct { y int vx int vy int + explode int inGoal bool } -func main() { - tui.Start() +var username = os.Getenv("USER") + +var score struct { + home int + guest int +} +func main() { s := tui.Size() - var balls [20]ball + var balls [50]ball for i := 0; i < len(balls); i++ { balls[i].x = rand.Int() % s.Width - 1 balls[i].y = rand.Int() % s.Height @@ -36,69 +46,198 @@ func main() { } } - var sb strings.Builder + if username == "" { + username = "GUEST" + } + username = string([]rune(username)[:10]) + + tui.Start() + + var ( + sb strings.Builder + response string + lastKey keys.Key + mouseButton int + mouseHeld bool + scrolled int + responsesUnlocked = 5 + ) + t := time.After(time.Second / 15) for { - tui.Clear() - s := tui.Size() - for y := 0; y < s.Height; y++ { - for x := 0; x < s.Width; x++ { - if (x + 66) % 10 == 1 && (y + 2) % 5 == 1 { - tui.Write(x, y, "*", tui.Style {Fg: tui.Green}) + select { + case ev := <-tui.Events(): + if ev.Err != nil { + log.Fatal(ev.Err) + } + if ev.Key == keys.Escape || ev.Key == 'c' | keys.Ctrl { + tui.End() + return + } + if ev.Key == keys.Backspace { + sb.Reset() + } + if ev.Key == keys.Enter && len(sb.String()) > 0 { + sb.Reset() + var i int + if responsesUnlocked < 40 { + i = rand.Int() % responsesUnlocked + } else { + i = 30 + rand.Int() % (responsesUnlocked - 30) } + response = platitudes[i] + if responsesUnlocked < len(platitudes) && rand.Int() % 3 == 0 { + if responsesUnlocked < 12 || score.guest > 0 { + responsesUnlocked++ + } + } + } + if ev.TextInput != 0 { + sb.WriteRune(ev.TextInput) + } + if ev.Mouse.Pressed { + mouseHeld = true + mouseButton = ev.Mouse.Button + fire(balls[:], ev.Mouse.X, ev.Mouse.Y) + } else if ev.Mouse.Released { + mouseHeld = false + } + scrolled += ev.Mouse.Scroll + if ev.Key != 0 { + lastKey = ev.Key } + case <-t: + stepFootball(balls[:]) + t = time.After(time.Second / 15) } - tui.Write(2, 1, "normal", tui.Style {Fg: tui.Red}) - tui.Write(2, 2, "bold", tui.Style {Fg: tui.Yellow, Bold: true}) - tui.Write(2, 3, "italic", tui.Style {Fg: tui.Green, Italic: true}) - tui.Write(2, 4, "underline", tui.Style {Fg: tui.Blue, Underline: true}) - tui.Write(2, 5, "strikethrough", tui.Style {Fg: tui.Magenta, Strikethrough: true}) - tui.Write(2, 6, "hooray!", tui.Style {Fg: tui.White, Bold: true, Italic: true, Underline: true, Strikethrough: true}) - gx := s.Width / 2 - 1 - for i := 0; i < len(balls); i++ { - if balls[i].inGoal { - continue + if score.home == len(balls) { + response = "wow, you did very poorly." + } + + tui.Clear() + drawFootball(balls[:]) + tui.Write(1, 9, " DIALOG:", tui.Style {Fg: tui.Red, Bold: true}) + tui.Write(1, 10, " ", tui.DefaultStyle) + w := tui.Write(2, 10, sb.String(), tui.DefaultStyle) + tui.MoveCursor(2 + w, 10) + tui.Write(1, 11, " RESPONSE:", tui.Style {Fg: tui.Green, Bold: true}) + tui.Write(1, 12, " ", tui.DefaultStyle) + tui.Write(2, 12, response, tui.DefaultStyle) + + tui.Write(1, 14, " TIP: click the mouse", tui.Style {Fg: tui.Yellow, Bold: true}) + + tui.Write(1, 15, " ", tui.DefaultStyle) + tui.Write(2, 15, lastKey.Name(), tui.DefaultStyle) + tui.Write(11, 15, " ", tui.DefaultStyle) + tui.Write(12, 15, strconv.FormatInt(int64(rune(lastKey)), 16), tui.DefaultStyle) + + if mouseHeld { + tui.Write(1, 18, " ", tui.DefaultStyle) + tui.Write(2, 18, strconv.Itoa(mouseButton), tui.DefaultStyle) + } + tui.Write(1, 19, " ", tui.DefaultStyle) + tui.Write(2, 19, strconv.Itoa(scrolled), tui.DefaultStyle) + + s := tui.Size() + tui.Write(s.Width - 26, 1, " ", tui.DefaultStyle) + tui.Write(s.Width - 25, 1, "HOME", tui.Style {Bg: tui.Green, Bold: true}) + hs := fmt.Sprintf(" %02d", score.home) + tui.Write(s.Width - 26, 2, hs, tui.Style {Fg: tui.Yellow, Bold: true}) + + tui.Write(s.Width - 16, 1, " ", tui.DefaultStyle) + tui.Write(s.Width - 15, 1, username, tui.Style {Bg: tui.Red, Bold: true}) + gs := fmt.Sprintf(" %02d", score.guest) + tui.Write(s.Width - 16, 2, gs, tui.Style {Fg: tui.Yellow, Bold: true}) + + if err := tui.Present(); err != nil { + log.Fatal(err) + } + } +} + +func stepFootball(balls []ball) { + s := tui.Size() + gx := s.Width / 2 - 1 + for i := 0; i < len(balls); i++ { + if balls[i].inGoal { + continue + } + if balls[i].explode > 0 { + balls[i].explode-- + if balls[i].explode == 0 { + balls[i].inGoal = true } - balls[i].x += balls[i].vx - balls[i].y += balls[i].vy - if balls[i].x < 0 { - balls[i].x = 0 - balls[i].vx = -balls[i].vx - } else if balls[i].x >= s.Width - 1 { + continue + } + + balls[i].x += balls[i].vx + balls[i].y += balls[i].vy + if balls[i].x < 0 { + balls[i].x = 0 + balls[i].vx = -balls[i].vx + } else if balls[i].x >= s.Width - 1 { + if balls[i].x - s.Width < 2 { balls[i].x = s.Width - 2 balls[i].vx = -balls[i].vx + } else { + balls[i].x = rand.Int() % s.Width } - if balls[i].y < 0 { - balls[i].y = 0 - balls[i].vy = -balls[i].vy - } else if balls[i].y >= s.Height { + } + if balls[i].y < 0 { + balls[i].y = 0 + balls[i].vy = -balls[i].vy + } else if balls[i].y >= s.Height { + if balls[i].y - s.Height < 2 { balls[i].y = s.Height - 1 balls[i].vy = -balls[i].vy + } else { + balls[i].y = rand.Int() % s.Height } - if balls[i].x >= gx - 1 && balls[i].x <= gx + 1 && balls[i].y == 0 { - balls[i].inGoal = true - continue - } - tui.Write(balls[i].x, balls[i].y, "⚽", tui.DefaultStyle) } - tui.Write(gx, 0, "🥅", tui.DefaultStyle) + if balls[i].x >= gx - 1 && balls[i].x <= gx + 1 && balls[i].y == 0 { + balls[i].inGoal = true + score.home++ + continue + } + } +} - w := tui.Write(2, 8, sb.String(), tui.DefaultStyle) - tui.MoveCursor(2 + w, 8) - err := tui.Present() - if err != nil { - log.Fatal(err) +func fire(balls []ball, x int, y int) { + for i := 0; i < len(balls); i++ { + if balls[i].explode > 0 || balls[i].inGoal { + continue } + if x >= balls[i].x - 2 && x <= balls[i].x + 3 && + y >= balls[i].y - 1 && y <= balls[i].y + 1 { + balls[i].explode = 5 + score.guest++ + } + } +} - select { - case ev := <-tui.Events(): - switch ev := ev.(type) { - case tui.TextInput: - sb.WriteRune(rune(ev)) - case error: - log.Fatal(ev) +func drawFootball(balls []ball) { + s := tui.Size() + for y := 0; y < s.Height; y++ { + for x := 0; x < s.Width; x++ { + if (x + 66) % 10 == 1 && (y + 2) % 5 == 1 { + tui.Write(x, y, "*", tui.Style {Fg: tui.Green}) } - case <-time.After(time.Second / 16): } } + tui.Write(2, 1, "normal", tui.Style {Fg: tui.Red}) + tui.Write(2, 2, "bold", tui.Style {Fg: tui.Yellow, Bold: true}) + tui.Write(2, 3, "italic", tui.Style {Fg: tui.Green, Italic: true}) + tui.Write(2, 4, "underline", tui.Style {Fg: tui.Blue, Underline: true}) + tui.Write(2, 5, "strikethrough", tui.Style {Fg: tui.Magenta, Strikethrough: true}) + tui.Write(2, 6, "hooray!", tui.Style {Fg: tui.White, Bold: true, Italic: true, Underline: true, Strikethrough: true}) + + for _, b := range balls { + if b.explode > 0 { + tui.Write(b.x, b.y, "💥", tui.DefaultStyle) + } else if !b.inGoal { + tui.Write(b.x, b.y, "⚽", tui.DefaultStyle) + } + } + gx := s.Width / 2 - 1 + tui.Write(gx, 0, "🥅", tui.DefaultStyle) } -- cgit v1.2.3