mirror of
https://github.com/maaslalani/confetty.git
synced 2024-12-22 22:26:37 +00:00
Inital commit
This commit is contained in:
commit
1d4070136b
10
go.mod
Normal file
10
go.mod
Normal file
@ -0,0 +1,10 @@
|
||||
module github.com/maaslalani/confetty
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/charmbracelet/bubbles v0.8.0
|
||||
github.com/charmbracelet/bubbletea v0.14.1
|
||||
github.com/charmbracelet/lipgloss v0.3.0
|
||||
golang.org/x/term v0.0.0-20210422114643-f5beecf764ed
|
||||
)
|
47
go.sum
Normal file
47
go.sum
Normal file
@ -0,0 +1,47 @@
|
||||
github.com/atotto/clipboard v0.1.2/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
github.com/charmbracelet/bubbles v0.8.0 h1:+l2op90Ag37Vn+30O1hbg/0wBl+e+sxHhgY1F/rvdHs=
|
||||
github.com/charmbracelet/bubbles v0.8.0/go.mod h1:5WX1sSSjNCgCrzvRMN/z23HxvWaa+AI16Ch0KPZPeDs=
|
||||
github.com/charmbracelet/bubbletea v0.13.1/go.mod h1:tp9tr9Dadh0PLhgiwchE5zZJXm5543JYjHG9oY+5qSg=
|
||||
github.com/charmbracelet/bubbletea v0.14.1 h1:pD/bM5LBEH/nDo7nKcgNUgi4uRHQhpWTIHZbG5vuSlc=
|
||||
github.com/charmbracelet/bubbletea v0.14.1/go.mod h1:b5lOf5mLjMg1tRn1HVla54guZB+jvsyV0yYAQja95zE=
|
||||
github.com/charmbracelet/lipgloss v0.1.2/go.mod h1:5D8zradw52m7QmxRF6QgwbwJi9je84g8MkWiGN07uKg=
|
||||
github.com/charmbracelet/lipgloss v0.3.0 h1:5MysOD6sHr4RP4jkZNWGVIul5GKoOsP12NgbgXPvAlA=
|
||||
github.com/charmbracelet/lipgloss v0.3.0/go.mod h1:VkhdBS2eNAmRkTwRKLJCFhCOVkjntMusBDxv7TXahuk=
|
||||
github.com/containerd/console v1.0.1 h1:u7SFAJyRqWcG6ogaMAx3KjSTy1e3hT9QxqX7Jco7dRc=
|
||||
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
|
||||
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68 h1:y1p/ycavWjGT9FnmSjdbWUlLGvcxrY0Rw3ATltrxOhk=
|
||||
github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ=
|
||||
github.com/muesli/termenv v0.7.2/go.mod h1:ct2L5N2lmix82RaY3bMWwVu/jUFc9Ule0KGDCiKYPh8=
|
||||
github.com/muesli/termenv v0.8.1 h1:9q230czSP3DHVpkaPDXGp0TOfAwyjyYwXlUCQxQSaBk=
|
||||
github.com/muesli/termenv v0.8.1/go.mod h1:kzt/D/4a88RoheZmwfqorY3A+tnsSMA9HJC/fQSFKo0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20210422114643-f5beecf764ed h1:Ei4bQjjpYUsS4efOUz+5Nz++IVkHk87n2zBA0NxBWc0=
|
||||
golang.org/x/term v0.0.0-20210422114643-f5beecf764ed/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
18
main.go
Normal file
18
main.go
Normal file
@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/maaslalani/confetty/pkg/confetty"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
func main() {
|
||||
p := tea.NewProgram(confetty.InitialModel())
|
||||
if err := p.Start(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
148
pkg/confetty/confetty.go
Normal file
148
pkg/confetty/confetty.go
Normal file
@ -0,0 +1,148 @@
|
||||
package confetty
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/charmbracelet/bubbles/viewport"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
const (
|
||||
fps = 60.0
|
||||
)
|
||||
|
||||
var colors = []lipgloss.Color{
|
||||
lipgloss.Color("#a864fd"),
|
||||
lipgloss.Color("#29cdff"),
|
||||
lipgloss.Color("#78ff44"),
|
||||
lipgloss.Color("#ff718d"),
|
||||
lipgloss.Color("#fdff6a"),
|
||||
}
|
||||
|
||||
type frameMsg time.Time
|
||||
|
||||
func animate() tea.Cmd {
|
||||
return tea.Tick(time.Second/fps, func(t time.Time) tea.Msg {
|
||||
return frameMsg(t)
|
||||
})
|
||||
}
|
||||
|
||||
func waitASec(ms int) tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
time.Sleep(time.Millisecond * time.Duration(ms))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type model struct {
|
||||
particles []*Particle
|
||||
viewport viewport.Model
|
||||
}
|
||||
|
||||
type Particle struct {
|
||||
char string
|
||||
acc Acceleration
|
||||
vel Velocity
|
||||
pos Position
|
||||
color lipgloss.Color
|
||||
}
|
||||
|
||||
type Position struct {
|
||||
x float64
|
||||
y float64
|
||||
}
|
||||
|
||||
type Velocity struct {
|
||||
x float64
|
||||
y float64
|
||||
}
|
||||
|
||||
type Acceleration struct {
|
||||
x float64
|
||||
y float64
|
||||
}
|
||||
|
||||
var characters = []string{"▄", "▀", "█"} // "▓", "▒", "░"}
|
||||
|
||||
func InitialModel() model {
|
||||
particles := []*Particle{}
|
||||
|
||||
width, height, err := term.GetSize(0)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for i := 0; i < 25; i++ {
|
||||
x := float64(width / 2)
|
||||
y := float64(height / 2)
|
||||
|
||||
p := &Particle{
|
||||
char: lipgloss.NewStyle().Foreground(colors[rand.Intn(len(colors))]).Render(characters[rand.Intn(len(characters))]),
|
||||
pos: Position{x: x, y: y},
|
||||
vel: Velocity{x: (rand.Float64() - 0.5) * 100, y: (rand.Float64() - 0.5) * 100},
|
||||
acc: Acceleration{x: 0, y: 9.8},
|
||||
}
|
||||
particles = append(particles, p)
|
||||
}
|
||||
|
||||
return model{particles: particles}
|
||||
}
|
||||
|
||||
func (m model) Init() tea.Cmd {
|
||||
return tea.Sequentially(waitASec(500), animate())
|
||||
}
|
||||
|
||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
return m, tea.Quit
|
||||
case frameMsg:
|
||||
for _, p := range m.particles {
|
||||
p.pos.y, p.vel.y = p.pos.y+p.vel.y/fps, p.vel.y+p.acc.y/fps
|
||||
p.pos.x, p.vel.x = p.pos.x+p.vel.x/fps, p.vel.x+p.acc.x/fps
|
||||
}
|
||||
return m, animate()
|
||||
case tea.WindowSizeMsg:
|
||||
m.viewport.Width = msg.Width
|
||||
m.viewport.Height = msg.Height
|
||||
return m, nil
|
||||
default:
|
||||
return m, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m model) View() string {
|
||||
if m.viewport.Height <= 0 || m.viewport.Width <= 0 {
|
||||
return ""
|
||||
}
|
||||
var out strings.Builder
|
||||
grid := make([][]string, m.viewport.Height)
|
||||
for i := range grid {
|
||||
grid[i] = make([]string, m.viewport.Width)
|
||||
}
|
||||
for _, p := range m.particles {
|
||||
y := int(math.Round(p.pos.y))
|
||||
x := int(math.Round(p.pos.x))
|
||||
if y < 0 || x < 0 || x >= m.viewport.Width-1 || y >= m.viewport.Height-1 {
|
||||
continue
|
||||
}
|
||||
grid[y][x] = p.char
|
||||
}
|
||||
for i := range grid {
|
||||
for _, col := range grid[i] {
|
||||
if col == "" {
|
||||
fmt.Fprint(&out, " ")
|
||||
} else {
|
||||
fmt.Fprint(&out, col)
|
||||
}
|
||||
}
|
||||
fmt.Fprint(&out, "\n")
|
||||
}
|
||||
return out.String()
|
||||
}
|
Loading…
Reference in New Issue
Block a user