package main import ( "math" "math/rand" "github.com/gen2brain/raylib-go/raylib" ) type ContourLayer struct { field Field actors []*Actor rng *rand.Rand } func NewContourLayer(sketch *Sketch, rng *rand.Rand, field Field) *ContourLayer { actors := make([]*Actor, 0) layer := ContourLayer { rng: rng, field: field, actors: actors, } layer.AddActors(1, sketch.sourceWidth, sketch.sourceHeight) return &layer } func (s *ContourLayer) AddActors(n, sourceWidth, sourceHeight int32) { for range n { x := s.rng.Int31() % sourceWidth y := s.rng.Int31() % sourceHeight newActor := &Actor { position: rl.Vector2{X: float32(x), Y: float32(y)}, field: s.field, stepSize: 1, color: rl.NewColor(11, 35, 176, 50), } s.actors = append(s.actors, newActor) } } func (s *ContourLayer) Update(ctx *RenderCtx) { s.AddActors(100, ctx.SourceWidth, ctx.SourceHeight) } func (s *ContourLayer) Draw(ctx *RenderCtx) { rl.BeginBlendMode(rl.BlendAdditive) for _, actor := range s.actors { actor.Draw() } rl.EndBlendMode() } func (s *ContourLayer) IsDirty() bool { return true } type Actor struct { position rl.Vector2 field Field stepSize float32 color rl.Color } func (a *Actor) Draw() { v := a.field.Get(a.position.X, a.position.Y) rad := rl.Remap(v, 0, 1, 0, 3*math.Pi) nextPosition := rl.Vector2{X: a.position.X + a.stepSize*float32(math.Cos(float64(rad))), Y: a.position.Y + a.stepSize*float32(math.Sin(float64(rad)))} rl.DrawLineV(a.position, nextPosition, a.color) //fmt.Printf("position %v -> nextPosition %v \n", a.position, nextPosition) a.position = nextPosition } func RandRadialVec(rng *rand.Rand, minRadius float32, maxRadius float32, loAngle float32, hiAngle float32) rl.Vector2 { r := float64(rl.Remap(rng.Float32(), 0, 1, minRadius, maxRadius)) deg := float64(rl.Remap(rng.Float32(), 0, 1, loAngle, hiAngle)) rad := rl.Deg2rad * deg return rl.Vector2{X: float32(r * math.Cos(rad)), Y: float32(r * math.Sin(rad))} } type Worm struct { position rl.Vector2 angles []float32 angleIndex int stepSize int renderPct float32 } func (w *Worm) Draw(ctx *RenderCtx) { rl.PushMatrix() rl.Translatef(w.position.X, w.position.Y, 0) lastAngle := float32(0.0) stepCount := 0 nudged := false for i := range w.angles { ii := (i + w.angleIndex) % len(w.angles) angle := w.angles[ii] deltaAngle := angle - lastAngle if !nudged { rad := float64(deltaAngle * math.Pi / 180.0) nudge := rl.Vector2{X: float32(w.stepSize) * float32(math.Cos(rad)), Y: float32(w.stepSize) * float32(math.Sin(rad))} w.position = rl.Vector2Add(w.position, nudge) nudged = true } rl.Rotatef(deltaAngle, 0, 0, 1) rl.DrawLine(0, 0, int32(w.stepSize), 0, rl.NewColor(184, 187, 38, 50)) rl.Translatef(float32(w.stepSize), 0, 0) lastAngle = angle stepCount++ if stepCount > int(float32(len(w.angles))*w.renderPct) { break } } rl.PopMatrix() w.angleIndex = (w.angleIndex + 1) % len(w.angles) }