Use harmonica

This commit is contained in:
Maas Lalani 2021-11-05 00:24:58 -04:00
parent 9c59ff5446
commit c1f984adc7
6 changed files with 38 additions and 64 deletions

View File

@ -8,6 +8,7 @@ import (
"github.com/maaslalani/confetty/simulation" "github.com/maaslalani/confetty/simulation"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/harmonica"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
) )
@ -41,11 +42,11 @@ func Spawn(width, height int) []*simulation.Particle {
y := float64(0) y := float64(0)
p := simulation.Particle{ p := simulation.Particle{
Physics: simulation.NewProjectile( Physics: harmonica.NewProjectile(
simulation.FPS(framesPerSecond), harmonica.FPS(framesPerSecond),
simulation.Point{X: x + (float64(width/4) * (rand.Float64() - 0.5)), Y: y, Z: 0}, harmonica.Point{X: x + (float64(width/4) * (rand.Float64() - 0.5)), Y: y, Z: 0},
simulation.Vector{X: (rand.Float64() - 0.5) * 100, Y: rand.Float64() * 50, Z: 0}, harmonica.Vector{X: (rand.Float64() - 0.5) * 100, Y: rand.Float64() * 50, Z: 0},
simulation.Vector(simulation.TerminalGravity), harmonica.TerminalGravity,
), ),
Char: lipgloss.NewStyle(). Char: lipgloss.NewStyle().
Foreground(lipgloss.Color(array.Sample(colors))). Foreground(lipgloss.Color(array.Sample(colors))).

View File

@ -9,6 +9,7 @@ import (
"github.com/maaslalani/confetty/simulation" "github.com/maaslalani/confetty/simulation"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/harmonica"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
) )
@ -20,8 +21,8 @@ const (
var ( var (
colors = []string{"#a864fd", "#29cdff", "#78ff44", "#ff718d", "#fdff6a"} colors = []string{"#a864fd", "#29cdff", "#78ff44", "#ff718d", "#fdff6a"}
characters = []string{"+", "*", "•"} characters = []string{"+", "*", "•"}
head_char = "▄" head = "▄"
tail_char = "│" tail = "│"
) )
type frameMsg time.Time type frameMsg time.Time
@ -39,18 +40,16 @@ type model struct {
func SpawnShoot(width, height int) *simulation.Particle { func SpawnShoot(width, height int) *simulation.Particle {
color := lipgloss.Color(array.Sample(colors)) color := lipgloss.Color(array.Sample(colors))
v := float64(rand.Intn(15) + 15.0) v := float64(rand.Intn(15) + 15.0)
x := rand.Float64() * float64(width) x := rand.Float64() * float64(width)
p := simulation.Particle{ p := simulation.Particle{
Physics: simulation.NewProjectile( Physics: harmonica.NewProjectile(
simulation.FPS(framesPerSecond), harmonica.FPS(framesPerSecond),
simulation.Point{X: x, Y: float64(height)}, harmonica.Point{X: x, Y: float64(height)},
simulation.Vector{X: 0, Y: -v}, harmonica.Vector{X: 0, Y: -v},
simulation.Vector(simulation.TerminalGravity), harmonica.TerminalGravity,
), ),
Char: lipgloss.NewStyle().Foreground(color).Render(head_char), Char: lipgloss.NewStyle().Foreground(color).Render(head),
TailChar: lipgloss.NewStyle().Foreground(color).Render(tail_char), TailChar: lipgloss.NewStyle().Foreground(color).Render(tail),
Shooting: true, Shooting: true,
ExplosionCall: SpawnExplosion, ExplosionCall: SpawnExplosion,
} }
@ -65,11 +64,11 @@ func SpawnExplosion(x, y float64, width, height int) []*simulation.Particle {
for i := 0; i < numParticles; i++ { for i := 0; i < numParticles; i++ {
p := simulation.Particle{ p := simulation.Particle{
Physics: simulation.NewProjectile( Physics: harmonica.NewProjectile(
simulation.FPS(framesPerSecond), harmonica.FPS(framesPerSecond),
simulation.Point{X: x, Y: y}, harmonica.Point{X: x, Y: y},
simulation.Vector{X: math.Cos(float64(i)) * v, Y: math.Sin(float64(i)) * v / 2}, harmonica.Vector{X: math.Cos(float64(i)) * v, Y: math.Sin(float64(i)) * v / 2},
simulation.Vector(simulation.TerminalGravity), harmonica.TerminalGravity,
), ),
Char: lipgloss.NewStyle().Foreground(color).Render(array.Sample(characters)), Char: lipgloss.NewStyle().Foreground(color).Render(array.Sample(characters)),
Shooting: false, Shooting: false,

1
go.mod
View File

@ -4,6 +4,7 @@ go 1.16
require ( require (
github.com/charmbracelet/bubbletea v0.19.0 github.com/charmbracelet/bubbletea v0.19.0
github.com/charmbracelet/harmonica v0.1.1-0.20211102215834-9db67628b1a0 // indirect
github.com/charmbracelet/lipgloss v0.4.0 github.com/charmbracelet/lipgloss v0.4.0
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
golang.org/x/sys v0.0.0-20211031064116-611d5d643895 // indirect golang.org/x/sys v0.0.0-20211031064116-611d5d643895 // indirect

2
go.sum
View File

@ -1,5 +1,7 @@
github.com/charmbracelet/bubbletea v0.19.0 h1:1gz4rbxl3qZik/oP8QW2vUtul2gO8RDDzmoLGERpTQc= github.com/charmbracelet/bubbletea v0.19.0 h1:1gz4rbxl3qZik/oP8QW2vUtul2gO8RDDzmoLGERpTQc=
github.com/charmbracelet/bubbletea v0.19.0/go.mod h1:VuXF2pToRxDUHcBUcPmCRUHRvFATM4Ckb/ql1rBl3KA= github.com/charmbracelet/bubbletea v0.19.0/go.mod h1:VuXF2pToRxDUHcBUcPmCRUHRvFATM4Ckb/ql1rBl3KA=
github.com/charmbracelet/harmonica v0.1.1-0.20211102215834-9db67628b1a0 h1:JgZg3p93jE4i2p1GaraDD63jFpTYFoH5jJJckG4Di7E=
github.com/charmbracelet/harmonica v0.1.1-0.20211102215834-9db67628b1a0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
github.com/charmbracelet/lipgloss v0.4.0 h1:768h64EFkGUr8V5yAKV7/Ta0NiVceiPaV+PphaW1K9g= github.com/charmbracelet/lipgloss v0.4.0 h1:768h64EFkGUr8V5yAKV7/Ta0NiVceiPaV+PphaW1K9g=
github.com/charmbracelet/lipgloss v0.4.0/go.mod h1:vmdkHvce7UzX6xkyf4cca8WlwdQ5RQr8fzta+xl7BOM= github.com/charmbracelet/lipgloss v0.4.0/go.mod h1:vmdkHvce7UzX6xkyf4cca8WlwdQ5RQr8fzta+xl7BOM=
github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE= github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE=

View File

@ -1,33 +0,0 @@
package simulation
type Projectile struct {
Position Point
Velocity Vector
Acceleration Vector
DeltaTime float64
}
type Point struct {
X, Y, Z float64
}
type Vector struct {
X, Y, Z float64
}
var Gravity = Vector{0, -9.81, 0}
var TerminalGravity = Vector{0, 9.81, 0}
func NewProjectile(del float64, pos Point, vel, acc Vector) *Projectile {
return &Projectile{pos, vel, acc, del}
}
func (p *Projectile) Update() {
p.Position.X += (p.Velocity.X * p.DeltaTime)
p.Position.Y += (p.Velocity.Y * p.DeltaTime)
p.Position.Z += (p.Velocity.Z * p.DeltaTime)
p.Velocity.X += (p.Acceleration.X * p.DeltaTime)
p.Velocity.Y += (p.Acceleration.Y * p.DeltaTime)
p.Velocity.Z += (p.Acceleration.Z * p.DeltaTime)
}

View File

@ -4,6 +4,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"time" "time"
"github.com/charmbracelet/harmonica"
) )
type System struct { type System struct {
@ -14,7 +16,7 @@ type System struct {
type Particle struct { type Particle struct {
Char string Char string
TailChar string TailChar string
Physics *Projectile Physics *harmonica.Projectile
Hidden bool Hidden bool
Shooting bool Shooting bool
ExplosionCall func(x, y float64, width, height int) []*Particle ExplosionCall func(x, y float64, width, height int) []*Particle
@ -38,13 +40,13 @@ func RemoveParticleFromArray(s []*Particle, i int) []*Particle {
func (s *System) Update() { func (s *System) Update() {
for i := len(s.Particles) - 1; i >= 0; i-- { for i := len(s.Particles) - 1; i >= 0; i-- {
p := s.Particles[i] p := s.Particles[i]
pos := p.Physics.Position pos := p.Physics.Position()
// if the shooting particle is slow enough then hide it and call the explosion function // if the shooting particle is slow enough then hide it and call the explosion function
if !p.Hidden && p.Shooting && p.Physics.Velocity.Y > -3 { if !p.Hidden && p.Shooting && p.Physics.Velocity().Y > -3 {
p.Hidden = true p.Hidden = true
if p.ExplosionCall != nil { if p.ExplosionCall != nil {
s.Particles = append(s.Particles, p.ExplosionCall(p.Physics.Position.X, p.Physics.Position.Y, s.Frame.Width, s.Frame.Height)...) s.Particles = append(s.Particles, p.ExplosionCall(pos.X, pos.Y, s.Frame.Width, s.Frame.Height)...)
} }
} }
@ -58,8 +60,9 @@ func (s *System) Update() {
} }
func (s *System) Visible(p *Particle) bool { func (s *System) Visible(p *Particle) bool {
y := int(p.Physics.Position.Y) pos := p.Physics.Position()
x := int(p.Physics.Position.X) x := int(pos.X)
y := int(pos.Y)
return !p.Hidden && y >= 0 && y < s.Frame.Height-1 && x >= 0 && x < s.Frame.Width-1 return !p.Hidden && y >= 0 && y < s.Frame.Height-1 && x >= 0 && x < s.Frame.Width-1
} }
@ -71,13 +74,14 @@ func (s *System) Render() string {
} }
for _, p := range s.Particles { for _, p := range s.Particles {
if s.Visible(p) { if s.Visible(p) {
plane[int(p.Physics.Position.Y)][int(p.Physics.Position.X)] = p.Char pos := p.Physics.Position()
plane[int(pos.Y)][int(pos.X)] = p.Char
if p.Shooting { if p.Shooting {
l := -int(p.Physics.Velocity.Y) l := -int(p.Physics.Velocity().Y)
for i := 1; i < l; i++ { for i := 1; i < l; i++ {
y := int(p.Physics.Position.Y) + i y := int(pos.Y) + i
if y > 0 && y < s.Frame.Height-1 { if y > 0 && y < s.Frame.Height-1 {
plane[y][int(p.Physics.Position.X)] = p.TailChar plane[y][int(pos.X)] = p.TailChar
} }
} }
} }