From 8c852c39ba63d547251e2325bcf529a336011620 Mon Sep 17 00:00:00 2001 From: Louis Dalibard Date: Sun, 3 Nov 2024 14:48:53 +0100 Subject: [PATCH] feat: add particles --- config/config.go | 72 ++++++++++++++++++++++++------------------ go.mod | 1 + go.sum | 2 ++ main.go | 36 ++++++++++++++++++--- particles/particles.go | 11 +++++++ 5 files changed, 88 insertions(+), 34 deletions(-) create mode 100644 particles/particles.go diff --git a/config/config.go b/config/config.go index af47878..e181509 100644 --- a/config/config.go +++ b/config/config.go @@ -14,39 +14,51 @@ import ( ) type ConfigS struct { - FPSCounter bool - ShowMPRIS bool - MPRISTextOpacity uint8 - TargetFPS int32 - WindowWidth int32 - WindowHeight int32 - CaptureDeviceIndex int - SampleRate uint32 - RingBufferSize uint32 - ReadBufferSize uint32 - Gain float32 - LineOpacity uint8 - LineBrightness float64 - LineThickness float32 - LineInvSqrtOpacityControl bool + FPSCounter bool + ShowMPRIS bool + MPRISTextOpacity uint8 + TargetFPS int32 + WindowWidth int32 + WindowHeight int32 + CaptureDeviceIndex int + SampleRate uint32 + RingBufferSize uint32 + ReadBufferSize uint32 + Gain float32 + LineOpacity uint8 + LineBrightness float64 + LineThickness float32 + LineInvSqrtOpacityControl bool + Particles bool + ParticleGenPerFrameEveryXSamples int + ParticleMaxCount int + ParticleMinSize float32 + ParticleMaxSize float32 + ParticleAcceleration float32 } var DefaultConfig = ConfigS{ - FPSCounter: false, - ShowMPRIS: true, - MPRISTextOpacity: 255, - TargetFPS: 240, - WindowWidth: 1300, - WindowHeight: 1300, - CaptureDeviceIndex: 0, - SampleRate: 96000, - RingBufferSize: 9600, - ReadBufferSize: 9600, - Gain: 1, - LineOpacity: 200, - LineBrightness: 1, - LineThickness: 3, - LineInvSqrtOpacityControl: false, + FPSCounter: false, + ShowMPRIS: true, + MPRISTextOpacity: 255, + TargetFPS: 240, + WindowWidth: 1300, + WindowHeight: 1300, + CaptureDeviceIndex: 0, + SampleRate: 96000, + RingBufferSize: 9600, + ReadBufferSize: 9600, + Gain: 1, + LineOpacity: 200, + LineBrightness: 1, + LineThickness: 3, + LineInvSqrtOpacityControl: false, + Particles: true, + ParticleGenPerFrameEveryXSamples: 9600, + ParticleMaxCount: 3000, + ParticleMinSize: 0.2, + ParticleMaxSize: 2.0, + ParticleAcceleration: 0.01, } var Config ConfigS diff --git a/go.mod b/go.mod index 2fb4c0f..c1b3eae 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module xyosc go 1.23.2 require ( + github.com/chewxy/math32 v1.11.1 github.com/flopp/go-findfont v0.1.0 github.com/fsnotify/fsnotify v1.8.0 github.com/gen2brain/malgo v0.11.22 diff --git a/go.sum b/go.sum index 888f5a9..111c71e 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/chewxy/math32 v1.11.1 h1:b7PGHlp8KjylDoU8RrcEsRuGZhJuz8haxnKfuMMRqy8= +github.com/chewxy/math32 v1.11.1/go.mod h1:dOB2rcuFrCn6UHrze36WSLVPKtzPMRAQvBvUwkSsLqs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/ebitengine/gomobile v0.0.0-20240911145611-4856209ac325 h1:Gk1XUEttOk0/hb6Tq3WkmutWa0ZLhNn/6fc6XZpM7tM= diff --git a/main.go b/main.go index b48bbb7..a78f8f9 100644 --- a/main.go +++ b/main.go @@ -5,15 +5,18 @@ import ( "image" "image/color" "log" + "math/rand/v2" "xyosc/audio" "xyosc/config" "xyosc/fastsqrt" "xyosc/fonts" "xyosc/icons" "xyosc/media" + "xyosc/particles" "fmt" + "github.com/chewxy/math32" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/ebitenutil" "github.com/hajimehoshi/ebiten/v2/text/v2" @@ -35,6 +38,7 @@ func (g *Game) Draw(screen *ebiten.Image) { var BY float32 binary.Read(audio.SampleRingBuffer, binary.NativeEndian, &AX) binary.Read(audio.SampleRingBuffer, binary.NativeEndian, &AY) + S := float32(0) for i := uint32(0); i < config.Config.ReadBufferSize/audio.SampleSizeInBytes/2; i++ { binary.Read(audio.SampleRingBuffer, binary.NativeEndian, &BX) binary.Read(audio.SampleRingBuffer, binary.NativeEndian, &BY) @@ -43,17 +47,41 @@ func (g *Game) Draw(screen *ebiten.Image) { fBX := float32(BX) * config.Config.Gain * float32(scale) fBY := -float32(BY) * config.Config.Gain * float32(scale) if config.Config.LineInvSqrtOpacityControl { - inv := fastsqrt.FastInvSqrt32((fBX-fAX)*(fBX-fAX) + (fBY-fBY)*(fBY-fBY)) colorAdjusted := color.RGBA{config.ThirdColor.R, config.ThirdColor.G, config.ThirdColor.B, uint8(float32(config.Config.LineOpacity) * inv)} - vector.StrokeLine(screen, float32(config.Config.WindowWidth/2)+fAX, float32(config.Config.WindowWidth/2)+fAY, float32(config.Config.WindowWidth/2)+fBX, float32(config.Config.WindowWidth/2)+fBY, config.Config.LineThickness, colorAdjusted, true) + vector.StrokeLine(screen, float32(config.Config.WindowWidth/2)+fAX, float32(config.Config.WindowHeight/2)+fAY, float32(config.Config.WindowWidth/2)+fBX, float32(config.Config.WindowHeight/2)+fBY, config.Config.LineThickness, colorAdjusted, true) } else { - vector.StrokeLine(screen, float32(config.Config.WindowWidth/2)+fAX, float32(config.Config.WindowWidth/2)+fAY, float32(config.Config.WindowWidth/2)+fBX, float32(config.Config.WindowWidth/2)+fBY, config.Config.LineThickness, config.ThirdColorAdj, true) - + vector.StrokeLine(screen, float32(config.Config.WindowWidth/2)+fAX, float32(config.Config.WindowHeight/2)+fAY, float32(config.Config.WindowWidth/2)+fBX, float32(config.Config.WindowHeight/2)+fBY, config.Config.LineThickness, config.ThirdColorAdj, true) } + S += float32(AX)*float32(AX) + float32(AY)*float32(AY) + if config.Config.Particles { + if rand.IntN(config.Config.ParticleGenPerFrameEveryXSamples) == 0 { + if len(particles.Particles) >= config.Config.ParticleMaxCount { + particles.Particles = particles.Particles[1:] + } + particles.Particles = append(particles.Particles, particles.Particle{ + X: float32(AX) * config.Config.Gain, + Y: float32(AY) * config.Config.Gain, + VX: 0, + VY: 0, + Size: rand.Float32()*(config.Config.ParticleMaxSize-config.Config.ParticleMinSize) + config.Config.ParticleMinSize, + }) + } + } + AX = BX AY = BY } + + for i, particle := range particles.Particles { + vector.DrawFilledCircle(screen, float32(config.Config.WindowWidth/2)+particle.X*float32(scale), float32(config.Config.WindowHeight/2)+particle.Y*float32(scale), particle.Size, config.ThirdColor, true) + norm := math32.Sqrt(particles.Particles[i].X*particles.Particles[i].X + particles.Particles[i].Y*particles.Particles[i].Y) + particles.Particles[i].X += particle.VX / float32(ebiten.ActualTPS()) + particles.Particles[i].Y += particle.VY / float32(ebiten.ActualTPS()) + particles.Particles[i].VX += config.Config.ParticleAcceleration * particle.X / norm * S / float32(ebiten.ActualTPS()) + particles.Particles[i].VY += config.Config.ParticleAcceleration * particle.Y / norm * S / float32(ebiten.ActualTPS()) + } + //audio.SampleRingBuffer.Reset() if config.Config.FPSCounter { ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f", ebiten.ActualTPS())) diff --git a/particles/particles.go b/particles/particles.go new file mode 100644 index 0000000..61b1eaa --- /dev/null +++ b/particles/particles.go @@ -0,0 +1,11 @@ +package particles + +type Particle struct { + X float32 + Y float32 + VX float32 + VY float32 + Size float32 +} + +var Particles = []Particle{}