-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathboid.go
More file actions
126 lines (106 loc) · 2.76 KB
/
boid.go
File metadata and controls
126 lines (106 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main
import (
"math/rand"
"sync"
"github.com/dhconnelly/rtreego"
"github.com/gravestench/mathlib"
)
const tol = 0.01
type Boid struct {
Id int
position rtreego.Point
Velocity *mathlib.Vector2
trail []mathlib.Vector2
}
func (boid Boid) Bounds() *rtreego.Rect {
return boid.position.ToRect(tol)
}
func (boid *Boid) Position() *mathlib.Vector2 {
return mathlib.NewVector2(boid.position[0], boid.position[1])
}
func (boid *Boid) calculateVelocity() {
var velocityChan = make(chan *mathlib.Vector2, global.velocityComponentCount)
var wg sync.WaitGroup
wg.Add(global.velocityComponentCount)
for _, velocityComponent := range global.velocityComponents {
component := velocityComponent
go func() {
defer wg.Done()
velocityChan <- component.Delta(boid)
}()
}
wg.Wait()
close(velocityChan)
for velocity := range velocityChan {
boid.Velocity.Add(velocity)
}
boid.Velocity.Limit(global.params.maximumVelocity.value())
}
func wrap(position *mathlib.Vector2) {
switch {
case position.X < 0:
position.X += fWidth
case position.X > fWidth:
position.X -= fWidth
}
switch {
case position.Y < 0:
position.Y += fHeight
case position.Y > fHeight:
position.Y -= fHeight
}
}
func (boid *Boid) update(tick int) {
position := boid.Position()
boid.trail[tick%global.params.trailLength.value()] = *position
boid.calculateVelocity()
position.Add(boid.Velocity)
wrap(position)
boid.position = rtreego.Point{position.X, position.Y}
}
type TrailPixel struct {
pixelIndex int
colourValue byte
}
func newTrailPixel(pixelIndex int, colourValue byte) *TrailPixel {
return &TrailPixel{pixelIndex, colourValue}
}
func (boid *Boid) getTrailPixels(tick int, trailChan chan *TrailPixel) {
var wg sync.WaitGroup
trailLength := global.params.trailLength.value()
wg.Add(trailLength)
for i := 0; i < trailLength; i++ {
trailPartIndex := i
go func() {
defer wg.Done()
trailPosition := boid.trail[(tick+trailPartIndex)%trailLength]
x := int(trailPosition.X)
y := int(trailPosition.Y)
pixelIndex := (y*Width + x) * 4
colourValue := byte(255 * float64(trailLength-trailPartIndex) / float64(trailLength))
trailChan <- newTrailPixel(pixelIndex, colourValue)
}()
}
wg.Wait()
close(trailChan)
}
func newBoid(id int, position *mathlib.Vector2) *Boid {
if position == nil {
px := rand.Float64() * Width
py := rand.Float64() * Height
position = mathlib.NewVector2(px, py)
}
vx := rand.Float64() - .5
vy := rand.Float64() - .5
trailLength := global.params.trailLength.value()
trail := make([]mathlib.Vector2, trailLength)
for i := 0; i < trailLength; i++ {
trail = append(trail, *position)
}
return &Boid{
Id: id,
position: rtreego.Point{position.X, position.Y},
Velocity: mathlib.NewVector2(vx, vy),
trail: trail,
}
}